やりたい放題

好き勝手やってます。関西弁で書きます。

Pythonで足し算馬券の発生確率を解いてみた①

よう、俺だ。
関西弁で書くっていいながら、全然書いてない。まぁいいか。
今回は「足し算馬券の発生確率を探る」という競馬ブログ用のネタをPythonで解いてみたからその紹介だ。 だいたい、こんな風に書いて解いたぜ!っていう紹介でしかないので、もっと良い方法なりあると思うし、そのあたりを指摘していただければ嬉しいが、まぁ初心者の方は、「へー」なんて思いながら見てくれればよいかと思う。
結構思いつくままに書いたので、むちゃくちゃしている自覚はあるがw

その結論部分は以下ブログに書いてあるので、興味がある人は見てほしい。

keiba-talk.com

今回やること

jupyterを使って、組み合わせの問題と発生確率を解く。 jupyterに関しては前回の記事を参照してほしい。

demrum.hatenablog.com

今回は競馬のお題だが、そんな専門的な話はない。中学~高校1年の数学をPythonで解いてみようというだけの話だ。

もうちょっと詳しくやること

競馬には5頭しか走らないレースから、18頭まで走るレースがある。
その走る馬はにはそれぞれ番号が振られているわけだ。
その番号が馬券に使われる番号だね。

その中で、馬券の組み合わせが足し算になっているもの。
例えば、1番と4番と5番が3着までに入ったら、1+4=5というように足し算になっている。
このような組み合わせ決着が多いので、これを狙うと儲かる。というようなオカルト馬券術があるわけだ。

今回はその真偽を確かめる。

さらに詳しくやること

  1. 各出走頭数のレースの馬番の組み合わせを全部求める

  2. 各出走頭数のレースの足し算になる馬番の組み合わせを全部求める

  3. 「1.」と「2.」より足し算の発生する理論値(確率)を求める

  4. 実際の過去の成績から、各出走頭数のレース数を求める

  5. 実際の過去の成績から、各出走頭数の足し算馬券の発生数を求める

  6. 「4.」と「5.」より足し算の発生した実績値を求める

  7. 「3.」と「6.」の比較を行う

以上だ。 ではやってみよう。

1.全組み合わせを数える

f:id:DemRum:20180130200143j:plain

上の画像の内容はこれ

import matplotlib.pyplot as plt #オマケ用グラフ作るのに使います

#リストの初期化(0~17までの箱に0を入れて初期化してます) 
uma_no = [0]*18

#馬番で1~18頭立てのレースで組み合わせ数を計算
for i in range(1,19) :     #馬番1~18までのループ。 iには1~18が入ります
    if(i>=5) :                #5頭以上のレースのとき、全組み合わせを計算
        uma_no[i-1]=((i*(i-1)*(i-2))//6)

#確認用出力
uma_no

コメント通りなので特に説明ないけれども、range(1,19)で1~18ってのはわかりにくいかも。
そういうものだと理解するしかないんだけど、1~19の前(18)までということ。

これが書ければ、for文とif文がわかるので、もう怖いものはない。
競馬では5頭未満では競争成立しないので、最低数は5にしている。
5未満のところは気にしないので、とりあえず0を突っ込んでいっている。

全馬券の組み合わせは、X頭から3頭を抜き出す順列の計算になるので、xC3の順列になる。
つまり、X×(X-1)×(X-2) / (3×2×1)である。
このX(出走頭数)を5~18と変化させながら、それぞれについて求めている。

2. 足し算になる馬番の組み合わせを全部求める

f:id:DemRum:20180130200226j:plain

count=[0]*18      #18頭立てのレースまで、0で初期化

# 各出走頭数 5頭立て~18頭立てまで
for i in range(5,19): 
    
    #馬番1から出走頭数-2まで
    for a in range(1,i-1) :  
        
        #馬番aの次の馬番から出走頭数-1まで
        for b in range(a+1, i) : 
            c = a+b
            if(c<=i) : 
                count[i-1] += 1

#確認用出力
count

ここはわかりにくいかも。 最初の

for i in range(5,19) : 

の文で5~18頭立てのレースを順に計算していくとしてる。
iには5~18が入る。これは出走頭数

次の

for a in range(1,i-1) :  

では、aに1番~出走頭数(i)の一個前までの馬番を入れてる。
例えば10頭立てレース(i=10)のときは、aは1番から9番までの馬番が入るループになる。

そして、さらに次の

for b in range(a+1, i) : 

では、bにaの次の馬番から、出走頭数までの数字が入っている。
例えば10頭立て(i=10)で、一頭目の馬番が3(a=3)のときは、4番から10番までの馬番をループする。

最後の

c = a+b
if(c<=i) : 
    count[i-1] += 1

は、別にcに入れなくてもいいんだけど、3頭の馬番、という意味でa,b,cとなるように入れてる。
頭目aと2頭目bの馬番の合計が、3頭目cの馬番となるときを作っている。
当然、出走頭数(i)以上にはならないので、a+b=cのcが出走頭数以下の場合だけをカウントしている。

3. 「1.」と「2.」より足し算の発生確率を求める

f:id:DemRum:20180130200300j:plain

per = [0]*18

# 各出走頭数 最大18頭分
for i in range( 18 ) :
    if(uma_no[i]!=0) : per[i] = (count[i] / uma_no[i] * 100)

#確認用出力        
per

これは簡単。割って、100をかけるだけ。

おまけでグラフ化してみましょう。 一番最初の

import matplotlib.pyplot as plt 

が必要です。

x=[]
y=[]

for i in range(5,19):
    x.append(i)
    y.append(per[i-1])

plt.plot(x,y)
plt.show()

f:id:DemRum:20180129222824j:plain

出走頭数が増えるとだんだん足し算馬券の割合が減っていくのが分かる。

半分まとめ

まずは今回はここまで。
書くのに疲れたわけじゃないぞ。
一気にやっても初心者にはしんどいだろうからね。
まずは基本的な構文の意味なんかを考えながら、書いたり消したりしてもらえれば、と思う。
何より、jupyterに慣れてくれれば良いのだけども。

次回は後半戦。
多分、関西弁で書く。