Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
Solved

# Random numbers

Posted on 2005-03-15
Medium Priority
214 Views
Hi

I have a simple array at following code that generates 6 numbers between 1 and 60. Sometimes it generates duplicate numbers. How can I create an array without duplicate numbers?

Thanks

<?
\$arr_lottery = array();

for(\$i=0; \$i<6; \$i++){
\$arr_lottery[\$i] = rand(1,60);
sort(\$arr_lottery);
}

foreach (\$arr_lottery as \$value) {
echo "\$value&nbsp;&nbsp;&nbsp;";
}
?>
0
Question by:hasozduru
• 11
• 10
• 8
• +2

LVL 32

Expert Comment

ID: 13550208
<?
\$arr_lottery = array();

for(\$i=0; \$i<6; \$i++){
\$arr_lottery[\$i] = rand(1,60);
while(in_array(\$arr_lottery[\$i], \$arr_lottery)) \$arr_lottery[\$i] = rand(1, 60);
}
sort(\$arr_lottery);
foreach (\$arr_lottery as \$value) {
echo "\$value&nbsp;&nbsp;&nbsp;";
}
?>
0

Author Comment

ID: 13550316
Hi

Above code is not working! Could you please check it?

Thanks
0

LVL 17

Expert Comment

ID: 13550488
If you want to be more statistical about it, I think this is a better approach.  At least, for something like a 'lottery ball bin' picking system...

\$arr_lottery = array();
for (\$i=0; \$i<6; \$i++)
{
\$newnum = rand(1, (60-\$i));
for (\$j=0; \$j<\$i; \$j++) // loop through all previous picks
if (\$newnum<=\$arr_lottery[\$j]) \$newnum++;
\$arr_lottery[\$i] = \$newnum;
}

Description:

1. The 'rand(1, (60-\$i))' is because you are really picking from 60 total 'balls', then 59, then 58...

2. The 'if(\$newnum)' thing is used to 'push' the new number up one for every number below it, as that fills the statistical gap from the 'ball' having already been picked in that slot.  Basically, if you got '6' the first time, and then you got '59' the second time, the '59' turns into '60', as the '6' is 'filling a space' in the choices.

Up to you if you want to sort them or not... ;)

-d
0

Author Comment

ID: 13550549
Hi

If you change "\$newnum = rand(1, (60-\$i));" to "\$newnum = rand(1, (15-\$i));" and try the program several times, you will see some duplicate numbers occuring. I don't want any duplicate numbers. So the code is not working properly.

Thanks
0

LVL 11

Expert Comment

ID: 13550589
How 'bout?

<?php
\$arr_lottery = array();
for(\$i=0; \$i<6; \$i++) {
\$rand = rand(1,60);
if (!array_search(\$rand, \$arr_lottery))
\$arr_lottery[] = \$rand;
else --\$i;
}
sort(\$arr_lottery);
foreach (\$arr_lottery as \$value) {
echo "\$value&nbsp;&nbsp;&nbsp;";
}
?>
0

Author Comment

ID: 13550594
Hello

Still it's not working.

Thanks
0

LVL 1

Expert Comment

ID: 13550616
Here ya go. This code works. Ran it severl times and never saw duplicates. Notice the ! in front of the in_array

<?
\$arr_lottery = array();

for(\$i=0; \$i<6; \$i++){
\$arr_lottery[\$i] = rand(1,60);
while(!in_array(\$arr_lottery[\$i], \$arr_lottery)) \$arr_lottery[\$i] = rand(1, 60);
}
sort(\$arr_lottery);
foreach (\$arr_lottery as \$value) {
echo "\$value\t\t";
}
echo "\n";
?>
0

LVL 11

Accepted Solution

matt_mcswain earned 400 total points
ID: 13550620
Ok, looks good now.
<?php

