運の采配
運はどのような結果をもたらすでしょうか。保有資産のゲームという分かりやすい形で表示してみます。
【ルール】
参加者の全員が同じ収入で同じ支出と仮定します。ひと月に、全員が同じ金額の10円を得て、同じ金額の1円を使うとしましょう。
誰かが使った1円は、その他の誰かの臨時収入になります。その他の誰かを選ぶ時にrandom
を使うことにします。
運が良ければ臨時収入をたくさん得続け、運が悪ければ臨時収入が得られません。
- 1ターンをひと月とする。
- 指定ターンの終わった時点での総合金額を競うゲーム。
- ひと月あたりの定収入は全員等しく10円とする。
- ひと月あたりの支出も全員等しく1円とする。
- 誰かの支出はその他の誰かの収入になるとする。
【予想】
参加者全員が同額の支出入だし、支出の額も少なく、臨時収入を得る確率も全員同じなのだから大して差が拡がらず、保有金額は全員平均的になるだろうと思いますが、果たして…
では、ここからは実際にプログラムを作って行きます。
参加者リスト作成関数
参加人数を指定すると、メンバーのリストを自動で作ります。
def make_member_list(num:int)->list: # 参加者リスト member_list = ["No." + str(i+1) for i in range(num)] return member_list
実行
# 参加人数の指定 n = 7 # 参加者リスト member_list = make_member_list(n) print(member_list)
['No.1', 'No.2', 'No.3', 'No.4', 'No.5', 'No.6', 'No.7']
参加人数を適当に7名としました。ラッキーセブンは誰なのか!?
各人の名前はNoで分けました。囚人番号のようです…
臨時収入を得る参加者をランダムに選ぶ
参加者リストから自分以外のメンバーをrandom.choice()
で選びます。もし自分が選ばれたらチョイスをやり直すようにif
で分けます。
選ばれた参加者のリストを返します。
import random def choose_member(member_list:list)->str: choose_list = [] for num in member_list: while True: choose_member = random.choice(member_list) if choose_member != num: choose_list.append(choose_member) break else: pass return choose_list
実行
# 参加人数 n = 7 # 参加者リスト member_list = make_member_list(n) # 臨時収入の人選 choose_list =choose_member(member_list) print(choose_list)
['No.2', 'No.6', 'No.7', 'No.1', 'No.4', 'No.3', 'No.1']
このリストに多く載るほど運の良い人です。
選ばれた参加者のリストから出現回数を数える関数
標準ライブラリのcollections
を使って選ばれた参加者のリストから各要素の出現回数をカウントし、辞書を返します。
import collections def lucky_counter(choose_list:list)->dict: lucky_count_dict = collections.Counter(choose_list) return lucky_count_dict
実行
# 参加人数 n = 7 # 参加者リスト member_list = make_member_list(n) # 臨時収入の人選 choose_list =choose_member(member_list) # 選ばれた人の出現回数をカウント count_dict = lucky_counter(choose_list) print(count_dict)
Counter({'No.4': 2, 'No.1': 2, 'No.7': 2, 'No.2': 1})
定支出入差額算出関数
全員が毎月定額で10円得て1円使うので、9円ずつ保有金額が増えることになります。
# 収入と支出の差額を計算する関数 def in_and_out(income:int,outgo:int)->int: # 収入と支出の差額 diff = income - outgo return diff
実行
income = 10 outgo = 1 diff = in_and_out(income,outgo) print(diff)
9
参加者所有額の辞書化関数
上で作ったlist型の参加者リストを引数にして辞書に自動で作成します。
所有金額の初期値はゼロ円。
def start_asetts_dict(member_list:list)->dict: # 資産額リスト asetts_dict = {name:0 for name in member_list} return asetts_dict
実行
# 参加人数 n = 7 # 参加者リスト member_list = make_member_list(n) # 資産額ディクト asetts_dict = start_asetts_dict(member_list) print(asetts_dict)
{'No.1': 0, 'No.2': 0, 'No.3': 0, 'No.4': 0, 'No.5': 0, 'No.6': 0, 'No.7': 0}
スタート時点での参加者の所有金額の辞書が出来ました。
月締め支出入計算関数
定支出入と臨時収入を計算して辞書を返します。
定支出入加算
def add_asetts(asetts_dict:dict, diff:int)->dict: for k,v in asetts_dict.items(): v = v + diff asetts_dict[k] = v new_asetts_dict = asetts_dict return new_asetts_dict
臨時収入加算関数
def lucky_add_asetts(asetts_dict:dict, lucky_count_dict:dict, outgo:int)->dict: for name, v in lucky_count_dict.items(): asetts_dict[name] = asetts_dict[name] + v*outgo last_asetts_dict = asetts_dict return last_asetts_dict
実行
# 参加人数 n = 7 # 参加者リスト member_list = make_member_list(n) # 資産額ディクト asetts_dict = start_asetts_dict(member_list) # 定収入 income = 10 # 定支出 outgo = 1 # 支出入差額 diff = in_and_out(income,outgo) # 所有金額に差額を追加 new_asetts_dict = add_asetts(asetts_dict,diff) # ラッキーメンバー choose_list = choose_member(member_list) # ラッキーカウンター lucky_dict = lucky_counter(choose_list) # 所有金額に臨時収入を加算 lucky_add_asetts(new_asetts_dict,lucky_dict,outgo)
{'No.1': 10,
'No.2': 10,
'No.3': 9,
'No.4': 10,
'No.5': 10,
'No.6': 9,
'No.7': 12}
実行用のメイン関数作成
細々した機能を別個の関数にした為に、実行する部分が矢鱈と長くなった。
一応動いたので実行部分をまとめる
def main(n:int,income:int,outgo:int,turns:int)->dict: # 参加者リスト member_list = make_member_list(n) # 初期資産額ディクト asetts_dict = start_asetts_dict(member_list) # 支出入差額 diff = in_and_out(income,outgo) for turn in range(turns): # 所有金額に差額を追加 new_asetts_dict = add_asetts(asetts_dict,diff) # ラッキーメンバー choose_list = choose_member(member_list) # ラッキーカウンター lucky_dict = lucky_counter(choose_list) # 所有金額に臨時収入を加算 last_asetts_dict = lucky_add_asetts(new_asetts_dict,lucky_dict,outgo) return last_asetts_dict
最終実行
1ターン後の保有額
# 参加人数 n = 7 # 定収入 income = 10 # 定支出 outgo = 1 # ターン回数 turns = 1 result = main(n,income,outgo,turns) print(result) print("~~~~~~~~~~~~~~~~~~~~~~~~")
{'No.1': 11, 'No.2': 10, 'No.3': 10, 'No.4': 9, 'No.5': 11, 'No.6': 10, 'No.7': 9}
~~~~~~~~~~~~~~~~~~~~~~~~
数ヵ月後の保有額
3ヶ月後のと24ヶ月後を出してみる。
金額だけのリストも出す。
# 参加人数 n = 7 # 定収入 income = 10 # 定支出 outgo = 1 #3ヶ月後の保有金額 # ターン回数 turns = 3 result_3 = main(n,income,outgo,turns) print(result_3) print(result_3.values()) print("~~~~~~~~~~~~~~~~~~~~~") # 24ヶ月後の保有金額 turns = 24 result_24 = main(n,income,outgo,turns) print(result_24) print(result_24.values()) print("~~~~~~~~~~~~~~~~~~~~~")
{'No.1': 28, 'No.2': 30, 'No.3': 30, 'No.4': 31, 'No.5': 29, 'No.6': 30, 'No.7': 32}
dict_values([28, 30, 30, 31, 29, 30, 32])
~~~~~~~~~~~~~~~~~~~~~
{'No.1': 242, 'No.2': 237, 'No.3': 249, 'No.4': 241, 'No.5': 234, 'No.6': 238, 'No.7': 239}
dict_values([242, 237, 249, 241, 234, 238, 239])
~~~~~~~~~~~~~~~~~~~~~
平均的。
というか、このプログラムは期待通りに正しく動いてるんだろうか…
参加人数のみ増やして実行
7人から20人に増やしてみる。保有金額のみ表示にする。
# 参加人数 n = 20 # 定収入 income = 10 # 定支出 outgo = 1 #3ヶ月後の保有金額 # ターン回数 turns = 3 result_3_2 = main(n,income,outgo,turns) #print(result_3_2) print(result_3_2.values()) print("~~~~~~~~~~~~~~~~~~~~~") # 24ヶ月後の保有金額 turns = 24 result_24_2 = main(n,income,outgo,turns) #print(result_24_2) print(result_24_2.values()) print("~~~~~~~~~~~~~~~~~~~~~")
dict_values([29, 31, 29, 29, 30, 32, 30, 28, 30, 34, 27, 30, 29, 30, 32, 29, 29, 29, 31, 32])
~~~~~~~~~~~~~~~~~~~~~
dict_values([234, 238, 238, 238, 233, 235, 240, 242, 241, 246, 237, 232, 243, 238, 252, 243, 237, 237, 243, 253])
~~~~~~~~~~~~~~~~~~~~~
平均的。
支出大幅アップで実行
1円から8円に変えてみる。
# 参加人数 n = 20 # 定収入 income = 10 # 定支出 outgo = 8 #3ヶ月後の保有金額 # ターン回数 turns = 3 result_3_3 = main(n,income,outgo,turns) #print(result_3_3) print(result_3_3.values()) print("~~~~~~~~~~~~~~~~~~~~~") # 24ヶ月後の保有金額 turns = 24 result_24_3 = main(n,income,outgo,turns) #print(result_24_3) print(result_24_3) print("~~~~~~~~~~~~~~~~~~~~~")
dict_values([14, 46, 22, 30, 22, 22, 54, 22, 30, 30, 30, 46, 30, 38, 14, 30, 14, 38, 30, 38])
~~~~~~~~~~~~~~~~~~~~~
{'No.1': 232, 'No.2': 224, 'No.3': 184, 'No.4': 264, 'No.5': 232, 'No.6': 280, 'No.7': 216, 'No.8': 304, 'No.9': 264, 'No.10': 264, 'No.11': 224, 'No.12': 216, 'No.13': 288, 'No.14': 216, 'No.15': 216, 'No.16': 248, 'No.17': 240, 'No.18': 256, 'No.19': 208, 'No.20': 224}
~~~~~~~~~~~~~~~~~~~~~
10年後の保有金額
120ヶ月後の保有金額を見てみる。
# 参加人数 n = 20 # 定収入 income = 10 # 定支出 outgo = 8 #3ヶ月後の保有金額 # ターン回数 turns = 3 result_3_4 = main(n,income,outgo,turns) #print(result_3_4) print(result_3_4.values()) print("~~~~~~~~~~~~~~~~~~~~~") # 120ヶ月後の保有金額 turns = 120 result_120_4 = main(n,income,outgo,turns) #print(result_120_4) print(result_120_4.values()) print("~~~~~~~~~~~~~~~~~~~~~")
dict_values([46, 22, 38, 14, 6, 22, 38, 38, 46, 30, 6, 30, 62, 22, 38, 30, 22, 30, 30, 30])
~~~~~~~~~~~~~~~~~~~~~
dict_values([1288, 1184, 1280, 936, 1112, 1192, 1344, 1176, 1216, 1232, 1176, 1120, 1160, 1312, 1216, 1128, 1352, 1288, 1112, 1176])
~~~~~~~~~~~~~~~~~~~~~
参加人数を100人にして120ヶ月後の最大値と最小値のみ取り出す
# 参加人数 n = 100 # 定収入 income = 10 # 定支出 outgo = 8 # 120ヶ月後の保有金額 turns = 120 result_120_5 = main(n,income,outgo,turns) #print(result_120_5) #print(result_120_5.values()) print("最小値",min(result_120_5.values())) print("最大値",max(result_120_5.values())) print("~~~~~~~~~~~~~~~~~~~~~")
最小値 1016
最大値 1392
~~~~~~~~~~~~~~~~~~~~~
おわりに
このプログラムは正しいのか?…