24
Help us understand the problem. What are the problem?

posted at

updated at

Organization

エンジニアならこの問題、解けるよなぁ?!

どうも。タイトルほどの威勢はありません。
ということでTwitterみてたら我らがしみけんさんがこんなツイートしてた。
mojikyo45_640-2.gif

簡単にいうと、コインを100回投げて、裏表を10*10マスに文章の横書きの順番で記録してこい。ただし捏造しても良い。というものだ。
で?って話なんだけどこの課題を出した教授は捏造されたものを簡単に見分けたのだとか。
じゃあどうやって見分けたんだ?ってのが面白そうだったから考えてみて、そしてエンジニアらしくプログラムを組んでみた。
読み進める前に、ちょっと考えてみて欲しい。

考える

注目すべきは100回試行するうちに何回連続して何回同じ面が出現しているんだってところ。
左は連続の最大値は3で、右は連続の最大値は7。
100回試行して最大値が3というのは少し変だなと思い、計算をしてみる。
4回連続して同じ面が出る確率は、ある一定地点から観測すると
1*(1/2)**3 = 1/8 = 12.5%
つまり、12.5%の確率で4回以上(継続している場合があるため以上)同じ面が続く可能性を毎回持ちながらコインを投げていることになる(ちょっと違うかもだけど)。

とはわかっていても、一見左の図の方がまばら感があってランダムに生成された感が漂っている。
実際に100回コインを投げるのは面倒なので機械に任せてプログラムを組んでみた。

実装

今回はrubyで実装。したんですけど構築が昔使ってたPHPほど簡単ではなく、あんまりよくわからなくてrailsで作った。(オーバースペックや)
1から100までのループ処理の中で、

  • 表を作る処理
    • ○と●で表記。
    • 10*n番目の処理の時改行するようにしてスタイルを整える。
  • 連続数とその回数と確率を算出する処理
    • 基本的に前回のコインの向きと同じかどうかによって処理内容を変えた。
の大きく二つに分けてコードを書いた。
main.html.erb
<%
if params[:flag] == "true"

  result_map = '' # 結果の図
  pre_rand_val = nil # 一回前のループ処理でのrandomの値
  result = {}
  for i in 1..100 do
  
    #### 図作る処理 ####
    random = rand(0..1) # ランダムで0or1を返す
    if random == 0
      result_map += '○'
    elsif random == 1
      result_map += '●'
    end
    result_map += '<br>' if i%10 == 0 # 10回で行を折り返す

    #### 連続を数える処理 ####
    if pre_rand_val == nil #1回目のループ
      count = 1
    elsif pre_rand_val == random #前と裏表が同じだったとき
      count += 1
    else #表裏同じ向きの連続が終わった時
      result[count] ? result[count] = result[count] + 1 : result.store(count, 1)
      count = 1
    end
    pre_rand_val = random #初期化

  end
  result[count] ? result[count] = result[count] + 1 : result.store(count, 1) #100回目保存処理

  sum = result.values.inject(:+) # 割合出すための分母算出
  result = result.sort
  description = ""
  result.each do |item|
    probability = item[1]/sum.to_f*100 # 割合算出
    description += "#{item[0]}回同じ向きが連続した場合が出現した回数: #{item[1]}回(約#{probability}%)<br>"
  end

end
%>

<form  action="" method="get">
 <input name="flag" type="hidden" value="true">
 <input type="submit" value="実行">
</form>

<form  action="" method="get">
 <input name="flag" type="hidden" value="false">
 <input type="submit" value="リセット">
</form>

<div style = "line-height: 15px" >
  <%= result_map.html_safe if result_map %>
</div>
<%= description.html_safe if description %>

んで実行結果はこんな感じになっている。
mojikyo45_640-2.gif

何回か試しても4回以上連続しないというパターンを出現させるのは至難。面白い。
herokuに上げているので下のリンクから試してみてください。(アクセス時間かかります)

感想

あれに似てるな。クラスメイト40人くらいいたとして、誰1人誕生日に被りがない確率がかなり低いというやつ。
10%くらいらしい。
誰かが数字は嘘をつかないが、嘘つきは数字を使うって言ってたように、数字って人間の感覚とはまた違った結果になるんやな。
おもしろい。
おしまい。

https://twitter.com/ugkajiwara
ツイッターフォローとLGTMをください!!!

追記

コメントで@scivola様よりrubyでの簡略化した書き方をご教授いただきましたので参考にしてみてください!

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
24
Help us understand the problem. What are the problem?