誕生日の組を求めるプログラム (c++/c言語)

  • このエントリーをはてなブックマークに追加

スポンサーリンク

※サイト運営にサーバーは必須です※
ロリポップ! はコスパのよい初心者向けサーバーです~

目次

はじめに

※追記:完成したアプリの紹介→同じ誕生日のペアがどのくらいいるかシミュレーション

ひと昔前、同じ誕生日の組がいくついるか数えるプログラムの方針という記事で誕生日のペアを求めるプログラムの方針を書いた。

……で、その記事では方針だけ書いたのがプログラム自体は書いていなかったので、なんとなく片手落ちな気がして、落ち着かなかった。

祝日を使って、なんとかプログラムが組めたので、この記事では、そのプログラムの具体的に紹介する。

紹介するのは、以下の6つのプログラム

  • ある人数の集団の誕生日の組を求める [1ループ]
  • ある人数の集団の誕生日の組(期待値)を求める [2ループ]
  • 2人~特定の人数までの誕生日の組(期待値)を求める [3ループ]

うるう年を考慮したバージョンとそうでないバーションの2通りがある。
結果として3×2の6種類。

プログラムではfor文を最大1+3回使っている。
全てに共通するbに加えて、i、k、pを使用している

[1ループ]はi
[2ループ]はiとk
[3ループ]はiとkとpを使用している

使用している言語はC++。コンパイルする時は、g++を使えば問題ない。
(全てを確かめてはいないが、C言語としてgccを使ってコンパイルしても通ると思う)

※この記事を書いている人間は、大学時代にプログラムを少しかじった程度しか勉強していない

ある人数の集団の誕生日の組を求める [1ループ](うるう年なし)

 

最も単純に、うるう年を抜いて考えたプログラム。

p_maxで人数を指定する。
day[b_max]で365個の配列を用意する。

その後、0~364の乱数を発生させる。
例えば、5が出たら、day[b_max]の内、上から5番目に+1する。

プログラムの結果は0~364日目で表示される。
1~365ではないが、両者とも365日分あるので、やっていることは本質的に同じ。

配列の中身が2以上の場合、同じ誕生日のペアがあるとカウントする

結果は「simulation.dat」に出力される。

例えば、p_max=100(人数が100人の時)の結果は以下のようになった

結果は、

0日目の人は2人いる
1日目の人は0人いる
2日目の人は1人いる
~(省略)~
360日目の人は1人いる
361日目の人は0人いる
362日目の人は0人いる
363日目の人は0人いる
364日目の人は0人いる
同じ誕生日の組は12組

乱数を生み出すときに、時間を参照しているので、実行するタイミングで結果は変わる。

三回ほどプログラムを走らせてみた結果

10組
15組
16組

このように一回しか試行していないので当然ながら結果がバラつく。

その問題を解決するには、このプログラムを何度も走らせて期待値をとる必要がある。

ある人数の集団の誕生日の組(期待値)を求める [2ループ](うるう年なし)

 

実質的に、一番最初に紹介したプログラムを何度も走らせて平均をとるプログラム。

例えば、p_max=100(人数が100人の時)で試行回数を1000回にした時の結果を示す

結果

1番目で同じ誕生日の組は9組
2番目で同じ誕生日の組は14組
3番目で同じ誕生日の組は13組
~(省略)~
998番目で同じ誕生日の組は13組
999番目で同じ誕生日の組は12組
1000番目で同じ誕生日の組は9組
試行回数(k_max)は1000
100人いる時のpair_expは11.414000

100人いる時の同じ誕生日のペアの期待値(pair_exp)は11.414000組だとわかる。

2人~特定の人数までの誕生日の組(期待値)を求める [3ループ](うるう年なし)

 

 

上までの例は、100人と固定して、その時の誕生日のペアを求めてきた。
最後はこの100人の部分を動かしたい。

人数とそれに対応する誕生日のペア(期待値)が求められる。

以下、試行回数10000で3000人まで調べた時の結果。

#人数 同じ誕生日のペアの期待値(pair_exp)
2 0.002500
3 0.008800
4 0.017100
~(省略)~
2998 364.102600
2999 364.095500
3000 364.095700

ちなみに、ここまでforによるループがあると計算にかなり時間がかかる。
(この結果を出すのに2~3分は少なくともかかっている)

ここの部分の結果を詳しく知りたい場合は、人数VS誕生日が同じペア(組):うるう年なしバージョンをみてください

ある人数の集団の誕生日の組を求める [1ループ](うるう年あり)

 

うるう年がないバージョンとの主な変更点は、
用意する配列をint b_max=365から365×4+1に変更し、
乱数もこれに合わせて増やし、0から365×4までの乱数を出す。

※追記:よくよく考えたら、発生させる乱数を0~365でなく、0~365.25で振って、365~365.25をうるう年に対応させると、用意する配列が少なく済む。

 

方針は0日目をうるう年と考えている。
それ以外の番号の時は
day[b]=day[b]+day[b+365]+day[b+730]+day[b+1095]のように考えている。

そして、
うるう年:day[0]=day[0]
それ以外:day[b]=day[b]+day[b+365]+day[b+730]+day[b+1095]
と割り当てることで、うるう年が4年に1くることに対応させる。

p_max=100000人いる時の結果を以下示す

0日目の人は63人いる
1日目の人は288人いる
2日目の人は270人いる
3日目の人は290人いる
~(省略)~
363日目の人は283人いる
364日目の人は284人いる
365日目の人は292人いる
同じ誕生日の組は366組

うるう年に相当する0日目が他の日の1/4程度になる。

ある人数の集団の誕生日の組(期待値)を求める [2ループ](うるう年あり)

 

上で紹介したプログラムの組み合わせなので、特に述べることはない。

2人~特定の人数までの誕生日の組(期待値)を求める [3ループ](うるう年あり)

 

 

上で紹介したプログラムの組み合わせなので、特に述べることはない。

ここの部分の結果を詳しく知りたい場合は、人数VS誕生日が同じペア(組):うるう年ありバージョンをみてください

関連記事

※追記:完成したアプリの紹介→同じ誕生日のペアがどのくらいいるかシミュレーション

~ギャンブルに絶対儲かる必勝法があるのだろうか?~

私(サイト主)はこの疑問に対して非常に興味を持ち、プログラミングで検証してみました。

このサイトを応援してもいいかなと思う人はぜひとも購入を検討してみてください。

ギャンブルの必勝法が本当に儲かるかプログラミングで検証してみた

     

コメント

コメントを残す

*

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)