見出し画像

大学入試センター試験「情報関係基礎」問3をPythonで書く

 高等学校「情報」の新教育指導要領でのプログラミング導入と,その先にあるかもしれない(まだ決定ではない)大学入試共通テストへの「情報」導入へ向けて,大学入試センター試験の「情報関係基礎」のプログラミング問題を実際にコーディングする。
 前回は2020年度の宝探しゲームをCindyScriptで書くことをやってみた。

 宝探しゲームでは,ボタンを含むボードの設定や表示のためのコードが必要だが,CindyScriptならそれが比較的簡単にできる,という話であった。すると,全部で140行くらいになった。そのうち,試験問題として出題されているコードの部分を,生徒が書くことになる。出題形式に合わせれば,実際に書くのは15ヶ所程度,前後のコードを書いても40行程度だ。

 では,盤面の設定などいらないものではどうか。2009年度の素数の問題をやってみる。リスト処理と繰り返し処理でできる。テスト問題のコード量とほぼ同じで,問題では17行,実際にコーディングしても20数行である。

 問題は次のようなものだ。
まず,2から100までの数について,素数の判別表を作る。
初めはすべて0

画像1

(b) 0の値に対応する番号のうち,最も小さい番号を n とする。
 n の倍数の番号に対応する値の欄を,すべて n に書き換える。
(C) 値の欄に0がなくなるまで(b)の手順を繰り返して,判別表を完成させる。

画像2

この判別表を用いて,任意の数を素因数分解する。

プログラムは次のように区分して出題されている。
(1) 判別表の初期化
(2) 判別表の作成
(3) 判別表を用いて素数だけを印刷(表示)する。
(4) 任意の数(ここでは100)を素因数分解する。

(4) は,そのアルゴリズムも含めて,次のように出題されている。

42ページの図2の手続きを実行した結果,配列Yakusuの それぞれの要素 には,添 字の約数のうちで (ス) が入っている。よって, この配列 Yakusu を利用すれば,素因数分解することができる。図4は,100を 素因数分解する 手続きである。

画像3

整数を素因数分解するには,商が1になるまで,次々と素数の約数で割っていけばよい。とはいえ,問題文の(ス)とコードは,判別表の意味と構造がしっかり理解されていないとできない。

とはいえ,全体としては対した分量ではなく,やさしい方に入るだろう。

 ところが,実際に教材を作成するつもりでコーディングしてみると,このときにはわからなかった様々な問題が出てきた。簡単だと思ったが以外に手間取ったのだ。以下にそれを見ていく。

(1) 判別表の初期化

 整数列のリストは

 Yakusu=list(range(101))

で簡単にできる。ただし,range() の使い方がわかっていれば,の話である。文科省の研修用教材ではリストの作り方は書かれていないし,range() は for の繰り返しで使われているが,「高等学校情報のプログラミング教育を考える(3)」に書いた通り,文科省のテキストの range() の使い方ではちゃんとした理解はできない。

(2) 判別表の作成

 問題のコードにある通り,繰り返しを使って作っていく。i を 2 から始めて,Yakusu[i] が 0 のとき,iの倍数のところに i を書き入れていく。

for i in range(2,101):
   if Yakusu[i]==0:
       j=i
       while j<=100:
           Yakusu[j]=i
           j=j+i

これも問題ない。

(3) 判別表を用いて素数だけを印刷(表示)する

for i in range(2,101):
   if Yakusu[i] == i:
       print(i)

これもひとまずは問題ないだろう。

(4) 任意の数(ここでは100)を素因数分解する

 素因数分解した結果をどう表示するか。問題のコードには,このことは書かれていない。問題文は前掲したが,単に「表示する」である。しかし,できれば,

28=7×2×2

のように表示したい。そのために,Yakusu[k] をその都度印刷(表示)するのではなく,この素因数をリスト prime にすることにした。「印刷する」を「リストに追加する」に変えるのだ。

リストに追加するのは,CindyScript なら

 prime=append(prime,Yakusu_k);

でよい。
Python ではどうするか。「高等学校情報のプログラミング教育を考える」を書いた時点では知らなかったので(入門書にもない),Webで調べた。Python の場合は

prime.append(Yakusu[k])

とすればよい。
ところが,問題のコードでうまくいかないところがあった。

 k ← ソ

である。正解は k/Yakusu[k]。 ← は代入を表すので k = k / Yakusu[k] となる。しかし,

while k>1:
   prime.append(Yakusu[k])
   k = k / Yakusu[k]

ではエラーが出てしまう。

画像4

エラーが出たときの対処法の一つは,どんな値になっているか表示してみることだ。
print(k) で,kの値を表示すると, 4.0 と表示された。
これで,エラーメッセージの意味もわかった。リストの要素番号は整数かスライスでなければならないのに,k が浮動小数点数 (float) になっている。
そこで,Webで,「Python 商 整数」で検索してみると,// にすれば 商を整数で得られることがわかった。

