サザエさんのじゃんけん同じ手5連続の確率の理論値と実測値をRubyで検証してみた

# TL;DR
ランダムに出す手を決めているなら，30年間で少なくとも1度は同じ手が5回連続で出る確率は，
理論値で `99.999999%`, 実測値で `99.999%`．
にもかかわらずサザエさんは30年間同じ手を5回連続で出したことがなかった．
サザエさんはランダムでじゃんけんしてない．中に人がいる．


# そもそも
Twitterで知ったのですが，↓ のように，"サザエさん"，"じゃんけん" とかでぐぐると，じゃんけんの同じ手が5連続で出た，30年の歴史で初，のような記事がHitします．
https://nlab.itmedia.co.jp/nl/articles/2006/08/news108.html

30年で初，というと超スーパーレアな気がしてしまいますが，実際，どれくらいレアなのか『計算(理論)』+『試行(実測)』してみます．
(手元でぱぱっと使えるToolがRubyだったのでRubyで書きました)


# 前提
じゃんけんでどの手を出すか，は完全にランダム (`rand(3)`同等のランダム性)


# 計算(理論)

### 5回連続で同じ手が出る確率

まず，5回連続でじゃんけんの同じ手がでる確率は，
任意の1手目 (1) x 同じ手4回 (1/3の4乗)
となるので，

```ruby
SERIES_COUNT = 5 # 連続5回

rate_5 = 1.0 * (1.0 / 3.0) ** (SERIES_COUNT - 1)

=> 0.012345679012345677
```
だいたい `1.2%`というところ．

### 30年間で1度でも5回連続で同じ手が出る確率

1週に1回じゃんけん，30年の歴史で初，とのことなので，今までのじゃんけんの回数は，
`1 [janken/week] * 30 [year] * 52 [week/year] = 1560 [janken]`
となります．

1560回じゃんけんして，1度でも5連続同じ手が出る確率は，
`1 - (1560回の中で1度も5回連続で同じ手が出ない確率)`
と考えることができます．

また，1560回のうち，最後の4回はそこから5連続になることはないので，
1560回の中で5回連続同じ手に挑戦できる回数は
`1560 - (5 - 1) = 1556`
となります．

たとえば全10回だと，↓ の `10 - (5 - 1) = 6` 回挑戦するイメージ．
●●●●●○○○○○
○●●●●●○○○○
○○●●●●●○○○
○○○●●●●●○○
○○○○●●●●●○
○○○○○●●●●●

5回連続で同じ手が出ない確率は，
`1 - (5回連続で同じ手が出る確率)`
なので，
`1 - 0.012345679012345677`
となります，

1560回の中で，1度も5回連続で同じ手が出ない確率は，↑ の確率が1556回連続することになるので，
`(1 - 0.012345679012345677) ^1556 = 0.00000000403024`
となります．

1560回のじゃんけんの中で1度でも5回連続で同じ手が出る確率は，
`1 - 0.00000000403024 = 0.99999999596976`

イレブンナインまではいかないですが，エイトナイン，もうほぼほぼ100%です．
30年毎週じゃんけんをしていれば，すくなくとも1度は5回連続で同じ手が出ていることになります．


```ruby:Rubyに計算させたやつ
YEARS = 30
WEEKS_PER_YEAR = 52
SERIES_COUNT = 5

trial_probability = 1.0 * (1.0 / 3.0) ** (SERIES_COUNT - 1)
trial_n = YEARS * WEEKS_PER_YEAR
total_no_hit_probability = (1.0 - trial_probability) ** (trial_n - SERIES_COUNT + 1)
total_hit_probability = 1 - total_no_hit_probability

total_hit_probability
=> 0.9999999959697649
```


# 試行(実測)
力技で，実際に1560回じゃんけんをして，同じ手が5連続で出ていないか，を確認する，
を100万回試行してどのくらい5連続で同じ手がでるか，実測します．

```ruby:Rubyに試行させたやつ
YEARS = 30
WEEKS_PER_YEAR = 52
SERIES_COUNT = 5

# 渡された配列の中で同じ値が5回連続しているかどうかを確認する関数
def check_serial_same_5(values)
  hit_count = 0

  (values.size - SERIES_COUNT + 1).times { |i|
      if values[i] == values[i + 1] &&
          values[i] == values[i + 2] &&
          values[i] == values[i + 3] &&
          values[i] == values[i + 4]
        hit_count += 1
      end
  }

  return hit_count
end

N = 1000000 # 100万回試行

total_hit = 0 # 100万回のうち，5回連続で同じ手があった回数

N.times {
  # 30年ぶんのじゃんけん
  values = []
  (YEARS * WEEKS_PER_YEAR).times {
    values << rand(3) # じゃんけんの手をrand(3)で代替
  }

  hit = check_serial_same_5(values)

  if hit != 0
    total_hit += 1
  end
}

real_trial_probability = total_hit.to_f / N.to_f

real_trial_probability
=> 0.999998 # 100万回試行の1回目
=> 1.0      # 100万回試行の2回目
=> 0.999996 # 100万回試行の3回目
```

100万回試行だと原理的にエイトナインとかにはならないんですが，
こちらもほぼほぼ100%という数字です．
30年毎週じゃんけんをしていれば少なくとも1度は5回連続で同じ手が出ていることになります．

## 追記 (10億回試行してみた)
30年毎週じゃんけんして，少なくとも1度，5回連続で同じ手が出る確率，を
10億回試行して確認してみました．
結果は，
`0.999998264`
で100万回試行とほぼ同じ確率(ファイブナイン)になりました．


# まとめ
約30年，毎週じゃんけんをしてきたサザエさん，
今まで1度たりとも5回連続で同じ手を出したことがなかった，という事実は，
サザエさんは完全ランダムで出す手を決めているのではなく，
そこには人の意志が介在しているのでは? ということを示唆しています．

完全ランダムで30年毎週じゃんけんをしてきたなら，99.999%以上の確率で1度は5回連続で同じ手が出ているはずです．
理論に反するということは，人の意思が介在しているのであろう，ということ．


# あとがき
整数 n, N, が n < N のとき，
N回じゃんけんをして，同じ手が n 回連続する確率
の計算が ↑ に書いた方法で正しいのかどうか，ちょっとあやしいです．

N = 10
n = 5
のとき，5回連続で同じ手がでるかどうか，の抽選回数が6回，というあたり．

理論値がエイトナインで，実測値がファイブナインという数字はほぼ100%という意味では同じですが，
精度としては桁が違うので，理論値の計算が間違っている可能性があります．

↑ で計算した確率よりも下がる( = もっと同じ手が連続で出にくくなる)条件が他にもある，ってことなんですかね．．．



---///