大学入学共通テストのプログラミングが出題されると聞いてサンプル問題をやってみた感想と解説

828

大学入学共通テストのプログラミングが出題されると聞いてサンプル問題をやってみた

2022年から高校1年生で学ぶ「情報1」からプログラミングが必修化されたことをご存知でしょうか?
それに合わせて、令和7年度から「大学入学共通テスト(旧センター試験)」にてプログラミングが出されることになります。

その試作問題が公表されていたため、実際に解いてみて、解説したい思います。
先に言っておくと、私は初見で満点でしたが、たぶんある程度プログラミングを実際にやったことがあればだれでも満点とれるレベルです。
でも逆にほとんどプログラミングをやったことがないまま、教科書で読んだ知識だけで挑むと半分ぐらいしか正解しないんじゃないかと思います。
つまり知識を問うような問題ではなく、どちらかというと経験を問われるような問題です。

情報1の試作問題全文はこちら

情報1の試験は「第1問~第4問」で区切られていますが、プログラミングが出てくる問題は「第3問」だけだったので、ここだけやります。

まず問1です。

--以下は引用--

問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 まで調べれば十分でしょう。 
--引用ここまで--

まずは【 ア 】を解きましょう。
この時点で、まったくわからなくて脱落する人も出てくるかと思うのですが、それは先ほどの関数を理解できていないからです。
上の「関数の説明と例」を、読んでわからない人は多分用語が理解できていません。
特に「引数(ひきすう)」と「戻り値(もどりち)」は一般的な用語ではないので、これが理解できてるかが重要になります。
まずは引数とは、単純にいうと()の中の数字です。
今回の場合では「枚数(46)」なので、引数は46です。
次に戻り値とは「関数を実行したら、戻ってくる値」のことで、「関数を実行した結果のこと」と思っておけば良いです。
今回の場合は引数が46なので、ピッタリになる最短の硬貨の組み合わせは10円玉が4枚、5円玉が1枚、1円玉が1枚、になります。
つまり戻り値(結果)は6です。
なので【 ア 】は6です。

次は【 イ 】です。
ここは文章さえ理解できていればプログラミングは関係なくて「51円払って、5円受けとった時の合計硬貨数」つまり「51円の硬貨数と、5円の硬貨数の合計」なのですから正解の⓪番の「枚数(51) + 枚数(5)」です。
国語の問題ですね。

次は【 ウ 】【 エ 】です。
ここはちょっと悩むかも知れませんが、シンプルに考えましょう。
結局、やりたいことは一貫して「支払う金額 + 釣銭」の硬貨数です。
先ほどの問題を思い出してみると「商品代金46(x)円、支払う金額51円、釣銭5(y)円」でしたよね?
それが「枚数(51) + 枚数(5)」になったわけです。
つまり「枚数( 支払う金額  )+枚数( 釣銭 ) 」なのです。
釣銭はyにする、と文章に書かれていますので、
これで「枚数( 支払う金額  )+枚数( y ) 」になりました。
残りの「支払う金額」ですが、これは「商品代金( x )+釣銭( y )」ですよね?
なので「枚数( x + y  )+枚数( y ) 」になります。
このことから【 ウ 】【 エ 】は②と①になります。


問2

--以下は引用--

 問2 次の文章の空欄【 オ 】 ~ 【 コ 】に入れるのに最も適当なものを,後の解 答群のうちから一つずつ選べ。 

S:まずは,関数「枚数(金額)」のプログラムを作るために,与えられた金額 ちょうどになる最小の硬貨枚数を計算するプログラムを考えてみます。も う少しヒントが欲しいなぁ。 
T:金額に対して,高額の硬貨から使うように考えて枚数と残金を計算してい くとよいでしょう。また,金額に対して,ある額の硬貨が何枚まで使えて, 残金がいくらになるかを計算するには,整数値の商を求める演算『÷』と その余りを求める演算『%』が使えるでしょう。例えば,46 円に対して 10 円玉が何枚まで使えるかは 【 オ 】で,その際にいくら残るかは【 カ 】 で求めることができますね。 
S:なるほど!あとは自分でできそうです。 

