【问题标题】:Divide / Hand out random amount分配/分发随机数量
【发布时间】:2017-10-02 17:17:07
【问题描述】:

假设我有 8 个人5000 个苹果
我想把所有的苹果都分发给 8 个人,所以我没有剩下苹果了。
但每个人都应该得到不同的数量

将它们全部释放出来的最佳方式是什么?

我是从这个开始的:

let people = 8
let apples = 5000

function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min
}

while (people--) {
  // last person get the rest
  let x = people ? getRandomInt(0, apples) : apples

  // subtract how many apples i got left
  apples -= x 

  console.log(`Giving person ${people + 1} ${x} apples (got ${apples} left)`)
}

但我不喜欢的是最后一个人得到的苹果很少(有时少于 5 个),而第一个人得到的苹果比其他人多

【问题讨论】:

  • 您可以取 80% 的苹果,然后将它们平均分配,然后随机分配最后的 20%。根据口味调整百分比。
  • 您还可以根据人数 var minPercentage = (100 / 人) - 10// 或任何您想要的差异来设置苹果的最小百分比,然后检查苹果是否每人等于或大于最小百分比。您需要一个数组来存储它们,并在打印任何内容之前运行检查。
  • 你能给我举个例子吗?
  • 有很多不同的方法;最臭名昭著的一个是尝试选择 N 个随机数,均匀分布,总和为 M(这并不像听起来那么明显)。在没有任何其他信息的情况下,我建议您可能想要模拟一个过程,您可以选择一个随机的人给一个苹果,5000 次,这通常给每个人大致相同数量的苹果,但可以,非常概率低,把所有的苹果给一个人。
  • @sh1 提到的“选择 N 个均匀分布的随机数,总和为 M”问题的简单解决方案见 this answer

标签: javascript math random


【解决方案1】:

如果您每次都需要随机但“平衡”的结果,则需要优先考虑平衡或随机性。以下是满足您的“最宽间隙”要求的一种可能解决方案:

function randomDeltas(length, widestGap, remToGet) {
  // widestGap >= length * 2 - 1
  let deltas = [];
  let sum = 0;
  let start = 0;
  let origLength = length;
  while (length--) {
    start += 1 + Math.floor(Math.random() * widestGap);
    deltas.push(start);
    sum += start;
  }
  
  let rem = sum % origLength;
  let correction = remToGet - rem;
  if (correction !== 0) {
    sum -= deltas[0];
    deltas[0] += correction;
    if (deltas[0] >= deltas[1]) {
      deltas[0] -= origLength;
    }
    else if (deltas[0] < deltas[1] - widestGap) {
      deltas[0] += origLength;
    }
    sum += deltas[0];
  }
  return {
    deltas,
    sum
  };  
}

function randomDistinctDistribute(apples, people) {
  let rem = apples % people;
  let { deltas, sum } = randomDeltas(people, people * 2 - 1, rem);
  let div = (apples - sum) / people;
  let distribution = [];
  while (deltas.length) {
    distribution.push(div + deltas.shift());
  }
  return distribution;
}

console.log(randomDistinctDistribute(5000, 8));
console.log(randomDistinctDistribute(2500, 6));

这里的想法是随机化增量(以确保差距永远不会变大),然后将这些增量应用于除数。


这是获得具有不同值的平衡分布的原始(确定性)方法:

function distinctDividents(apples, people) {
  let distribution = [];
  let div = Math.floor(apples / people);
  let rem = apples % people;
  if (people % 2) {
    distribution.push(div);
    people--;
  }
  let half = people / 2;
  let i = 1;
  while (i <= half) {
    distribution.push(div - i);
    distribution.unshift(div + i);
    i++;
  }
  if (rem) {
    distribution[0] += rem; 
  }
  return distribution;
}

console.log(distinctDividents(5000, 8));

【讨论】:

  • 聪明,但一个问题是它是可预测的。每次我运行它时总是相同的结果。我希望它每次都是随机的。我还认为它是平分的(最大和最小之间的差异只有 15)
  • 用随机平衡分布方法的插图更新了代码。并不是说您可以根据需要更改参数(例如尝试 2500 和 6;甚至 2600 和 9!)。
【解决方案2】:

我想我明白了。只是有点tweeking。

let x = people ? getRandomInt(0, Math.floor(apples / people)) : apples

let people = 8
let apples = 5000

function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min
}

while (people--) {
  // last person get the rest
  let x = people ? getRandomInt(0, Math.floor(apples / people)) : apples

  // subtract how many apples i got left
  apples -= x 

  console.log(`Giving person ${people + 1} ${x} apples (got ${apples} left)`)
}

仍然没有人得到少于 100 个苹果或多于 1000 个的苹果,但这样就可以了。否则它会变得更加复杂。第二天我可能只有2500个苹果和6个人……

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-27
    相关资源
    最近更新 更多