patternjavascriptModerate
Prevent repetitive random numbers
Viewed 0 times
randompreventrepetitivenumbers
Problem
Is this a good way to prevent two sequential numbers from repeating, or is there a better, more efficient way of doing this? By efficient, I mean a less CPU and memory consuming process.
while (random === lastrandom) {
random = Math.floor(Math.random() * 3) + 1;
}
lastrandom = random;Solution
In practice, your code will be fine. In theory, it is not guaranteed to terminate, but the probability of that happening is literally negligible.
However, what you are doing is picking a random integer between 1 and 3 (both inclusive), with the number not repeating. With only three possibilities, we could draw up a state machine:
Unfortunately, that involves generating all the states first, which is impractical for larger ranges. There, we could use this more clever approach:
So if we are choosing the first number, everything works as usual. But for any subsequent number, we choose an integer from a set one smaller (to reflect that one number, the
Test to compare code:
However, what you are doing is picking a random integer between 1 and 3 (both inclusive), with the number not repeating. With only three possibilities, we could draw up a state machine:
states = {
1: [2, 3],
2: [1, 3],
3: [1, 2] };
if (lastRandom === undefined) {
random = Math.floor(Math.random() * 3) + 1;
}
else {
random = states[lastRandom][Math.floor(Math.random() * 2)];
}
lastRandom = random;Unfortunately, that involves generating all the states first, which is impractical for larger ranges. There, we could use this more clever approach:
var min = 1;
var max = 3;
if (lastRandom === undefined) {
random = Math.floor(Math.random() * (max - min + 1)) + min;
}
else {
random = Math.floor(Math.random() * (max - min )) + min;
if (random >= lastRandom) random += 1;
}
lastRandom = random;So if we are choosing the first number, everything works as usual. But for any subsequent number, we choose an integer from a set one smaller (to reflect that one number, the
lastRandom, can't be chosen). If the random number obtained like this is less than the lastRandom, it can be used as is. Otherwise it has to be incremented by one, so that the lastRandom has been skipped.Test to compare code:
Code Snippets
states = {
1: [2, 3],
2: [1, 3],
3: [1, 2] };
if (lastRandom === undefined) {
random = Math.floor(Math.random() * 3) + 1;
}
else {
random = states[lastRandom][Math.floor(Math.random() * 2)];
}
lastRandom = random;var min = 1;
var max = 3;
if (lastRandom === undefined) {
random = Math.floor(Math.random() * (max - min + 1)) + min;
}
else {
random = Math.floor(Math.random() * (max - min )) + min;
if (random >= lastRandom) random += 1;
}
lastRandom = random;Context
StackExchange Code Review Q#62018, answer score: 10
Revisions (0)
No revisions yet.