k = k // Yakusu[k]

として解決した。

 次に,表示。得られたリスト prime を使って,28=7×2×2 と表示したい。CindyScript では,print() は改行せず,println() で改行する。Python はどうか。再び Web で,「Python print 改行」で検索すると,次のことがわかった。
 Python の print() では行末に 改行コードを自動的に挿入する。オプション end を使うと,この行末のコードを変えることができる。
 そこで,

   if n != len(prime)-1:
       print(prime[n],end="*")
   else:
       print(prime[n])

として完成である。

問題点を整理する

 筆者は,CindyScriptを常に用いていて(授業でも),CindyScriptについてはほとんど頭にはいっている。それは,英文のマニュアルを翻訳する作業をしたからだ。細かいことは忘れても,どんなことがマニュアルに書かれているかはわかっているからすぐに探しだせる。
 一方,Pythonは初心者である。文科省の研修用教材を読み,入門書も読んで,基本的なことは学んだ。これについては,覚え書きとして「高等学校情報のプログラミング教育を考える(1)」「高等学校情報のプログラミング教育を考える(2)」「高等学校情報のプログラミング教育を考える(3)」「高等学校情報のプログラミング教育を考える(4)」に書いた。
 しかし,それでも,前述の通り,わからないことが出てきた。ピックアップして整理しよう。

(1) リスト処理は必須だがどこまでできればよいか

 整数列のリストを Yakusu=list(range(101)) で作る,ということは range() についてちゃんと理解していて,リストと関連付けていないとできない。
 では,リスト処理について,どの程度の知識が必要だろうか。
授業で扱っている内容を書きあげてみる。

・リストの要素は 0 から数える ・・・ CindyScriptは 1 から。当然学ぶ。
・リスト要素は後ろからでもカウントできる。末尾は -1 ・・・ いちおう学ぶだろう
・リストの要素の個数は len(list) で得られる ・・・ いちおう学ぶだろう
・リストに要素を追加するには list.append() を用いる
  ・・・ 授業では必須事項として使っているが,Python については今回調べた。

 問題は,どれだけ知っているか,というより,使ったことがあるか,かもしれない。他の言語(筆者の場合,CindyScript)で使っていれば,検索して解決することもできるが,そうでなければ,そもそも「リストに追加する」という発想すら浮かばないかもしれない。

(2) 演算

 / で割算ができる。ところが,整数どうしのわり算で割りきれる場合でも,商は浮動小数点数になる。番号に使うためには商を整数で得る必要があり,// を使う。
 このことは四則演算のところで学ぶだろうか。私が読んだ入門書にはなかったと思う。

追記:
 入門書といえるかどうかはわからないが,「Pythonで学ぶ統計学の教科書」(馬場真哉:翔泳社2018年4月19日初版)には,第3章 Pythonによるプログラムの基本 の初め,四則演算に,「小数点以下を明示的に切り捨てる場合」として,// を紹介している。型についての説明は次のページにある。
 なお,本書は,Python3 と Jupyter Notebook を使う前提。
                              2020.11.15

(3) print() の仕様

 Pythonでは,末尾に改行コード(¥n)を付加する。
print() はプログラミングの最初に使うコマンドだが,このことを説明していることはまずない。

(4) エラーにどう対処するか

 どんな値になっているかを表示してみる。
これは,プログラミングをしている人にとっては常識だろう。しかし,入門時点で教えられるかどうか。バグの見つけ方を書いた入門書を見たことがない。
 実際,授業をしていても,うまくいかないという質問があって行ってみると,エラーメッセージも意味がわからず,バグの原因がわかっていないことがほとんどだ。たいていはタイプミスなのだが,「(タイピングは)合っているねえ」というときにどう対処するかは生徒はまったく知らない。これを知らないと指導はできない。文科省の研修くらいでできるようになるとは思えない,非常に大きな問題だ。

(5) float の意味がわかったか : 型の問題

 Python では,変数の型宣言をしなくてもよい。ということは,「型を意識しなくてもとりあえず済む」ということになる。
 しかし,型のことを知らなければ,先ほどのエラーに対して,値が 4.0 と表示されたときに対処できただろうか。
 型を知っているから,「浮動小数点数になっている → 整数にするにはどうするか」となって検索して解決した。しかし,知らなければ「4.0 で値は合っているのに」で止まってしまうだろう。

 以上,CindyScriptにはある程度精通しており,Python の初心者だからわかったことだ。プログラミング言語そのものがまったく初めてで Python の初心者だったら,こんな簡単な(?)プログラムでさえも立ち往生してしまうかもしれない。
また,Python に精通していたら,初心者がどこでつまづくかもわからず,「読んでもわからない」テキストを作ってしまいそうだ。(このことは,CindyScriptでのテキストづくりで常に考えていることである。

 こうしてやってみると,文科省の研修用教材程度の研修で,プログラミングが指導できるようになるのかおおいに疑問である。