随机选择一个选项,其中更大的指数有更大的机会出现

时间:2019-04-03 12:43:16

标签: javascript

所以,我正在尝试创建一种ai...。而我陷入了这个问题。

让我们假设我们有四个选择。

a。 -23 b。 -10 C。 +4 d。 +80

我必须随机选择上述选项中的1个...但是结果不应完全是随机的。具有较高价值的期权必须具有更大的结果机会,而否定期权必须具有较低的结果机会。

我需要一个方程式来完成这个任务!

通过我在js中执行此操作的方式

var a=-23;
var b=-10;
var c=4;
var d=80;

var optiontochoose=(equation which choose an option randomly by giving more preference to option with greater values)

4 个答案:

答案 0 :(得分:2)

您可以将变量放入数组中,通过多次选择想要的变量来权衡选项,然后在数组长度范围内选择一个随机数。

var optionsArray = [a, b, b, c, c, c, d, d, d, d];
var chosenOption = optionsArray[Math.round(Math.random()*optionsArray.length)];

答案 1 :(得分:1)

我绝对同意@user11260787。据我所知,增加被选择价值的机会的唯一方法是增加其在源数据中的存在。

考虑到您希望使用一些权重来按比例增加机会,我会提出以下解决方案:

//source values along with corresponding weights,
//increasing proportionally pick-up probability
const src = [
  {value: -23, chance: 3},
  {value: -10, chance: 5},
  {value: 4, chance: 10},
  {value: 80, chance: 20}
];
//pick randomly, considering weights
const weightedRand = src => src.map(entry => (new Array(entry.chance)).fill(entry.value)).flat()[Math.floor(Math.random()*src.reduce((chanceTotal, item) => chanceTotal+=item.chance, 0))];
//do test run for 1M times to check outcome
const outcome1M = {'80':0,'4':0,'-10':0,'-23':0};
[...Array(1000000)].forEach(run => outcome1M[weightedRand(src)]++);
console.log(Object.fromEntries(Object.entries(outcome1M).map(entry => [entry[0],entry[1]/1000000])));
.as-console-wrapper {max-height:100% !important; top: 0}

答案 2 :(得分:1)

首先,您可以将这些值视为百分比值(即使未提及),并采用线性概率,然后将值的25100 / length数组)。

然后取和并归一化给定数据以生成array的随机索引。

function getRandomFn(percent) {
    var parts = percent.map((p, _, { length }) => (100 + p) / length),
        sum = parts.reduce((a, b) => a + b),
        normalized = parts.map((s => v => s += v / sum)(0));

    return () => normalized.findIndex((r => v => r < v)(Math.random()));
}

var array = ['a', 'b', 'c', 'd'],
    randomIndex = getRandomFn([-23, -10, 4, 80]),
    l = 1e6,
    count = Object.assign(...array.map(k => ({ [k]: 0 }))),
    index;

while (l--) {
    index = randomIndex();
    count[array[index]]++;
}

console.log(count);

答案 3 :(得分:0)

这是另一种选择。此解决方案的工作方式是首先移动整个数字列表,以使列表中的最小值等于0。然后向每个值添加百分比或静态值。将所有值求和,然后根据此总数选择一个随机值。

visual explanation

function pickSemiRandom(values) {
  if (!values.length) return; // guard against empty arrays

  var min = Math.min(...values),
      max = Math.max(...values),
      diff = max - min,
      diffZero = min - 0,
      percentage = diff * 0.20,
      shifted = values.map(nr => nr - diffZero + percentage),
      //                                       ^^^^^^^^^^^^
      // Offset each numbers to give the minimum value more than 0%
      // change of being picked. The higher the percentage the less
      // influence each value by itself has. An ofset of 0 will 
      // result in a 0% pick chance for the minimum value. You can
      // also change this into a static value instead of a percentage
      // of the difference between minimum and maximum value.
      total = shifted.reduce((sum, nr) => sum + nr, 0),
      randomNr = Math.random() * total;

  for (let index = 0; index < values.length; index++) {
    randomNr -= shifted[index];
    if (randomNr < 0) return values[index];
  }
  
  console.error("for-loop should aways return");
}

var results = new Array(100).fill([-23, -10, 4, 80])
              .map(values => pickSemiRandom(values));

// log results
console.log(results.join(", "));
console.log(results.reduce((counter, result) => {
  counter[result] = (counter[result] || 0) + 1;
  return counter;
}, {}));

您可以调整percentage的值以更改值分布。