@koxac

Как вызывать случайную функцию с заданной вероятностью?

Есть 4 функции:

var _func1 =  () => console.log('func1');
var _func2 =  () => console.log('func2');
var _func3 =  () => console.log('func3');
var _func4 =  () => console.log('func4');

Как сделать, чтобы func1 вызывалась в 10%, func2 вызывалась в 20%, func3 вызывалась в 30%, func4 вызывалась в 40%?
  • Вопрос задан
  • 214 просмотров
Решения вопроса 2
0xD34F
@0xD34F Куратор тега JavaScript
function randomCall(items) {
  const max = items.reduce((acc, n) => acc + n.ratio, 0);

  return function(...args) {
    const val = Math.random() * max;
    for (let sum = 0, i = 0; i < items.length; i++) {
      sum += items[i].ratio;
      if (sum > val) {
        return items[i].func.apply(this, args);
      }
    }
  };
}


const func = randomCall([
  { func: func1, ratio: 1 },
  { func: func2, ratio: 2 },
  { func: func3, ratio: 3 },
  { func: func4, ratio: 4 },
]);

https://jsfiddle.net/pgnL6at1/
Ответ написан
Комментировать
profesor08
@profesor08 Куратор тега JavaScript
// функция, которая вернет функцию, которая будет на основе указанных вероятностей вызывать одну из указанных функций
const randomFuncBuilder = items => {
  const total = items.reduce((sum, item) => sum + item.rate, 0);
  
  return () => {
    const rand = Math.random() * total;
    let sum = 0;
    
    for(const {func, rate} of items) {
      sum += rate; 
      
      if (sum >= rand) {
        return func();
      }
    }
  };
};

// список функций и некоторого абстрактного значения частоты вызова
// в данном случае диапазон не 0-100, а 0-150.
const funcArray = [
  {
    func: () => 1,
    rate: 10
  },
  {
    func: () => 2,
    rate: 20
  },
  {
    func: () => 3,
    rate: 30
  },
  {
    func: () => 4,
    rate: 40
  },
  {
    func: () => 5,
    rate: 50
  }
];

// сама готовая функция, которую надо вызывать
const randomFunc = randomFuncBuilder(funcArray);

// результаты будут тут
let res = [];

for(let i = 0; i < 100000; i++) {
  res.push(randomFunc());
}

// подсчет результатов, соответствует числу вызовов функций
const count = res.reduce((acc, v) => {
  acc[v] += 1;
  return acc;
}, {
  "1": 0,
  "2": 0,
  "3": 0,
  "4": 0,
  "5": 0,
});

// проверка результатов, считать вероятности умеет же? значит вопросов не возникнет.
const total = funcArray.reduce((sum, item) => sum + item.rate, 0);

console.log(count);

console.log({
  "1": count[1] / 100000 * total,
  "2": count[2] / 100000 * total,
  "3": count[3] / 100000 * total,
  "4": count[4] / 100000 * total,
  "5": count[5] / 100000 * total,
});
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
hzzzzl
@hzzzzl
Math.random() вернет 0-1

если random > 0.6, то _func4(); return
если > 0.3, то _func3(); return
Ответ написан
Комментировать
IceRD
@IceRD
получить число от 1-100 (это и будет %) и через нужное условие использовать
let random = Math.floor(Math.random() * Math.floor(100))
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы