ペプシ算ファイナル
サンプルスクリプト
use Pepsi; # 問題設定をする。 my $pepsi = Pepsi->new( kind=>5 # 5種類のおまけつき食玩具 ); print $pepsi->percent(10); # 10本あけて、コンプする確率は? print "\n"; print $pepsi->limit(0.9); # では、コンプ率が90%を超えるのは何本から? print "\n"; print $pepsi->limit(0.95); # では、コンプ率が95%を超えるのは何本から? print "\n"; my $res = $pepsi->probability(15); # 15本開けた時、どんな確率で何種類集まる? my $num = 0; foreach my $proba ( @{$res} ) { print 'get '.$num.' kind(s) : % '.$proba."\n"; ++ $num; } print "\n"; $res = $pepsi->get_patern(15); # 同じ内容を、分母で割る前の値で取得したい。 $num = 0; foreach my $proba ( @{$res} ) { print 'get '.$num.' kind(s) : % '.$proba."\n"; ++ $num; } print "\n"; print $pepsi->mother(15); # その時の分母を取得する。
実行結果
0.5225472 18 21 get 0 kind(s) : % 0 get 1 kind(s) : % 0.00000000016384 get 2 kind(s) : % 0.00001073676288 get 3 kind(s) : % 0.00466963857408 get 4 kind(s) : % 0.166550372352 get 5 kind(s) : % 0.8287692521472 get 0 kind(s) : % get 1 kind(s) : % 5 get 2 kind(s) : % 327660 get 3 kind(s) : % 142506060 get 4 kind(s) : % 5082714000 get 5 kind(s) : % 25292030400 30517578125
モジュール
package Pepsi; use strict; use bignum; use base qw ( Class::Accessor ); __PACKAGE__->mk_accessors(qw( bottle kind )); sub new { my $invocant = shift; my $class = ref $invocant; $class ||= $invocant; my $self = bless {@_}=>$class; $self->init; return $self; } sub open_bottle { my $self = shift; my $now_bottle = $self->bottle; my $next_bottle = $now_bottle + 1; foreach my $kind ( 0..$self->kind ) { # かぶる場合 my $new_num = $self->{table}->[$now_bottle]->[$kind] * $kind; $new_num and $self->{table}->[$next_bottle]->[$kind] += $new_num; # 新しい種類が出る場合 $new_num = $self->{table}->[$now_bottle]->[$kind] * ($self->kind - $kind); $new_num and $self->{table}->[$next_bottle]->[$kind+1] += $new_num; } ++ $self->{bottle}; } sub get_patern { my $self = shift; my $bottle = undef; if ( @_ ) { $bottle = shift; } else { $bottle = $self->bottle; } $bottle += 0; until ( $self->{table}->[$bottle] ) { $self->open_bottle; } return $self->{table}->[$bottle]; } sub percent { my $self = shift; my ( $bottle, $kind ) = (); @_ and ( $bottle, $kind ) = @_; $bottle ||= $self->bottle; $kind ||= $self->kind; my $patern = $self->get_patern($bottle); my $result = $patern->[$kind]; $result /= $self->mother($bottle); return $result; } sub probability { my $self = shift; my $bottle = undef; if ( @_ ) { $bottle = shift; } else { $bottle = $self->bottle; } my $patern = $self->get_patern($bottle); my $mother = $self->mother($bottle); my @res = @{$patern}; map { $_ /= $mother } @res; return \@res; } sub limit { my $self = shift; my $limit = shift; $limit ||= 0.9; my $bottle = 1; while ( $self->percent($bottle) < $limit ) { ++ $bottle; } return $bottle; } sub mother { my $self = shift; my $bottle = undef; if ( @_ ) { $bottle = shift; } else { $bottle = $self->bottle; } $bottle += 0; $self->{mother}->[$bottle] ||= $self->mother($bottle-1) * $self->kind; return $self->{mother}->[$bottle]; } sub init { my $self = shift; $self->{bottle} = 0; $self->{mother} = [1]; $self->{table} = [[1]]; } 1;
感想
でもさあ、よく考えたら、今の食玩って中身まる見えでないといけないんだよね。コンプするのに買い込む必要がないと言うか……。