4節 シミュレーション
[第5章 問題解決とその方法] 
焼きそば店のおつり(確率的モデル)
授業 第7回
【課題】
一人一皿限定の200円,現金扱いのみの焼きそば店を開くことにした。
お客は料金を100円玉で支払うか,500円玉で支払いお釣りを100円玉で受け取るかのいずれかである。これまでの記録から,お客が100円玉で支払う確率は70%であることが分かっている。
全部で100皿を販売する計画を立てた。開店前にお釣り用の100円硬貨を何枚用意すればよいか,望ましい枚数を提案して欲しい。

【考察】
アルゴリズムの要点
・それぞれのお客が100円硬貨で支払うか500円硬貨で支払うかは,
 コンピュータで発生した 0 以上 1 未満の乱数の値により決める。
・支払いが100円硬貨のときは,100円硬貨が2枚増加する。また支払いが
 500円硬貨のときは,500円硬貨が1枚増加し,100円硬貨が3枚減少する。
・100円硬貨の最小枚数は,毎回支払いが終わった時点で,そのときの枚数と
 その前までの最小枚数とを比較し,より小さい方を以降の最小枚数とする。
変数一覧
販売総数
支払い硬貨の決定確率
100円硬貨の枚数
500円硬貨の枚数
100円硬貨の最小枚数
お客の番号(1~sosu)
:sosu
:kakuritsu
:coin100
:coin500
:min100
:kyaku
関数の説明
乱数() ・・・ 0 以上 1 未満のランダムな小数を返す。
例えば,x = 乱数() のとき x に 0.57309 など無作為な小数が代入される。
【DNCL】
sosu = 100
kakuritsu = 0.7
coin100 = 0
coin500 = 0

min100 = 300
kyaku を 1 から sosu まで 1 ずつ増やしながら繰り返す:
│   もし 乱数() < kakuritsu ならば:
│   │   coin100 = coin100 + 2
│   そうでなければ:
│   │   coin500 = coin500 + 1
│   │   coin100 = coin100 - 3
│   │   もし coin100 < min100 ならば:
│   ⎿   ⎿   min100 = coin100
⎿   表示する("客",kyaku,":100円",coin100,":500円",coin500)

表示する("100円硬貨 最小枚数:",min100)
 ⇨ IDEで動作確認 
 
coin100-1  coin100-3  coin100+2  coin100+1
coin500-1  coin500-3  coin500+2  coin500+1
coin100=min100  min100=coin100+coin500
min100=coin100  min100=coin100-coin500
×
【研究:配列を用いたDNCL】
すべてのお客について,支払い後の100円硬貨の枚数と500円硬貨の枚数を配列変数に代入していく手法でコーディングしてみよう。あるお客の支払後の各硬貨の枚数は,その前のお客の支払後の各硬貨の枚数を増減させたものになる。100円硬貨の枚数の最小値は,その最小値を与えるお客の番号を記録しておくこととする。
変数一覧
販売総数
支払い硬貨の決定確率
100円硬貨の枚数
500円硬貨の枚数
お客の番号(1~sosu)
枚数最小のお客番号
:sosu
:kakuritsu
:配列 Coin100
:配列 Coin500
:kyaku
:minkyaku
Coin100[0],Coin500[0]
:初期値(開店前の硬貨枚数)
Coin100[n],Coin500[n]
:n番目のお客の後の硬貨枚数
minkyaku:100円硬貨の
 枚数を最小にするお客の番号
sosu = 100
kakuritsu = 0.7
Coin100 の全ての値を0にする
Coin500 の全ての値を0にする

minkyaku = 0
Coin100[minkyaku] = 0     #開店前に準備した100円硬貨の枚数
kyaku を 1 から sosu まで 1 ずつ増やしながら繰り返す:
│   もし 乱数() < kakuritsu ならば:
│   │   Coin100[kyaku] = Coin100[kyaku - 1] + 2
│   │   Coin500[kyaku] = Coin500[kyaku - 1]
│   そうでなければ:
│   │   Coin100[kyaku] = Coin100[kyaku - 1] - 3
│   │   Coin500[kyaku] = Coin500[kyaku - 1] + 1
│   │   もし Coin100[kyaku] < Coin100[minkyaku] ならば:
│   ⎿   ⎿   minkyaku = kyaku
│   表示する("客",kyaku,":100円硬貨",Coin100[kyaku],
⎿              ":500円硬貨",Coin500[kyaku])
表示する("100円硬貨 最小枚数:",Coin100[minkyaku])
 
Coin100[kyaku-1]
Coin100[kyaku-1]+2
Coin100[kyaku+1]+1
Coin100[kyaku-1]-3
minkyaku=kyaku
Coin100[kyaku]
Coin500[kyaku-1]
Coin500[kyaku+1]-1
Coin500[kyaku-1]+2
Coin500[kyaku-1]+1
kyaku=minkyaku
Coin100[minkyaku]
×
[通常版]
import random sosu = 100 kakuritsu = 0.7 coin100 = 0 coin500 = 0 coin100min = 300 for kyaku in range(1,sosu+1): if random.random() < kakuritsu: coin100 = coin100 + 2 else: coin500 = coin500 + 1 coin100 = coin100 - 3 if coin100 < coin100min: coin100min = coin100 print("客",kyaku,":100円硬貨",coin100,":500円硬貨",coin500) print("100円硬貨 最小枚数:",coin100min)
[研究:グラフ表示版] ※授業で用いたmonacaでは動作しません。
import random import matplotlib.pyplot as plt sosu = 100 kakuritsu = 0.7 coin100 = 0 coin500 = 0 Kyaku = [] Coin100 = [] Coin500 = [] coin100min = 300 for kyaku in range(1,sosu+1): if random.random() < kakuritsu: coin100 = coin100 + 2 else: coin500 = coin500 + 1 coin100 = coin100 - 3 if coin100 < coin100min: coin100min = coin100 print("客",kyaku,":100円硬貨",coin100,":500円硬貨",coin500) Kyaku.append(kyaku) Coin100.append(coin100) Coin500.append(coin500) print("100円硬貨 最小枚数:",coin100min) plt.plot(Kyaku,Coin100) plt.plot(Kyaku,Coin500) plt.show()