サイコロ問題をサイコロで解く

こんなサイコロ問題がTLに流れてきました。
「AとBがサイコロを振って、より大きい目を出した方を勝ちとすると、それぞれの勝率は1/2。ではAの出目を+1した時、Aの勝つ確率は?(同じ目の時は振りなおし)」
https://twitter.com/foehue/status/1008211625747234816

ちょっと面白そうです。
ぶっちゃけ得意じゃありませんが、パズルは割と好きかもしれません。
数学的に解くのは大変なのでサイコロを振りまくって検証しましょう。

#pythonでサイコロ問題を実装
from random import randint

c = 0
v = 0

while c < 100000:
  p1 = randint(1,6)
  p2 = randint(1,6)
  if p1 == p2:
     continue
  p1 += 1
  c += 1
  if p1-p2 >0:
    v += 1
    
print("{:.1}".format(float(v)/c))
[out] 0.5

サイコロを10万回振ってみました。
なんと結果は変わらず0.5。
てっきり勝率は上がるものかとばかり…。
(お恥ずかしい話、最初答えは0.7だと思ってました…。)
問題文に巧妙な罠が仕組まれてますね。
(ただの読み違えでした。追記参照)
まあ答え教えてもらってないので、間違ってるかもしれませんが。
(間違ってましたww)

たまにはパズルも楽しいですね。

追記
回答教えていただきました。
本当は等比数列の和を用いて算出するようです。
見事に覚えていません。ていうか、5/36の5乗とか計算できない…。

上のシミュレーションはこれはこれで正しそうなのですが、
振り直し判定のタイミングで答えが違ってくるようです。
タイミング①:出目に+1する前に判定
タイミング②:出目に+1してから判定
決着つけるための振り直し判定なので、
正しいのはパターン②でしょうね…(とほほ
パターン②を実装します。

from random import randint

c = 0
v = 0

while c < 1000000:
  p1 = randint(1,6)+1
  p2 = randint(1,6)
  if p1 == p2:
     continue
  c += 1
  if p1-p2 >0:
    v += 1
    
print(float(v)/c)
[out] 0.6772022

今更になりますが、こういう手法はモンテカルロ・シミュレーションと言うようです。



この記事が気に入ったらサポートをしてみませんか?