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);
| [reply] [d/l] |
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?. | [reply] [d/l] |
#!/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? | [reply] [d/l] |
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. | [reply] [d/l] |
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. | [reply] [d/l] [select] |
Hmm, see splice for why that doesn't work. Here's the fix:
print (splice @a, rand @a, 1); | [reply] [d/l] |