Sさんは,先生(T)との会話からヒントを得て,変数 kingaku に与えられ た目標の金額(100 円以下)に対し,その金額ちょうどになる最小の硬貨枚数 を計算するプログラムを考えてみた(図1)。
ここでは例として目標の金額を 46 円としている。 配列 Kouka に硬貨の額を低い順に設定している。なお,配列の添字は 0 か ら始まるものとする。最低額の硬貨が 1 円玉なので Kouka[0]の値は 1 とな る。
 先生(T)のヒントに従い,高額の硬貨から何枚まで使えるかを計算する方針で,(4)~(6)行目のような繰返し文にした。
この繰返しで,変数 maisu に 支払いに使う硬貨の枚数の合計が計算され,変数 nokori に残りいくら支払え ばよいか,という残金が計算される。
 実行してみると が表示されたので,正しく計算できていることが分か る。
いろいろな例で試してみたが,すべて正しく計算できていることを確認で きた。 
--引用ここまで--

ここでは、問1で出てきた「枚数」という関数を実際に作っていますね。

まずは、【 オ 】です。
この【 オ 】は「46 円に対して 10 円玉が何枚まで使えるか?」と言う式が入ります。
つまり、割り算の商(あまりは捨てた整数部のみ)を求めますので、記号は「÷」です。
なので、「46 ÷ 10」が正解になります。
(この【 オ 】は重要で、この【 オ 】の数が実質、必要な硬貨数を表しています)

【 カ 】は「46を 10で割った余り」だけが必要になりますので、記号は「%」です。
なので「46 % 10」です。

この次からはコードの中を穴埋めする問題になります。
このコードはPythonっぽいのですが、DNCLと呼ばれる疑似言語というもので、実際のプログラミング言語ではありません。
日本語とプログラミング言語っぽいやつが混じりあった試験の時だけ出てくる「奇妙な何か」です。
個人的にはPythonに統一したらいいと思うのですが、全国の高校で使われているプログラミング言語がバラバラのため、仕方なく疑似言語が使われます。
(なぜ、仕方なくPythonではなく、仕方なく疑似言語なのかは謎です)

とりあえずざっくりコードを解説していきます。

まず1行目では、複数の値 [1,5,10,50,100] が「Kouka」という箱に入れられています。
(複数の値を入れるモノを配列と呼びます)
プログラミングにおいて=は「同じ」という意味ではなく、「入れる(代入)」という意味です。

この配列のそれぞれの値にアクセスするには、[0]や[1]など番号(添字)で指定します。
(この番号は0から数えます)
例えば、Kouka[0]は1の事で、Kouka[1]なら5のことです。
Kouka[2]は10、Kouka[3]は50、Kouka[4]は100のことです。
(ここが最重要です)


2行目では、1つの値が46が「kingaku」変数に入れられています。
(1つの値を入れるモノを変数と呼びます)

3行目では「maisu」という変数に0が入れられ、「nokori」という変数に、kingakuが入れられています。
変数に変数を入れると、中身だけが移されます。
つまり、nokori変数には46が入っています。

4行目では「i を【 キ 】ながら繰り返す:」と書かれています。
(ここらへんから実際のプログラミング言語と全然違う、疑似言語の書き方になります)
この「 i 」も変数の一種で、数字を繰り返し増やしていったり、減らしていったりできます。
今回はこの i をどう使うか?が問題になっています。
プログラミングに慣れていたらすぐわかる問題ではあるのですが、この繰り返しで使う i は「配列の番号として使う」事が非常に多いです。
つまりKouka[i]というように使います。
こうすることで「配列の中身を順番に取り出す」ということが出来るようになります。
例えば「i を0から4まで1ずつ増やす」とした場合で考えてみましょう。
まず、最初に i の中には0が入ります。
すると「Kouka[i]」は、「Kouka[0]」となり、つまりは「1」と同じ意味です。

2回目の繰り返しでは i は1増えて、1になります。
すると「Kouka[i]」は、「Kouka[1]」となり、つまりは「5」と同じ意味です。

3回目の繰り返しでは i は1増えて、2になります。
すると「Kouka[i]」は、「Kouka[2]」となり、つまりは「10」と同じ意味です。

