select random value NOT in array - javascript

How would I select a random value (0 to 30) that is not in this array?
var list = new Array(1,3,4,7,8,9);

Build the complementary array and pick random values from it.
var list2 = new Array();
for(var i=0; i<30; i++)
if(!list.contains(i))
list2.push(i);
Then:
var rand = list2[Math.floor(Math.random() * list2.length)];

function RandomValueNotInArray(array)
{
var e;
do
{
e = Math.random() * 31; // n + 1
} while (array.contains(e))
return e;
}

Assuming your list is reasonable small in size, create a list of numbers that are not in the array and then select a number from that array at random.

You need a while loop that tests if rand is in your restricted array and, if so, re-generate a new random number:
var rand;
do {
rand = Math.floor(Math.random() * 31); // re-randomize, 0 to 30 inclusive
} while ($.inArray(rand, restricted) > -1);
return rand;
http://jsfiddle.net/mblase75/dAN8R/
Don't want jQuery? You can replace $.inArray(rand, restricted) with restricted.indexOf(rand) if you use this polyfill for old browsers.

A little recursive function:
getNum() {
let randomNum = Math.floor(Math.random() * (30 - 1)) + 1
if (list.includes(randomNum)) {
return getNum()
}
return randomNum
}
Might be a little faster, since it first tries to return a random number, and then checks if it's in the array.

I would probably make an array or linked list from which I would subtract the unwanted items. That way I could keep removing items and just randomly select items from position 0 to the array's length - 1 without having to select the same thing twice.
Another way of doing it is to randomize a number between 0 and 30 and to keep doing it while it is found in the array. The only problems with that is knowing when the array is full (to get rid of infinite loops) and that it is a whole lot more processor intensive.

you can use filter .
var filteredArray = list.filter(function(e){
return e!= Math.floor(Math.random() * (31));
});

PHP in 2 lines:
$result = array_diff(range(1,30), array(1,3,4,7,8,9));
echo $result[array_rand($result)];

Related

How to write an efficient algorithm that generates a list of unique random numbers? [duplicate]

This question already has answers here:
How do I shuffle a Javascript Array ensuring each Index is in a new position in the new Array?
(5 answers)
Closed 1 year ago.
I'm pretty new to algorithms and am trying to solve a problem that involves generating a list of 5,000 numbers in random order each time it is run. Each number in the list must be unique and be between 1 and 5,000 (inclusive).
function createRandomList() {
let arr = [];
while(arr.length < 5000){
const num = Math.floor(Math.random() * 5000) + 1;
if(arr.indexOf(num) === -1) arr.push(num);
}
console.log(arr);
}
createRandomList()
Here's the solution that I came up with. I wanted to know the Time/Space complexity of this solution. Would it just be O(1) for both space and time because the values are bounded?
Any feedback would be greatly appreciated as well better ways to optimize the solution.
Keep a sequential list around and shuffle it. Fisher-Yates shuffle in-place is O(n).
Mike Bostock suggests an implementation here.
function shuffle(array) {
var m = array.length, t, i;
// While there remain elements to shuffle…
while (m) {
// Pick a remaining element…
i = Math.floor(Math.random() * m--);
// And swap it with the current element.
t = array[m];
array[m] = array[i];
array[i] = t;
}
return array;
}
const sequence = [1,2,3,4,5,6,7,8,9] // or gen this for any length you choose
let randomNonRepeatingSequence = shuffle(sequence)
console.log(randomNonRepeatingSequence)
function createRandomList() {
let i=0, numbers=[]
while(i++<5000) numbers.push(i);
numbers.sort(() => (Math.random() > .5) ? 1 : -1);
return numbers
}
console.log(createRandomList())
Your approach has one big problem: towards the end, it will generate many random numbers which are already contained in your sequence. Consider, you already generated 4999 random numbers. Now for the last one, you only have one possibility left, but you still generate numbers in a range from 1 to 5000. So in average you'll 2500 tries to hit the correct number. Better would be, creating a sequence of your allowed elements and then shuffle this sequence. An easy possibly could be the following.
let arr = [1,2,3,4 ..., 5000]
for (let i = arr.length-1; i > 0; i--){
let r = Math.floor(Math.random() * (i + 1));
let x = a[i]; a[i] = a[r]; a[r] = x;
}
How does is work: first you initialize the array with all your allowed values. Then you pick a random index from your array and switch that with the last element of the array. In the next iteration, the range for your random index is decreased by one, and it's switched with the but-last element. And so on and so forth. Once the loop is down to 1, you have a random sequence of your allowed values.

How can I set a variable to one of two random options?

