newbio has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks, I want to select 5 integers randomly from integers in the range 1 to 1 +5. Assume these integers are uniformly distributed. A number once pic +ked should not be picked again (i.e. selection without replacement). +I tried this using function "random_uniform_integer()", however this +function picks one number more than once which I do not want. Please let me know what is the appropriate way of doing this. Thanks a lot.

Replies are listed 'Best First'.
Re: random number generation.
by ikegami (Patriarch) on Sep 11, 2007 at 17:40 UTC

    A particularly simple approach is:

    use List::Util qw( shuffle ); my @picks = (shuffle 1..15)[0..4];

    For picking a few numbers from a very long list, "rerolling" duplicates is probably the most efficient:

    my @picks; my %seen; for (1..5) { # Five numbers my $pick = int(rand(15000)) + 1; # in 1..15000. redo if $seen{$pick}++; push @picks, $pick; }
    Update: Added second method.
      Thanks guys for your replies. Hi Ikegami, how would your "rerolling duplicates" method work if the l +ist just thrice (not long enough) the total numbers to be drawn. I gu +ess "shuffle" would be a better alternative then? Thanks.
        The shorter the list, the more rerolls would have to be done. shuffle will work quite well in most settings even with hundreds of items.
Re: random number generation.
by FunkyMonk (Bishop) on Sep 11, 2007 at 17:42 UTC
    • Put your 15 integers into an array
    • use shuffle from List::Util to shuffle the array
    • Take the first 5 elements of the array using a slice
    use List::Util 'shuffle'; my @numbers = 1 .. 15; # could be any list @numbers = shuffle @numbers; print "@numbers[0 .. 4]";

Re: random number generation.
by derby (Abbot) on Sep 11, 2007 at 17:46 UTC

    How about you just List::Util shuffle 1 to 15 and then splice the first 5:

    #!/usr/bin/perl use Data::Dumper; use List::Util 'shuffle'; my @list = ( 1 .. 15 ); print Dumper( \@list ); my @shuffled = shuffle(@list); print Dumper( \@shuffled ); my @five = splice( @shuffled, 0, 5 ); print Dumper( \@five );

    -derby
Re: random number generation.
by Roy Johnson (Monsignor) on Sep 11, 2007 at 19:33 UTC
    It occurs to me that this could be accomplished by a partial Fisher-Yates shuffle. Hard to imagine the savings being important enough to warrant a new function in the List::Util family, though. In Perl:
    my @a = ('a'..'z'); my $take = 5; for (0..$take-1) { my $swap_with = $_ + rand(@a-$_); @a[$_,$swap_with] = @a[$swap_with,$_]; } print join(',', @a[0..$take-1]), "\n";

    Caution: Contents may have been coded under pressure.
Re: random number generation.
by injunjoel (Priest) on Sep 11, 2007 at 18:01 UTC
    Greetings,
    It may be overkill but have you looked into PDL? Specifically PDL::GSL::RNG?

    -InjunJoel
    "I do not feel obliged to believe that the same God who endowed us with sense, reason and intellect has intended us to forego their use." -Galileo