月並みですが,問題文をしっかりと読むって大事です ─EMIU情報模試2024夏のプログラミング問題について─
沢田篤史(南山大学)
EMIU情報模試2024夏
「大学入試を中心とした情報分野の学力評価手法の検討」という科研費$${^{☆1}}$$プロジェクトの一環として,2024年夏に情報模試が行われました.その模試で「従来の一般的な問題による学力評価」を目的として出題された従来型の問題が,その正解と配点,出題意図とともにプロジェクトのWebサイト$${^{☆2}}$$で公開されています.
公開されている従来型問題は4題で,うち2題(P001,P002)が「アルゴリズムとプログラミング」に関する問題,残り2題(M001,M002)が「モデル化とシミュレーション」に関する問題です.この記事では,4題の中からP001を取り上げ,特にプログラミング問題では,問題文を丁寧に読み,理解することが重要であることについて解説を試みます.
問題設定の説明が長いと感じるかもしれませんが
P001では,クラスで行った走り幅跳びの記録から最も長い記録(最長記録)と,次に長い記録(次点記録)を求めるプログラムが題材になっています.
この問題設定を説明した前文を見てみましょう.
「生徒の記録が配列に収められていて,大きいものから1位と2位の値を見つければよいだけなのに,説明文がやけに長いなあ」と感じられるかもしれません.でも,注意深く読んでみると説明それぞれに意味があることが分かります.
最初の段落には,処理の対象となる記録について次の3つの性質が書かれています.
cm単位の記録である
2種類以上の値が含まれる
同じ値を持つ記録もある
1の性質は,異なる単位で計測した記録が混在していないことを示しています.2の性質からは,必ず最長記録と次点記録があることが分かります.3の性質からは,最長記録や次点記録が複数含まれる場合もあることが分かります.
1と2の性質が明らかになっていないと,与えられた記録(数値)を処理するプログラムで,やりたいことが本当に可能なのかどうかが分かりません.また,3の性質をじっくり読むと,先の「1位と2位の値」というのは,誤解を招きかねない表現であることに気づきます.
2段落目にある6人の記録の例で考えてみましょう.確かにこの例にも同じ値の記録(547)が含まれています.この問題では最長記録と次点記録を見つけたいので,試しにこれらを大きい値から順に(降順に)並べ替えてみたとすると,547,547,496,485,482,381 となります.さらにこれに大きいものから順位を付けると,1位,1位,3位,4位,5位,6位となります.
実は,この考え方が「1位と2位の値」を誤解する原因になり得ます.問題文を注意深く読まないままで,上で行ったような並べ替えと順位付けを行ってみると,(少々強引ですが)次の1,2,3は,いずれも「1位と2位の値」の解釈として成り立ちそうに思えてきます.
最長記録も次点記録も同じ547となる$${^{☆3}}$$
最長記録は547で次点記録はなしとなる$${^{☆4}}$$
最長記録は547で次点記録は496となる
このように異なる解釈が生じるのを防ぐために,問題文の2段落目には,「最長記録」と「次点記録」として正しいのは3であることが例を用いて丁寧に説明されています.
基本的なプログラム構成能力を試す問題です
P001が問うているのは,配列に格納された数値の中から特定の性質を持つ値を求めるプログラムを構成する能力です.
問題では,2つの方針(方針1,2)にしたがってプログラムを構成しています.方針1は,配列の要素を一つずつ調べて最長記録を求めた(ステップ1)後に,もう一度配列の要素を一つずつ調べ,次点記録を求める(ステップ2)というものです.それに対して方針2は,配列の要素を一つずつ調べる中で,最長記録と次点記録を一緒に求めてしまおう(ステップ1)というものです.いずれの方針でも最後のステップでは,求めた最長記録と次点記録を表示しています.
方針1のステップ1で最長記録を求めるプログラムは,配列要素の中から最大値を求めるというごく基本的なものです.おそらくどの教科書にもその構成法が解説されていると思いますので,ここではあえて解説しません.
これに対して次点記録を求めるステップ2では,ステップ1で求めた最長記録との関係を考える必要がありますので,少し注意が必要です.図2を見てみましょう.
01行目の変数m2には最初に0が保存されますが,02行目から05行目でA[1]~A[N]を繰り返す間,次点記録候補となる値が保存されることになります.このとき,m1にはすでに最長記録値が保存されていることに注意してください.
繰り返しのi回目(i ≧ 2)では,m1に保存された最長記録値と,m2に保存された次点記録候補値,配列変数の要素A[i]に保存された値を比較して次点記録候補値を決めます.ここで,m1の値はA[1]~A[N]の中の最長記録値なので m1 ≧ A[i] が成り立ちます.また,m2の値は繰り返しのi - 1回目までに求めた次点記録候補値$${^{☆5}}$$なので,m1 > m2 が成り立ちます.このことを加味すると,m1,m2,A[i]の間の大小関係は次の4通りしかありません.
m1 > m2 > A[i]
m1 > m2 = A[i] (m1 > A[i] = m2)
m1 > A[i] > m2
m1 = A[i] > m2(A[i] = m1 > m2)
これら4通りの可能性のうちA[i]が次点記録候補になるのは3です.プログラムでは,m1 > A[i] かつ A[i] > m2 の条件が成り立つことを判断し,成立したら新たな次点記録候補値(m2)にA[i]を保存すればよいことになります.03~05行目のように条件分岐文を構成すると,03行目,04行目の2つの条件が両方成立する場合に05行目が実行されます.したがって,m1 > A[i] と A[i] > m2 をそれぞれの条件とすればよく,【ウ】と【エ】の答えはこの2つの組合せになります.ここで,選択肢には m1 > A[i] がありませんが,落ち着いて考えてください.m1が最長記録であることから,A[i]がm1と等しくなければ,すなわち A[i] != m1 ならばA[i]が次点記録候補であることが分かります.結果として,【ウ】と【エ】の答えは,A[i] > m2 と A[i] != m1 または A[i] != m1 とA[i] > m2 になり,m2にA[i]を保存する(m2 = A[i])のが【オ】の答えになります.
では,方針2はどうでしょうか.図3を見てみましょう.
方針2では,02行目から08行目でのA[1]~A[N]の繰り返し1つの中で最長記録と次点記録を求めようとしています.つまり,繰り返しのi回目(i ≧ 2)では,i - 1回目の繰り返しまでに求めた最長記録候補値がm1に,次点記録候補値がm2に保存されていることになります.
このとき,m1 > m2 が成り立っている$${^{☆6}}$$ことを加味すると,m1,m2,A[i]の大小関係として考えられるのは次の5通りです.
m1 > m2 > A[i]
m1 > m2 = A[i] (m1 > A[i] = m2)
m1 > A[i] > m2
m1 = A[i] > m2(A[i] = m1 > m2)
A[i] > m1 > m2
この中で,A[i]が最長記録候補値となる場合が5$${^{☆7}}$$ ,次点記録候補値となる場合が3ですので,条件分岐文によってそれぞれを判断し,m1とm2にA[i]の値を保存します.
図3では,03行目で A[i] > m1 を判断していますので,こちらが5の場合に対応することが分かります$${^{☆8}}$$.このとき,A[i]の値が最長記録候補値,m1の値が次点記録候補値になりますので,m1にはA[i]を,m2にはm1を保存します.ここで注意が必要なのが保存の順番です.m1へ先にA[i]を保存してしまうと,もともとm1に保存されていた値が上書きされて消えてしまいます.それを避けるために,m2にm1を保存(【カ】の答え:m2 = m1)してからm1にA[i]を保存(【キ】の答え:m1 = A[i])する必要があります.
一方,06行目では A[i] < m1 の条件を判断していますので,こちらが3の場合に対応します.ここで,さらに A[i] > m2(【ク】の答え)であればA[i]が新しい次点記録候補なので,m2にA[i]を保存(【ケ】の答え:m2 = A[i])すればよいということになります.
以上のプログラムはごく基本的なものですが,これらを正しく構成するには,最長記録と次点記録がどういうものかを正しく理解していなければなりません.クラスの生徒に関する記録を処理するという身近な題材が取り上げられていることもあり,早合点や思い込みが正解を求める際の思わぬ落とし穴になる可能性があります.問題文が長く感じられたとしても,これまでの自分の経験から「そんなの常識でしょ」と判断して求解を急いではいけません.書かれていることを慎重に読んで,問題設定をしっかりと理解することが正答への近道となります.この問題にはそのようなメッセージも込められているのではないでしょうか.
説明が長いのは入試問題だからなのでしょうか
長くて余分に見える説明文にも意味があり,しっかりと読解するべきことを,ここまでやや針小棒大に説明してきました.入試問題の問題文には,それを読んだ受験生なら誰でも,問題設定や題意がまぎれなく理解できるよう構成されていることが求められます.したがって,プログラミングの問題でこのように慎重な説明が展開されるのは当たり前と言えば当たり前かもしれません.
では,試験問題でなければ,かくも丁寧な説明は必要ないのでしょうか.
そうではありません.プログラムは,世の中のさまざまな問題をコンピュータによって解決するために作られます.その作り手は,解くべき問題の背景や設定を正確に理解した上でプログラムを作らねばなりません.この際に,誤解を生じないようにすることは大変重要です.
特に大規模で複雑なプログラムを作る場合には,次のような作業を複数の作り手からなるチームによって行います.
解決すべき問題は何かを明らかにする
その問題をどのように解決するかを決定する
決定した解法にしたがってプログラムを作る
いずれの作業においても,自分以外の人との正確な情報伝達や意思疎通が必要です.この情報伝達や意思疎通はさまざまな文書(文章や図式など)によって行われますが,ここに誤解の余地があると意図した通りのプログラムを作ることが難しくなります.
この構図は,出題者と受験生との関係と似ています.つまり,伝える側(=出題者)の意図が文書(=試験問題)によって十分に説明され,かつ,受ける側(=受験生)によって文書が十分に理解される必要があるということです.どちらかが一方でも欠けると思わぬ誤解が生じて意図通りのプログラムができなくなる(=プログラミング問題に正解できなくなる)事態に至ります.プログラムを作る現場では試験問題以上に丁寧でまぎれのない説明が求められることもあります.
情報入試とプログラミング問題に期待
この記事では,EMIU情報模試2024夏のプログラミング問題P001についての解説をしてきました.その中で,プログラムを作るには,問題やその解法を説明した文書をしっかりと読んで理解する必要があり,自分以外の人にまぎれなく理解してもらうような文書を作る必要があることを説明してきました.これらのことは,チームで協力してプログラムを作る経験をしてみないと,なかなか実感することができません.しかし,これから情報入試が一般化すると状況が変わるかもしれません.プログラミング問題への接触時間が増えることで,文書を正しく理解し,また正しく理解できるように書くことの重要性を生徒たちが感じられるようになるのではないでしょうか.大学で「ソフトウェア工学」なる学問の研究と教育に携わる教員として,そのような実感を持った学生が多く入学してくることに期待しています.
$${^{☆1}}$$ https://www.jsps.go.jp/j-grantsinaid/index.html
$${^{☆2}}$$ https://emiu.sfc.keio.ac.jp/wp/?p=169
$${^{☆3}}$$ 降順に並べ替えた記録の1番目と2番目の値だから.
$${^{☆4}}$$ 降順に並べ替えた記録に順位を付けると1位はあって2位はないから.
$${^{☆5}}$$ i = 1のときは例外で,02行目から05行目の繰り返しは一度も行われておらず,m2には01行目の0が保存されています.A[1]~A[N]はいずれも正の数で,これらの中には2種類以上の値が含まれますので,1回目以降の繰り返しで0より大きい次点記録候補値がm2に保存されます.なお,i ≧ 2 のときに m2 = 0 である可能性もあります.その場合,A[1]~A[i - 1]がすべて最長記録(m1)と等しいはずなので,その時点での次点記録候補値はm2(= 0)であると考えてよいです.
$${^{☆6}}$$ 繰り返しの1回目(i = 1の場合)だけは例外で,m1,m2は両方とも0ですが,A[1]が正の数であることから,5通りの大小関係のうち1~4は成り立たないことが分かります.
$${^{☆7}}$$ 1回目の繰り返し(i = 1)のときは,A[1] > m1 = m2 = 0 となりますが,5の特別な場合と考えることができます.
$${^{☆8}}$$ ここでは m1 > m2 を判断していませんが,m1とm2は,i – 1回目(i ≧ 2)の繰り返しまでに求めた最長記録候補値と次点記録候補値ですので,あえて判断する必要はありません.i = 1 の場合も同じ A[1] > m1 の判断だけで最長記録候補値がm1に保存されます.
(2024年10月25日受付)
(2024年12月5日note公開)
情報処理学会ジュニア会員へのお誘い
小中高校生,高専生本科~専攻科1年,大学学部1~3年生の皆さんは,情報処理学会に無料で入会できます.会員になると有料記事の閲覧,情報処理を学べるさまざまなイベントにお得に参加できる等のメリットがあります.ぜひ,入会をご検討ください.入会はこちらから!