Random numbers

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;";
}
?>
hasozduruAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ldbkuttyCommented:
<?
$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
hasozduruAuthor Commented:
Hi

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

Thanks
0
davebytesCommented:
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
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

hasozduruAuthor Commented:
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
matt_mcswainCommented:
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
hasozduruAuthor Commented:
Hello

Still it's not working.

Thanks
0
a2literCommented:
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
matt_mcswainCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
hasozduruAuthor Commented:
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
matt_mcswainCommented:
What! I decreased to 8 as you can see from code I posted, and wasn't getting dups.
Let me look again.
0
hasozduruAuthor Commented:
Hi

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

Thanks
0
matt_mcswainCommented:
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
matt_mcswainCommented:
Are you copy/pasting all the code. Make sure the array is being declared.
0
davebytesCommented:
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
davebytesCommented:
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
ldbkuttyCommented:
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
davebytesCommented:
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
davebytesCommented:
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
ldbkuttyCommented:
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
matt_mcswainCommented:
Nice use of shuffle ldbkutty; gives it a real lottery feel. :)
0
ldbkuttyCommented:
> btw, funny that  ldbkutty  and I both independently struck for array-based solutions!

:=)

array_rand is faster than shuffle. Good choice!
0
ldbkuttyCommented:
> Nice use of shuffle ldbkutty; gives it a real lottery feel. :)

Thanks, long-time-no-see matt :)
0
hasozduruAuthor Commented:
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
ldbkuttyCommented:
> 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
hasozduruAuthor Commented:
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
davebytesCommented:
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
hasozduruAuthor Commented:
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
ldbkuttyCommented:
>> 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
ldbkuttyCommented:
> ---. 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
hasozduruAuthor Commented:
So do you mean you cannot use shuffle and sort functions for same array ($total) ?

Thanks
0
ldbkuttyCommented:
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
davebytesCommented:
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
matt_mcswainCommented:
>>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
davebytesCommented:
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
matt_mcswainCommented:
No worries. ;^)
0
ldbkuttyCommented:
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
hasozduruAuthor Commented:
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
ldbkuttyCommented:
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.