Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

run for random numbers and keep state [duplicate]

I use the following code to get random value from specifed range

var provideRanges = function(){
    var aa = [];
    _.times(3, function(i) {
      console.log(i);
      let num = _.random(10, 20)
      console.log("num = :" + num)
      debugger;
      aa.push(num);
      console.log("value is :" + aa[i]);
    });
}

This is working and provide array of 3 values between the specified range when you call to this function, but the problem here become more difficult when I need that if I call it again ignore exclude the previous provided number from the provided numbers (like if it provide 10,11,12 the next time those numbers should not be provided...), is there is nicer way to do it? I try to use recoursive call but get lost:( ,any idea how to do it?

like image 282
John Jerrby Avatar asked Jan 22 '26 14:01

John Jerrby


2 Answers

One approach would be to create an array to store existing selections, push selected elements to an array, check if the array contains the element and if the array storing values .length is greater than or equal to maximum range minus minimum range.

It is not clear from description at Question what should occur once all of the elements in the range have been returned?

var range = [10, 20];
var not = [];

function randomRange(range, n) {
  if (not.length >= range[1] - range[0]) {
    return "all numbers in range used"
  }
  var curr = [];
  var res = [];
  for (let i = range[0]; i < range[1]; i++) {
    if (!not.some(function(num) {
      return i == num
    }) && not.length < range[1] - range[0]) {
      curr.push(i)
    }
  }
  for (let i = 0; i < n; i++) {
    var j = curr.splice(Math.floor(Math.random() * curr.length), 1)[0];
    res[i] = not[not.length] = j;
  }

  return res.filter(Boolean)
}

console.log(randomRange(range, 3));
console.log(randomRange(range, 3));
console.log(randomRange(range, 3));
console.log(randomRange(range, 3));
console.log(randomRange(range, 3));
like image 81
guest271314 Avatar answered Jan 25 '26 05:01

guest271314


My solution uses Set to retain the uniqueness of the values:

const getRangeRandomizer = ([min, max]) => { // create the range randomizer
  const state = new Set(); // the numbers that were produced from the range
  
  /** the returned method can be used to get more numbers from the range **/
  return (numOfRandoms) => {
    const discarded = new Set(); // this Set is used to count numbers that are not unique
    const range = max - min + 1;
    const result = [];
    let i = 0;
    let randNum;

    while (i < numOfRandoms && discarded.size < range) { // if we added numOfRandoms times or we discarded delta optionsm the loop end - this prevents endless loops
      randNum = Math.floor(Math.random() * (range) + min);

      if (state.has(randNum)) {
        discarded.add(randNum);
      } else {
        state.add(randNum);
        result.push(randNum);
        i++;
      }
    }

    return result;
  }
}

const provideRanges = getRangeRandomizer([10, 20]); // create a range randomizer

console.log(provideRanges(4));
console.log(provideRanges(3));
console.log(provideRanges(2));
console.log(provideRanges(4)); // only 2 results will be provided, because the rest were used

const provideOtherRanges = getRangeRandomizer([15, 20]);  // create a range randomizer
console.log(provideOtherRanges(100));
like image 32
Ori Drori Avatar answered Jan 25 '26 03:01

Ori Drori