\$arr_lottery = array();
for(\$i=0; \$i<6; \$i++) {
\$rand = rand(1,8);
if (array_search(\$rand, \$arr_lottery) === false)
\$arr_lottery[] = \$rand;
else --\$i;
}
sort(\$arr_lottery);
foreach (\$arr_lottery as \$value) {
echo "\$value&nbsp;&nbsp;&nbsp;";
}
?>
0

Author Comment

ID: 13550660
Hi

Previous two comments are not good as well. If you decrease 60 to 10 or 15 and try, you will see that it still creating duplicate numbers sometimes.

Thanks
0

LVL 11

Expert Comment

ID: 13550677
What! I decreased to 8 as you can see from code I posted, and wasn't getting dups.
Let me look again.
0

Author Comment

ID: 13550684
Hi

Did you run the code? When I run it, it gives me "Fatal error: Maximum execution time of 30 seconds exceeded".

Thanks
0

LVL 11

Expert Comment

ID: 13550688
I ran this like 20 times and got 1,2,3,4,5,6 everytime.

<?php

\$arr_lottery = array();
for(\$i=0; \$i<6; \$i++) {
\$rand = rand(1,6);
if (array_search(\$rand, \$arr_lottery) === false)
\$arr_lottery[] = \$rand;
else --\$i;
}
sort(\$arr_lottery);
foreach (\$arr_lottery as \$value) {
echo "\$value&nbsp;&nbsp;&nbsp;";
}
?>
0

LVL 11

Expert Comment

ID: 13550697
Are you copy/pasting all the code. Make sure the array is being declared.
0

LVL 17

Expert Comment

ID: 13550708
Ahh, missed the extra test.  This works, and again it provides for a more normalized output:

<?php
\$arr_lottery = array();
for (\$i=0; \$i<6; \$i++)
{
\$newnum = rand(1, (10-\$i));
\$orignum = \$newnum;
for (\$j=0; \$j<\$i; \$j++) // loop through all previous picks
if (\$arr_lottery[\$j]<\$orignum)
\$newnum++;
for (\$j=0; \$j<\$i; \$j++) // loop through all previous picks
if (\$arr_lottery[\$j]==\$newnum)
\$newnum++;
\$arr_lottery[\$i] = \$newnum;
}
//sort(\$arr_lottery); // uncomment if you want sorted
foreach (\$arr_lottery as \$value) {
echo "\$value&nbsp;&nbsp;&nbsp;";
}
?>
0

LVL 17

Expert Comment

ID: 13550714
ugh.  just ran another dozen tests, and finally found a match (and the above code uses 10 instead of 60)... gimme a sec...
-d
0

LVL 32

Assisted Solution

ldbkutty earned 1200 total points
ID: 13550764
My proposal :

<?php
\$arr_lottery = array();
\$result = array();
for(\$i=1; \$i<=60; \$i++) {
\$result[] = \$i;
}
shuffle(\$result);
for(\$i=0; \$i<6; \$i++) {
\$arr_lottery[\$i] = \$result[\$i];
}
foreach (\$arr_lottery as \$value) {
echo "\$value&nbsp;&nbsp;&nbsp;";
}
?>
0

LVL 17

Assisted Solution

davebytes earned 400 total points
ID: 13550775
not as elegant, but the 'balls' can be 'named' anything (could be alphabet letters, words, whatever 'in' each ball).

<?php
\$arr_lottery = array();
\$balls = array();
for (\$i=1; \$i<=10; \$i++)
\$balls[\$i] = \$i;
\$arr_picks = array_rand(\$balls, 6);
foreach(\$arr_picks as \$key => \$val)
\$arr_lottery[] = \$val;
sort(\$arr_lottery);
foreach (\$arr_lottery as \$value) {
echo "\$value&nbsp;&nbsp;&nbsp;";
}
?>
0

LVL 17

Expert Comment

ID: 13550782
sorry -- test code again... the <=10 was supposed to be <=60.. that one line fixed is:

