Javascript Challenge: Lotto Number Generator
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
// 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.
- Login to post comments
Comments
Anonymous - Wed, 09/23/2009 - 15:31
for(var n=[],i=0;++i<50;n.push(i));for(;--i>6;n.splice(i*Math.random()|0,1));return n
Cheers, Stephan
Anonymous - Wed, 09/23/2009 - 16:01
How about skipping push and assigning directly?
- n.push(i)
+ n[i-1]=i
1 char saved.
Anonymous - Wed, 09/23/2009 - 19:05
for(n=[],i=0;i<49;n[i++]=i);for(;i>6;n.splice(i--*Math.random()|0,1));return n
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
49>n[i++]=i
as it would have shaved off another characterAleksander
Anonymous - Wed, 09/23/2009 - 19:12
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.
Anonymous - Wed, 09/23/2009 - 19:14
for(n=[],i=0;i<49;n[i++]=i);for(;i>6;n.splice(i--*Math.random(),1));return n
76 characters
-no floor needed for splice argument
Aleksander
Matthias Reuter - Thu, 09/24/2009 - 08:01
removing var leads to global variables, which was prohibited by the rules.
So this is no valid solution.
Christian Harms - Wed, 09/23/2009 - 17:31
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.
Anonymous - Wed, 09/23/2009 - 17:42
return [1,2,3,4,5,6];
Oh, is it supposed to be different every time?
return [1,2,3,4,5,5+Math.random()*10|0];
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}?
Matthias Reuter - Thu, 09/24/2009 - 08:03
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?
Anonymous - Wed, 09/23/2009 - 18:01
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
Anonymous - Wed, 09/23/2009 - 18:41
@DavidG: what is the initial value of n supposed to be?
Matthias Reuter - Thu, 09/24/2009 - 10:24
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
Anonymous - Thu, 09/24/2009 - 03:10
I'll see your 76 bytes and raise you 75 bytes.
for(;n^6;)for(var a=[],i=0,n=0;++i<50;)Math.random()<.1?a[n++]=i:0;return a
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
Matthias Reuter - Thu, 09/24/2009 - 11:08
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.
Anonymous (not verified) - Fri, 08/27/2010 - 09:09
anyone cares to dissect this one? i'm still unsure why the values are unique
Anonymous - Wed, 09/23/2009 - 19:09
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.
Matt (not verified) - Wed, 09/23/2009 - 19:43
72 bytes
Christian Harms - Wed, 09/23/2009 - 20:04
This simple solution doesn't check for doubles!
Matt (not verified) - Wed, 09/23/2009 - 20:56
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.
Anonymous - Wed, 09/23/2009 - 21:41
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
Anonymous - Wed, 09/23/2009 - 21:45
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
Anonymous - Wed, 09/23/2009 - 23:55
for(var n=[],i=6,r;i;r=Math.random()*49|1,n[-r]?0:n[--i]=n[-r]=r);return n
74 bytes. Fails on the sorting, but c'mon – it's a lottery ;-).
— hzr
Anonymous - Thu, 09/24/2009 - 03:41
in firefox. 48bytes
[0,0,0,0,0,0].map(function() Math.random()*50|1)
Anonymous - Thu, 09/24/2009 - 03:50
interesting how the lambda expression makes it more readable.
Anonymous - Thu, 09/24/2009 - 04:21
42
[,,,,,,].map(function()Math.random()*50|1)
Anonymous - Thu, 09/24/2009 - 06:42
This is not ECMA-262. Play by the rules.
Christian Harms - Thu, 09/24/2009 - 06:42
Hmmmm, nice - but it's not sorted and map not part of the of ECMA-262 definition.
marcelduran (not verified) - Thu, 09/24/2009 - 21:57
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})
marcelduran (not verified) - Fri, 09/25/2009 - 22:08
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})
Anonymous - Thu, 09/24/2009 - 10:16
I got 72 bytes with an algorithm that memoizes the already chosen numbers.
var a=[],r=n=0;for(;++n<7;a[r]=r)while(a[r=Math.random()*49|1]);return a
The array is not consecutively indexed, but that shouldn't matter, because it is in order and still has only 6 elements.
Anonymous - Mon, 09/28/2009 - 04:45
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.
Anonymous - Mon, 09/28/2009 - 21:08
New algorithm: 65 bytes
for(var v=[],m=6,n=49;m;--n)Math.random()*n>m?0:v[--m]=n;return v
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.
JavaScript Challenge Revisited: Lotto Number Generator in Ch (not verified) - Tue, 04/13/2010 - 23:07
[...] 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 [...]
Forfeit game - coding contest since 50 years | united-coders (not verified) - Mon, 11/08/2010 - 17:46
[...] older articles (javascript lotto generator or articles with code puzzles tag), here on united-coders.com we linked articles and got comments [...]
Anonymous (not verified) - Wed, 07/06/2011 - 14:50
So in lay man terms.. How do I win the lottery???