#!/usr/bin/perl
#( Time-stamp: "2008-03-10 15:35:01 AKDT sburke@cpan.org"
#( desc{  output lines in random order }
#======================================================================
#
# shuffle - output lines in random order
#
# This is a utility that reads lines like cat(1) does (i.e., from
#  files if you name any, otherwise from STDIN), and then outputs them
#  *in a random order.*
#
# Examples:
#
#  ls | shuffle
#
#  shuffle ideas.txt | head -3
#
#  find . -type f -name '*.mp3' | shuffle > shuffle_play.m3u
#
#======================================================================

use strict;
use warnings;
my @lines = <>;
shuffle(@lines);
for(@lines) { print }
exit;

#
# This could probably be done more efficiently if we were shuffling a
# million lines, but for me the need for that optimization has not
# arisen.
#

sub shuffle {
  # made cleverly context-sensitive by sburke@cpan.org
  my $target;
  if(!defined wantarray) { # void or scalar context.  edit in-place
    return if @_ < 2;
    $target = \@_;
    #print "In-place\n";
  } else { # list context.  return a copy
    return @_ if @_ < 2;
    $target = [@_];
    #print "Copy\n";
  }

  my $j;
  for(my $i = @$target; --$i; ) {
    @$target[$i, $j] = @$target[$j, $i] # swap
     unless $i == ($j = int rand ($i+1));
    # Fisher-Yates algorithm.  See perlfaq4.
  }

  if(wantarray) {
    return @$target;
  } else {
    return;
  }
}
#======================================================================

__END__
