I\'m generating random numbers from 1 to 20 by calling generateRandom(). How can I exclude some values, say 8 and 15?
function generateRandom(mi
I have answered a similar question for Java: Generate random numbers except certain values. I just copy and paste the answer as follows.
Actually, we do not need to use
contains(random)with a while loop.To simplify the question, let's see what happens if we only have one excluding value. We can split the result to
2parts. Then the number of possible values isrange-1. If the random number is less than the excluded value, just return it. Otherwise, we could add1.For multiple excluding values, We can split the result set into
size+1parts, wheresizemeans the number of excluding values. Then the number of possible values isrange-size. Then we sort excluding values in ascending order. If random number is less than the excluding value minusi, then we just return the random number addi, whereiis the index of the the excluding value.public int generateRandomNumberWithExcepts(int start, int end, List<Integer> excepts) { int size = excepts.size(); int range = end - start + 1 - size; int randNum = random.nextInt(range) + start; excepts.sort(null); // sort excluding values in ascending order int i=0; for(int except : excepts) { if(randNum < except-i){ return randNum + i; } i++; } return randNum + i; }
You could take an offset for random values greater or equal than zerow ith a sorted (ascending) array and return a sum with adjusted random value.
const
getRandomWithoutZero = (lower, upper, gaps) => () => {
const r = Math.floor(Math.random() * (upper - lower + 1 - gaps.length) + lower);
return gaps.reduce((s, g) => s + (s >= g), r);
},
random = getRandomWithoutZero(-9, 9, [-3, 0, 4]),
count = {};
for (let i = 0; i < 1.6e6; i++) {
const r = random();
count[r] = (count[r] || 0) + 1;
}
console.log(count);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can simply do like this
function generatedRandExclude(showed,max) {
let randNo = -1;
while(showed.length < max) {
randNo = Math.floor(Math.random() * Math.floor(max));
if(!showed.includes(randNo)) {
showed.push(randNo);
break;
}
}
return randNo;
}
let showed = [];
function run() {
console.log(generatedRandExclude(showed,6));
}
run();
run();
run();
run();
generatedRandExclude generate random number excluded using array showed.
Here is a really stupidly overcomplicated solution...
<script>
var excludedNumbers = [];
excludedNumbers.push(8);
excludedNumbers.push(15);
excludedNumbers.push(10);
var array = generateExclude(excludedNumbers, 1, 20);
function generateExclude(excludedNumbers, min, max){
var newNumbers = [];
for(var i = min; i <= max; i++) {
for(var j = 0; j < excludedNumbers.length; j++) {
var checker = $.inArray(i, excludedNumbers)
if(checker > -1){
}else{
if($.inArray(i, newNumbers)<= -1){
newNumbers.push(i);
}
}
};
};
return newNumbers;
}
function generateRandomNumbers(items){
var num = items[Math.floor(Math.random()*items.length)];;
return num;
}
console.log(generateRandomNumbers(array))
</script>
Here is a slightly modified answer that is similar to all the others but it allows your to pass a single or an array of failing numbers
function generateRandom(min, max, failOn) {
failOn = Array.isArray(failOn) ? failOn : [failOn]
var num = Math.floor(Math.random() * (max - min + 1)) + min;
return failOn.includes(num) ? generateRandom(min, max, failOn) : num;
}
I've read through all these answers and they differ a lot in philosophy, so I thought I might add my very own 2 bits, despite of this question having an answer, because I do think there is a better and more elegant way of approaching this problem.
We can make a function that takes min, max and blacklist as parameters and outputs a random result without using recursion (and with close to 0 if statements):
const blrand = function(min, max, blacklist) {
if(!blacklist)
blacklist = []
let rand = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
let retv = 0;
while(blacklist.indexOf(retv = rand(min,max)) > -1) { }
return retv;
}
usage:
let randomNumber = blrand(0, 20, [8, 15]);