Sさんが所属する気象観測部では,校庭に置いた雨量計で,毎日の降水量を記録している。ある日,地域の消防団の人から「雨の降らない日が続くと,空気や枯れ草が乾いて火事が起きやすくなる。雨の降らない日がどのくらい続いたのかを,記録から調べてもらえないか」と頼まれた。そこでSさんは,部の記録をもとに,雨の降らない日が続いた期間を調べることにした。
Sさんは,11月1日から11月18日までの18日間の記録を調べた。以下では,11月1日を1日目,11月2日を2日目,…と呼ぶ。降水量が0 mmの日を「雨の降らなかった日」とし,雨の降らなかった日がとぎれずに続いている期間を無降水期間と呼ぶ。Sさんは,各日の連続日数(その日までに雨の降らなかった日が何日続いているか)を,次の規則1・規則2で求めることにした。また,答えとする期間を規則3で決めることにした。
表1は,18日間の降水量と,規則1・規則2によって求めた連続日数である。
| 何日目 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 降水量(mm) | 0 | 0 | 0 | 8 | 0 | 2 | 0 | 0 | 21 | 0 | 0 | 0 | 0 | 6 | 0 | 0 | 0 | 0 |
| 連続日数 | 1 | 2 | 3 | 0 | 1 | 0 | 1 | 2 | 0 | 1 | ア | 3 | 4 | 0 | 1 | 2 | イ | 4 |
例えば,1日目から3日目までは雨が降らなかったので,連続日数は順に1,2,3となる。4日目は8 mmの雨が降ったので,規則2により連続日数は0となり,5日目は0に1を加えて1となる。表1で隠してある11日目の連続日数はア,17日目の連続日数はイである。
ある日の連続日数は,その日で終わる無降水期間の日数を表しているので,連続日数が最も大きい日は,最も長い無降水期間の最後の日である。表1から,最も長い無降水期間はウ日間であり,規則3により答えとなるのは,エオ日目に始まる期間である。
Sさんは,この作業をプログラムで行うために,次の方法を考えた。それまでに見た連続日数の最大値を,最初は0として覚えておく。表1を1日目から順に見ていき,その日の連続日数が,覚えている最大値カときに限り,覚えている最大値をその日の連続日数に書き換え,あわせてその日が何日目かも覚えておく。こうすれば,最後まで見終わったときに覚えている日が,規則3で答えとなる期間の最後の日になる。
Sさんは,問1の規則1〜3と,問1の最後に考えた方法に従って,最も長い無降水期間の日数と,その期間の最後の日を表示するプログラムを作成した(図1)。
(01)行目の配列 Kousui には,表1の降水量を1日目から順に格納する。配列の添字は1から始まり,添字の値が何日目の記録かを表す。例えば,Kousui[9] の値は9日目の降水量21である。(02)行目では,関数「要素数」を用いて,記録した日数を変数 nissu に代入する。
Ame が [5, 0, 0, 12, 3] のとき,要素数(Ame)は5となる。変数 renzoku は,いま調べている日の連続日数を表す。変数 saichou は,問1で覚えておくことにした連続日数の最大値を表し,変数 owari は,その最大値になった日が何日目かを表す。(03)〜(05)行目で,これらの変数に最初の値として0を代入する。
(06)〜(13)行目の繰り返しでは,i 日目について,次の二つの処理を順に行う。まず(07)〜(10)行目で,規則1・規則2によって i 日目の連続日数を求め,renzoku を書き換える。次に(11)〜(13)行目で,求めた連続日数を saichou と比べ,問1の方法で書き換えるべきときだけ,saichou と owari を書き換える。繰り返しが終わった後,(14)行目で最長の日数と最後の日を表示する。
図1のプログラムを実行すると,「最長」の後に日数が,「日目まで」の前に最後の日が表示された。表示された日数と最後の日は,問1で表1から読み取った,規則3で答えとなる無降水期間のものと一致した。また,(08)行目または(10)行目を実行した直後の renzoku の値は,毎回,表1のその日の連続日数と一致した。
Sさんは,図1の結果を顧問の先生に見せた。
kaishi に入れておけば,連続日数は kaishi と i から計算できます。雨が降った日には,その後に始まる無降水期間に備えて,kaishi を書き換えておけばよいですね。saichou を書き換えるときに,その時点の kaishi を一緒に覚えておけば,始まりの日が分かりますね。Sさんは,図1を書き換えて,最も長い無降水期間の日数と始まりの日を表示するプログラムを作成した(図2)。変数 hajime は,saichou が表す最大値になった無降水期間の始まりの日が何日目かを表す。(02)行目で kaishi に1を代入しているのは,記録の1日目から雨の降らなかった日が続く場合に,その無降水期間が1日目に始まると考えるためである。(05)行目の繰り返しの上限には,図1の nissu の代わりに関数「要素数」をそのまま用いている。(07)行目では,i 日目の降水量が0 mmのとき,kaishi 日目から i 日目までの日数を連続日数として求めている。(11)〜(13)行目では,図1と同じように saichou を書き換えるときに,hajime を kaishi の値に書き換えている。
図2の空欄スに適切なものを入れてプログラムを実行すると,表示された日数と始まりの日は,どちらも問1で表1から求めたものと一致した。
続いてSさんは,12月1日から12月15日までの15日間の記録を調べることにした。11月27日には雨が降ったが,11月28日から30日までの3日間は雨が降らなかったので,12月1日から始まる無降水期間は,実際には11月から続いていることになる。図1の(03)行目で renzoku に0を代入していたのは,記録の1日目より前には雨の降らなかった日が続いていないと考えていたからである。そこでSさんは,図1の(01)行目と(03)行目を次のように変更し,前の月から続く日数も含めて調べることにした。
変更した図1のプログラムを実行すると,(12)行目の saichou への代入は,全部でセ回行われる。