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


In reply to Re: Unexpected value of $_ in a for loop. by Abigail-II
in thread Unexpected value of $_ in a for loop. by David Caughell

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.