export class NumUtils { /** * 计算两点间的直线距离 * @param point1 * @param point2 * @returns */ private calculateDistance(point1, point2) { let dx = point2.x - point1.x; let dy = point2.y - point1.y; return Math.sqrt(dx * dx + dy * dy); } /** * 把一个数字随机拆分成n个数字 * @param total 要拆分的数字 * @param parts 拆分个数 * @returns */ public static splitNumberIntoRandomParts(total: number, parts: number): number[] { if (parts <= 0 || total <= 0) { throw new Error("Invalid input: parts must be greater than 0 and total must be greater than 0."); } if (parts === 1) { return [total]; } // Generate N-1 random points that will divide the total into parts let points: number[] = []; let remainingTotal = total; let result: number[] = []; for (let i = 0; i < parts - 1; i++) { // Generate a random number between 0 and the remaining total const max = remainingTotal - (parts - i - 1); // Ensure we can still distribute the remaining total const randomPoint = Math.floor(Math.random() * max) + 1; points.push(randomPoint); result.push(randomPoint); remainingTotal -= randomPoint; } // Add the last part which is the remaining total result.push(remainingTotal); // Shuffle the result array to ensure randomness in order for (let i = result.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [result[i], result[j]] = [result[j], result[i]]; } return result; } /** * 返回随机不相等的数字数组 * @param min * @param max * @param count * @returns */ public static getRandomUniqueNumbers(min: number, max: number, count: number): number[] { if (max - min + 1 < count) { throw new Error("Range is too small to get the required number of unique numbers."); } const result: number[] = []; const usedNumbers: Set = new Set(); while (result.length < count) { const randomNum = Math.floor(Math.random() * (max - min + 1)) + min; if (!usedNumbers.has(randomNum)) { result.push(randomNum); usedNumbers.add(randomNum); } } return result; } /** * 返回随机的数字数组 * @param min * @param max * @param count * @returns */ public static getRandomNumbers(min: number, max: number, count: number): number[] { const result: number[] = []; // const usedNumbers: Set = new Set(); while (result.length < count) { const randomNum = Math.floor(Math.random() * (max - min + 1)) + min; // if (!usedNumbers.has(randomNum)) { result.push(randomNum); // usedNumbers.add(randomNum); // } } return result; } /** * 把一个数字随机拆分成n个数字,数字之间大小不超过x * @param total 总数 * @param n 拆分等数 * @param x 相差的数 * @returns */ public static splitNumberRandomly(total: number, n: number, x: number): number[] { if (n <= 0 || total <= 0) { throw new Error("Invalid input: n and total must be positive."); } // 先尽量均匀分配 const avg = Math.floor(total / n); const remainder = total % n; // 初始化结果数组 let result: number[] = new Array(n).fill(avg); // 处理余数,将其随机分配到结果数组中 for (let i = 0; i < remainder; i++) { result[Math.floor(Math.random() * n)]++; } // 检查并调整结果数组,确保相邻数字之间相差不超过 3 for (let i = 1; i < n; i++) { while (Math.abs(result[i] - result[i - 1]) > x) { // 如果相差超过 3,则尝试调整 if (result[i] > result[i - 1] + x) { // 从 result[i] 中减去一个单位,并尝试加到 result[i-1]、result[i+1] 或其他合适的位置 result[i]--; // 为了简化,这里只尝试加到前一个或后一个元素(如果存在) if (i > 0 && Math.abs(result[i] - result[i - 1]) <= 2) { result[i - 1]++; } else if (i < n - 1 && Math.abs(result[i + 1] - (result[i] - 1)) <= 2) { result[i + 1]++; } else { // 如果无法直接调整,则随机选择一个其他位置进行调整(这里为了简化,直接抛出错误) throw new Error("Unable to adjust numbers to meet the difference constraint."); } } else if (result[i - 1] > result[i] + x) { // 类似地处理 result[i-1] 大于 result[i] + 3 的情况 result[i - 1]--; if (i > 0 && Math.abs(result[i - 1] - result[i - 2]) <= 2) { result[i - 2]++; } else if (i < n && Math.abs(result[i] - (result[i - 1] - 1)) <= 2) { result[i]++; } else { throw new Error("Unable to adjust numbers to meet the difference constraint."); } } } } // 由于上述调整可能不完全保证总和等于 total(尤其是在处理复杂情况时),我们需要最后校验并调整总和 let currentSum = result.reduce((a, b) => a + b, 0); if (currentSum !== total) { // 如果总和不匹配,则通过微调最后一个元素来修正(这里为了简化,假设总是可以通过这种方式修正) let diff = total - currentSum; result[n - 1] += diff; } return result; } /** * 判断数字数组里面的数字是否全部相等 * @param arr * @returns */ public static allEqual(arr: number[]): boolean { return arr.reduce((acc, val, index, array) => acc && (index === 0 || val === array[index - 1]), true); } }