カードをシャッフルする
mikeda
mikeda
ATOMRSS
  • ソースコードID: 534
  • 登録日時: 2008/06/16 14:09
  • 最終更新日時: 2008/06/17 16:55
  • アクセス数: 1013
  • タグ:  perl シャッフル
  • codeなにがしブックマークに追加する 0 users
  • このページを del.icio.us に追加
  • このページをはてなブックマークに追加
  • GoodJob
  • 6

GJGJGJGJGJGJ

説明

ソートについて書いたので小ネタをもう1つ。

それぞれに1から10までの数値が書かれた10枚のカード。
これをシャッフルするにはどうしたらいいでしょうか。

1から10までの乱数を作ってまだ出てない数値だったら出力、を繰り返す。
なんてやってたら数が多くなると無駄ループが多くなってそうとう時間かかります。
(可変長配列を使って抜き出した値を取り除き、乱数の幅を徐々に小さくすれば高速にできると思いますが。)


簡単な方法はそれぞれに乱数をくっつけてその乱数でソートすることです。

ソースコード

コメント

  • sion
  • 1:sion
  • 2008/06/16 16:13

@cards のデータが 演算子で文字列連結でき、「,」を含まないデータならそれも良いですが、量が増えるとソート時の split に負荷がかかり、s// で連結文字列の除外というのもトリッキーな気がします。

そのアルゴリズムのまま、もう少し工夫するとこんな感じでしょうか。

#! /usr/bin/perl
use strict;

### @cardsは1から10までの数値の配列
my @cards (1..10);

### 元の値と、並べ替え用のキー(乱数)を持ったハッシュに置き換えます
$_ {key => rand(), value => $_} for(@cards);

### 並べ替え用のキーでソートします
@cards sort {$a->{'key'} <=> $b->{'key'}} @cards;

### 元の値に戻します
$_ $_->{'value'} for(@cards);

## 結果の表示
print "$_\n" for (@cards);



参考までに、よくある汎用な配列のシャッフルはこんな感じじゃないでしょうか?

#! /usr/bin/perl
use strict;

sub shuffle(@) {
    my @list @_;
    my @ret ();

    push(@ret, splice(@list, int(rand(scalar(@list))), 1)) while(@list);

    return @ret;
}


my @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' },
);

foreach my $item (shuffle @cards) {
    printf "[%s] [%d]\n", $item->{'name'}, $item->{'value'};
}

GJGJGJGJGJGJ

いきなりこんな完璧な返答が返ってくるとはww
素晴らしいです。みなさんどんどん移植しましょう。


とりあえずハッシュやリファレンスを使わず簡単な文字列処理で、と書きました。
当然、汎用性を考えればソートすべきは値ではなく参照です。
split使ったり正規表現使ったりのポリシーの不一致はわかりやすさ重視半分、ネタ半分ですww
セパレータを含む文字列問題も、splitの添字工夫したり正規表現の量指定子使ったりはとりあえず省略して反応待ちでw



しかしいきなり自分レベルでは完璧と思えるコードが返ってきたのでまともなお返しコードがすぐに思いつかない・・・
というわけで以下、perlに限ったネタコード、よいこのみなさんは絶対マネしないように

### 末尾じゃなくてアタマに乱数つければsplitもいらない手抜きコード
my @cards (1..10);

$_  rand() ",$_" for(@cards);
@cards sort @cards;
$_ =~ s/^.*?,// for(@cards);

print "$_\n" for (@cards);


### 乱数はかぶったりしないだろう思想に基づいた乱数をキーにハッシュを作る手抜きコード
my @cards (1..10);

my %hash map {(rand, $_)} @cards;
@cards @hash{sort keys %hash};

print "$_\n" for (@cards);


### さらにハッシュ関数なんて乱数みたいなものだろう思想に基づいたひどい手抜きコード(毎回同じ並び><)
my @cards (1..10);

@hash{@cards} ();
print "$_\n" for (keys %hash);

GJGJGJ

前へ 1 次へ

プレゼン公開・共有サイト handsOut.jp チーム・マイナス6% - みんなで止めよう温暖化

ソースコードのブログパーツ

デフォルトのフォントサイズ
修飾
表示サイズ
px px
プレビュー (表示する)
下のプレビュー領域をクリックすると、ポップアップで全体を見ることができます。
パラメータが不正です

    GoodJobしたユーザ

    ブックマークコメント

    関連するなにがし

    前へ 1 次へ

    タグ

    raketime machineイベントログfilesystemobjectdeveloperprogrammingprimenumberflexriatagged電卓分数逆ポーランド記法ポーランド記法jaxbdyndnsarraylistdeepcopyディープコピーobjectoutputstreambytearrayoutputstreamobjectinputstreambytearrayinputstreamiterator複数チェックボックスmultibytexencentos文字エンコーディングinit_connectcharacter-set-servercollation-serverdefault-character-setヘルパーメソッド動的メソッド呼び出しf:labelwsse2重登録防止prototype.js位置positionedoffsetscrolltoスクロールpositionlink_tocyclecheck_box_tagチュートリアルactive_formerror_messages_forハイライトバリデーションvalidate便利リストデコレーションメールデコメ非対応機種tilestext_field_tag一括複数情報etherealrtphexテキストデータ抽出validwhenリセット一括更新plop置換replacepcoslogmixisregソケットnet::telnetfopenmutexサンプルcalendar[linux][bash][シェルスクリプト][大容量]mobilerorrails2.1クリップボードclipboard横向きピラミッドs2jdbc-genjsonicお絵かきフルパス名抽出サブドメインサブドメイン名s2jdbc自動生成エンティティxhtml

    前へ 1 2 3 ... 8 次へ