Kさんは,自宅から高校まで路線バスで通学している。バスの運賃は,乗るたびに支払う方法(以下,都度払いと呼ぶ。)のほかに,1か月の間なら何回でも乗ることのできる定期券を買って支払う方法もある。通学する日が少ない月は都度払いの方が安く,通学する日が多い月は定期券の方が安くなりそうである。部活動の大会や試験期間があるので,1か月に通学する日数は月によって違う。そこでKさんは,1か月に何日以上通学すると定期券の方が安くなるのかを,プログラムを使って調べることにした。
Kさんが乗るバス会社の都度払いでは,1回の運賃が,その月の何回目の乗車であるかによって変わる。また,定期券の1か月分の代金(以下,定期代と呼ぶ。)は5500円である。Kさんは,その月に通学した日を順に1日目,2日目,…と数えることにし,次の規則1・規則2をもとに,d 日目までに都度払いで支払う運賃の合計(以下,合計と呼ぶ。)を求めた。
表1は,1日目から10日目までの合計を,規則1・規則2によって求めたものである。
| 日数 | 1日目 | 2日目 | 3日目 | 4日目 | 5日目 | 6日目 | 7日目 | 8日目 | 9日目 | 10日目 |
|---|---|---|---|---|---|---|---|---|---|---|
| 合計 | 400 | 800 | 1200 | 1600 | 2000 | ? | アイウエ | ? | ? | 3500 |
(表の一部を“?”で隠してある)
1日目は1回目と2回目の乗車で,運賃は1回200円なので合計は400円である。5日目は9回目と10回目の乗車であり,5日目までは合計が1日に400円ずつ増えて,5日目の合計は2000円となる。6日目からは1回の運賃が変わり,7日目の合計はアイウエ円である。
Kさんは,合計が定期代より多ければ,定期券を買う方が安いと考えた。ただし,合計と定期代が等しいときは,定期券の方が安いとはいわないことにする。表1の10日目の合計と規則2から,その月に通学する日数がオのとき,定期券の方が安くなることがわかる。
Kさんは,問1の規則にしたがって,定期券の方が安くなる最小の日数を求めるプログラムを作成することにした。1か月に通学する日数は最も多くて23日なので,1日目から23日目までを順に調べればよい。
規則1から,Kさんは1日に2回乗車するので,1回目から10回目までの乗車は1日目から5日目まで,11回目から20回目までの乗車は6日目から10日目まで,21回目以降の乗車は11日目以降となる。そこでKさんは,1日に支払う運賃が同じになる日のまとまりを区分と呼び,1日目から5日目までを区分1,6日目から10日目までを区分2,11日目以降を区分3とした。
図1の(01)行目の配列 Ofuku には,区分ごとに,1日に支払う運賃(行きと帰りの2回分)を格納する。(02)行目の配列 Saigo には,区分ごとに,その区分の最後の日を格納する。区分3には終わりがないので,Saigo[3] には,1か月の日数より大きい31を格納しておく。配列の添字は1から始まり,区分の番号を表す。例えば,Ofuku[2] の値は区分2の1日分の運賃300であり,Saigo[2] の値は区分2の最後の日10である。
変数 teiki は定期代を,変数 goukei は合計を,変数 kubun は d 日目がどの区分であるかを表す。変数 saisho は定期券の方が安くなる最小の日数を表し,(06)行目で代入する0は,まだ見つかっていないことを表す。
(07)〜(12)行目の繰り返しでは,d 日目について次の処理を行う。まず(08)行目で,d 日目がいまの区分の最後の日より後かどうかを調べ,後であれば(09)行目で次の区分へ進む。次に(10)行目で,d 日目に支払う運賃を goukei に加える。最後に(11)行目で,まだ最小の日数が見つかっておらず,かつ定期券の方が安くなったかどうかを調べ,そうであれば(12)行目で saisho に記録する。
図1のプログラムを実行すると,問1で求めた日数のうち最も小さい日数が表示された。また,(10)行目を実行した後の変数 goukei の値を1日ごとに調べると,1日目から10日目までは表1の合計と一致した。
Kさんは,図1のプログラムを情報科の先生に見てもらった。
saisho も要らなくなります。ただし,日数を表す変数を繰り返しの中のどこで増やしているかに注意してください。繰り返しが終わったとき,その変数が何日目を指しているかに関わります。Kさんは,図1の(06)〜(13)行目を書き換えて,図2のプログラムを作成した。(06)行目で変数 d に1を代入する。(07)行目からの繰り返しでは,d 日目について区分を調べて,その日の運賃を goukei に加えた後,(11)行目で d の値を1増やして次の日に進む。図2の(08)〜(10)行目は,図1の(08)〜(10)行目と同じ処理である。(07)行目の条件は,繰り返しの最初と,(11)行目を実行した後に調べられる。繰り返しが終わった後,(12)行目で定期券の方が安くなる最小の日数を表示する。なお,定期券の方が安くなる日は,必ず23日目までにあるものとする。
図2のプログラムを実行すると,図1と同じ日数が表示された。
続いてKさんは,別の路線のバスで通学している兄の場合も調べることにした。兄が乗るバス会社では,1回の運賃が,その月の1回目から8回目までの乗車は220円,9回目から16回目までの乗車は170円,17回目以降の乗車は120円であり,定期代は6240円である。兄も,通学する日には行きと帰りに1回ずつ乗車する。したがって兄の路線では,区分1は1日目から4日目まで,区分2は5日目から8日目まで,区分3は9日目以降となる。そこでKさんは,図2の(01)〜(03)行目を次のように変更して,プログラムを実行した。
その結果,「定期の方が安くなる最小の日数:セソ日」と表示された。