説明
ソートについて書いたので小ネタをもう1つ。
それぞれに1から10までの数値が書かれた10枚のカード。
これをシャッフルするにはどうしたらいいでしょうか。
1から10までの乱数を作ってまだ出てない数値だったら出力、を繰り返す。
なんてやってたら数が多くなると無駄ループが多くなってそうとう時間かかります。
(可変長配列を使って抜き出した値を取り除き、乱数の幅を徐々に小さくすれば高速にできると思いますが。)
簡単な方法はそれぞれに乱数をくっつけてその乱数でソートすることです。
コメント

- 2:mikeda
- 2008/06/17 16:55
いきなりこんな完璧な返答が返ってくるとはww
素晴らしいです。みなさんどんどん移植しましょう。
とりあえずハッシュやリファレンスを使わず簡単な文字列処理で、と書きました。
当然、汎用性を考えればソートすべきは値ではなく参照です。
split使ったり正規表現使ったりのポリシーの不一致はわかりやすさ重視半分、ネタ半分ですww
セパレータを含む文字列問題も、splitの添字工夫したり正規表現の量指定子使ったりはとりあえず省略して反応待ちでw
しかしいきなり自分レベルでは完璧と思えるコードが返ってきたのでまともなお返しコードがすぐに思いつかない・・・
というわけで以下、perlに限ったネタコード、よいこのみなさんは絶対マネしないように
###
my
$_
@cards
$_
print
###
my
my
@cards
print
###
my
@hash{@cards}
print
前へ 1 次へ![]()











@cards のデータが . 演算子で文字列連結でき、「,」を含まないデータならそれも良いですが、量が増えるとソート時の split に負荷がかかり、s// で連結文字列の除外というのもトリッキーな気がします。
/usr/bin/perl strict;
@cardsは1から10までの数値の配列 @cards = (1..10);
元の値と、並べ替え用のキー(乱数)を持ったハッシュに置き換えます = {key => rand(), value => $_} for(@cards);
並べ替え用のキーでソートします = sort {$a->{'key'} <=> $b->{'key'}} @cards;
元の値に戻します = $_->{'value'} for(@cards);
結果の表示 "$_\n" for (@cards);
/usr/bin/perl strict;
shuffle(@) {
my @list = @_;
my @ret = ();
push(@ret, splice(@list, int(rand(scalar(@list))), 1)) while(@list);
return @ret;
@cards = (
{ name => 'AAA', value => '1' },
{ name => 'BBB', value => '2' },
{ name => 'CCC', value => '3' },
{ name => 'DDD', value => '4' },
{ name => 'EEE', value => '5' },
{ name => 'FFF', value => '6' },
{ name => 'GGG', value => '7' },
{ name => 'HHH', value => '8' },
{ name => 'III', value => '9' },
{ name => 'JJJ', value => '0' },
my $item (shuffle @cards) {
printf "[%s] - [%d]\n", $item->{'name'}, $item->{'value'};
そのアルゴリズムのまま、もう少し工夫するとこんな感じでしょうか。
#!
use
###
my
###
$_
###
@cards
###
$_
##
print
参考までに、よくある汎用な配列のシャッフルはこんな感じじゃないでしょうか?
#!
use
sub
}
my
);
foreach
}