Stanislav Matveyevich
Stanislav Matveyevich

Reputation: 45

How to generate numbers so that there's never a back-to-back repeat?

I found the following code in an old Stack posting. Could someone walk me through how this code ensures that the numbers within the given range (0 - 4) are never consecutively repeated.

var getNumber = (function() { 
    var previous = NaN;
  
  return function() {
    var min = 0;
    var max = 4 + (!isNaN(previous) ? -1 : 0);
    var value = Math.floor(Math.random() * max);
  
    if (value >= previous) {
       value += 1;
    }
       previous = value;
       return value;
   };
  })();
  
for (var i = 0; i < 100; i++) {console.log(getNumber());}

Upvotes: 1

Views: 52

Answers (2)

Gopinath
Gopinath

Reputation: 4937

The above code demonstrates the algorithm for avoiding back-to-back repetition using the IIFE pattern of Javascript.

The algorithm for avoiding back-to-back repetition is:

  • Step 1: Generate a random integer below 5.
  • Step 2: Keep on generating a new random number as long as it is not the same as that of the previous one.
  • Step 3: Print the new value

Interesting points to note:

The pattern var x = function() { // some code... }() is called the 'Immediately Invoked Function Expression (IIFE)' in Javascript.

This pattern is used for defining a variable as the result of some function that will be executed before initializing the variable.

The IIFE pattern helps achieve the desired result of generating a random number, comparing it with previous value and repeating the generation till the current value is not the same as that of the previous one.

Here is a simplified version of the code, without the unnecessary statements, that highlights the working of the IIFE pattern for the generation of the random numbers:

// File name: no-repeat-demo.js

var getNumber = (
    function() { 
        var previous = NaN
        return (
            function() {
                var value = Math.floor(Math.random() * 5)
                while (value == previous) {
                    value = Math.floor(Math.random() * 5)
                }
                previous = value
                return value
            }
        )
    }
)()

for (var i = 0; i < 10; i++) {
    console.log(getNumber())
}

Output:

>node no-repeat-demo.js
1
2
3
2
3
2
3
1
3
4

More information:

https://developer.mozilla.org/en-US/docs/Glossary/IIFE

Upvotes: 1

huan feng
huan feng

Reputation: 8623

var getNumber = (function() {
  var previous = NaN;

  return function() {
    var min = 0;
    // if previous is a number
    // max = (4 - 1); max = 3
    // if previous is not a number
    // max = 4;
    // Actually the max will always be 3 except the first value
    var max = 4 + (!isNaN(previous) ? -1 : 0);

    // value < 4 or value < 3, value will integer between 0-4, or 0-3 depend on the max number is 4 or 3
    var value = Math.floor(Math.random() * max);
    // value will always less than 3, except the first time less than 4
    if (value >= previous) {
    // value >= previous, include value = previous, so it will not repeat
      value += 1; // (0 - 2) + 1 will be (1 - 3)
    }
    previous = value;
    return value;
  };
})();

for (var i = 0; i < 100; i++) {
  ` console.log(getNumber()); }`

Upvotes: 2

Related Questions