Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Re: Unexpected value of $_ in a for loop.

by Coruscate (Sexton)
on Jan 16, 2004 at 05:21 UTC ( [id://321740]=note: print w/replies, xml ) Need Help??


in reply to Unexpected value of $_ in a for loop.

If you don't quite understand Roger's explanation, here is a rewrite of the code that is much more obvious:

sub shuffle_deck { my @orig_deck = @_; my @new_deck; for (0 .. $#orig_deck) { my $rand = int(rand $#orig_deck); push @new_deck, splice(@orig_deck, $rand, 1); } return @new_deck; }

I probably would have used a fisher-yates shuffle or the shuffle() from List::Util.

Replies are listed 'Best First'.
Re: Unexpected value of $_ in a for loop.
by Abigail-II (Bishop) on Jan 16, 2004 at 10:22 UTC
    I probably would have used a fisher-yates shuffle or the shuffle() from List::Util.
    Benchmarking shows that the XS version is much, much faster than anything done in Perl. But if you stick to a Perl solution, one that acts on an array instead of a list is the winner. Here are some benchmark results, followed by the benchmark itself. Note the dramatic decrease in performance of 'coruscate' when the lenght of the list to be sorted increases - this is due to the splicing, which results in a quadratic algorithm; all other solutions are linear.

    Benchmarking with a deck of 13. Rate roger coruscate fisher fisher2 list roger 18931/s -- -0% -4% -21% -85% coruscate 18959/s 0% -- -4% -20% -85% fisher 19747/s 4% 4% -- -17% -85% fisher2 23821/s 26% 26% 21% -- -82% list 129419/s 584% 583% 555% 443% -- Benchmarking with a deck of 52. Rate fisher roger coruscate fisher2 list fisher 4917/s -- -2% -3% -18% -85% roger 5021/s 2% -- -1% -17% -85% coruscate 5062/s 3% 1% -- -16% -85% fisher2 6031/s 23% 20% 19% -- -82% list 33210/s 575% 561% 556% 451% -- Benchmarking with a deck of 1024. Rate coruscate fisher roger fisher2 list coruscate 246/s -- -2% -6% -21% -86% fisher 251/s 2% -- -4% -19% -86% roger 261/s 6% 4% -- -16% -85% fisher2 310/s 26% 23% 19% -- -82% list 1767/s 619% 603% 577% 471% -- Benchmarking with a deck of 50000. Rate coruscate fisher roger fisher2 list coruscate 0.909/s -- -72% -73% -85% -94% fisher 3.19/s 251% -- -7% -47% -78% roger 3.43/s 277% 7% -- -43% -76% fisher2 6.03/s 563% 89% 76% -- -58% list 14.3/s 1474% 349% 318% 137% -- #!/usr/bin/perl use strict; use warnings; use List::Util; use Benchmark qw /timethese cmpthese/; our (@cards, @cards2, @tmp); foreach my $size (qw /13 52 1024 50000/) { @cards = 1 .. $size; @cards2 = 1 .. $size; print "Benchmarking with a deck of $size.\n"; cmpthese -10 => { roger => '@tmp = roger @cards', coruscate => '@tmp = coruscate @cards', fisher => '@tmp = fisher @cards', fisher2 => ' fisher2 \@cards2', list => '@tmp = List::Util::shuffle @cards', }; } sub roger { my @new = (); for (@_) { my $i = int rand($#new+1); push @new, $new[$i]; $new[$i] = $_; }; return(@new); } sub coruscate { my @orig_deck = @_; my @new_deck; for (0 .. $#orig_deck) { my $rand = int(rand $#orig_deck); push @new_deck, splice(@orig_deck, $rand, 1); } return @new_deck; } sub fisher { my $i = my @deck = @_; while (-- $i) { my $j = int rand ($i + 1); @deck [$i, $j] = @deck [$j, $i]; } @deck; } sub fisher2 { my $deck = shift; my $i = @$deck; while (-- $i) { my $j = int rand ($i + 1); @$deck [$i, $j] = @$deck [$j, $i]; } } __END__

    Abigail

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://321740]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2024-04-24 02:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found