Sさんの祖母は,健康のために毎日の歩数をスマートフォンのアプリで記録している。このアプリには,決めた歩数を何日も続けて歩くとポイントがたまり,たまったポイントを地域の商店街での買い物に使える機能がある。祖母は,毎晩その日のポイントを確かめるのを楽しみにしている。Sさんは,ポイントのたまり方や,目標を何日続けて達成できたかを,プログラムを使って調べることにした。
祖母は,1日に歩く歩数の目標を8000歩にしている。アプリは,毎日の歩数をもとに,次の規則1・規則2によって,その日の連続達成日数と,その日にもらえるポイントを決める。
祖母によると,達成の日が続くほど1日にもらえるポイントが増えていくが,途中で未達成の日があると,また1ポイントからやり直しになるとのことである。表1は,祖母のある週の7日間の歩数と,規則1・規則2によって決めた連続達成日数とポイントである。
| 1日目 | 2日目 | 3日目 | 4日目 | 5日目 | 6日目 | 7日目 | |
|---|---|---|---|---|---|---|---|
| 歩数 | 9200 | 8100 | 6500 | 8000 | 10300 | 9100 | 8600 |
| 連続達成日数 | 1 | 2 | 0 | ア | ? | ? | ? |
| ポイント | 1 | 2 | 0 | ? | 2 | 3 | イ |
(表の一部を“?”で隠してある)
1日目と2日目はどちらも達成であり,連続達成日数はそれぞれ1と2,もらえたポイントもそれぞれ1と2である。3日目は歩数が目標に届かなかったので未達成となり,連続達成日数は0に戻って,ポイントはもらえなかった。4日目の連続達成日数はアであり,7日目にもらえるポイントはイである。
Sさんは,表1を見ているうちに,達成の日の連続達成日数を別の言い方で表せることに気づいた。それは,「達成の日の連続達成日数は,ウに等しい」というものである。ただし,1日目の前の日については,連続達成日数とポイントをどちらも0と考える。
Sさんは,規則1・規則2に従って,毎日もらえるポイントと,1日目からその日までのポイントの合計を表示するプログラムを作成した(図1)。
(01)行目の変数 mokuhyou は目標の歩数を表す。配列 Hosuu には,表1の7日間の歩数を順に格納する。Hosuu[i] は i 日目の歩数を表し,例えば Hosuu[4] の値は8000である(添字は1から始まる)。(03)行目では,関数「要素数」を用いて,記録した日数を変数 nissu に代入する。変数 renzoku はその日の連続達成日数を,変数 p はその日にもらえるポイントを,変数 goukei は1日目からその日までのポイントの合計を表す。renzoku と goukei には,(04)行目と(05)行目で最初の値として0を代入しておく。
A が [5, 2, 9] のとき,要素数(A)は3となる。(06)〜(14)行目の繰り返しで,1日目から順に,i 日目について規則1と規則2を行う。(07)行目で i 日目が達成かどうかを判定する。達成の日は,(08)行目で連続達成日数を求め,(09)行目でポイントを求める。(09)行目では,関数「最小値」を用いて,ポイントが上限の3を超えないようにしている。未達成の日は,(11)行目と(12)行目で連続達成日数とポイントを決める。どちらの日も,(13)行目でポイントの合計を更新し,(14)行目でその日の結果を表示する。なお,表示する(…)は,引数の値や文字を,区切りを入れずにつなげて1行に表示する。
図1のプログラムを実行すると,1行目に「1日目:1ポイント(合計1ポイント)」と表示され,3行目には「3日目:0ポイント(合計3ポイント)」と表示された。7行目まで表示されたポイントは,どれも表1のポイントと一致していた。
Sさんが図1の結果を祖母に見せると,次のような会話になった。
祖母:3日目は雨だったから,あまり外を歩けなかったのよ。せっかく続いていたのに,そこで途切れてしまったわ。
祖母:それはうれしいわね。新しい決まりだと,2週間で何日まで続けられたことになるのかしら。
Sさんは,新しい規則2に従って,2週間(14日間)の歩数の記録から,連続達成日数のうち最も大きい値(以下,最長記録と呼ぶ。)を求めるプログラムを作成した(図2)。図2では,ポイントの計算は省いてある。配列 Hosuu には,祖母の今月の14日間の歩数を格納する。(07)行目・(08)行目・(10)行目は,それぞれ図1の(07)行目・(08)行目・(11)行目と同じ処理である。(09)行目では,未達成の日について,連続達成日数を0にする日かどうかを判定する。未達成の日のうち(09)行目の条件が成り立たない日には何も行わないので,renzoku の値は前の日のまま変わらない。変数 saichou は最長記録を表し,(05)行目で0を代入しておき,(11)行目で表示する。saichou を更新するには,関数「最大値」を用いた1行の文「saichou = 最大値(saichou, renzoku)」を使う。この文をどこに置くかは後で考える。
(図2の⓪〜③の印は,文を入れる候補の場所である。⓪は(06)行目と(07)行目の間で,毎日の処理の最初に実行される場所である。①は(08)行目と(09)行目の間で,(07)行目の条件が成り立つ日だけ実行される場所である。②は(10)行目の後で,(09)行目の条件が成り立つ日だけ実行される場所である。③は(10)行目と(11)行目の間で,繰り返しが終わった後に1回だけ実行される場所である。)
Sさんは,saichou を更新する1行の文を,図2のサの位置に挿入した。このプログラムを実行すると「最長記録:5日」と表示され,Sさんが今月の記録を見ながら新しい規則2に従って手で数えた値と一致した。
続いてSさんは,翌月の2週間分の記録でも最長記録を調べることにした。図2の(02)行目を次のように変更し,サの位置に文を挿入したままでプログラムを実行すると,「最長記録:シ日」と表示された。