というように、繰り返しと変数iを組み合わせることで、配列のそれぞれの要素を取り出すことが出来るというわけです。
今回の問題では「高額の硬貨から何枚まで使えるかを計算する方針」と書かれているので、取り出す順番は逆になります。
つまり「4から0まで1ずつ減らし」になります。

次は5行目です。
まず「maisu = 」と書かれているので、maisu変数に何かを入れようとしていることがわかります。
(=は入れるでしたね)
入れるものは「【 ク 】+【 ケ 】」になっています。
これだけだと手掛かりがないように思いますが、ポイントは「このmaisu変数がどういう変数か?」です。
このmaisuがどこで使われているかと言うと、最終行の「表示する(maisu)」の部分です。
最終的に硬貨の枚数を求めているので、最後に表示している変数maisuは、合計の硬貨数を入れる変数だというのがわかります。
変数の値を変えるには2つの方法があり「maisu = 10」のように入れたい値を直接入れる方法と、
「maisu = maisu + 10」のように「現在の変数から、増やしたり、減らしたり、演算した数を入れる」という方法です。
1行の中で変数名(maisu)が2か所に出てくるので、プログラミングに慣れていないと違和感があるかも知れませんが、この書き方は必ずと言っていいほど出てきます。
今回のコードは「繰り返しの中で、徐々に硬貨数を増やしていく」というコードなので「【 ク 】+【 ケ 】」の【 ク 】はmaisuで確定します。
つまり今のところ「maisu = maisu +【 ケ 】」です。

次に【 ケ 】ですが、ここには「maisuをいくつ増やすのか?」が入るはずです。
ここで【 オ 】の問題の答え「46 ÷ 10」を思い出しましょう。
実質、この計算の結果分が増える硬貨数でしたね。
式としては「46」は残りの支払い金額、10は硬貨(Kouka配列)なので「残りの支払い金額 ÷ Kouka[i]」になります。
「残りの支払う金額」は、問題文の中で変数「nokori」のことと記載がありますので【 ケ 】は「nokori ÷ Kouka[i]」で確定します。
最終的5行目は「maisu = maisu + nokori ÷ Kouka[i]」なります。
このように複数の演算子がある場合は、プログラミングでも数学のように「掛け算割り算が先、足し算引き算は後」という優先順位で計算されます。
ただし「= は一番最後」です。
=の右側がすべて計算された後、その結果が=の左側に入る、という事です。

次に6行目です。
「nokori = 」と書かれていますので、nokori変数に何か入れていますね。
5行目でnokori変数は「残りの支払う金額」を入れる変数というのが確定しているので、「残りの支払う金額をどう計算するか?」です。
これも【 カ 】の所でやった通り、【 オ 】の計算(46 ÷ 10)の、余りだけを求めるバージョンです。
つまり「46 % 10」みたいな形です。
「46」の部分は「残りの支払う金額」なのでnokori変数自身です。
つまり「nokori = nokori 」まで確定します。
解答群を見てみると、%とnokoriが使われているのは「nokori % Kouka[i] 」だけです。
最後の【 コ 】は1で確定します。

以上で問2が終了です。

一応解説を書くと言った手前上、細かく解説を書きましたが、実際にはこの問題は直感だけで解ける問題です。
ある程度プログラミングに慣れていれば「たぶん変数名的に、こう使っているだろう」みたいにある程度最初に仮説を立て、各穴抜け部分にコードを当てはめてから、その後におかしいとこはないか確認する、いう思考プロセスで解けます。


問3

--以下は引用--

 問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では、問2で作った「枚数」関数を使って、最終的な「支払う硬貨数 + 釣銭の硬貨数」が最小になる支払い方法を求めています。

問題のコードを見ていきましょう。
1行目ではkakaku変数に46が入れられています。
2行目ではmin_maisu変数に100が入れられています。
3行目では「【 サ 】を【 シ 】から99まで繰り返す:」と書いています。
このコードだけでは手がかりはありませんが、文章の中に「釣り銭無しの場合も 含め,99 円までのすべての釣り銭~」と書かれていますので、【 サ 】は釣銭(tsuri)、で【 シ 】は「0」の事がわかります。

