Fill an array with distanced random integers

我是研究僧i 提交于 2021-01-28 01:20:56

问题


I need an array to be filled with random integers Those integers should be very distinct from each other i.e. must at least be 20 units of separation between each items

This is what i have tried so far :

var all = [];
var i = 0;

randomDiff();

function randomDiff() {
    var num1 = randomNumber(10, 290); //chose a first random num in the range...
    all[0] = num1; //...put it in first index of array
    do // until you have 12 items...
    {
        var temp = randomNumber(10, 290); //...you pick a temporary num              
        var j;
        for (j = 0; j < all.length; j++) // for each item already in the array
        {
            if ((temp < all[i] - 10) || (temp > all[i] + 10)) // if the temporary num is different enough                                                            from others members...
            {
                all.push(temp); //then you can store it
                i++; //increment until....
                console.log(all[i]);
            }
        }
    }
    while (i < 11) // ...it is filled with 12 items in array    
}
////////////Radom in int range function///////////////////////////////////////
function randomNumber(min, max) {
    return Math.floor(Math.random() * (max - min) + min);
}

but always unsuccessful, including infinite loops...


回答1:


Have a look on something like this:

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

const LIST_SIZE = 20;
const DISTANCE = 10;

const STOP_AFTER_ATTEMPT = 2000;
const randomList = [];

let attempt = 0;
while(randomList.length < LIST_SIZE && attempt < STOP_AFTER_ATTEMPT) {

  const num = randomNumber(10, 290);

  const numberExistsWithSmallerDistance = randomList.some(r => Math.abs(r - num) < DISTANCE)

  if (!numberExistsWithSmallerDistance) {
    randomList.push(num);
  }

  attempt++;
}
if (randomList.length === LIST_SIZE) {
    console.log(randomList);
} else {
    console.log("Failed to create array with distnct values after ", attempt, " tries");
}



回答2:


Here's a solution that will always work, as long as you allow enough room in the range/separation/count you choose. And it's way more efficient than a while loop. It doesn't just keep trying until it gets it right, it actually does the math to make sure it's right the first time.

This comes at the cost of tending to lean towards certain numbers more than others (like from + (i * separation)), so take note of that.

function getSeparatedRadomInts(from, through, separation, count) {
  if(through < from) return getSeparatedRadomInts(through, from, separation, count);
  if(count == 0) return [];
  if(separation == 0) return !!console.log("Please allow enough room in the range/separation/count you choose.");
  
  //pick values from pool of numbers evenly stepped apart by units of separation... adding 1 to from and through if from is 0 so we can divide properly
  var smallFrom = Math.ceil((from || 1) / separation);
  var smallThrough = Math.floor((through + (from == 0)) / separation);
  var picks = randoSequence(smallFrom, smallThrough).slice(-count).sort((a, b) => a - b);
  if(picks.length < count) return !!console.log("Please allow enough room in the range/separation/count you choose.");
  for (var i = 0; i < picks.length; i++) picks[i] *= separation;

  //go through each pick and randomize with any wiggle room between the numbers above/below it... adding 1 to from and through if from is 0
  for (var i = 0; i < picks.length; i++) {
    var lowerBound = picks[i - 1] + separation || from || 1;
    var upperBound = picks[i + 1] - separation || (through + (from == 0));
    picks[i] = rando(lowerBound, upperBound);
  }
  
  //subtract 1 from all picks in cases where from is 0 to compensate for adding 1 earlier
  for (var i = 0; i < picks.length; i++) if(from == 0) picks[i] = picks[i] - 1;
  
  return picks;
}

console.log(getSeparatedRadomInts(10, 290, 20, 12));
<script src="https://randojs.com/1.0.0.js"></script>

To be clear, from is the minimum range value, through is the maximum range value, separation is the minimum each number must be apart from each other (a separation of 20 could result in [10, 30, 50, 70], for example), and count is how many values you want to pick.

I used randojs in this code to simplify the randomness and make it easier to read, so if you want to use this code, just remember to paste this in the head of your HTML document:

<script src="https://randojs.com/1.0.0.js"></script>


来源:https://stackoverflow.com/questions/62083696/fill-an-array-with-distanced-random-integers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!