基礎プロI 100本ノック 上級編

**以下の C による初歩の C プログラミング 100 本ノックを Julia で解いてみました。**

基礎プロI 100本ノック 上級編
http://www.cc.kyoto-su.ac.jp/~mmina/bp1/hundredKnocksAdvanced.html

各プログラムにおいて、特に指定が無い限りは入力値が指定された形式であるかどうかをチェックする必要はない（例えば整数型の値を入力させるところでアルファベットを入力された場合など）。

問題の順序は難しさの順序ではないので、好きな問題から手をつけるとよいだろう。難しさの目安として問題の後ろに☆をつけておく（多いほど難しいと思われる）。

## No. 80 互いに素 ☆
2つの正の整数値を入力させ、互いに素であるか判定するプログラムを作成せよ。なお、2つの正の整数が互いに素とは、1以外に共通公約数を持たない関係のことである。

```julia
print("2つの値をスペースで区切って入力:")
(a, b) = parse.(Int, split(readline()))

if gcd(a, b) == 1
    println("互いに素")
else
    println("互いに素でない")
end
```

    2つの値をスペースで区切って入力:
    stdin>  69 23
    互いに素でない

ユークリッドの互除法により最大公約数を求める

```julia
print("2つの値をスペースで区切って入力:")
(a, b) = parse.(Int, split(readline()))

while b != 0
    (a, b) = (b, a%b)
end
# a が最大公約数
if a == 1
    println("互いに素")
else
    println("互いに素でない")
end
```

    2つの値をスペースで区切って入力:
    stdin>  69 23
    互いに素でない

## No. 81 中間値 ☆
３つの整数値を入力させ、3つの値のうち2番目に大きい値を表示するプログラムを作成せよ。

3つの整数値は相異なるという条件のもとであれば，「3個の整数は相異なるとすれば，3個の整数の和から，一番小さい整数と，一番大きい整数を引けばよい」。

```julia
print("3つの値を入力:")
(a, b, c) = parse.(Int, split(readline()))
println("$(a + b + c - minimum([a, b, c]) - maximum([a, b, c]))")
```

    3つの値を入力:
    stdin>  16 8 21
    16

3個の整数のいずれかは同じとすれば，
2 2 1 のときは 1
2 1 1 のときは 1
2 2 2 のときは 解なし

## No. 82 パスカルの三角形 ☆
パスカルの三角形とは、1段目は1のみ、2段目からは段の数だけ数字が並び、両端は1、その間は左上と右上の値を足した値、として作っていった数字の並びである（Wikipedia「パスカルの三角形」参照）。このパスカルの三角形を15段まで計算して表示するプログラムを作成せよ。ただし表示は左詰で値はスペースで区切って表示するのでよい（三角形に並べなくてもよい）

```julia
using Combinatorics
for n in 0:14
    [print(x, " ") for x in binomial.(n, 0:n)]
    println()
end
```

    1 
    1 1 
    1 2 1 
    1 3 3 1 
    1 4 6 4 1 
    1 5 10 10 5 1 
    1 6 15 20 15 6 1 
    1 7 21 35 35 21 7 1 
    1 8 28 56 70 56 28 8 1 
    1 9 36 84 126 126 84 36 9 1 
    1 10 45 120 210 252 210 120 45 10 1 
    1 11 55 165 330 462 462 330 165 55 11 1 
    1 12 66 220 495 792 924 792 495 220 66 12 1 
    1 13 78 286 715 1287 1716 1716 1287 715 286 78 13 1 
    1 14 91 364 1001 2002 3003 3432 3003 2002 1001 364 91 14 1 

愚直に作る

```julia
p = zeros(Int, 15, 17)
p[1, 2] = 1
println(1)
for i in 2:15
    for j in 2:i+1
        p[i, j] = p[i - 1, j - 1] + p[i - 1, j]
    end
    [print(x, " ") for x in p[i, 2:i+1]]
    println()
end
```

    1
    1 1 
    1 2 1 
    1 3 3 1 
    1 4 6 4 1 
    1 5 10 10 5 1 
    1 6 15 20 15 6 1 
    1 7 21 35 35 21 7 1 
    1 8 28 56 70 56 28 8 1 
    1 9 36 84 126 126 84 36 9 1 
    1 10 45 120 210 252 210 120 45 10 1 
    1 11 55 165 330 462 462 330 165 55 11 1 
    1 12 66 220 495 792 924 792 495 220 66 12 1 
    1 13 78 286 715 1287 1716 1716 1287 715 286 78 13 1 
    1 14 91 364 1001 2002 3003 3432 3003 2002 1001 364 91 14 1 

注
実際のパスカルの三角形は p[i, 2:i+1], i = 1, 2, ... に作られる。
これにより，最初の項だとか最後の項だとか考えなくて済む。

## No. 83 じゃんけん5回勝負 ☆
次の仕様のじゃんけんプログラムを作成せよ。

