Perlで配列をシャッフルする
このところ、ソートばっかりやってて相当(*1)疲れたので、
たまには逆にシャッフルしてみようと思う。
結論から言うと、Array::Shuffle
を使えばいんだけど、
その前に、いくつか実装してみた。
乱数をソートしてシャッフル
use strict; use warnings; use v5.10; my @data = 1..9; @data = map { $_->[0]; } sort { $a->[1] <=> $b->[1] } map { [ $_, rand ]; } @data; say join( ', ', @data );
実行結果はこんな感じ。
$ perl aaa.pl
8, 4, 2, 3, 1, 9, 6, 5, 7
これは、シャッフルしたいデータと乱数をペアにして、
ペアにした乱数でソートした後、シャッフルしたデータのみに変換している。
無駄にソートしなきゃいけない分、ちょっと微妙。
ランダムに選択した添え字同士でシャッフル
use strict; use warnings; use v5.10; my @data = 1..9; my $n = scalar @data; for ( 1..100 ) { my ( $a, $b ) = ( int(rand $n), int(rand $n) ); @data[$a,$b] = @data[$b,$a]; } say join( ', ', @data );
実行結果はこんな感じ。
$ perl bbb.pl
8, 4, 5, 3, 6, 2, 1, 7, 9
これだと、任意の回数だけシャッフルできるんだけど、
rand
を一度に2回呼ぶあたりが微妙。
先頭から順にランダムに選択した添え字でシャッフル
use strict; use warnings; use v5.10; my @data = 1..9; my $n = scalar @data; foreach my $i ( 0..($n - 1) ) { my $j = int( rand $n ); @data[$i,$j] = @data[$j,$i]; } say join( ', ', @data );
実行結果はこんな感じ。
$ perl ccc.pl
2, 4, 1, 8, 7, 3, 5, 9, 6
これは、metacpan.orgで、そのものズバリ”array shuffle”で検索して出てきた、
Array::Shuffle
を見ながら実装した。
これを何回か繰り返せばいんじゃないですかね。
Array::Shuffle
を使ってシャッフル
use strict; use warnings; use v5.10; use Array::Shuffle qw(shuffle_array); my @data = 1..9; shuffle_array( @data ); say join( ', ', @data );
実行結果はこんな感じ。
$ perl ddd.pl
9, 2, 6, 8, 3, 4, 1, 5, 7
特に説明する必要ないですね。
XSで書かれてるようなので、環境によっては使えないかもですが、
その場合は、一つ前に紹介したのを使う感じで。
あと、気付いた方も居ると思いますが、
実行結果は見ても「シャッフルされてるねー」、以上のアレはないデス。
おしまい。
(*1) ソートだけに。
Leave a Comment