Snippets

sironekotoro Perl入学式 2018 in東京 秋開講 第1回 ピザ会でのお題

Created by sironekotoro last modified
#!/usr/bin/env perl;
use strict;
use warnings;

# Perl入学式 2018 in東京 秋開講 第1回 ピザ会でのお題
#
# プレイヤーA, プレイヤーB どちらが勝率が高いか、Perlで解明せよ
# ルール
# プレイヤーA、プレイヤーBに手札が3枚配られる
#     今回は配られる手札は固定とする
#     プレイヤーA:1, 5, 10
#     プレイヤーB:2, 2, 2
#
# 1 〜 40 の目がランダムにでるルーレットを回し、手札と同じ数字が出たら手札を捨てる
# プレイヤーBのように同じ手札が複数枚ある場合には、同じ目が出ても捨てられるカードは1枚だけ
# 先にカードがなくなった方が勝ち
#
# 追加要素
# Perl入学式(1〜5回)の範囲内の要素だけでやってみる
# リファレンスは使わない

# 試行回数
my $game_count = 1_000_000;

my @player_a = ( 1, 5, 10 );
my @player_b = ( 2, 2, 2 );

# 勝敗結果を格納するハッシュ
my %result;


for my $count ( 1 .. $game_count ) {

# ルーレットを3回まわすサブルーチンから、3つの数を配列で受け取り
# @three_numbers に入る
    my @three_numbers = three_times_roulette();

# player_a の手札(1,5,10)と、ルーレットで出た3つの数を配列 @player_a_aggrigate に集める
    my @player_a_aggrigate = ( @player_a, @three_numbers );

# player_b の手札(2,2,2)と、ルーレットで出た3つの数を配列 @player_b_aggrigate に集める
    my @player_b_aggrigate = ( @player_b, @three_numbers );

# 配列の中の数字の出現回数を調べるサブルーチン number_count に渡し、
# ハッシュを受け取る
    my %hash_a = number_count(@player_a_aggrigate);
    my %hash_b = number_count(@player_b_aggrigate);

    # player_aの勝利条件は以下の2つを満たすこと
    #  1.数字の種類が3つ(1,5,10)
    #  2.それぞれの出現回数が2回ずつ
    if ( keys %hash_a == 3 ) {

       # ハッシュのvalueが2の時にカウントするスカラー変数
        my $count_value_is_two = 0;

        # for文でハッシュの要素1つずつ調べる
        for my $num ( keys %hash_a ) {

            # ハッシュのvalueが2だったらカウントを加える
            if ( $hash_a{$num} == 2 ) {
                $count_value_is_two++;
            }
        }

# カウントが3(ハッシュの3つのkeyに対するvalueがすべて2だった)であれば
# player_a の勝利
        if ( $count_value_is_two == 3 ) {
            $result{a} += 1;
        }
    }

    # player_bの勝利条件は以下を満たすこと
    #  1.数字の種類が1つ(2,2,2)だけ
    elsif ( keys %hash_b == 1 ) {
        $result{b} += 1;
    }

    # player_a, player_b どちらでもない場合には引き分け
    else {
        $result{even} += 1;
    }

    # プログレスバーの表示
    progres_bar($count);

}

# 結果発表
print "player_a が勝った回数:$result{a}\n";
print "player_b が勝った回数:$result{b}\n";
print "引き分けになった回数:$result{even}\n";

# ルーレットを回した結果をスカラー変数で返すサブルーチン
sub roulette {
    return int( rand(40) + 1 );
}

# ルーレットを3回した結果を配列で返すサブルーチン
sub three_times_roulette {
    my @array;
    for my $i ( 1 .. 3 ) {
        push @array, roulette();
    }
    return @array;
}

# 配列の中の数字をkeyに、出現回数をvalueに格納するハッシュを返すサブルーチン
sub number_count {
    my @array = @_;
    my %hash;
    for my $num (@array) {
        $hash{$num} += 1;
    }
    return %hash;
}

# 処理の進捗を示すプログレスバーの処理部
# (なくてもいいけど、あると見栄えする)
sub progres_bar {
    my $count = shift;

# 処理結果をためず、すぐに表示するようにするPerlの特殊変数をセット
    $| = 1;

    # 試行回数に達したら改行する
    if ( $count == $game_count ) {
        print "\n";
    }

    # 試行回数が100,000(10万回)ごとに * を表示
    elsif ( $count % 100000 == 0 ) {
        print '*';
    }

    # 試行回数が10,000(1万回)ごとに . を表示
    elsif ( $count % 10000 == 0 ) {
        print '.';
    }

}

Comments (0)