4行目ではshiharai変数にkakaku+tsuriが入れられています。
(つまりこれは現時点で「shiharai = 46 + 0」と同じ意味です)
kakak+tsuriということは「支払い金額」がこのsiharai変数だとわかりますね。
繰り返す度にtsuri変数が増えていきますので、tsuri変数が増えれば増えるほど、このshiharai変数も増えていくわけです。

5行目には 「maisu = 【 ス 】 + 【 セ 】」と書かれていますが、ここだけ見ると手掛かりがありません。
他の行のも、問題文でも変数maisuが出てきていないので、実はここは一番論理的な回答が難しい部分です。
ただ、今までの話からどこかで必ず「枚数」関数が使われるはずです。
さらに「枚数」関数は「支払い金額の硬貨数」と「釣銭の硬貨数」を同時に数えるわけではありません。
つまり「支払い金額の硬貨数」を数えるために1回と、「釣銭の硬貨数」を数えるために1回、合計2回「枚数」関数を実行しないといけません。
そして、それぞれ数えた数を足し合わせる必要があります。
他の行を見る限り「枚数」関数を使っているところはありませんし、足し算しているのもこの5行目だけです。
以上のことからこのmaisu変数には「支払い金額の硬貨数 + 釣銭の硬貨数」が入るのは確定します。
4行目の段階で「支払い金額」はshiharai変数とわかっており、問題文の中で「釣銭」はtsuri変数と記載がありますので、
つまり「maisu = 【 ス 】 + 【 セ 】」は「maisu = 枚数(shiharai) + 枚数(tsuri)」だというのが確定します。
再度同じことを言いますが、繰り返せば繰り返すほど、tsuri変数が増えていくので、同時にshiharai変数も増え、maisu変数もその都度変わっていきます。
例えば、1回目の繰り返しならtsuri変数は0なので「maisu = 枚数(46) + 枚数(0)」になり、「枚数」関数での計算の結果「maisu = 6 + 0」になり、maisu変数には6が入ります。
2回目の繰り返しならtsuri変数は1なので「maisu = 枚数(47) + 枚数(1)」になり、「枚数」関数での計算の結果「maisu = 7 + 1」になり、maisu変数には8が入ります。
つまり鍵になっているのはtsuri変数です。こいつが変化することで、他の数字にも影響をあたえています。
以上のことから、このmaisu変数は常に「最新のtsuri変数での硬貨数」が入っていると言えます。

6行目では、min_maisu変数と【 ソ 】が比較されています。
問題文に「最小値の計算では,これまでの払い方での最小枚数を変数 min_maisu に記憶しておき,それより少ない枚数の払い方が出るたびに更新している。」とありますので、これまでの最小枚数がmin_maisuであることがわかります。
「これまでの最小枚数」というのは、つまりは「過去のベスト記録」です。
これと比較する相手は「最新のtsuri変数での硬貨数」であることがわかります。
つまり【 ソ 】はmaisuになります。

7行目は、6行目の「もしmaisu < min_maisuならば:」の条件が満たされた時だけ実行されます。
つまり「最新のtsuri変数での硬貨数」が「過去のベスト記録」より少なかった、ベスト記録を更新した時だけ実行されます。
当然「ベスト記録」が更新されますよね?
なので【 タ 】はmin_maisuになります。

以上です。


実は、この試作問題が出る数年前、別のサンプル問題も公開されてたのですが、そっちはもう少しだけ難しかったように思います。
(選挙の比例代表制の時に使うドント方式というアルゴリズムを使うので、そのアルゴリズム自体が難しいだけかも知れない)
一応リンクはこちら


やはりプログラミングを文章で解説すると、どうしてもわかりにくいので、実際に自分でプログラミングを組んで見ることが一番の近道だと思います。
逆に言うと、プログラミングをある程度出来る人は満点が容易だと思いますので、ぜひ実際にプログラミング学んでください。
キノコードでも無料公開している、Pythonの基礎入門①②をやってもらうだけでもここは満点とれます。
無料でアカウント作れますのでぜひ!

キノコードE
(↑リンクを開いた後、左側のサインインから、アカウントが作れます)
※Python 3 エンジニア認定基礎試験が絶対受かる!コースも近日公開予定