【プログラム】宝くじナンバーズ分析もどき MATLABコード

宝くじの完全ランダム性を信じて

宝くじを分析して一等が簡単に当たるとは思っていませんが、MATLABを導入してみて、プログラムの練習がてら何か作ってみたくなったため題材に宝くじを選択してみます。

この記事では、ナンバーズ4を題材に、数字選びの一つの観点を示すまでのプログラムの内容を説明していきます。
(筆者の備忘録の意味合いが大きいですが)

このプログラムは宝くじが作為的な物は一切無く、完全なランダム性が確保されているということを仮定した内容になっています。

僕自身は暇つぶしで記事にしているだけなので、当選金額が少なくなってもいいやというノリで、下の方に予想した番号を載せています。

ただ、このページを参考にしたけど当たらない、みたいなクレームは勘弁して下さい…。

ナンバーズ4を選択した理由

皆さんはナンバーズという宝くじをご存知でしょうか?
ナンバーズには、
・ナンバーズ3
・ナンバーズ4
があります。

それぞれ、一桁の数字を三つ、四つ選び、その選んだ数が当たるかどうかのくじになります。

ロト6とかミニロトとかの規模の小さいものですね。

ですが、ロト6の数の組み合わせは6,096,454通り、ミニロトでも169,911通りと言われており、こんな天文学的な組み合わせの中からではとても当たる気がしません!

その点、ナンバーズ4は0000~9999の一万通り
上記ロトに比べれば比較的「当たるんじゃないか」と思わせる組み合わせ数です。

配当金もストレート(数の並び順まで全て当てること)だと100万円ほどで、結構うれしい額です。

組み合わせ数の少なさと配当金のバランスが良いことがナンバーズ4を選んだ理由の一つになります。

ナンバーズ3は当たりやすいために配当金が10万円くらいと少し物足りない感じ。

そして、さらにナンバーズ4はこの制度ができてから今までで4986回(2018年8月15日現在)実施されています。
そう、もう全組み合わせ数の半分ほどの試行回数があるのです。

これだけの試行回数があれば、今までどんな確率分布で出ているのかを分析することができます。

さらに、この宝くじが完全にランダム性を持っているのであれば、まだ出ていない数が出る確率の方が、既に出ている数が出る確率よりも高いはず。
かろうじて分析ができそうな試行回数があり、さらにその試行回数が全組み合わせ数の半分程度あるというのがナンバーズ4を選んだ二つ目の理由です。

ではその未だ出ていない数を、もっともらしい理由を付けて選んでやろう、というのが今回のプログラムの目的です。

以下にナンバーズ4を選んだ理由をまとめます。

①数の組み合わせ数がロトに比べて圧倒的に少ない。
②既に数の全組み合わせ数に対して半分程度の試行回数が回っている。

また、ナンバーズには数の順番まで予想するストレートという狙い方と、四つの数の順番は問わないボックスという狙い方(配当金が少なくなるが)がありますが、僕はストレートの金額にしか興味が無いのでストレートだけを狙います。

まずは今までの結果から数値の頻度分析をしてみる

プログラムを使って機械的に分析する場合、データが電子化されていなければ話になりません
全結果は以下のWebサイトからダウンロードして来ました。

宝くじデータダウンロード

少しデータを加工します。
ダウンロードしたデータはセル毎に一つずつの数値が入っています。
ストレートを予想するために、数値は全て繋げます。
Excelでは「&」記号を使うことで各セルの値を繋げることができます。

このデータをShift-JISのcsv形式で保存します。

続いて頻度を分析するMATLABコードを以下に示します。

まずファイル名を変数filereadに格納し、csvread関数でスプレッドシートからデータを読み取ります。

続いて先ほど各セルの数値を繋げた5列目のデータを変数yに格納します。
※MATLABは配列の指標が0からではなく、1から始まるので5となっています。他のプログラム言語では多くが0から始まるので、注意。

次に頻度分析としてヒストグラムの計算を行います。
edgesは横軸のビン調整用です。

最後にグラフを見やすいように表示設定をいじります。

このプログラムをmファイルで実行すると以下のグラフが出力されます。

この図から読み取れる情報としては、「過去のナンバーズ4の結果は0から9999まで満遍なく出ている」ということですね。
今回の仮定「宝くじは完全なランダム性を持っている」は間違っていないのかな、という結果で、まずは良しとします。
※ランダム性を統計的に分析したい時は、χ(カイ)二乗検定とかをやるみたいですが、それをやるには試行回数が足りなすぎるので、今回はやりません。

ここで、グラフを拡大して見てみると、過去6回も出ている数があったり、全く出ていない一帯があったりすることが確認できます。

今回ターゲットにするのは、上図の「全く出ていない一帯の中で一番広い所」を狙いたいと思います。
おそらくこの先数百回(一年か二年)の試行回数の中で、この一帯のどこかが当たる可能性は高いだろう…程度の考えしかありませんが。

これまで数値が全く出ていない一帯を探す

ここからが本記事でやりたいことの主題部分です。

ヒストグラムを算出したので、h.Valuesで頻度のカウント値を変数zに格納します。

次に格納したデータz配列の中で、0、すなわちまだ出ていない数をマーキングします。
⇒0だったら1、それ以外だったら0とし、配列aに格納します。

今まで出ていない数をグラフでわかりやすく視認可能にするために、先ほどマーキングした部分が位置事に何個連続しているかをカウントします。

カウントのための変数をcountとして、0が出るまでカウントアップし、0が出たらそれまでカウントした数値を配列bに上書き、カウント値を0に戻す、という作業を繰り返します。

forループの前にある変数はこの仕組みを使うために必要なデータ長操作や入れ物用のゼロ配列の準備をしています。
(もっとスマートな方法がありそうだけど、まだプログラミング初心者なのでこれしか思いつかなかった…もっと良い方法あれば教えて下さい!)

最後にグラフにして可視化します。
横軸を作成して、先ほどと同じように表示設定をいじります。

その結果、以下のグラフが出力されます。

この図からは、8000の辺りにまだ出ていない数の長い帯域がある(帯域の幅は18個)、ということがわかりますね。

コマンドウィンドウ上で平均を出してみると、今までストレートが出ていない一帯の幅は約2.6個ということがわかりました。
平均2.6の空白が全体的に散りばめられている中で、18連続の空白がある場所が8000台のところなんですね。へぇ。

グラフを拡大して見ると、この部分。

ではこの中の真ん中らへんの数を狙ってみましょうか。

ナンバーズの定期購入

せっかく予想した数値も、ある瞬間だけピンポイントで当てることは超能力者でもない限りできません。
世の中には宝くじを自動で購入してくれる定期購入システムがあるので、僕はこれを使ってみようと思います。

色々あるみたいですが、ジャパンネット銀行でできるみたいなので僕はここで先ほどの数値の中から一つ選んで定期購入を申し込みました。
(僕のブログの趣旨は、「実際にやってみる」という所に置いているため、自分でもやってみます。)

当たったらいいなぁ~程度の期待感で、放置!

こちらが定期購入の画面。

ナンバーズは平日毎日くじびきしているみたいなので、一枚200円とすると一ヵ月約2,500円くらい。
まぁこんくらいであればささやかな楽しみで済むレベルでしょうか。

まとめ

お盆休み結構暇だったこともあり、また無駄なプログラムを作ってしまった…。
これがMATLAB最初のプログラム…。
さらに宝くじの定期購入に手を出してしまった…。
もし当たったりしたらこのページでご報告しますが、何年後かは不明。

ソースコード全体