4

What I'm trying to do is generate 6 random numbers, five in a range of 1-45 and one in a range of 1-25 for a Greek lottery game (Tzoker). The first 5 numbers should be unique. By pressing a button, I want to add these numbers to a div using jQuery (I have some working code for this part).

I thought it would be pretty easy using a loop, but I've found myself unable to check if the number generated already exists. The loop would only contain the first 5 numbers, because the last number can be equal to one of the other 5.

mik01aj
  • 11,928
  • 15
  • 76
  • 119
imogik
  • 75
  • 1
  • 1
  • 7

5 Answers5

11

Let me propose you some simpler solution.

  1. Make a list of all numbers from 1 to 45.
  2. Sort the list using Math.random (plus minus something, read the docs of Array.sort to find out) as the comparison function. You will get the list in random order.
  3. Take 5 first items from the list.
  4. Then, when you already have the numbers, put them all into your div.

This way you don't mix your logic (getting the numbers) with your presentation (putting stuff into the DOM).

I leave the implementation as an exercise for the reader. :)

mik01aj
  • 11,928
  • 15
  • 76
  • 119
  • Nice solution, but how you provide the sixth number within range 1-25? – GreyRoofPigeon Aug 31 '15 at 10:22
  • Ah, I missed this one. Simple: `Math.ceil(Math.random()*25)`. – mik01aj Aug 31 '15 at 10:29
  • Good solution! I had this asked on an interview question. – Adrian Ciura Nov 10 '20 at 11:21
  • This algorithm is poor. There's no need to compare numbers randomly. Also, why sort *all* the numbers when you're only going to take 5? A Fisher-Yates (Knuth) Shuffle is the right approach. See [How to randomize (shuffle) a JavaScript array?](https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array) – Wyck Oct 26 '22 at 01:44
  • This only matters if you're dealing with (at least) thousands of numbers. Displaying the result of this on the screen requires orders of magnitude more computations than choosing the numbers in the first place. Premature optimization is the root of all evil. :) – mik01aj Nov 10 '22 at 13:14
4

Like this?

$(function() {
  $('button').on('click', function(e) {
    e.preventDefault();
    
    var numArray = [];
    
    while( numArray.length < 5 ) {
      var number = Math.floor((Math.random() * 45 ) + 1);
      if( $.inArray( number, numArray ) == -1 ) {
        numArray.push( number );
      }
    }
    numArray.push( Math.floor((Math.random() * 25 ) + 1) );
    $('div').html( numArray.join("<br />") );
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Generate</button>
<div></div>
GreyRoofPigeon
  • 17,833
  • 4
  • 36
  • 59
3

While this might be not exactly what you were asking for, if you would use lodash, this would be as simple as:

_.sample(_.range(1, 46), 5) // the 5 numbers from 1..45
_.random(1, 26)             // one more from 1..25

This is why functional programming is so cool. You can read for example Javascript Allonge to find out more.

Community
  • 1
  • 1
mik01aj
  • 11,928
  • 15
  • 76
  • 119
  • It will be good if you edit your previous answer and add it.. :) – Guruprasad J Rao Aug 31 '15 at 10:22
  • 1
    I did it on purpose, they are different answers. While the way it works is similar, one is an imperative and the other one is the functional approach. Additionally, this one proposes using a new external library, a thing that many people would reconsider. – mik01aj Aug 31 '15 at 10:27
1

http://jsfiddle.net/015d05uu/

var tzoker = $("#tzoker");
var results = $("#results");
tzoker.click(function() {
    results.empty();
    var properResults = [];
    var rand = 0;
    var contains = false;
    for (i = 1; i < 7; i++) {
        do 
        {
         (rand = Math.floor((Math.random() * (i != 6 ? 45 : 25)) + 1));
          contains = properResults.indexOf(rand) > -1;
        } while(contains)
        results.append("<br />", rand, "<br />");
        properResults.push(rand);
    }
});

Here is the main idea of a solution. You can define the max value as a parameter for the random. Then, check the existence of the item in a simple array with only the data you want.

Didier Aupest
  • 3,227
  • 2
  • 23
  • 35
1

You may use a general function which generates random numbers from 1 to maxValue, and adds them to an array only if they don't exist. Then, to display, cycle through the array items and append them to #randomNumbers.

HTML

<div id="randomNumbers"></div>

JS (with jQuery)

var randomNumbersArray = [];

$(function() {
    generateRandomNumbers();
    displayRandomNumbers();
});

function generateRandomNumbers() {
    for (i = 0; i < 5; i++) {
        generateRandomNumberFrom1To(45);
    }
    generateRandomNumberFrom1To(25);
}

function generateRandomNumberFrom1To(maxValue) {
    var randomNumber;
    do {
        randomNumber = Math.ceil(Math.random() * maxValue);
    } while ($.inArray(randomNumber, randomNumbersArray) > -1);
    randomNumbersArray.push(randomNumber);
}

function displayRandomNumbers() {
    for (i in randomNumbersArray) {
        $("#randomNumbers").append(randomNumbersArray[i] + "<br>");
    }
}
Alessio Cantarella
  • 5,077
  • 3
  • 27
  • 34