The German lottery currently holds a jackpot of about 30 million Euro. A friend of mine took the bait and participated yesterday. Since he is a software developer, he wrote a small program to get him six random numbers in the range of 1 and 49.

Well, it’s not difficult to write such a programm. The challenge is to do so in little bytes. So I challenge you:

Write a JavaScript function that generates random lotto numbers. This function has to return an array of six different numbers from 1 to 49 (including both) in ascending order. You may use features of ECMA-262 only, that means no Array.contains and stuff. You must not induce global variables.

The function has to look like this

var getRandomLottoNumbers = function () { // your implementation here };

Minify your function using JSMin (level aggressive) and count the bytes between the outer curly braces.

To participate in this challenge, simply post your solution as a comment.

**Spoiler warning** On the next page I describe the steps I took for my solution. Don’t read if you want to submit your own.

## First steps

First attempt. My idea is to generate an array containing the numbers from 1 to 49 and then remove elements until six remain. 117 bytes.

var getRandomLottoNumbers = function () { var n = []; for (var i = 1; i < 50; i++) { n.push(i); } while (n.length > 6) { n.splice(Math.floor(Math.random() * n.length), 1); } return n; };

First optimization: n.length is used twice, so store it in a variable. Use i, since that is defined already. 114 bytes.

var getRandomLottoNumbers = function () { var n = []; for (var i = 1; i < 50; i++) { n.push(i); } while ((i = n.length) > 6) { n.splice(Math.floor(Math.random() * i), 1); } return n; };

Next step: optimize variable declaration. Saves one var. 112 bytes.

var getRandomLottoNumbers = function () { var n = [], i; for (i = 1; i < 50; i++) { n.push(i); } while ((i = n.length) > 6) { n.splice(Math.floor(Math.random() * i), 1); } return n; };

Now I changed the algorithm. I switched from a while-loop to a for-loop, which saves another four bytes: 108 bytes.

var getRandomLottoNumbers = function () { var n = [], i; for (i = 1; i < 50; i++) { n.push(i); } for (i = 49; i > 6; i--) { n.splice(Math.floor(Math.random() * i), 1); } return n; };

## Below 100 bytes

Don’t you think, Math.floor(Math.random() * i) could be written shorter? Yes, it can. I accidently stumbled upon a way today. Replace it by Math.random() * i | 0. Saves 10 bytes, we’re down to 98.

var getRandomLottoNumbers = function () { var n = [], i; for (i = 1; i < 50; i++) { n.push(i); } for (i = 49; i > 6; i--) { n.splice(i * Math.random() | 0, 1); } return n; };

Save another byte moving the initializing of i one line up. This leaves an empty first statement in the for-loop, but that’s still valid JS. 97 bytes.

var getRandomLottoNumbers = function () { var n = [], i = 1; for (; i < 50; i++) { n.push(i); } for (i = 49; i > 6; i--) { n.splice(i * Math.random() | 0, 1); } return n; };

Now if the first loop starts at 0 and runs until 49, we don’t have to initialize the second for-loop. Saves two bytes, down to 95.

var getRandomLottoNumbers = function () { var n = [], i = 0; for (; i < 49; i++) { n.push(i + 1); } for (; i > 6; i--) { n.splice(i * Math.random() | 0, 1); } return n; };

Save another four bytes by moving the incrementation and decrementation of i. 91 bytes.

var getRandomLottoNumbers = function () { var n = [], i = 0; for (; ++i < 50;) { n.push(i); } for (; --i > 6;) { n.splice(i * Math.random() | 0, 1); } return n; };

~~Final~~ solution

Now, Douglas Crockford will hate me for this, but some semicolons are optional in Javascript. Remove them to get my final solution of 88 bytes:

var getRandomLottoNumbers = function () { var n = [], i = 0; for (; ++i < 50;) { n.push(i) } for (; --i > 6;) { n.splice(i * Math.random() | 0, 1) } return n };

## Addendum, 09/23/2009 16:02

Aww, curly braces are optional in my case. Needs two semicolons again, but saves four braces. 86 bytes

var getRandomLottoNumbers = function () { var n = [], i = 0; for (; ++i < 50;) n.push(i); for (; --i > 6;) n.splice(i * Math.random() | 0, 1); return n };

Minimized it’s this:

var getRandomLottoNumbers = function () { var n=[],i=0;for(;++i<50;)n.push(i);for(;--i>6;)n.splice(i*Math.random()|0,1);return n };

#### Christian Harms

#### Latest posts by Christian Harms (see all)

- google code jam 2013 – tic-tac-toe-Tomek solution - April 16, 2013
- Google code jam 2013 – the lawnmower - April 14, 2013
- code puzzles and permutations - April 11, 2013

Cheers, Stephan

How about skipping push and assigning directly?

– n.push(i)

+ n[i-1]=i

1 char saved.

A small pice in an other language: I have added the needed import to the effective codesize: ‘import random\n\ta=range(1,49)\n\twhile len(a)>6:a.remove(random.choice(a))\n\treturn a’ – then becomes 81 bytes.

Oh, is it supposed to be different every time?

See where I’m going with this? Please define your terms. Did you mean a uniform probability distribution over {(a,b,c,d,e,f) | 1 <= a < b < c < d < e < f <= 49}?

Here’s 76 bytes(!) using an algorithm that decides randomly whether to include each number from 1 to 49, then checks to see if there were 6 of them. The outer loop seems to run about 7 times on average, so not too bad.

The probability distribution is correct, and no global variables are created. I think this meets all the criteria.

Note that "push" returns the new length of the array, and "n^6" essentially means "n!=6".

-- DavidG

@DavidG: what is the initial value of n supposed to be?

78 characters (7 characters shorter):

-removed ‘var’

-replaced push with n[i++] (and removed ++ from i++<50)

-50 becomes 49

-moved the -- (could use --i>5, but it’s better for readability this way)

too bad you can’t do

as it would have shaved off another character

Aleksander

83 bytes: for(var n=[],i=0;++i<50;n[i-1]=i);for(;--i>6;n.splice(i*Math.random(),1));return n

(1) Splice will automatically convert the first argument to an integer, so floor is not needed. (2) n[i-1]=i can work instead of n.push(i). (3) last return needs no semi-colon.

for(n=[],i=0;i<49;n[i++]=i);for(;i>6;n.splice(i–*Math.random(),1));return n

76 chars

-call to floor is not needed.

76 characters

-no floor needed for splice argument

Aleksander

72 bytes

This simple solution doesn’t check for doubles!

Yeah, turns out I have trouble with this whole “reading comprehension” thing.

I also created a global var and the values aren’t in ascending order.

return (Math.random()+””).substr(2).match(/\d{2}/g).splice(0,6).sort().map(function(a){Math.ceil(a/2)})

Not the smallest but fun to write. Doesn’t check for dups and not sure the range is correct.

@mpr312

Should be even longer, forgot a return

return (Math.random()+””).substr(2).match(/\d{2}/g).splice(0,6).sort().map(function(a){return Math.ceil(a/2)})

@mpr312

74 bytes. Fails on the sorting, but c’mon – it’s a lottery ;-).

