1

I'm trying to fill 9 boxes with numbers, these numbers could be number 1 or number 2, being that number 2 can only be 4 times and number 1 should fill the other 5 times left... i know it's a problem of simple logic but someway I can't reach my goal... look at the piece of code that I have...

    <script type="text/javascript">
        for (cicloTipo = 1; cicloTipo < 10; cicloTipo++) {
            var tipo = Math.floor((Math.random() * 2) + 1);
                document.write(tipo);
        }
    </script>
  • 1
    What specifically are you having trouble with? The number generation (max four 2's and five 1's) or the writing to boxes? – fubar Sep 04 '17 at 23:57
  • 3
    Just define an array with 4 `2`s and 5 `1`s and perform a [random shuffle](https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array) on it. – Paul Rooney Sep 05 '17 at 00:03
  • …or just randomly splice values from the array. – RobG Sep 05 '17 at 00:07

2 Answers2

2

You can start with an array of the required values, then either shuffle the array or randomly select values from it. Some say Math.random isn't truely random, but it should be good enough.

The following uses splice to select values, so the loop iterates backwards since splicing shortens the source array each time.

function getRandoms(){
  for (var seed=[1,1,1,1,1,2,2,2,2], result=[], i=seed.length; i; i--) {
    result.push(seed.splice(Math.random() * i | 0, 1)[0]);
  }
  return result;
}

// Show randomness of result
(function() {
  var s = new Array(30).fill('+');
  var r;
  for (var i=9; i; ){
    document.getElementById(--i).textContent = s.join('');
  }
  
  var j = 300;    // Number of runs
  var delay = 20; // Default delay in ms

  function display(lag) {
    delay = lag || delay;
    getRandoms().forEach(function(v, i, rand) {
      var el = document.getElementById(i);

      if (v == 1) {
        el.textContent = el.textContent.slice(0,-1);

        // If run out of "+", add some to every line
        if (!el.textContent.length) {
          for (var k=0; k < 9; k++) {
            document.getElementById(k).textContent += '++++++++++';
          } 
        }

      } else {
        el.textContent += '+';
      }

      if (i == 0) {
        document.getElementById('msg').innerHTML = 'Remaining: ' + j +
          '<br>' + 'Values: ' + rand.join('');
      }

    });
    --j;
    if (j > 0) {
      setTimeout(display, delay);
    }
  }
  display(50);
}());

// Single call
// console.log(getRandoms().join());
<span id="0"></span><br>
<span id="1"></span><br>
<span id="2"></span><br>
<span id="3"></span><br>
<span id="4"></span><br>
<span id="5"></span><br>
<span id="6"></span><br>
<span id="7"></span><br>
<span id="8"></span><br>
<span id="msg"></span>

For fun I've added a display of the distribution. Each line represents a value in the result array from 0 to 8 and starts with a set number of "+" symbols. Each time a 1 is in the related position, a "+" is removed. Each time a 2 is in the position, a "+" is added. Since there are more 1s than 2s, the lines slowly get shorter. When a line gets to zero length, 10 more "+" are added to every line.

The important part is that the lines stay about equivalent lengths and that the same lines aren't longest or shortest after each run. If you think you see a pattern emerging, it must be sustained for at least 100 runs to show a bias.

RobG
  • 142,382
  • 31
  • 172
  • 209
0

Here's a solution which ensures that no more than 4 2's are in the chain. it means that the digits chain can contain from 0 2's to 4 2's and the rest is 1's

// 2s Counter
var c1 = c2 = 0;

for (var cicloTipo = 1; cicloTipo < 10; cicloTipo++) {
  var tipo = Math.floor((Math.random() * 2) + 1);
  // check if it's a 2 and 4 2s have been encountred
  if (tipo == 2) {
    if (c2 < 4) {
      // increment counter
      c2++;
    } else {
      tipo = 1;
      c1++;
    }
  }

  // check if it's a 1 and 5 1s have been encountred
  else if (tipo == 1) {
    if (c1 < 5) {
      // increment counter
      c1++;
    } else {
      tipo = 2;
      c2++;
    }
  }

  document.write(tipo);
}

it looks like your criteria forces 4 2's and 5 1's; i fixed this code to fit this criteria but @Paul Rooney 's suggestion is the best.

Faical ARAB
  • 387
  • 3
  • 14