- 人間は、グー、チョキ、パーをそれぞれ0、1、2の数字で入力する。
- コンピュータは乱数を使って出す手を選ぶ。乱数の使い方は演習資料の高度なテクニック集を見よ。
- 5回勝負として、人間とコンピュータの勝った回数を数え、勝敗がつくたびに1回ずつ表示する。あいこは決着がつくまで再勝負。途中でどちらかが3勝しても、5回最後まで勝負を続ける。
- 指定された範囲以外の値を入力したら負けにする

```julia
function janken()
    print("あなたの手を選んでください(グー0、チョキ1、パー2):")
    while true
        you = parse(Int, replace(readline(), "." => "9"))  # 小数点を含む数は 0, 1, 2 以外の数になる
        if you ∉ 0:2  # ∉ は 'not in'
            println("そんな手はありません。あなたの負け")
            return 1
        end
        computer = rand(0:2, 1)[1]
        println("$you, $computer")
        result = (you - computer + 3) % 3
        result != 0 && return result
        print("あいこでした。もう一度あなたの手を選んでください(グー0、チョキ1、パー2):")
    end
end

(you, computer) = (0, 0)
for i in 1:5
    if janken() == 2
        you += 1
    else
        computer += 1
    end
    println("あなた$(you)勝，わたし$(computer)勝")
end
if you > computer
    print("あなたの総合勝利です。参りました。")
else
    print("わたしの総合勝利です。ありがとうございました。")
end
```

    あなたの手を選んでください(グー0、チョキ1、パー2):
    stdin>  0
    0, 1
    あなた1勝，わたし0勝
    あなたの手を選んでください(グー0、チョキ1、パー2):
    stdin>  0
    0, 1
    あなた2勝，わたし0勝
    あなたの手を選んでください(グー0、チョキ1、パー2):
    stdin>  0
    0, 2
    あなた2勝，わたし1勝
    あなたの手を選んでください(グー0、チョキ1、パー2):
    stdin>  0
    0, 0
    あいこでした。もう一度あなたの手を選んでください(グー0、チョキ1、パー2):
    stdin>  0
    0, 2
    あなた2勝，わたし2勝
    あなたの手を選んでください(グー0、チョキ1、パー2):
    stdin>  0
    0, 2
    あなた2勝，わたし3勝
    わたしの総合勝利です。ありがとうございました。

## No. 84 トランプを切る ☆☆
トランプをランダムに順番を変えて表示するプログラムを作成せよ。トランプは4つのスート（マーク）、1〜13までの数字の52枚である。トランプを表現する配列を作り、適当に順序を入れ替えていけばよい。適当に順序を入れ替えるには、例えば2つの入れ替えるカードを乱数を使って選び、それらを入れ替える操作を何回も繰り返せばよい。

```julia
using Random
suits = ["♥", "♦", "♠", "♣"]
numbers = string.(collect(1:13))
cards = vec([i*j for j in numbers, i in suits])
println(cards)
cards = cards[shuffle(collect(1:52))]
println(cards)
```

    ["♥1", "♥2", "♥3", "♥4", "♥5", "♥6", "♥7", "♥8", "♥9", "♥10", "♥11", "♥12", "♥13", "♦1", "♦2", "♦3", "♦4", "♦5", "♦6", "♦7", "♦8", "♦9", "♦10", "♦11", "♦12", "♦13", "♠1", "♠2", "♠3", "♠4", "♠5", "♠6", "♠7", "♠8", "♠9", "♠10", "♠11", "♠12", "♠13", "♣1", "♣2", "♣3", "♣4", "♣5", "♣6", "♣7", "♣8", "♣9", "♣10", "♣11", "♣12", "♣13"]
    ["♣12", "♠9", "♦1", "♥11", "♣9", "♠2", "♥10", "♣1", "♠13", "♥5", "♦3", "♥1", "♣3", "♦10", "♥7", "♣11", "♠4", "♣2", "♦11", "♠6", "♦4", "♦7", "♠11", "♥12", "♥13", "♠8", "♠5", "♦8", "♠3", "♣10", "♥6", "♣8", "♥4", "♦13", "♠1", "♣4", "♣5", "♦2", "♥3", "♥9", "♣13", "♦5", "♦12", "♦9", "♥8", "♥2", "♦6", "♣7", "♣6", "♠7", "♠12", "♠10"]

愚直に作る

```julia
suits = ["♥", "♦", "♠", "♣"]
numbers = string.(collect((1:13)))
cards = vec([i*j for j in numbers, i in suits])
println(cards)
for i in 1:52
    j = rand(1:52, 1)[1]
    (cards[j], cards[i]) = (cards[i], cards[j])
end
println(cards)
```

    ["♥1", "♥2", "♥3", "♥4", "♥5", "♥6", "♥7", "♥8", "♥9", "♥10", "♥11", "♥12", "♥13", "♦1", "♦2", "♦3", "♦4", "♦5", "♦6", "♦7", "♦8", "♦9", "♦10", "♦11", "♦12", "♦13", "♠1", "♠2", "♠3", "♠4", "♠5", "♠6", "♠7", "♠8", "♠9", "♠10", "♠11", "♠12", "♠13", "♣1", "♣2", "♣3", "♣4", "♣5", "♣6", "♣7", "♣8", "♣9", "♣10", "♣11", "♣12", "♣13"]
    ["♣8", "♦13", "♥10", "♠8", "♦9", "♠2", "♥12", "♦5", "♥5", "♠10", "♥8", "♦2", "♠13", "♠3", "♥4", "♦8", "♦6", "♠6", "♥3", "♦3", "♠11", "♠9", "♣2", "♠5", "♠12", "♥1", "♥6", "♣13", "♦7", "♦12", "♣3", "♣9", "♠7", "♥2", "♣1", "♣7", "♦4", "♣10", "♣4", "♣11", "♠1", "♣6", "♥9", "♥7", "♥11", "♦11", "♣12", "♣5", "♥13", "♠4", "♦10", "♦1"]

