本記事は設問2ーBの解説に続き、令和7年度大学入学共通テスト 試作問題『情報Ⅰ』を社会人向けに解説します。今回は設問3です。
この設問では、読解力に加え、アルゴリズムやプログラミングの基本的な理解が問われます。問1から問3までありますが、全てつながっているため、問1が理解できないと全てつまづいてしまうような設問です。
しかし、基本的なプログラミングの理解と、しっかり読み、問われていることが何かを理解できる力があれば難易度はそこまで高くはありません。というのも、問題文中にヒントが散りばめられているからです。簡単に言うと、問題文中で言葉で表されている処理を、プログラムで表現せよ、という設問になっています。
ここで必要となるプログラミングの知識は「変数」と「繰り返し(ループ)処理」だけ。「配列」もあるとなお良いですが、問題中に説明があります。この問題が解けなくても、ここで出てくるプログラミングの知識や考え方は身に着けておきたいものばかりです。
設問3:読解力やアルゴリズム、プログラミングの理解が問われる問題
問題文
次の問い(問1~3)に答えよ。
問1
次の生徒(S)と先生(T)の会話文を読み,空欄(ア)に当てはまる数字をマークせよ。また,空欄(イ)~(エ)に入れるのに最も適当なものを,後の解答群のうちから一つずつ選べ。ただし,空欄(ウ)・(エ)は解答の順序は問わない。
S:この前,お客さんが460円の商品を買うのに,510円を払って,釣り銭を50 円受け取っていたのを見て,授業で勉強したプログラミングで,そんな「上手な払い方」を計算するプログラムを作ってみたいと思いました。
T:いいですね。まず,「上手な払い方」とは何かを考える必要がありますね。
S:普通は手持ちの硬貨の枚数を少なくするような払い方でしょうか。
T:そうですね。ただ,ここでは,客が支払う枚数と釣り銭を受け取る枚数の合計を最小にする払い方を考えてみませんか? 客も店も十分な枚数の硬貨を持っていると仮定しましょう。また,計算を簡単にするために,100円以下の買い物とし,使う硬貨は1円玉,5円玉,10円玉,50円玉,100円玉のみで500円玉は使わない場合を考えてみましょう。例えば,46円をちょうど支払う場合,支払う枚数はどうなりますか?
S:46円を支払うには,10円玉4枚,5円玉1枚,1円玉1枚という6枚で払い方が最小の枚数になります。
T:そうですね。一方,同じ46円を支払うのに,51円を支払って釣り銭5円を受け取る払い方では,支払いに2枚,釣り銭に1枚で,合計3枚の硬貨のやり取りになります。こうすると交換する硬貨の枚数の合計が最小になりますね。
S:これが上手な払い方ですね。
T:そうです。このように,客と店が交換する硬貨の合計が最小となる枚数,すなわち「最小交換硬貨枚数」の計算を考えましょう。
S:どうやって考えればいいかなぁ。
T:ここでは,次の関数のプログラムを作り,それを使う方法を考えてみましょう。目標の金額を釣り銭無くちょうど支払うために必要な最小の硬貨枚数を求める関数です。
T:これは,例えば,枚数(46)=(ア)と計算してくれるような関数です。これを使って最小交換硬貨枚数の計算を考えてみましょう。例えば,46円支払うのに,51円払って5円の釣り銭を受け取る払い方をした場合,客と店の間で交換される硬貨枚数の合計は,この関数を使うと,どのように計算できますか?
S:(イ)で求められますね。
T:一般に,商品の価格x円に対して釣り銭y円を0,1,2,…と変化させて,それぞれの場合に必要な硬貨の枚数の合計を
枚数(ウ)+枚数(エ)
と計算し,一番小さな値を最小交換硬貨枚数とすればよいのです。
S:なるほど。それで,釣り銭yはいくらまで調べればよいでしょうか?
T:面白い数学パズルですね。まあ,詳しくは今度考えるとして,今回は 100円以下の商品なのでyは99まで調べれば十分でしょう。
こたえと解説
こたえ:(ア)6(イ)0(ウ・エ)2,1
【ア】
まずは、直前にある「これ」という指示語が何を指しているかを明確にしましょう。ここでは、一つ前のTの発言内「目標の金額を釣り銭無くちょうど支払うために必要な最小の硬貨枚数を求める関数」を指しています。つまり、ぴったり46円となる最小の硬貨の枚数が(ア)に入ります。46円をぴったり払うには、10円×4枚、5円×1枚、1円×1枚の合計6枚となるので、答えは6です。
【イ】
(ア)と同様に、まずは何を聞かれているかを明確にしましょう。ここでは、一つ前のTの発言内「51円払って5円の釣り銭を受け取る払い方をした場合,(省略)硬貨枚数の合計は,この関数を使うと,どのように計算できますか」です。そして、この発言内の「この関数」とは、「枚数(46)=6」のように、最小の硬貨の枚数を求める関数を指しています。
つまり、ここで聞かれているのは、51円を払う時に必要な硬貨の枚数と、5円をお釣りとして支払う時に必要な硬貨の枚数の合計であり、それを関数で表すように言われているのです。それを求める関数は0「枚数(51)+枚数(5)」です。
【ウ・エ】
ここでも同様に、何を聞かれているのかをまず明確にします。該当の文章は、Tの疑問に対するSの「(イ)で求められますね」という回答に続き、「~のです」で終わる発言です。つまり、Sの発言を言い換え、自身の質問の答えを示す内容が入ると予想されます。となると、ここで聞かれているのは(イ)を商品の価格xと釣銭yでどう表せるかということなのです。
(イ)は先ほど求めたように「枚数(51)+枚数(5)」です。これを分解し、xとyでどう表せるか考えてみます。まず、「枚数(51)」は商品の値段である46円と、お釣りの5円を足した時の硬貨の枚数を求めている部分です。つまり、枚数(x+y)となります。「枚数(5)」の部分は、お釣り5円の硬貨の枚数を求めている部分です。つまり、枚数(y)です。よって、ウには選択肢2「x+y」とエには選択肢1「y」が入ります。
問2
次の文章の空欄(オ)~(コ)に入れるのに最も適当なものを,後の解答群のうちから一つずつ選べ。
S:まずは,関数「枚数(金額)」のプログラムを作るために,与えられた金額ちょうどになる最小の硬貨枚数を計算するプログラムを考えてみます。もう少しヒントが欲しいなぁ。
T:金額に対して,高額の硬貨から使うように考えて枚数と残金を計算していくとよいでしょう。また,金額に対して,ある額の硬貨が何枚まで使えて,残金がいくらになるかを計算するには,整数値の商を求める演算『÷』とその余りを求める演算『%』が使えるでしょう。例えば,46円に対して10円玉が何枚まで使えるかは(オ)で,その際にいくら残るかは(カ)で求めることができますね。
S:なるほど!あとは自分でできそうです。
Sさんは,先生(T)との会話からヒントを得て,変数kingakuに与えられ た目標の金額(100 円以下)に対し,その金額ちょうどになる最小の硬貨枚数 を計算するプログラムを考えてみた(図1)。ここでは例として目標の金額を46 円としている。
配列Koukaに硬貨の額を低い順に設定している。なお,配列の添字は0から始まるものとする。最低額の硬貨が1円玉なのでKouka[0]の値は1とな る。
先生(T)のヒントに従い,高額の硬貨から何枚まで使えるかを計算する方針で,(4)~(6)行目のような繰返し文にした。この繰返しで,変数maisuに支払いに使う硬貨の枚数の合計が計算され,変数nokoriに残りいくら支払えばよいか,という残金が計算される。
実行してみると(ア)が表示されたので,正しく計算できていることが分かる。いろいろな例で試してみたが,すべて正しく計算できていることを確認できた。
こたえと解説
こたえ:(オ)2(カ)3(キ)1(ク)1(ケ)0(コ)1
【オ】
ここで聞かれているのは「46円に対して10円玉が何枚まで使えるか」です。難しく考えず、単純に「46」の中に「10」が何回使えるかを求めればよいので、答えは選択肢2「46÷10」です。
【カ】
ここで聞かれているのは「いくら残るか」、つまり余りのことです。少し前の発言に書かれている「余りを求める演算『%』」というヒントを使いましょう。そうすると、選択肢3「46%10」が答えとなります。
【キ】
ここからはプログラミングの基礎を問われる問題です。ただし、問題文に「先生(T)のヒントに従い,高額の硬貨から何枚まで使えるかを計算する方針」とあるように、問題文中にヒントがあります。
このプログラムでは、図1の(1)~(3)は、変数を定義している(変数の中身を決めている)部分で、(4)からTの発言のような処理を行なっています。
(1)配列Kouka(下で説明)に硬貨の種類を格納
(2)変数(値を入れておくもの)kingakuに46を入れる
(3)変数maisuに初期値として0、変数nokoriに変数kingakuの値を入れる
(4)繰り返す処理(ループ)の条件
ーーーここから繰り返しーーー
(5)maisuにク+ケの結果を入れる ※硬貨の枚数
(6)nokoriにコを入れる ※計算の残り
ーーーーーーーーーーーーーー
(7)繰り返し処理が終わったらmaisuの結果を出す
つまり、このプログラムでは、(4)~(6)で各硬貨ごとに何枚使えるかを計算して、その結果をmaisuに加算し最終的に必要な枚数を求めているのです。
(4)からのプログラムがTの発言内容と同じになれば良いと考えると、まず最初に「金額に対して,高額の硬貨から使うように考え」ます。ここで必要となるのが、「配列」の理解です。配列とは、複数の値を入れて保持しておくことができる箱のようなものです。プログラムの(1)で値を入れています。
そして、問題文に「配列Koukaに硬貨の額を低い順に設定している。なお,配列の添字は0から始まるものとする。最低額の硬貨が1円玉なのでKouka[0]の値は1となる」とあるように、配列の中に入れた値は「添字」と呼ばれる[ ]の中の値によって区別がつくようになっています。例えばここでは以下の通りです。
Kouka[0]=1(1円玉)
Kouka[1]=5(5円玉)
Kouka[2]=10(10円玉)
Kouka[3]=50(50円玉)
Kouka[4]=100(100円玉)
(キ)はこの添字にどのように値が入っていくかを聞かれているのです。そしてTは「高額の硬貨から使う」と言っているので、Kouka[4]からKouka[0]へと徐々に金額を下げながら計算を行ないます。つまり、答えは選択肢1です。
【ク】【ケ】
(5)は「支払いに使う硬貨の枚数の合計」を計算する処理です。Kouka[i]円玉ごと、つまり各硬貨ごとに何枚必要になるか計算し、その枚数をmaisuに入れていきます。
具体的には、最初の処理は「46÷100」でmaisuは0、次に「46÷50」でmaisuは0、「46÷10」でmaisuは4、「6(計算の残り)÷5」でmaisuは5(10円玉が4枚と5円玉1枚)……というように繰り返されていくイメージです。これが成立する処理を考えると「maisu=maisu+nokori÷Kouka[i]」が答えになります。
【コ】
nokoriという変数名のとおり、次に計算しなければならない残りの金額をここで計算します。これは、既出の(カ)の考え方と同じです。割ったときの余りは「%」で求められるので、現時点の残り金額を硬貨の金額で割り算します。それを表しているのが「nokori÷Kouka[i]」です。
問3
次の文章を参考に,図2のプログラムの空欄(サ)~(タ)に入れるのに最も適当なものを,後の解答群のうちから一つずつ選べ。ただし,空欄(ス)・(セ)は解答の順序は問わない。
T:プログラム(図1)ができたようですね。それを使えば,関数「枚数(金額)」のプログラムができます。関数の引数として与えられる金額の値を プログラム(図1)の変数kingakuに設定し,(7)行目の代わりに変数maisuの値を関数の戻り値とすれば,関数「枚数(金額)」のプログラム となります。では,その関数を使って最小交換硬貨枚数を計算するプログラムを作ってみましょう。ここでも,100円以下の買い物として考えてみます。
Sさんは,図2のようなプログラムを作成した。変数kakakuに与えられる商品の価格に対して,釣り銭を表す変数tsuriを用意し,妥当なtsuriのすべての値に対して交換する硬貨の枚数を調べ,その最小値を求めるプログラム である。なお,ここでは例として商品の価格を46円としている。
このプログラムでは,先生(T)のアドバイスに従い,釣り銭無しの場合も含め,99円までのすべての釣り銭に対し,その釣り銭になるように支払う場合に交換される硬貨の枚数を求め,その最小値を最小交換硬貨枚数として計算している。
最小値の計算では,これまでの払い方での最小枚数を変数min_maisuに記憶しておき,それより少ない枚数の払い方が出るたびに更新している。min_maisu の初期値には,十分に大きな値として100を用いている。100円以下の買い物では,使う硬貨の枚数は100枚を超えないからである。
このプログラムを実行してみたところ3が表示された。46円を支払うときの 最小交換硬貨枚数は,支払いで50円玉が1枚,1円玉が1枚,釣り銭で5円玉が1枚の計3枚なので,正しく計算できていることが分かる。同様に,kakakuの値をいろいろと変えて実行してみたところ,すべて正しく計算できていることを確認できた。
こたえと解説
こたえ:(サ)3(シ)0(ス・セ)0,2(ソ)0(タ)1
【サ】【シ】
該当箇所である図2の(3)を見てみると、99という数字があります。これを問題文で探してみると「釣り銭無しの場合も含め,99円までのすべての釣り銭に対し」という記述があり、これを表している処理だと予測できます。「釣銭が無い場合から99円まで」をプログラムで表すと(3)は「tsuriを0から99まで」になります。
【ス・セ】
(4)(5)に見覚えのあると感じた方もいるのではないでしょうか。これは、問1で既に出てきている考え方です。(4)は「46円支払うのに,51円払って5円の釣り銭を受け取る払い方」、(5)は(ウ)(エ)の空欄問題「それぞれの場合に必要な硬貨の枚数の合計を枚数(x+y)+枚数(y) と計算」にあたります。
この(5)をプログラムで表現するように求められている問題なのです。ですから、xは「価格」、yは「釣銭」を意味していたので、答えは「maisu=枚数(shiharai)+枚数(tsuri)」となります。
【ソ】【タ】
まず、変数min_maisuが何かを問題文で見てみると、「これまでの払い方での最小枚数を変数min_maisuに記憶しておき,それより少ない枚数の払い方が出るたびに更新している」とあります。つまり、釣銭が0から99までの場合を計算する中で最も少ない枚数を記録するため、より少ないmaisuが出たら更新するようにしているのです。
その処理が(6)(7)にあたります。(6)で、より少ない枚数かどうかを比較し、少なかった場合に(7)で更新を行っています。それをプログラムで表現すると、(6)でmaisuとそれまでの最小枚数min_maisuを比較する「maisu<min_maisu」、そしてこの条件に当てはまる場合に(7)でmin_maisuを更新「min_maisu=maisu」となります。
まとめ
最初は難しい、とっつきづらいと感じてしまいそうな設問です。しかし、ちょっとの知識を持って、整理しながら順を追って考えていくと、案外簡単に解けてしまいます。
この記事で実際に試験を受けているわけではないので、時間制限や、調べてはいけないという縛りもありません。解説をじっくり読んで一緒に解いてみたり、用語やプログラミングの基礎を調べてみたり。これを機に、少しでも情報に触れる機会が増えたら嬉しく思います。次回、最後の設問4の解説まで、ぜひご覧ください。