こんなん?
for id:dasm:20050919#1127092572
無駄が多いビンゴカード抽選プログラム。
ビンゴカードを作り抽選を行って、ビンゴカードと何回目に何回ビンゴしたかを返す。一応モンテカルロ法、無駄にMersenne Twister。
1から15までrandom permutation掛けるの面倒臭かったので、一様分布で強引に代用。本当はどうやってするのか、知らね。
use Strict;
use Math::Random::MT qw(srand rand);
package main;
# print "Sim\n";
srand(1);
my $count = 100;
my %numbers = ();
foreach (1 .. $count){
my $time = $_;
my $bingo = new Bingo;
# ビンゴカードを出力する場合は以下を適当に弄る
# print $_,":bingo:";
# foreach (1 .. 9) {
# print $bingo->getnumber($_),",";
# }
# print ":\n";
# ここでビンゴを行う.
my $i = 0; # チェック用フラグ
my $j = 0;
my $ball = new Bingo;
# ボールを出力する場合は以下を適当に弄る
# print $_,":balls:";
# foreach (1 .. 15) {
# print $ball->getnumber($_),",";
# }
# print ":\n";
while ($i ==0){
# ボールを取り出してビンゴカードから消す
my $curnum = $ball->{$j};
foreach (1 .. 15){
if ($curnum == $bingo->getnumber($_)){
$bingo->setnumber($_,0);
}
}
# 処理
$i = $bingo->check();
$j = $j+1;
}
my $nu = $j-1;
print $nu," count,",$i," bingo";
print "\n";
# 配列の配列とか嫌なので、ハッシュで。
my $curs = $nu.",".$i;
if (!$numbers{$curs}){
$numbers{$curs} = 1;
} else {
$numbers{$curs} = $numbers{$curs}+1;
}
}
foreach (3 .. 15){
my $i = $_;
print $i,":";
foreach (1 .. 3){
my $curs = $i.",".$_;
print $_,",",$numbers{$curs},",";
}
print "\n";
}
package Bingo;
sub new{
my $this = shift;
my @nls = (0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
my @nl = (0);
foreach (1 .. 15) {
# 強引なrandom permutation。強引過ぎ(わらい
# 今まで出てきていない乱数を得たら、それを配列に加える
# my $cur = int(rand(15)+1);
# while(grep {$_ == $cur} @nl){
# $cur = int(rand(15)+1);
# }
# push(@nl,$cur);
# 修正
# 配列使って、1個ずつランダムに選んで消していく。
my $cur = int(rand(15-$_)+1); # 1 .. $_の乱数を生成
push(@nl,$nls[$cur]);
@nls = grep {$_ != $nls[$cur]} @nls;
}
my $number = {
"1" => @nl[1],
"2" => @nl[2],
"3" => @nl[3],
"4" => @nl[4],
"5" => @nl[5],
"6" => @nl[6],
"7" => @nl[7],
"8" => @nl[8],
"9" => @nl[9],
"10" => @nl[10],
"11" => @nl[11],
"12" => @nl[12],
"13" => @nl[13],
"14" => @nl[14],
"15" => @nl[15]};
bless $number, $this;
return $number;
}
sub getnumber{
$this = shift;
return $this->{$_[0]};
}
sub setnumber{
$this = shift;
$this->{$_[0]} = 0;
return $this->{$_[0]};
}
sub check{
$this = shift;
my $i = 0;
# 横方向と縦方向
foreach (0 .. 2){
if ($this->{$_*3+1}==0 && $this->{$_*3+2}==0 && $this->{$_*3+3}==0){
$i = $i+1;
}
if ($this->{$_+1}==0 && $this->{$_+4}==0 && $this->{$_+7}==0){
$i = $i+1;
}
}
# 斜め
if ($this->{1}==0 && $this->{5}==0 && $this->{9}==0){
$i = $i+1;
}
if ($this->{3}==0 && $this->{5}==0 && $this->{7}==0){
$i = $i+1;
}
return $i;
}