注
2個の乱数番目のカードを入れ替えることを52回繰り返しても，ランダム性は保証できない（シャッフルされないカードが残る可能性がある）。かと言って，数千回やるのは無駄というものである。
i = 1,2,..., 52 に対して，i 番目のカードと乱数番目のカードを入れ替えるを行えばランダム性が保証できる。

## No. 85 石取りゲーム ☆☆
最初に石の個数を入力し（10個以上とする）、二人のプレイヤーが交互に1〜3個ずつ石を取り、最後の1個を取った方が負けとなるゲームがある。このゲームプログラムを作成せよ。具体的には実行例を参照のこと。

```julia
function 石取り(石の数, player)
    println("石の数 = $石の数")
    while true
        print("プレイヤー$(player)の番です\n何個取る（1〜$(min(石の数, 3))個）?")
        n = parse(Int, readline())
        if 1 <= n <= min(石の数, 3)
            石の数 -= n
            break
        end
    end
    if 石の数 == 1
        println("プレイヤー$(player)の勝ちです")
    end
    return 石の数
end

print("石の数を入力してください（10以上）:")
石の数 = parse(Int, readline())

while 石の数 > 0
    (石の数 = 石取り(石の数, 1)) == 1 && break
    (石の数 = 石取り(石の数, 2)) == 1 && break
end
```

    石の数を入力してください（10以上）:
    stdin>  10
    石の数 = 10
    プレイヤー1の番です
    何個取る（1〜3個）?
    stdin>  1
    石の数 = 9
    プレイヤー2の番です
    何個取る（1〜3個）?
    stdin>  2
    石の数 = 7
    プレイヤー1の番です
    何個取る（1〜3個）?
    stdin>  1
    石の数 = 6
    プレイヤー2の番です
    何個取る（1〜3個）?
    stdin>  2
    石の数 = 4
    プレイヤー1の番です
    何個取る（1〜3個）?
    stdin>  1
    石の数 = 3
    プレイヤー2の番です
    何個取る（1〜3個）?
    stdin>  2
    プレイヤー2の勝ちです

## No. 86 コンピュータ必勝石取りゲーム ☆☆☆
No. 85の石取りゲームを人間とコンピュータが対戦する。どちらから石を取り始めるかはコンピュータが決めてよいとしたとき、コンピュータが必ず勝つプログラムを作成せよ。

最初に指定された数が４の倍数プラス１なら後手、それ以外なら先手を選ぶ。

先手を選んだ場合
まず最初の１手は、とった後の残りの石の数が４の倍数プラス１になるようにとる。
そのあとは、相手の取った石の数との和が４になるようにとっていく。

後手を選んだ場合
最初から相手の取った数との和が４になるようにとっていく。

```julia
print("石の数を入力してください（10以上）:")
石の数 = parse(Int, readline())

if 石の数 % 4 != 1
    println("石の数: ", 石の数)
    println("ではわたしから")
    n = (石の数%4 + 3)%4
    println(n, "個とります")
    石の数 -= n
end
while 石の数 > 1
    println("石の数: ", 石の数)
    while true
        print("何個取る（1〜3個）?")
        n = parse(Int, readline())
        if 1 <= n <= min(石の数, 3)
            石の数 -= n
            break
        end
    end
    println("石の数: ", 石の数)
    n = 4 - n
    println(n, "個とります")
    石の数 -= n
    if 石の数 == 1
        println("石の数: ", 石の数)
        println("次の手で，あなたは残った 1 個を取らざるを得ないので，あなたの負けです。")
        break
    end
end
```

    石の数を入力してください（10以上）:
    stdin>  21
    石の数: 21
    何個取る（1〜3個）?
    stdin>  2
    石の数: 19
    2個とります
    石の数: 17
    何個取る（1〜3個）?
    stdin>  2
    石の数: 15
    2個とります
    石の数: 13
    何個取る（1〜3個）?
    stdin>  2
    石の数: 11
    2個とります
    石の数: 9
    何個取る（1〜3個）?
    stdin>  2
    石の数: 7
    2個とります
    石の数: 5
    何個取る（1〜3個）?
    stdin>  2
    石の数: 3
    2個とります
    石の数: 1
    次の手で，あなたは残った 1 個を取らざるを得ないので，あなたの負けです。