<?php
\$arr_lottery = array();
\$balls = array();
for (\$i=1; \$i<=60; \$i++)
\$balls[\$i] = \$i;
\$arr_picks = array_rand(\$balls, 6);
foreach(\$arr_picks as \$key => \$val)
\$arr_lottery[] = \$val;
sort(\$arr_lottery);
foreach (\$arr_lottery as \$value) {
echo "\$value&nbsp;&nbsp;&nbsp;";
}
?>

(btw, funny that  ldbkutty  and I both independently struck for array-based solutions! ;) )

-d
0

LVL 32

Expert Comment

ID: 13550785
Still better :

<?php

\$arr_lottery = array();
\$total = array();

for( \$i = 1; \$i <= 60; \$i++)
{
\$total[] = \$i;
shuffle( \$total );
}

for( \$i = 0; \$i < 6; \$i++ )
{
\$arr_lottery[\$i] = \$total[\$i];
}

foreach ( \$arr_lottery as \$value )
{
echo "\$value &nbsp;&nbsp;&nbsp;";
}

?>
0

LVL 11

Expert Comment

ID: 13550811
Nice use of shuffle ldbkutty; gives it a real lottery feel. :)
0

LVL 32

Expert Comment

ID: 13550813
> btw, funny that  ldbkutty  and I both independently struck for array-based solutions!

:=)

array_rand is faster than shuffle. Good choice!
0

LVL 32

Expert Comment

ID: 13550816
> Nice use of shuffle ldbkutty; gives it a real lottery feel. :)

Thanks, long-time-no-see matt :)
0

Author Comment

ID: 13550866
Hi ldbkutty and matt_mcswain

Thanks for your codes, both are working. I thing shuffle does not create duplicate values, isn't it? Also how did you understand that array_rand is faster than shuffle?

Thanks
0

LVL 32

Expert Comment

ID: 13550898
> shuffle does not create duplicate values
There is no duplicate values now because the generated \$balls (or \$total) array holds values from 1 till 60.

array_rand(\$balls, 6); selects 6 random values from the \$balls array.

shuffle replaces(shuffles?) all the elements in the array which is not necessary if you just want 6 numbers. So, array_rand is faster.

btw, you can minimize the code to this :

<?php
\$arr_lottery = array();
\$balls = array();
for (\$i=1; \$i<=60; \$i++)
\$balls[\$i] = \$i;
\$arr_lottery = array_rand(\$balls, 6);
sort(\$arr_lottery);
foreach (\$arr_lottery as \$value) {
echo "\$value&nbsp;&nbsp;&nbsp;";
}
?>
0

Author Comment

ID: 13550923
Ok I see

ldbkutty I couldn't understand at your code why did you use ...

for( \$i = 0; \$i < 6; \$i++ )
{
\$arr_lottery[\$i] = \$total[\$i];
}

... and without using above, you didn't do sort(\$total);

Thanks
0

LVL 17

Expert Comment

ID: 13550989
thanks ldbkutty -- it was actually what I was going to use originally, just wanted to write the 'real' algorithm.  I had it all in my head, but realized I needed to insertion-sort along the way or my tests all eventually failed.

hasozduru (I'm the other one writing up code examples here, not matt btw...) -- array_rand is faster as shuffle randomizes the entire array, while array_rand does picking from the array.  meaning the larger the array, the worse the overhead.

ldbkutty's last 'minimize' on my example is a great approach to tighten things up, so long as the \$balls array is always created with the array key/index equal to the value -- or more importantly, that the array keys become the important thing, and the actual values in the array aren't being used (in his minimized variation on my array_rand code...).  cute.

glad that both of us came up with working approaches finally. ;)

-d
0

Author Comment

ID: 13551017
Ok I see

ldbkutty, I couldn't understand at your code why did you use ...

for( \$i = 0; \$i < 6; \$i++ )
{
\$arr_lottery[\$i] = \$total[\$i];
}