— hzr

I’ll see your 76 bytes and raise you 75 bytes.

Also, this will not cause an undefined error for 0.6% of the calls of the function, as your entry seems to do. Or am I wrong on this?

--Stephan

in firefox. 48bytes

[0,0,0,0,0,0].map(function() Math.random()*50|1)

interesting how the lambda expression makes it more readable.

42

[,,,,,,].map(function()Math.random()*50|1)

This is not ECMA-262. Play by the rules.

Hmmmm, nice – but it’s not sorted and map not part of the of ECMA-262 definition.

removing var leads to global variables, which was prohibited by the rules.

So this is no valid solution.

When in doubt use your common sense

To clarify: Yes, I mean a uniform probability distribution. Would you use a lotto number generator, if only one number was randomly generated?

I got 72 bytes with an algorithm that memoizes the already chosen numbers.

The array is not consecutively indexed, but that shouldn't matter, because it is in order and still has only 6 elements.

it’s undefined. In a function, Javascript first generates all variables, no matter where they’re declared. If no value is given, the value is undefined.

undefined^6 is 6, which converts to true in the outer for-loop

Wow.

My first thought was: n is global, but no, it’s not. My second thought was: what the f*** is happening here? It took me a while to understand what the algorithm does. My third thought was: That’s not uniformly distributed. But it is.

So this algorithm meets all the criteria.

They are not the smallest but they’re in a single line (jQuery-like) using features of ECMA-262 only.

This one has 204 bytes (211 including return) and has no repetitions:

new Array(7).join(‘,x’).replace(/x/g,function(){Array.a=Array.a||{};var x;while((x=Math.random()*50|1)in Array.a);Array.a[x]=1;return x}).slice(1).split(‘,’).sort(function(a,b){delete Array.a;return a-b})

Note: I augmented Array by adding an object to it but removed it later, so no global vars added.

This one has 127 bytes (134 including return) and might have repetitions:

new Array(7).join(‘,x’).replace(/x/g,function(){return Math.random()*50|1}).slice(1).split(‘,’).sort(function(a,b){return a-b})

even smaller:

no dupes: 192 or 199 w/ return

[0,0,0,0,0,0].join().replace(/0/g,function(){Array.a=Array.a||{};var x;while((x=Math.random()*50|1)in Array.a);Array.a[x]=1;return x}).split(‘,’).sort(function(a,b){delete Array.a;return a-b})

w/ dupes: 115 or 122 w/ return

[0,0,0,0,0,0].join().replace(/0/g,function(){return Math.random()*50|1}).split(‘,’).sort(function(a,b){return a-b})

That defines a variable n in the global scope. Also, it has more than 6 elements. Exactly 6 elements are not undefined, but there are more than 6 nonetheless.

New algorithm: 65 bytes

Looping until all numbers have been “found”, checking numbers 49 to 1 one by one, updating probabilities for each number found/not found.

The probability of the next unchecked number is a number chosen by the lottery is P(number) = m / n where n are the number of unchecked numbers and m are the number of selected numbers left.

[…] Reuter from United Coders proposed a JavaScript Challenge: A Lotto Number Generator which the rules follow: Write a JavaScript function that generates random lotto numbers. This […]

anyone cares to dissect this one? i’m still unsure why the values are unique

[…] older articles (javascript lotto generator or articles with code puzzles tag), here on unitedcoderscom.appspot.com we linked articles and got comments […]

So in lay man terms.. How do I win the lottery???

You also need to take into account the star or mega numbers which indeed CAN be duplicates of the main numbers.

I know that for my Powerball, you have 5 numbers and a powerball number. The powerball number can be the same as any of the 5 main numbers. So all these examples would not work.