## No. 87 運命数 ☆☆
カバラ数秘術という簡単な占いがある。誕生日を年（西暦）・月・日で表し、それぞれの数字を足し合わせる。合計した数字が10以上であれば、再びすべての桁の数字を足し合わせる。これを1桁の数字になるまで繰り返し、得られた数字を運命数とする。ただし、計算途中で11、22、33のようにゾロ目の数字になった場合は、それを運命数とする。
例：2015年12月23日→2+0+1+5+1+2+2+3=16→1+6=7
運命数を計算するプログラムを作成せよ。

```julia
print("誕生日をYYYYMMDDの形式で入力してください:")
i = readline()

n = 0  # 注
while true
    n = sum(parse.(Int, split(i, "")))
    n < 10 && break
    if 11 <= n <= 99
        (n1, n2) = divrem(n, 10)
        n1 == n2 && break
    end
    i = string(sum(n))
end
println(n) 
```

    誕生日をYYYYMMDDの形式で入力してください:
    stdin>  20201212
    1

注
代入する値は何でもよいが，これがないと while ループ内で設定される n がローカル変数になり，したがってwhile ループを抜けた後に n を参照すると「未定義エラー」になる。
while ループの外で定義される n がある場合，while ループ内の n はループの外のグローバル変数になり，したがって while ループ内で再定義された n を while ループを抜けた後に n を参照すると while ループ内で再定義された n になる。
REPL 環境で実行している場合などでは，これ以前の何処かで n に何らかの値が代入されていることもありうる。そのような場合にはここで n = 0 する必要はない。

## No. 88 big or small ☆
コンピュータは1から99の数字をランダムに選ぶ（正解値と呼ぶ）。プレイヤは値を入力し、正解値と一致すればクリアとなり値を入力した回数を表示する。一致しなければ正解値が入力値より大きいか小さいかを表示する。この数当てゲームプログラムを作成せよ。

```julia
正解値 = rand(1:99, 1)[1]  # 1 個の要素を持つベクトルなので，取り出すには添字指定が必須

count = 0
while true
    count += 1
    print("数を入力:")
    n = parse(Int, readline())
    n == 正解値 && (println("正解!! $(count)回でクリア"); break)
    println("それより" * (n < 正解値 ? "大き" : "小さ") * "いです")
end
```

    数を入力:
    stdin>  50
    それより小さいです
    数を入力:
    stdin>  25
    それより大きいです
    数を入力:
    stdin>  37
    それより小さいです
    数を入力:
    stdin>  31
    それより大きいです
    数を入力:
    stdin>  34
    それより小さいです
    数を入力:
    stdin>  32
    それより大きいです
    数を入力:
    stdin>  33
    正解!! 7回でクリア

## No. 89 逆 big or small ☆☆☆
プレイヤは1から99の数字をランダムに選ぶ（正解値と呼ぶ）。コンピュータは値を推測して表示する（推測値と呼ぶ）。プレイヤは、推測値が正解値と一致していれば0、推測値よりも正解値が大きければ正の値、推測値よりも正解値が小さければ負の値を入力する。推測値が正解値と一致すればクリアとなり回数を表示して終了する。プレイヤがズルをしない（正解値を変えたりしないなど）場合、多くとも7回までに必ずクリアできるプログラムを作成せよ。

```julia
print("input number:")
正解値 = parse(Int, readline())

count = 0
(lo, hi) = (1, 99)
while true
    count += 1
    n = (lo + hi) ÷ 2
    println("$(n)ですか？")
    n == 正解値 && (println("正解!! $(count)回でクリア"); break)
    if n < 正解値  # 注
        println("それより大きいです")
        lo = n
    else
        println("それより小さいです")
        hi = n
    end
end
```

    input number:
    stdin>  58
    50ですか？
    それより大きいです
    74ですか？
    それより小さいです
    62ですか？
    それより小さいです
    56ですか？
    それより大きいです
    59ですか？
    それより小さいです
    57ですか？
    それより大きいです
    58ですか？
    正解!! 7回でクリア

注
大きいか小さいかだけを教えてもらい，二分探索する。

## No. 90 ブラックジャックその1 ☆☆
トランプをシャッフルするプログラムはNo.84で作成した。これを使って、ブラックジャックゲームを作ってみよう。ブラックジャックは、最初に2枚のカードを配り、2〜10は数字通り、JとQとKは10、Aは1か11として合計し21に近いほど勝ちとなるが、21を超えると負け（バストと呼ぶ）というゲームである。
まず最初にトランプをシャッフルし、2枚を先頭から順番に引き、それらのカードの数字（マークは無視してよい）と合計値を表示するプログラムを作成せよ。