I know how to get a random number with Javascript, but I do not know how to set a variable to text randomly. I want it to randomly choose between saying one thing and another thing. I realize that this is probably a fairly basic question, but I can't find any tutorials online on it.
You can create an array with the two options for text:
var array = ["hello", "world"];
Then you will choose random index of the array as follow:
var index = Math.floor(Math.random() * array.length);
Now you can just get random chosen text (between the texts in the array) by the random index:
var chosenText = array[index];
Notice that this would work no matter what the length of the array would be.
Try to run it:
var array = ["hello", "world"];
var index = Math.floor(Math.random() * array.length);
var chosenText = array[index];
console.log(chosenText);
Math.random() generates an number between 0 and 1. You can check if its greater than 0.5 then return thing1 otherwise thing2. Both results will have 50% chance.
const res = Math.random() > 0.5 ? "thing1" : "thing2"
console.log(res)
Another way is create an array and use Math.round() on random float value and use it as index of array.
const things = ["thing1","thing2"];
let res = things[Math.round(Math.random())]
console.log(res)
One way might be to create an array of the 2 strings, and then select the index by creating a random number between 1 and 2 ( or 0 and 1 );
const num = Math.floor(Math.random() * 2); // generates a random number
const arr = ["String One", "String Two"]; // create array of strings
const randomString = arr[num]; // select string with index of random number

Math.random to never generate same number as other Math.random [duplicate]

