- **Perl Misc**
(*http://www.velocityreviews.com/forums/f67-perl-misc.html*)

- - **random numbers**
(*http://www.velocityreviews.com/forums/t892721-random-numbers.html*)

random numbersHi,
I want to generate 6 random numbers from 1 to 10. The 6 numbers must not the same. These numbers must match to the number of an array. I like to know how many iterations to get the match. I am having troubles with the do-until loop. Could someone point out the problem for me? #!/usr/bin/perl -w # generate 6 random numbers (1~10) that match exactly to the @ticket # count the number of loops use strict; srand(time||$$); my @ticket = sort (2, 3, 5, 7, 8, 10); my @all_number = (); my @new_number = (); my $count = 0; # generate 10 numbers for (my $i = 0; $i < 10; $i++) { my $number = $i + 1; push (@all_number, $number) } do { #reset @new_number to the empty array each time through the loop. @new_number = (); #get 6 random numbers for (my $i = 0; $i < 6; $i++) { my $position = randomposition (@all_number); # Pick a random number from @all_number my $number = splice (@all_number, $position, 1); push (@new_number, $number); } @new_number = sort (@new_number); print "@new_number\n"; $count++; } until (($new_number[0] eq "$ticket[0]") && ($new_number[1] eq "$ticket[1]") && ($new_number[2] eq "$ticket[2]") && ($new_number[3] eq "$ticket[3]") && ($new_number[4] eq "$ticket[4]") && ($new_number[5] eq "$ticket[5]")); print $count, "\n"; ################################################## ######## sub randomposition { my(@all_number) = @_; # This expression returns a random number return int(rand(scalar(@all_number))); } |

Re: random numbers"Mei" <h0p2468@yahoo.com> wrote in news:d81eva$h2i$1@news.isu.edu.tw:
[ what's up with the extra line-feeds? ] > I want to generate 6 random numbers from 1 to 10. > The 6 numbers must not the same. > These numbers must match to the number of an array. > I like to know how many iterations to get the match. I am not sure what you mean by this. > #!/usr/bin/perl > > use strict; use warnings; is better because it allows you to turn warnings for selected lexical scopes. > srand(time||$$); Why? Note that, unless your Perl is severely broken, this is equivalent to srand(time). From perldoc -f srand: In versions of Perl prior to 5.004 the default seed was just the current "time". This isn't a particularly good seed, so many old programs supply their own seed value (often "time ^ $$" or "time ^ ($$ + ($$ << 15))"), but that isn't necessary any more. > my @ticket = sort (2, 3, 5, 7, 8, 10); > my @all_number = (); > my @new_number = (); > my $count = 0; Declare variables in the smallest applicable scope. > # generate 10 numbers > > for (my $i = 0; $i < 10; $i++) { > > my $number = $i + 1; > > push (@all_number, $number) > > } So, instead of this for loop, use: my @all_number = (1 .. 10); > do { > #reset @new_number to the empty array each time through the loop. > @new_number = (); my @new_number(); > > #get 6 random numbers > for (my $i = 0; $i < 6; $i++) { > my $position = randomposition (@all_number); > # Pick a random number from @all_number > my $number = splice (@all_number, $position, 1); > push (@new_number, $number); > } This is realy convoluted (and therefore confuses me still further as to what you are trying to do). for (1 .. 6) { push @new_number, $all_number[ int(rand( scalar @all_number )) ]; } It seems to me like what you are really doing is to check how long it would take for you to generate the sequence (0, 1, 2, 3, 4, 5) by randomly selecting (with replacement) from the set {0, 1, 2, 3, 4, 5}. Here is one way of doing it: # !/usr/bin/perl use strict; use warnings; my @ticket = sort {$a <=> $b } (2, 3, 5, 7, 8, 10); my $ticket = "@ticket"; my $count = 0; while ( 1 ) { ++$count; my @new; for (1 .. 6) { push @new, $ticket[ int(rand( scalar @ticket )) ]; } @new = sort {$a <=> $b } @new; my $new = "@new"; print "$new\tvs\t$ticket\n"; last if $new eq $ticket; } print "Count = $count\n"; __END__ Please do read the posting guidelines for this group tolearn how you can help yourself and help others help you. Sinan -- A. Sinan Unur <1usa@llenroc.ude.invalid> (reverse each component and remove .invalid for email address) comp.lang.perl.misc guidelines on the WWW: http://mail.augustmail.com/~tadmc/cl...uidelines.html |

Re: random numbers* Mei schrieb:
> > I want to generate 6 random numbers from 1 to 10. > The 6 numbers must not the same. > These numbers must match to the number of an array. > I like to know how many iterations to get the match. > > I am having troubles with the do-until loop. Could someone point out the > problem for me? > > #!/usr/bin/perl -w > # generate 6 random numbers (1~10) that match exactly to the @ticket > # count the number of loops > use strict; > srand(time||$$); You don't have to call srand() explicitly. It is called implicitly at the first use of rand() since your Perl isn't very old. Have a look at `perldoc -f srand` for details. > > my @ticket = sort (2, 3, 5, 7, 8, 10); Your numbers are already sorted numerically. After calling sort() on them, your list looks like (10,2,3,5,7,8). This doesn't matter since you sort your numbers in the same order later -- but be aware of this. > > my @all_number = (); > my @new_number = (); > my $count = 0; > > # generate 10 numbers > for (my $i = 0; $i < 10; $i++) { > my $number = $i + 1; > push (@all_number, $number) > } To get a list with all numbers from 1 to 10, please use my @all_number = 1 .. 10; > > do { > #reset @new_number to the empty array each time through the loop. > @new_number = (); > > #get 6 random numbers > for (my $i = 0; $i < 6; $i++) { > my $position = randomposition (@all_number); > # Pick a random number from @all_number > my $number = splice (@all_number, $position, 1); > push (@new_number, $number); > } Consider to use map instead of this for loop. And IMHO is splice() too much pverhead for this -- you could access each array element directly since you know its position. Try to use one of (I don't know which is more readable to you): @new_number = map { $all_number[ rand @all_number ] } 0 .. 5; @new_number = @all_number[ map { rand @all_number } 0 .. 5 ]; > > @new_number = sort (@new_number); This is what I've meant above. This sort() doesn't sort your numbers numerically too. But it's just important to sort the numbers in the same order as above (and this is what you're doing). If -- and only if -- you left out the sort statement above, you should sort numerically here, I think your code gets more clarity then. @new_number = sort { $a <=> $b } @new_number; > > print "@new_number\n"; > $count++; > } until (($new_number[0] eq "$ticket[0]") && ($new_number[1] eq "$ticket[1]") > && ($new_number[2] eq "$ticket[2]") && ($new_number[3] eq "$ticket[3]") > && ($new_number[4] eq "$ticket[4]") && ($new_number[5] eq "$ticket[5]")); To compare numbers there is the == operator, eq is for comparing strings only. I haven't checked it out yet, but AFAIK the numerical ones should be a little bit faster. And well, it's not funny to read such repeated code fragments. Perhaps you could use grep() instead. } until ! grep { $ticket[$_] != $new[$_] } 0 .. 5; > > print $count, "\n"; > > ################################################## ######## > > sub randomposition { > my(@all_number) = @_; > return int(rand(scalar(@all_number))); > } This sub could be shortened to sub randomposition { int rand @_ } and since writing "int rand @_" is shorter than "randomposition" you could omit to declare a sub for such a triviality. All in one, I would write your script as something like: #!/usr/bin/perl -w use strict; my @ticket = sort 2, 3, 5, 7, 8, 10; my @all = 1 .. 10; my @new; my $count = 0; do { @new = sort @all[ map { rand @all } 0 .. 5 ]; $count++; } until ! grep { $ticket[$_] != $new[$_] } 0 .. 5; print $count; __END__ regards, fabian |

Re: random numbers"Mei" <h0p2468@yahoo.com> wrote:
> Hi, > > I want to generate 6 random numbers from 1 to 10. > > The 6 numbers must not the same. my %h; $h{int(rand(10)+1)} =1 while (6 > keys %h) ; # the keys of %h are now 6 distinct random numbers between 1 and 10. (I couldn't figure out how your code pertained to what you said you wanted above, so I ignored it) Xho -- -------------------- http://NewsReader.Com/ -------------------- Usenet Newsgroup Service $9.95/Month 30GB |

Re: random numbersFabian Pilkowski wrote:
> * Mei schrieb: > >>I want to generate 6 random numbers from 1 to 10. >>The 6 numbers must not the same. >>These numbers must match to the number of an array. >>I like to know how many iterations to get the match. > All in one, I would write your script as something like: > > > #!/usr/bin/perl -w > use strict; > > my @ticket = sort 2, 3, 5, 7, 8, 10; > my @all = 1 .. 10; > my @new; > my $count = 0; > > do { > @new = sort @all[ map { rand @all } 0 .. 5 ]; > $count++; > } until ! grep { $ticket[$_] != $new[$_] } 0 .. 5; > > print $count; > __END__ or if only the number of iterations is of interest: use strict; use warnings; my %ticket = map { $_ => 1 } qw/2 3 5 7 8 10/; my $count = 0; $count++ && delete $ticket{int(rand(10))+1} while keys %ticket; print $count; Thomas -- $/=$,,$_=<DATA>,s,(.*),$1,see;__END__ s,^(.*\043),,mg,@_=map{[split'']}split;{#>J~.>_an~>>e~......>r~ $_=$_[$%][$"];y,<~>^,-++-,?{$/=--$|?'"':#..u.t.^.o.P.r.>ha~.e.. '%',s,(.),\$$/$1=1,,$;=$_}:/\w/?{y,_, ,,#..>s^~ht<._..._..c.... print}:y,.,,||last,,,,,,$_=$;;eval,redo}#.....>.e. r^.>l^..>k^.- |

Re: random numbersHi,
--Thanks all. The reason that I did not use 1..10 is because the six numbers must be different. --Once I take off the do-until loop, you will see the result like: ¡§1 3 4 6 8 10 vs 2 3 5 7 8 10¡¨. So far, this works. -- But as you pointed out, I want to see how long would it take for me to generate the sequence (2, 3, 5, 7, 8, 10). So far, I am still having troubles. ###### modified from the previous script ##### #!/usr/bin/perl -w # generate 6 random numbers (1~10) that match exactly to the @ticket # count the number of loops use strict; my @ticket = sort {$a <=> $b} (2, 3, 5, 7, 8, 10); my $ticket = "@ticket"; my @all_number = (); my @new_number = (); my $count = 0; # generate 10 numbers for (my $i = 0; $i < 10; $i++) { my $number = $i + 1; push (@all_number, $number) } for (my $i = 0; $i < 6; $i++) { my $position = int(rand(scalar(@all_number))); # Pick a random number from @all_number my $number = splice (@all_number, $position, 1); push (@new_number, $number); } @new_number = sort {$a <=> $b} (@new_number); my $new_number = "@new_number"; print "$new_number\tvs\t$ticket\n"; $count++; |

Re: random numbers* Mei schrieb:
> > --Thanks all. The reason that I did not use 1..10 is because the six numbers > must be different. The "1..10" has almost nothing to do with your 6 numbers. "1..10" is generating ten numbers, not six. > > --Once I take off the do-until loop, you will see the result like: ¡§1 3 4 6 > 8 10 vs 2 3 5 7 8 10¡¨. So far, this works. > > -- But as you pointed out, I want to see how long would it take for me to > generate the sequence (2, 3, 5, 7, 8, 10). So far, I am still having > troubles. You don't mention which kind of troubles you have. > > ###### modified from the previous script ##### > > #!/usr/bin/perl -w > # generate 6 random numbers (1~10) that match exactly to the @ticket > # count the number of loops > use strict; > > my @ticket = sort {$a <=> $b} (2, 3, 5, 7, 8, 10); > my $ticket = "@ticket"; > my @all_number = (); > my @new_number = (); > my $count = 0; > > # generate 10 numbers > for (my $i = 0; $i < 10; $i++) { > my $number = $i + 1; > push (@all_number, $number) > } This for loop is generating the numbers from 1 to 10 and saves them in the array @all_number -- not more, not less. This has absolutely nothing to do with your six different numbers you want to get afterwards. And as Sinan has pointed out you could replace this with @all_number = 1 .. 10; This is absolutely equivalent, but shorter -- and better to read. > > for (my $i = 0; $i < 6; $i++) { > my $position = int(rand(scalar(@all_number))); > # Pick a random number from @all_number > my $number = splice (@all_number, $position, 1); > push (@new_number, $number); > } This for loop *calculates* your six random numbers. First, it gets a random position in the array. With splice() you ask for the specified element in your array to push it into the array @new_number. This could be simplified to for ( 1 .. 6 ) { my $pos = int rand @all_number; # no scalar() needed my $number = $all_number[ $pos ]; # no splice() needed push @new_number, $number; } You could write this all in one, without saving some values in $pos and $number. That is, what Sinan has written: for ( 1 .. 6 ) { push @new_number, $all_number[ rand @all_number ]; } Sure, you could use map() instead of a for loop. That is, what I've done in my posting: @new_numbers = map { $all_number[ rand @all_number ] } 1 .. 6; Remember that this are just improvements to the code you've posted. I think, your problem is to get six *different* numbers. Neither your code nor our improvements will do this. But Xho has told you how this could be done with a hash: my %hash; $hash{ int rand @all_number } = 1 while keys %hash < 6; @new_numbers = @all_number[ keys %hash ]; Another solution is to use List::Util's shuffle algorithm and cut off a subarray of six elements. This could be more readable, especially if you're not so familiar with hashes. use List::Util qw( shuffle ); @new_numbers = ( shuffle @all_number )[ 0 .. 5 ]; Please, try to run the following script: #!/usr/bin/perl -w use strict; use List::Util qw( shuffle ); my @ticket = sort 2, 3, 5, 7, 8, 10; my @all = 1 .. 10; my $count = 0; while ( ++$count ) { # get six different elements from @all my @new = sort +( shuffle @all )[ 0 .. 5 ]; # print out for debugging print "@ticket vs @new\n"; # stop if @ticket and @new are equal last if "@ticket" eq "@new"; } print $count; __END__ regards, fabian |

Re: random numbers> I want to generate 6 random numbers from 1 to 10.
> > The 6 numbers must not the same. > > These numbers must match to the number of an array. > > I like to know how many iterations to get the match. That should be OK, but it's VERY IMPORTANT not to generate too many random numbers, or you could end up with the same problem as calculating pi: you may inadvertently generate copyright infringements, child pr0n, death threats, etc. Thanks, Don |

All times are GMT. The time now is 04:04 PM. |

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.

SEO by vBSEO ©2010, Crawlability, Inc.