```julia
using Random
numbers = shuffle(repeat(1:13, 4))
# println(numbers)
for i in 1:13*2
    one = popat!(numbers, 1)
    two = popat!(numbers, 1)
    one == 1 && (one = -11)  # J の 11 と区別するため -11 にする
    two == 1 && (two = -11)
    result = abs(one) + abs(two)
    result > 21 && -11 in [one, two] && (result -= 10)  # 1 にして合計するのと同じ
    println("$one + $two ==> $result")
end
```

    13 + 11 ==> 24
    5 + 12 ==> 17
    3 + 7 ==> 10
    3 + 9 ==> 12
    6 + 2 ==> 8
    12 + 3 ==> 15
    5 + 11 ==> 16
    8 + 7 ==> 15
    8 + 3 ==> 11
    -11 + 13 ==> 14
    7 + 2 ==> 9
    10 + 9 ==> 19
    13 + -11 ==> 14
    5 + 4 ==> 9
    9 + 2 ==> 11
    11 + 6 ==> 17
    12 + 6 ==> 18
    2 + 4 ==> 6
    11 + -11 ==> 12
    7 + 12 ==> 19
    10 + 10 ==> 20
    10 + 5 ==> 15
    4 + 9 ==> 13
    4 + 8 ==> 12
    8 + 6 ==> 14
    13 + -11 ==> 14

## No. 91 ブラックジャックその2 ☆☆☆☆
No.90で作ったブラックジャックゲームをさらに進化させよう。ブラックジャックでは、最初に配られた2枚の合計では足りない場合、21を超えない限り何枚でもカードを追加で引くことができる。
合計が16以下の場合はもう一枚カードを引き、17以上になったら止める、というルールで自動的にカードを引くプログラムを作成せよ。

```julia
using Random
function replace2(x, old, new)
    res = indexin([old], x)[1]
    isnothing(res) || (x[res] = new)
    return x
end;
```

```julia
function blackjack()
    numbers = shuffle(repeat(vcat([-11, collect(2:13)...]), 4))
    println(numbers)
    hands = []
    append!(hands, popat!(numbers, 1))
    append!(hands, popat!(numbers, 1))
    while length(numbers) > 10  # とりあえずゲームを進められるだろうという限界を設定する
        result = sum(abs.(hands))
        if result > 21
            hands = replace2(hands, -11, 1)
        end
        result = sum(abs.(hands))
        println("sum($hands) ==> $result")
        if result > 18
            return result
        end
        append!(hands, popat!(numbers, 1))
    end
end;
```

```julia
for i in 1:10
    result = blackjack()
    if result > 21
        println("負け")
    else
        println("勝ち")
    end
end
```

    [11, 3, 2, 13, 9, 2, 4, 10, 3, 6, 5, 9, 13, 11, -11, 7, 3, 10, 11, 10, 8, 8, 6, 5, 9, 3, -11, 2, 6, 7, 12, -11, -11, 4, 12, 6, 5, 12, 4, 8, 13, 4, 5, 10, 9, 8, 12, 11, 2, 7, 7, 13]
    sum(Any[11, 3]) ==> 14
    sum(Any[11, 3, 2]) ==> 16
    sum(Any[11, 3, 2, 13]) ==> 29
    負け
    [10, 4, 12, 13, 8, 11, 5, 7, 7, 10, 3, 9, 7, 8, 11, 5, 3, 3, 10, 11, 12, 2, 2, 4, -11, 9, 12, -11, 2, 5, 8, 11, 8, 6, 4, -11, 4, 13, 6, 5, 9, 9, 6, 3, -11, 6, 7, 13, 13, 10, 2, 12]
    sum(Any[10, 4]) ==> 14
    sum(Any[10, 4, 12]) ==> 26
    負け
    [8, -11, 10, 9, 11, 9, 12, 4, 13, 3, 2, 8, 6, 11, -11, 13, 4, 13, 4, 2, 2, 5, 10, 5, 5, 12, 8, 9, 11, 3, 6, -11, 11, 7, 3, 10, 8, 13, 12, 12, 10, 7, 5, 2, 6, 3, 6, 4, -11, 9, 7, 7]
    sum(Any[8, -11]) ==> 19
    勝ち
    [4, 7, -11, 11, 8, 3, 9, 7, 6, 7, 10, 8, 10, 9, 12, 6, 11, 12, 10, 3, 6, 2, 2, 3, -11, 9, 13, 8, 7, 2, 13, 11, -11, 5, 8, -11, 12, 6, 3, 5, 5, 13, 11, 4, 5, 2, 4, 13, 4, 12, 10, 9]
    sum(Any[4, 7]) ==> 11
    sum(Any[4, 7, 1]) ==> 12
    sum(Any[4, 7, 1, 11]) ==> 23
    負け
    [9, 5, 12, 9, 7, 8, 3, 3, 10, -11, 5, 13, 6, 5, 6, 3, -11, 2, 6, 12, 11, 7, 11, 8, 13, 4, 9, 5, 4, 3, 13, 11, 8, 12, 7, 2, 4, 10, 12, -11, 8, 10, -11, 2, 10, 11, 6, 2, 13, 9, 4, 7]
    sum(Any[9, 5]) ==> 14
    sum(Any[9, 5, 12]) ==> 26
    負け
    [3, 12, 8, 3, 10, 9, 10, 7, 9, -11, 6, 13, 2, 3, 9, 2, 13, -11, -11, 11, 5, 7, 12, 6, 11, 11, 4, 6, 7, 5, 9, 11, 2, 12, 10, 8, 4, 4, 5, 10, 13, 13, 8, 5, 6, 2, -11, 3, 8, 12, 4, 7]
    sum(Any[3, 12]) ==> 15
    sum(Any[3, 12, 8]) ==> 23
    負け
    [8, 6, 4, 12, 8, 4, 5, 11, 5, 2, 8, 11, -11, 11, 6, 6, 12, 9, 3, 8, -11, 3, 6, 5, 7, 10, -11, 11, 9, 13, 2, 3, 10, 7, 13, 9, 4, 13, 10, 7, 5, 2, 13, 10, 12, 3, -11, 4, 2, 7, 12, 9]
    sum(Any[8, 6]) ==> 14
    sum(Any[8, 6, 4]) ==> 18
    sum(Any[8, 6, 4, 12]) ==> 30
    負け
    [-11, 8, 9, 7, 6, 10, 10, 5, -11, 3, 5, 6, 3, 2, 4, 13, 7, 9, 3, 3, 11, 11, 9, 7, 7, 2, 5, 6, 8, 8, 12, 6, 2, 4, 10, 13, 13, 12, -11, 2, 5, 4, 11, 11, 8, 9, 13, 12, 12, -11, 10, 4]
    sum(Any[-11, 8]) ==> 19
    勝ち
    [11, 3, 10, 3, -11, 6, 9, 4, 3, 6, 5, 12, 2, 7, 5, 4, 13, 7, 7, 9, 12, 7, -11, 4, 12, 6, 13, 10, 6, 5, 4, 2, 11, 5, 2, 8, 9, 8, 10, 13, 12, 10, 8, 3, 13, 11, -11, 2, 9, 11, 8, -11]
    sum(Any[11, 3]) ==> 14
    sum(Any[11, 3, 10]) ==> 24
    負け
    [10, -11, 7, 11, 12, 10, 7, 3, 2, 12, 2, 8, 6, 7, 13, 6, 7, 6, 10, 8, 2, 5, 11, 11, -11, 13, 3, 2, 13, 12, 3, 6, 11, 5, 13, 3, 4, 5, -11, 4, 12, 4, -11, 9, 9, 4, 8, 9, 8, 9, 10, 5]
    sum(Any[10, -11]) ==> 21
    勝ち