This question already has answers here:
How to get a number of random elements from an array?
(25 answers)
Closed 4 years ago.
I got 4 Math.random generators. Each picking 1 of the X objects from the array.
var randomItem1 = projects[Math.floor(Math.random()*projects.length)];
var randomItem2 = projects[Math.floor(Math.random()*projects.length)];
var randomItem3 = projects[Math.floor(Math.random()*projects.length)];
var randomItem4 = projects[Math.floor(Math.random()*projects.length)];
How can I write a function that prevents the Math.random to generate the same number as other Math.random generator.
My guess:
Creating a loop that loops through the var randomItem 1 till 4. If it finds 1 or more outputs to be the same, it will regenerate a new output for 1 or more the duplicated outputs.
Any other suggestions?
Edit: This is for a website.
Thanks for the interesting problem. I always used a library for this sort of thing so it was fun figuring it out.
var projects
var randomProjects
function getRandomProjects(projects, sampleSize) {
var projectsClone = projects.slice();
var randomItems = [];
while (sampleSize--) {
randomItems.push(
projectsClone.splice(Math.floor(Math.random()*projectsClone.length), 1)[0]
);
}
return randomItems;
}
projects = ['1st project', '2nd project', '3rd project', '4th project', '5th project', '6th project'];
randomProjects = getRandomProjects(projects, 4);
randomProjects.forEach(function(randomProject) {
console.log(randomProject);
});
The projectsClone.splice(...) deletes a random project from projectsClone and returns it as a single item in an array ([<project>]). Thus in the next iteration of the loop that value (<project>) can no longer be chosen.
However I would suggest using a library if you are using this in production code. For example losdash's _.sampleSize(projects, 4)
Update
Removed unneeded parts like Set, for loop, and added splice(). This function will mutate the original array due to splice(). Using splice() on an array of consecutive ordered numbers (even after shuffling) guarantees a set of unique numbers.
/**
* genRan(quantity, length)
*
* Need a given amount of unique random numbers.
*
* Given a number for how many random numbers are to be returned (#quantity) and a
* number that represents the range of consecutive numbers to extract the random
* numbers from (#length), this function will:
* - generate a full array of numbers with the length of #length
* - use shuffle() to shuffle the array to provide an array of randomly ordered numbers
* - splices the first #quantity numbers of the shuffled array
* - returns new array of unique random numbers
*
* #param {Number} quantity length of returned array.
* #param {Number} length length of an array of numbers.
*
* #return {Array} An array of unique random numbers.
*/
Demo
Details commented in Demo
var qty = 4
var len = 100;
function genRan(quantity, length) {
// Ensure that quantity is never greater than length
if (quantity > length) {
quantity = length;
}
// Create an array of consecutive numbers from 1 to N
var array = Array.from({
length: length
}, (value, key = 0) => key + 1);
// Run shuffle get the returned shuffled array
var shuffled = shuffle(array);
// return an array of N (quantity) random numbers
return shuffled.splice(0, quantity);
}
console.log(genRan(qty, len));
/* shuffle utility
|| Uses Fisher-Yates algorithm
*/
function shuffle(array) {
var i = 0;
var j = 0;
var temp = null;
for (i = array.length - 1; i > 0; i -= 1) {
j = Math.floor(Math.random() * (i + 1))
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}

Every Time on a button click, generate a UNIQUE random number in a range of 1 - 100 - JavaScript

I have a function. Every time I call the function, it should return a UNIQUE (for example, if I call this function 90 times, it should have given 90 different numbers) random number under 100.
I am currently doing
var randomNumber = Math.floor(Math.random() * 100);
But, it's not returning unique numbers. It's only returning random numbers.
Thanks in advance.
Edit:
It should return some alert after calling 100 times.
Make an array of a 100 numbers an cut the chosen number out each time you call it:
var unique = (function() { // wrap everything in an IIFE
var arr = []; // the array that contains the possible values
for(var i = 0; i < 100; i++) // fill it
arr.push(i);
return function() { // return the function that returns random unique numbers
if(!arr.length) // if there is no more numbers in the array
return alert("No more!"); // alert and return undefined
var rand = Math.floor(Math.random() * arr.length); // otherwise choose a random index from the array
return arr.splice(rand, 1) [0]; // cut out the number at that index and return it
};
})();
console.log(unique());
console.log(unique());
console.log(unique());
console.log(unique());

Pick random combination from 194481 possibilities

I have a file of 194481 permutations for
0,1,2,3,4,5,6,...,21
which looks like this;
[0,0,0,0],[0,0,0,1],[0,0,0,2],[0,0,0,3],[0,0,0,4],[0,0,0,5],[0,0,0,6],[0,0,0,7],[0,0,0,8],[0,0,0,9],[0,0,0,10],[0,0,0,11],[0,0,0,12],[0,0,0,13],[0,0,0,14],[0,0,0,15],[0,0,0,16],[0,0,0,17],[0,0,0,18],[0,0,0,19],[0,0,0,20],[0,0,1,0],[0,0,1,1],[0,0,1,2],[0,0,1,3],[0,0,1,4],[0,0,1,5],[0,0,1,6],[0,0,1,7],[0,0,1,8],[0,0,1,9],[0,0,1,10],[0,0,1,11],[0,0,1,12],[0,0,1,13],[0,0,1,14],[0,0,1,15],[0,0,1,16],[0,0,1,17],[0,0,1,18],[0,0,1,19],[0,0,1,20],[0,0,2,0],[0,0,2,1],[0,0,2,2],[0,0,2,3],[0,0,2,4],[0,0,2,5],[0,0,2,6],[0,0,2,7],[0,0,2,8],[0,0,2,9],[0,0,2,10],[0,0,2,11],[0,0,2,12],[0,0,2,13],[0,0,2,14],[0,0,2,15],[0,0,2,16],[0,0,2,17],[0,0,2,18],[0,0,2,19],[0,0,2,20],[0,0,3,0],[0,0,3,1],[0,0,3,2],[0,0,3,3],[0,0,3,4],[0,0,3,5],[0,0,3,6],[0,0,3,7],[0,0,3,8],[0,0,3,9],[0,0,3,10],[0,0,3,11],[0,0,3,12],[0,0,3,13],[0,0,3,14],[0,0,3,15],[0,0,3,16],[0,0,3,17],[0,0,3,18],[0,0,3,19],[0,0,3,20],[0,0,4,0],[0,0,4,1],[0,0,4,2],[0,0,4,3],[0,0,4,4],[0,0,4,5],[0,0,4,6],[0,0,4,7],[0,0,4,8],[0,0,4,9],[0,0,4,10],[0,0,4,11],[0,0,4,12],[0,0,4,13],[0,0,4,14],[0,0,4,15],[0,0,4,16],[0,0,4,17],[0,0,4,18],[0,0,4,19],[0,0,4,20],[0,0,5,0],[0,0,5,1],[0,0,5,2],[0,0,5,3],[0,0,5,4],[0,0,5,5],[0,0,5,6],[0,0,5,7],[0,0,5,8],[0,0,5,9],[0,0,5,10],[0,0,5,11],[0,0,5,12],[0,0,5,13],[0,0,5,14],[0,0,5,15],[0,0,5,16],[0,0,5,17],[0,0,5,18],[0,0,5,19],[0,0,5,20],[0,0,6,0],[0,0,6,1],[0,0,6,2],[0,0,6,3],[0,0,6,4],[0,0,6,5],[0,0,6,6],[0,0,6,7],[0,0,6,8],[0,0,6,9],[0,0,6,10],[0,0,6,11],[0,0,6,12],[0,0,6,13],[0,0,6,14],[0,0,6,15],[0,0,6,16],[0,0,6,17],[0,0,6,18],[0,0,6,19],[0,0,6,20],[0,0,7,0],[0,0,7,1],[0,0,7,2],[0,0,7,3],[0,0,7,4],[0,0,7,5],[0,0,7,6],[0,0,7,7],[0,0,7,8],[0,0,7,9],[0,0,7,10],[0,0,7,11],[0,0,7,12],[0,0,7,13],[0,0,7,14],[0,0,7,15],[0,0,7,16],[0,0,7,17],[0,0,7,18],[0,0,7,19],[0,0,7,20],[0,0,8,0],[0,0,8,1],[0,0,8,2],[0,0,8,3],[0,0,8,4],[0,0,8,5],[0,0,8,6],[0,0,8,7],[0,0,8,8],[0,0,8,9],[0,0,8,10],[0,0,8,11],[0,0,8,12],[0,0,8,13],[0,0,8,14],[0,0,8,15],[0,0,8,16],[0,0,8,17],[0,0,8,18],[0,0,8,19],[0,0,8,20],[0,0,9,0],[0,0,9,1],[0,0,9,2],[0,0,9,3],[0,0,9,4],[0,0,9,5],[0,0,9,6],[0,0,9,7],[0,0,9,8],[0,0,9,9],[0,0,9,10],[0,0,9,11],[0,0,9,12],[0,0,9,13],[0,0,9,14],[0,0,9,15],[0,0,9,16],[0,0,9,17],[0,0,9,18],[0,0,9,19],[0,0,9,20],[0,0,10,0],[0,0,10,1],[0,0,10,2],[0,0,10,3],[0,0,10,4],[0,0,10,5],[0,0,10,6],[0,0,10,7],[0,0,10,8],[0,0,10,9],[0,0,10,10],[0,0,10,11],[0,0,10,12],[0,0,10,13],[0,0,10,14],[0,0,10,15],[0,0,10,16],[0,0,10,17],[0,0,10,18],[0,0,10,19],[0,0,10,20],[0,0,11,0],[0,0,11,1],[0,0,11,2],[0,0,11,3],[0,0,11,4],[0,0,11,5],[0,0,11,6],[0,0,11,7],[0,0,11,8],[0,0,11,9],[0,0,11,10],[0,0,11,11],[0,0,11,12],[0,0,11,13],[0,0,11,14],[0,0,11,15],[0,0,11,16],[0,0,11,17],[0,0,11,18],[0,0,11,19],[0,0,11,20],[0,0,12,0],[0,0,12,1],[0,0,12,2],[0,0,12,3],[0,0,12,4],[0,0,12,5],[0,0,12,6],[0,0,12,7],[0,0,12,8],[0,0,12,9],[0,0,12,10],[0,0,12,11],[0,0,12,12],[0,0,12,13],[0,0,12,14],[0,0,12,15],[0,0,12,16],[0,0,12,17],[0,0,12,18],[0,0,12,19],[0,0,12,20],[0,0,13,0],[0,0,13,1],[0,0,13,2],[0,0,13,3],[0,0,13,4],[0,0,13,5],[0,0,13,6],[0,0,13,7],[0,0,13,8],[0,0,13,9],[0,0,13,10],[0,0,13,11],[0,0,13,12],[0,0,13,13],[0,0,13,14],[0,0,13,15],[0,0,13,16],[0,0,13,17],[0,0,13,18],[0,0,13,19],[0,0,13,20],[0,0,14,0],[0,0,14,1],[0,0,14,2],[0,0,14,3],[0,0,14,4],[0,0,14,5],[0,0,14,6],[0,0,14,7],[0,0,14,8],[0,0,14,9],[0,0,14,10],[0,0,14,11],[0,0,14,12],[0,0,14,13],[0,0,14,14],[0,0,14,15],[0,0,14,16],[0,0,14,17],[0,0,14,18],[0,0,14,19],[0,0,14,20],[0,0,15,0],[0,0,15,1],[0,0,15,2],[0,0,15,3],[0,0,15,4],[0,0,15,5],[0,0,15,6],[0,0,15,7],[0,0,15,8],[0,0,15,9],[0,0,15,10],[0,0,15,11],[0,0,15,12],[0,0,15,13],[0,0,15,14],[0,0,15,15],[0,0,15,16],[0,0,15,17],[0,0,15,18],[0,0,15,19],[0,0,15,20],[0,0,16,0],[0,0,16,1],[0,0,16,2],[0,0,16,3],[0,0,16,4],[0,0,16,5],[0,0,16,6],[0,0,16,7],[0,0,16,8],[0,0,16,9],[0,0,16,10],[0,0,16,11],[0,0,16,12],[0,0,16,13],[0,0,16,14],[0,0,16,15],[0,0,16,16],[0,0,16,17],[0,0,16,18],[0,0,16,19],[0,0,16,20],[0,0,17,0],[0,0,17,1],[0,0,17,2],[0,0,17,3],[0,0,17,4],[0,0,17,5],[0,0,17,6],[0,0,17,7],[0,0,17,8],[0,0,17,9],[0,0,17,10],[0,0,17,11],[0,0,17,12],[0,0,17,13],[0,0,17,14],[0,0,17,15],[0,0,17,16],[0,0,17,17]... etc.
It ends at [20,20,20,20].
I need to pick 50 combinations from the file and assign it to a variable so it would be like
var combinationsArr = [
[0,0,17,9],[0,0,17,10],[0,0,17,11],[0,0,17,12]
]; //BUT 50 of them
it's okay if it is just in order like [0,0,0,0],[0,0,0,1],[0,0,0,2],[0,0,0,3],[0,0,0,4],[0,0,0,5],[0,0,0,6],[0,0,0,7],[0,0,0,8],[0,0,0,9],[0,0,0,10],[0,0,0,11],[0,0,0,12] and doesn't have to be super random like [1,2,3,4],[9,12,13,15],[20,12,6,7]
as long as it is able to pick 50 of them.
I am doing this because 194481 combinations are a lot and makes my program carsh. so I just decided i'll put it in a text file and pick random points from the text file like from [0,0,0,1] to [0,0,0,50] OR
from [0,1,0,0] to [0,1,0,49] if that's possible.
because i have to generate a random combination. I have another array of combinations which are not supposed to be generated. Let's call it notAllowedArr.
var notAllowedArr = [
[0,0,17,9],[0,0,17,12]
];
I am thinking, i'll just generate 50 combinations and remove the ones listed in notAllowedArr then pick one from combinationsArr as the final result. I will still have to find code to remove those from combinationsArr but the result should be like.
var combinationsArr = [[0,0,17,10],[0,0,17,11]];
then i'll have a code to pick a random value from combinationsArr.
example. combinationsArr[0].
so the final result would be; [0,0,17,10]
Does anyone have a better solution?
If I understand correctly, you need to pick one random combination, which is not present in a list of forbidden combinations.
You can consider a combination of four numbers from 0 to 20 as a number from 0 to 194480 in base-21 notation. So instead of having to store all combinations in a file, we just pick a random number and convert it to base-21.
To choose a random number in a range where some values are forbidden, choose a number in the range from 0 to the maximum minus the number of forbidden values; then iterate over the forbidden values from small to large, and increment the random number every time you find a smaller or equal forbidden value.
This will make sure that every combination has the same probability of being chosen, and avoids the possibility of repeatedly choosing a forbidden combination.
function randomBase21(skip) {
var dec = [], result = [], num;
// CONVERT FORBIDDEN COMBINATIONS FROM BASE-21 TO DECIMAL AND SORT
for (var i = 0; i < skip.length; i++) {
dec[i] = skip[i][0] * 9261 + skip[i][1] * 441 + skip[i][2] * 21 + skip[i][3];
}
dec.sort(function(a, b){return a - b});
// GENERATE RANDOM NUMBER FROM 0 TO MAX - NUMBER OF FORBIDDEN COMBINATIONS
num = Math.floor(Math.random() * (194481 - skip.length));
// INCREMENT RANDOM NUMBER FOR EVERY SMALLER FORBIDDEN COMBINATION
for (var i = 0; i < skip.length && num >= dec[i]; i++) {
++num;
}
// CONVERT RANDOM NUMBER TO FOUR BASE-21 DIGITS
for (var i = 3; i >= 0; i--, num /= 21) {
result[i] = Math.floor(num % 21);
}
return result;
}
var notAllowed = [[0,0,17,9],[0,0,17,12],[20,19,17,12],[15,16,17,12]];
document.write(randomBase21(notAllowed));
Something like this should work (off the top of my head and not tested/debugged):
var samples = new Array();
for(var index = 0; index < 50; index++) {
samples.push(generatePermutation());
}
function generatePermutation() {
var result = [Math.floor(Math.random() * 20) + 1,
Math.floor(Math.random() * 20) + 1,
Math.floor(Math.random() * 20) + 1,
Math.floor(Math.random() * 20) + 1];
}
I just thought of a better way.
I think I will make a function that generates a random combination.
Then check if it exists in notAllowedArr. If it exists, it will generate another one. If not then that will return that combination :D
I think this will work faster ^^;

Categories