| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- 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<number> = 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<number> = 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);
- }
- }
|