## No. 92 世界の人 ☆
1から50まで順に表示していくが、3の倍数と3のつく数字のときは頭に"aho"と付けて表示するプログラムを作成せよ。

```julia
for i in 1:50
    (i1, i2) = divrem(i, 10)
    (i % 3 == 0 || (i1 == 3 || i2 == 3)) && print("aho")
    println(i)
end
```

    1
    2
    aho3
    4
    5
    aho6
    7
    8
    aho9
    10
    11
    aho12
    aho13
    14
    aho15
    16
    17
    aho18
    19
    20
    aho21
    22
    aho23
    aho24
    25
    26
    aho27
    28
    29
    aho30
    aho31
    aho32
    aho33
    aho34
    aho35
    aho36
    aho37
    aho38
    aho39
    40
    41
    aho42
    aho43
    44
    aho45
    46
    47
    aho48
    49
    50

## No. 93 宇宙の人 ☆☆☆
まず開始値と終了値をそれぞれ入力させる。次に、開始値から終了値まで順に、3の倍数と3のつく数字のときは頭に"aho"と付けて表示するプログラムを作成せよ。開始値と終了値の値の妥当性（例えば終了値の方が開始値よりも大きいか）チェックは省略してよい。

```julia
print("開始値:")
開始値 = parse(Int, readline())
print("終了値:")
終了値 = parse(Int, readline())

for i in 開始値:終了値
    n0 = i
    flag = i % 3 == 0
    while i > 0
        (n1, n2) = divrem(i, 10)
        flag |= n2 == 3
        i = n1
    end
    flag && print("aho ")
    println(n0)
end
```

    開始値:
    stdin>  290
    終了値:
    stdin>  310
    290
    aho 291
    292
    aho 293
    aho 294
    295
    296
    aho 297
    298
    299
    aho 300
    aho 301
    aho 302
    aho 303
    aho 304
    aho 305
    aho 306
    aho 307
    aho 308
    aho 309
    aho 310

## No. 94 hit and blow その1 ☆☆☆
hit and blowという数当てゲームがある。出題者は0〜9999の範囲の数字を正解として選ぶ。次に、解答者は予想する数字を言う。出題者は同じ桁（位置）に同じ数字があればヒット、桁は違うが同じ数字があればブローとして数え、ヒットとブローの数を答える（3桁以下の数字は頭に0が付いているものとする）。例えば、次のようになる：
正解:1234 予想:1234 → 4ヒット（＝クリア）
正解:1234 予想:5678 → 0ヒット0ブロー
正解:1234 予想:1892 → 1ヒット1ブロー
正解:0034 予想:3400 → 0ヒット4ブロー
正解:1222 予想:1234 → 2ヒット0ブロー（ヒットはブローより優先して判定する）
正解:1112 予想:1221 → 1ヒット2ブロー

