Re: Random but non-repeating array loop
by japhy (Canon) on Jan 18, 2002 at 21:16 UTC
|
You could shuffle the array (using the Fisher-Yates method from the FAQ) and then loop over it.
_____________________________________________________
Jeff[japhy]Pinyan:
Perl,
regex,
and perl
hacker.
s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??; | [reply] |
|
|
use Algorithm::Numerical::Shuffle;
foreach my $element (shuffle @array) {
...
}
-----------------------------------------------------
Dr. Michael K. Neylon - mneylon-pm@masemware.com
||
"You've left the lens cap of your mind on again, Pinky" - The Brain
"I can see my house from here!"
It's not what you know, but knowing how to find it if you don't know that's important
| [reply] [d/l] |
Re: Random but non-repeating array loop
by I0 (Priest) on Jan 18, 2002 at 21:21 UTC
|
for (0 .. $#chars){
my $randomIndex = rand( @chars );
print "\n$chars[$randomIndex]";
$chars[$randomIndex] = $chars[-1];
pop @chars;
}
| [reply] [d/l] |
Re: Random but non-repeating array loop
by sifukurt (Hermit) on Jan 18, 2002 at 23:05 UTC
|
As japhy suggests, the Fisher-Yates shuffle is a good solution. If you want to save yourself the trouble of coding it, I've got it implemented in Math::NumberCruncher. Math::NumberCruncher also has numerous other similar functions that may be useful. Using Math::NumberCruncher, you could do the above like so:
use strict;
use Math::NumberCruncher;
my @chars = ( 'A' .. 'Z' );
my $ref = Math::NumberCruncher->new();
$ref->ShuffleArray( \@chars );
foreach my $char ( @chars ) {
print $char, "\n";
}
UPDATE:
Pursuant to Juerd's post, in the interest of TMTOWTDI, here's the code using Math::NumberCruncher through its original functional interface:
use strict;
use Math::NumberCruncher;
my @chars = ( 'A' .. 'Z' );
Math::NumberCruncher::ShuffleArray( \@chars );
foreach my $char ( @chars ) {
print $char, "\n";
}
___________________
Kurt
| [reply] [d/l] [select] |
|
|
| [reply] [d/l] |
|
|
Thanks. And you're absolutely right...there isn't a need for it to do OO. You don't have to use it that way; it still supports use as functions. In the first versions, it didn't have an OO interface, but I added it as an option for the sake of being complete, and also to open the door for the use of persistent data in future versions. It is also handy as shorthand if you're making repeated calls to numerous functions within Math::NumberCruncher.
___________________
Kurt
| [reply] |
Re: Random but non-repeating array loop
by YuckFoo (Abbot) on Jan 19, 2002 at 00:35 UTC
|
Seems perfectly reasonable to me. Here's a similar but shorter construction:
while ($ch = splice(@chars, rand(@chars), 1)) { print "$ch"; }
YuckFoo | [reply] [d/l] |
|
|
Nice, but what happens if @chars happens to contain the element '0'? To avoid having the data potentially short-circuit your loop, I might use something like:
while ($ch = splice(@chars, rand(@chars), 1),@chars) { print "$ch"; }
Which will exit the loop when @chars is empty, instead of when splice returns FALSE....
-Blake
| [reply] [d/l] |
|
|
Except that returns false BEFORE @chars is actually empty. One element short.
You should use:
while (($ch = splice(@chars, rand(@chars), 1))) { print "$ch"; }
Or wherever you want to place the parentheses. | [reply] [d/l] |
|
|
|
|
Doh! Thanks for the pointer. Seems this will also fix '0' data:
while (($ch) = splice(@chars, rand(@chars), 1)) { print "$ch"; }
YuckFoo | [reply] [d/l] |
Re: Random but non-repeating array loop
by Stegalex (Chaplain) on Jan 18, 2002 at 22:04 UTC
|
If this is for the purposes of debugging, I believe you could also just use Data::Dumper.
I like chicken. | [reply] |