?
Solved

Random numbers

Posted on 2005-03-15
39
Medium Priority
?
210 Views
Last Modified: 2008-03-17
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
Comment
Question by:hasozduru
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 11
  • 10
  • 8
  • +2
39 Comments
 
LVL 32

Expert Comment

by:ldbkutty
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

by:hasozduru
ID: 13550316
Hi

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

Thanks
0
 
LVL 17

Expert Comment

by:davebytes
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

Author Comment

by:hasozduru
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

by:matt_mcswain
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

by:hasozduru
ID: 13550594
Hello

Still it's not working.

Thanks
0
 
LVL 1

Expert Comment

by:a2liter
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

by:
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

by:hasozduru
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

by:matt_mcswain
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

by:hasozduru
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

by:matt_mcswain
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

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

Expert Comment

by:davebytes
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

by:davebytes
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

by:ldbkutty
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

by:davebytes
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

by:davebytes
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

by:ldbkutty
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

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

Expert Comment

by:ldbkutty
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

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

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

Author Comment

by:hasozduru
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

by:ldbkutty
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

by:hasozduru
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

by:davebytes
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

by:hasozduru
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

by:ldbkutty
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

by:ldbkutty
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

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

Thanks
0
 
LVL 32

Expert Comment

by:ldbkutty
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

by:davebytes
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

by:matt_mcswain
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

by:davebytes
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

by:matt_mcswain
ID: 13552585
No worries. ;^)
0
 
LVL 32

Expert Comment

by:ldbkutty
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

by:hasozduru
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

by:ldbkutty
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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

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

Author Note: Since this E-E article was originally written, years ago, formal testing has come into common use in the world of PHP.  PHPUnit (http://en.wikipedia.org/wiki/PHPUnit) and similar technologies have enjoyed wide adoption, making it possib…
Part of the Global Positioning System A geocode (https://developers.google.com/maps/documentation/geocoding/) is the major subset of a GPS coordinate (http://en.wikipedia.org/wiki/Global_Positioning_System), the other parts being the altitude and t…
The viewer will learn how to count occurrences of each item in an array.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.
Suggested Courses

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question