このゲームを3回に分けて作ってみよう。まず、コンピュータは正解となる4つの数字をランダムに選ぶ（同じ数字を何回使ってもよいし、0で始まってもよい）。次に、プレイヤーに4桁の数字を入力させる。そして、ヒットの数を数え、表示するプログラムを作成せよ。

```julia
正解 = rand(0:9, 4)
print("4桁の数を入力:")
数 = parse.(Int, split(readline(), ""))

hit = sum([x == y for (x, y) in zip(正解, 数)])
println(正解)
println("$hit hit")
```

    4桁の数を入力:
    stdin>  1222
    [9, 6, 4, 3]
    0 hit

## No. 95 hit and blow その2 ☆☆☆☆☆
No.94に続いて、ブローの数も数えて表示するプログラムを作成せよ。（No.94のプログラムをコピーして、それに追加するとよい。）

```julia
正解 = rand(0:9, 4)
print("4桁の数を入力:")
数 = parse.(Int, split(readline(), ""))

正解0 = copy(正解)
数0   = copy(数)
hit = 0
for i in 1:4
    if 数[i] == 正解[i]
        数[i] = -1
        正解[i] = -1
        hit += 1
    end
end
blow = 0
for i in 1:4
    数[i] < 0 && continue
    for j in 1:4
        正解[j] < 0 && continue
        if 数[i] == 正解[j]
            for k = 1:4
                数[k] == 数[i] && (数[k] = -1)
                正解[k] == 正解[j] && (正解[k] = -1)
            end
            blow += 1
        end
    end
end
println(正解0)
println("$hit hit")
println("$blow blow")
```

    4桁の数を入力:
    stdin>  1111
    [8, 1, 2, 5]
    1 hit
    0 blow

## No. 96 hit and blow その3 ☆☆☆☆☆
No.95に続いて、正解と一致するまで繰り返して予想させるようにしてゲームを完成させよう。

```julia
function counthitandblow(正解0, 数)
    正解 = copy(正解0)
    hit = 0
    for i in 1:4
        if 数[i] == 正解[i]
            数[i] = -1
            正解[i] = -1
            hit += 1
        end
    end
    blow = 0
    for i in 1:4
        数[i] < 0 && continue
        for j in 1:4
            正解[j] < 0 && continue
            if 数[i] == 正解[j]
                for k = 1:4
                    数[k] == 数[i] && (数[k] = -1)
                    正解[k] == 正解[j] && (正解[k] = -1)
                end
                blow += 1
            end
        end
    end
    return (hit, blow)
end
```

    counthitandblow (generic function with 1 method)

```julia
function hitandblow()
    正解 = rand(0:9, 4)
    loop = 0
    while true
        loop += 1
        print("$(loop)回目  0000 を入力すれば答えを表示して終了\n4桁の数を入力:")
        数 = parse.(Int, split(readline(), ""))
        join(string.(数), "") == "0000"　&& (println("正解 = $(join(string.(正解), ""))"); break)
        (hit, blow) = counthitandblow(正解, 数)
        hit == 4 && (println("正解です"); break)
        println("$hit hit, $blow blow")
    end
end

hitandblow()
```

    1回目  0000 を入力すれば答えを表示して終了
    4桁の数を入力:
    stdin>  1234
    0 hit, 1 blow
    2回目  0000 を入力すれば答えを表示して終了
    4桁の数を入力:
    stdin>  5678
    2 hit, 0 blow
    3回目  0000 を入力すれば答えを表示して終了
    4桁の数を入力:
    stdin>  9011
    0 hit, 0 blow
    4回目  0000 を入力すれば答えを表示して終了
    4桁の数を入力:
    stdin>  2367
    0 hit, 1 blow
    5回目  0000 を入力すれば答えを表示して終了
    4桁の数を入力:
    stdin>  0000
    正解 = 7478

## No. 97 ビンゴその1 ☆☆☆
ビンゴゲームのカードを作るプログラムを作ろう。縦5マス、横5マス、計25マスのそれぞれに1〜75までの数字をランダムに配置する※。同じ番号は2回以上配置しない。作成したカードは、実行例のようにタブ(\t)を開けて表示すること。
※一般的なビンゴカードは、縦の5列それぞれは1〜15、16〜30、31〜45、46〜60、61〜75のそれぞれの数字のうち5つずつを配置し、中央のマスはフリーとしているが、ここでは簡単のためにこのようにしている。余裕があれば一般的なカードを作ってるとよいだろう。

```julia
using Random
function prepare()
    bingocard = zeros(Int, 5, 5)
    for i in 1:5
        bingocard[:, i] = shuffle(15(i-1)+1:15i)[1:5]
    end
    bingocard[3, 3] = 0
    return bingocard
end

bingocard = prepare()
Base.print_matrix(stdout, bingocard)
```

      7  29  44  54  72
     15  28  39  60  73
      6  16   0  58  75
      2  21  34  51  63
      5  26  36  46  68

