Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

How can I print all the numbers from 1 to n in random order?

by vroom (His Eminence)
on Jan 17, 2000 at 09:16 UTC ( [id://2127]=perlquestion: print w/replies, xml ) Need Help??

vroom has asked for the wisdom of the Perl Monks concerning the following question: (numbers)

How can I print all the numbers from 1 to n in random order?

Originally posted as a Categorized Question.

  • Comment on How can I print all the numbers from 1 to n in random order?

Replies are listed 'Best First'.
Re: How can I print all the numbers from 1 to n in random order?
by ChrisS (Monk) on Nov 14, 2003 at 17:36 UTC
    I'd use the List::Util module.
    use List::Util qw(shuffle); my $n = 10; # use $ARGV[0] or whatever to set $n print join " ", shuffle(1 .. $n);
Re: How can I print all the numbers from 1 to n in random order?
by btrott (Parson) on Apr 03, 2000 at 06:44 UTC
    I don't see the original here, so I don't know if this has been suggested... but you could just stick the numbers in an array, then shuffle the array, then print them. Use the Fisher-Yates Shuffle, which avoids the splice quadratic algorithm bit.
    sub fisher_yates_shuffle { my $array = shift; my $i; for ($i = @$array; --$i; ) { my $j = int rand ($i+1); next if $i == $j; @$array[$i,$j] = @$array[$j,$i]; } } my $N = 50; my @array = (1..$N); fisher_yates_shuffle( \@array ); # permutes @array in place print "@array";
    From perlfaq4, How do I shuffle an array randomly?.
Re: How can I print all the numbers from 1 to n in random order?
by chromatic (Archbishop) on Apr 02, 2000 at 06:28 UTC
    Hmm, see splice for why that doesn't work. Here's the fix: print (splice @a, rand @a, 1);
Re: How can I print all the numbers from 1 to n in random order?
by lanval (Novice) on Apr 22, 2004 at 05:31 UTC
    $ cat numbers.pl
    #!/usr/bin/perl sub RandomiseArray { my (%b, $c); map { do { $c = rand } until(!exists $b{$c}); $b{$c} = $_ } @_ +; return values(%b); } my @a = RandomiseArray(1..10); print "@a\n";
    $ ./numbers.pl
    8 5 1 3 10 2 6 4 9 7
    $ ./numbers.pl
    4 2 3 9 5 8 6 1 7 10
    $ ./numbers.pl
    8 10 7 6 5 9 2 3 4 1


    Yeah?
      NO. (For an explanation, time it with RandomiseArray(1..1000) and RandomiseArray(1..100000) - it has exponential complexity in time)

      Here is a better way to do it:

      sub RandomiseArray { my @a=@_; my @b=(); while (scalar @a) { push(@b,splice(@a,int(rand @a))); } return(@b); }
      As the array becomes longer, the probablility of your routine finding an unused space becomes smaller and smaller. With a 1..10 shuffle the probablility of finding the right element for the last space is one in ten - which means you will need 10 tries (on the average). Not too bad. But with a 1..100000 array, you will need 100_000 tries to fill in the last element. and 99_999 to find the next to last, and... you get the idea. It will take a LOOONG time.

      Yeah, I could do it inplace (without the second copy of the array), but I'm going to save that for another time.

        The above comment would be true if it did $c = int(rand @_), but it doesn't. It just uses the floating point value returned from rand as a hash key. There are unlikely to be any collisions, even shuffling 1000000 numbers. You can test this with:
        perl -wle'undef $x{rand()} while keys(%x) == $x++; print $x'
        which adds keys until it gets a collision. Be prepared to wait a very long time.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (2)
As of 2025-07-10 10:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.