... and without using above, you didn't do sort(\$total);

Thanks
0

LVL 32

Expert Comment

ID: 13551024
>> ldbkutty I couldn't understand at your code why did you use ...

As explained, shuffle() does not select the random number of values. So, you need the for loop to iterate the first 6 elements.
0

LVL 32

Expert Comment

ID: 13551034
> ---. and without using above, you didn't do sort(\$total);

With my code, you should not do sort(\$total) but sort(\$arr_lottery). Like this :

....
....
for( \$i = 0; \$i < 6; \$i++ )
{
\$arr_lottery[\$i] = \$total[\$i];
}
sort(\$arr_lottery);
....
....
0

Author Comment

ID: 13551047
So do you mean you cannot use shuffle and sort functions for same array (\$total) ?

Thanks
0

LVL 32

Expert Comment

ID: 13551067
Hope this explains well..

<?php

\$arr_lottery = array();
\$total = array();

// Generate \$total array with values from 1 to 60.

for( \$i = 1; \$i <= 60; \$i++)
{
\$total[] = \$i;
}
/* Now \$total = 1, 2, 3, 4, 5, 6, ...... 60. The values are UNIQUE. */

// Shuffle (or re-arrange) the \$total array.

shuffle( \$total );
/* Now \$total contains 60 numbers from 1 to 60 but NOT in the order. */

// Let us take only the first 6 elements of the \$total array. Since it is re-arranged using shuffle, numbers will be RANDOM.

for( \$i = 0; \$i < 6; \$i++ )
{
\$arr_lottery[\$i] = \$total[\$i];
}

// Sort the result array.

sort( \$arr_lottery );

// Display

foreach ( \$arr_lottery as \$value )
{
echo "\$value &nbsp;&nbsp;&nbsp;";
}

?>
0

LVL 17

Expert Comment

ID: 13552142
note that the shuffle/copy and array_rand pieces are interchangeable -- ldbkutty and I basically use the same setup (that is, an array with the 60 'ball' values), just different approaches to getting X unique & random values out of that array.  feel free to play around with them (I don't know how intensive an application you are using this for, thus whether performance/overhead is truly an issue).

-d
0

LVL 11

Expert Comment

ID: 13552270
>>I'm the other one writing up code examples here, not matt btw...
What do you call the solution I posted then?
More than two people are allowed to post answers, correct?
Let me go check the Member Guidelines.
0

LVL 17

Expert Comment

ID: 13552577
Hey Matt - my apologies, long freakin week already... I had scrolled halfway up the page, saw the long code posts back to back of myself and ldbkutty, and a one-liner from you inbetween, had tunnel vision.  In my brain, I literally was scanning and just seeing our two handles.  Meant no offense by the post... -d
0

LVL 11

Expert Comment

ID: 13552585
No worries. ;^)
0

LVL 32

Expert Comment

ID: 13557309
Hmmm... you should have split the points hasozduru. Please post a request in Community Support ( http://experts-exchange.com/Community_Support/ )  to reopen this question.
0

Author Comment

ID: 13557564
I am sorry ldbkutty, I am new to Experts Exchange. I go to http://experts-exchange.com/Community_Support/ and I asked them to open the question. How can I split the points?

Thanks
0

LVL 32

Expert Comment

ID: 13557633
No problem and thanks for responding. :)

After this question has been re-opened, you will find a "Split Poits" hyperlink below this comment (well, after the last comment actually). Click it and split the points among the appropriate comments.

See here : http:help.jsp#hi19
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

3 proven steps to speed up Magento powered sites. The article focus is on optimizing time to first byte (TTFB), full page caching and configuring server for optimal performance.
There are times when I have encountered the need to decompress a response from a PHP request. This is how it's done, but you must have control of the request and you can set the Accept-Encoding header.
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will wâ€¦
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creatâ€¦
###### Suggested Courses
Course of the Month15 days, 7 hours left to enroll