## No. 98 ビンゴその2 ☆☆☆☆☆
No.97で作ったビンゴカードで、ビンゴの抽選をするプログラムを作ろう。1〜75の数字をランダムな順番で1つずつ選んでいく。選んだ数字がカードにあれば、その数字のマス目を開ける。空いたマス目が縦横斜めのいずれかに5つ並べばビンゴとなり終了する。抽選の経過がわかるように表示を工夫しよう。

```julia
function isbingo(bingocard)
   return any(vcat(vec(sum(bingocard, dims=1)), sum(bingocard, dims=2),
        sum(diag(bingocard)), sum(diag(bingocard[5:-1:1, :]))) .== 0)
end

bingocard = prepare()
抽選番号 = shuffle(1:75)
for (i, 番号) in enumerate(抽選番号)
    println("$(i)個目: $番号")
    where = bingocard .== 番号
    if sum(where) == 1
        println("あった!")
        bingocard[where] .= 0
        if isbingo(bingocard)
            println("BINGO")
            Base.print_matrix(stdout, bingocard)
            println()
            break
        end
    end
    Base.print_matrix(stdout, bingocard)
    println()
end
```

    1個目: 42
     12  24  43  48  62
      1  22  39  58  63
      7  23   0  53  74
      8  21  38  60  64
      4  17  34  46  75
    2個目: 19
     12  24  43  48  62
      1  22  39  58  63
      7  23   0  53  74
      8  21  38  60  64
      4  17  34  46  75
    3個目: 31
     12  24  43  48  62
      1  22  39  58  63
      7  23   0  53  74
      8  21  38  60  64
      4  17  34  46  75
    4個目: 43
    あった!
     12  24   0  48  62
      1  22  39  58  63
      7  23   0  53  74
      8  21  38  60  64
      4  17  34  46  75
    5個目: 54
     12  24   0  48  62
      1  22  39  58  63
      7  23   0  53  74
      8  21  38  60  64
      4  17  34  46  75
    6個目: 14
     12  24   0  48  62
      1  22  39  58  63
      7  23   0  53  74
      8  21  38  60  64
      4  17  34  46  75
    7個目: 68
     12  24   0  48  62
      1  22  39  58  63
      7  23   0  53  74
      8  21  38  60  64
      4  17  34  46  75
      :
      途中省略
      :
    51個目: 72
     0   0   0   0  62
     0  22  39   0   0
     0  23   0   0   0
     8   0   0   0   0
     0   0  34  46   0
    52個目: 23
    あった!
    BINGO
     0   0   0   0  62
     0  22  39   0   0
     0   0   0   0   0
     8   0   0   0   0
     0   0  34  46   0

## No. 99 自由制作 ☆×？
自由に作品を作ろう。HandyGrpahicなどのグラフィクスライブラリを使って絵を表示するプログラムでもよい。

サイコロを振って出た目の平均値を求める

$n$ 個のサイコロを $m$ 回振り，結果を $m \times n$ 行列に記録する。<br>
行方向の平均値は `mean(行列, dims=2)` で求められる。但し，結果は $m \times 1$ 行列なので，必要ならベクトルに変換する。 <br>
これを，1 行の関数で書く。

```julia
means(n, m=10000) = mean(rand(1:6, m, n), dims=2);
```

```julia
using Plots, Distributions, Statistics
function f(n, m=10000)
    x = means(n, m)
    p = histogram(x, normalize=:pdf, ylabel="pdf", xlabel="mean of $n dice", label="")
    println("mean = $(mean(x)), sd = $(std(x, corrected=false))")
    savefig("fig$n.png")
    plot!(range(1, 6, step=0.01), pdf.(Normal(mean(x), std(x)), range(1, 6, step=0.01)))
    plot!(p)
end;
```

1 個のダイス[^1]の場合は一様分布だが，要するに度数分布に過ぎない。<br>
平均値と標準偏差の理論値は 3.5 と std(1:6, corrected=false) = 1.707825127659933

「^1」: dice は複数形なので，「1 個のダイス」というのはおかしな言い方だそうだ。

```julia
f(1)
```

    mean = 3.4844, sd = 1.7101335152554602

![スクリーンショット 2023-08-27 22.15.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611739/cd6c5851-160a-ced5-caca-d701981b486f.png)


2 個では，三角分布。

```julia
f(2)
```

    mean = 3.50925, sd = 1.2042173547578527

![スクリーンショット 2023-08-27 22.15.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611739/3a00c422-1a46-548a-3799-90bb0cb87eac.png)

3 個だと，だんだん山型になる。

```julia
f(3)
```

    mean = 3.5073, sd = 0.9775093287420723

 ![スクリーンショット 2023-08-27 22.16.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611739/01c0718e-9bc0-9853-9b6b-e90f6bf045b2.png)



```julia
f(10)
```

    mean = 3.4940599999999997, sd = 0.5316302440606628

![スクリーンショット 2023-08-27 22.16.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611739/1d3c9899-7259-ecc4-8f88-e73b1dd71336.png)