とうとう令和二年の春期から基本情報技術者試験の午後のプログラミング問題に Python が追加されます!
IPA から Python のサンプル問題が公開されていましので、実際に問題を解き、Python 問題でどのような問題が出題され、どのような対策が必要になりそうかを予想してみました。
ちなみに私は Python は超初心者です…(C言語が一番得意)。ですが、一応問題は全て解くことができました。なので Python を本職としていない人にも割とオススメできるプログラミング言語問題になっているのではないかなぁと思います。
Contents
サンプル問題
Python のサンプル問題は IPA から下記ページに公開されています。
https://www.jitec.ipa.go.jp/1_00topic/topic_20191028.html
サンプル問題の解き方解説
まずはサンプル問題を解いてみて、回答するのに Python のどのような知識が必要になりそうかを調べてみました。Python の特徴的な単語に関しては赤字で記載しています。解き方の解説は不要という方は Python 問題の傾向を予想 に飛んでいただければと思います。
問題としては「命令を解釈」し、その命令によって「図形を描画する」プログラムに関するものになっています。
スポンサーリンク
設問1
まずは設問1から解き方を見ていきましょう!解くためにはどんな知識が必要になるでしょうか?
a の解き方
設問1の a に関しては、下記の命令列を解釈し、この命令実行後のマーカの状態を問うものになっています。
R3;R4;F100;T90;E0;F100;E0
命令列の各命令コード(R, F, T, E)と数値パラメータがどのようなものであるかは表1で解説されています。
表1より各命令は下記のように解釈することができます。今後の説明がしやすいように繰返し区間を「繰返し区間①」と「繰返し区間②」と区別するように図示しています。
繰返し区間①は4回、繰返し区間②は3回実行されることになりますので、下記のように命令が実行されていくことになります。
→命令2→命令3→命令2→命令3→命令2→命令3→命令2→命令3→命令5 →命令2→命令3→命令2→命令3→命令2→命令3→命令2→命令3→命令5 →命令2→命令3→命令2→命令3→命令2→命令3→命令2→命令3→命令5
ここまで理解できれば後は各命令を実行した時にどのように図形が描画され、マーカの情報がどのように変化していくかを考えることで a1 と a2 の設問の答えを導き出すことができます。
初期状態のマーカは下の図のように座標 (0, 0) に存在し、進行方向は x 軸の正方向になります。下の図では x 軸の正方向を角度 0 度としています。
最初の「命令2」実行によりマーカが進行方向に長さ “100” 分移動し、移動元と移動先を結ぶ線が描画されます。
さらに「命令3」実行によりマーカの進行方向が “90度” 分回転します。
この状態で再度「命令2」が実行されるので、今度は上方向に線が描画されることになります。
このように繰返し区間①が1度実行された時点では下の図のように線が描画され、マーカは初期状態と同じ状態に戻ることになります。
さらに繰返し区間①終了後に「命令5」が実行されますので、マーカは “0度” 方向に長さ “100” 移動します。これで繰返し区間②が1回終了したことになります。
つまり、繰返し区間②が1度実行されることで下記のように図形の描画され、マーカの状態が変わります。
- 開始時点のマーカ位置 (0, 0) を左下の頂点とした長さ “100” の正方形が描画される
- マーカの座標が開始時点から x 軸の正方向に “100” 移動する
(つまり x 座標が +100 されて (100, 0) になる) - マーカの進行方向は “0度” のまま(x 軸の正方向)
ポイントは繰返し区間②が1度実行されるとマーカの x 座標が +100 移動するところですね。これがさらに2回目・3回目と実行されることになりますので、最終的にマーカの状態は下記のようになります。
- マーカの座標:(300, 0)
- 進行方向: 0 度
したがって a の答えはウとなります。
b の解き方
設問1の b は図4で示される正五角形を描画するための命令列を問う設問になります。
まず b の選択肢を眺めてみると、最初に実行される命令は全て「F100」であることが確認できますので、まずは初期状態から「F100」を実行した時のマーカの状態を考えてみましょう。
「F100」を実行するとマーカは下図のようになります。
ここから図4のような正五角形を描画するためには、マーカの進行方向を反時計方向に72度回転させる必要があります(72という数字は、正五角形の各角の角度108度を180度から引くことで算出できます)。
つまり、「F100」実行後には「T72」の命令を実行する必要があります。ここで再度選択肢を見てみると、「T72」の命令が含まれるのは選択肢カのみですので、ここで答えが確定し、b の答えはカとなります。
設問2
次は設問2の解き方を見ていきましょう!設問2は Python プログラムの穴埋め問題になります。
c の解き方
設問2の c は関数 parse
の穴埋め問題になります。関数 parse
に関しては [プログラムの説明] の (1) で解説されています。
要は関数 parse
では下記が実行されます。
- 入力された命令列文字列 s を “;” で命令文字列 x に分解
- 各命令文字列 x を「命令コード」と「数値パラメタ」に分解
- 分解した各命令の命令コードと数値パラメタをタプルを要素とするリストに格納して返却
これが1行のプログラムで実行されていることになります。内包表記というやつですね。
命令列文字列を命令文字列への分解には、Python の組み込み文字列関数split
が使用されています。
問題を解くポイントは命令文字列の1文字目が「命令コード」であり、2文字目以降が「数値パラメタ」である点です。
命令文字列の1文字目を取得するためには x[0] と記述すれば良いですが、2文字目 “以降” を取得するためには x[1:] と記述する必要があります。スライスと呼ばれる表記になります。
したがって c の答えはイとなります。
この c を確実に解くためには「タプル」「リスト」「内包表記」「組み込み文字列関数 split」「スライス」の知識が必要になります。Python の特徴を活かした Python らしい問題だと思います。
d と e の解き方
d と e に関しては Marker クラスのメソッド forward
に関する問題になります。メソッド forward
に関しては [プログラムの説明] の (2) で解説されています。
要は下記を行うメソッドになります。
- 現在のマーカ(移動元マーカ)の座標と進行方向に基づき、入力された長さ val 分移動させたマーカ(移動先マーカ)の座標を計算
- 移動元マーカと移動先マーカを結ぶ線を描画
- マーカの座標を移動先マーカのものに更新
d は移動先マーカの座標を計算するために必要な処理の穴埋め問題になります。これを解くためには、ちょっとした数学の知識・考え方が必要になります。
移動元マーカの座標を (x, y) 、進行方向を angle 度、長さ val 、移動先マーカの座標は (x + dx, y + dy) とすると、それぞれの値の関係は下の図のようになります。
この時、dx と dy は下記の式により求めることが可能です。
dx = val * cos (rad) dy = val * sin (rad) rad:angle をラジアンに変換した値
したがって d の答えはイとなります。
次に e について考えます。e が含まれる行のプログラムより、e には x1 と y1 に代入する値が入ることが分かります(Python では左辺を “,” で区切ることで同時に複数の変数に値を格納可能)。
さらに、その次の行のプログラムを見てみると、x1 と y1 は、線を結ぶ座標の1つであることが分かります。x2 と y2 は移動先マーカの座標ですので、x1 と y1 は移動元マーカの座標であることが分かります。
移動元マーカの座標は、移動先マーカの座標 x2 と y2 がそれぞれ下記であるため、
x2:self.x + dx y2:self.y + dy
上で説明に用いた図より、移動元マーカの座標は下記であることが分かります。
x1:self.x y1:self.y
したがって e の答えはウとなります。
f の解き方
f は関数 draw
内でメソッド forward
やメソッド turn
に入力する値(変数)になります。メソッド forward
やメソッド turn
には数値パラメタを入力する必要があります。
さらに関数 draw
の下記部分で、関数 parse
の戻り値として数値パラメタは命令コードと共に insts リストに配列されていることが分かります。
insts = parse(s)
さらに下記で insts の opno 要素のタプルがアンパックされて第一要素が code に、第二要素が val に格納されています。
code, val = insts[opno]
関数 parse
により、数値パラメタは各タプルの第二要素に格納されていますので、val に数値パラメタが格納されることになります。したがってメソッド forward
やメソッド turn
には val が入力されると考えられます。したがって f の答えはエとなります。
g と h と i の解き方
g と h と i は命令コードが “E” の時のプログラムの穴埋めになります。
繰り返し区間のループをスタックを用いて制御している部分になり、説明は [プログラムの説明] の (3) の③④⑤に記載されています。さらに「実行結果2」にはスタックの途中の状態の表示結果が示されています。
ポイントは「実行結果2」の6行目から7行目への変化だと思います。
[{'opno': 0, 'rest': 2}, {'opno': 1, 'rest': 1}] ↓ [{'opno': 0, 'rest': 2}]
スタックの末尾の要素が削除されていますね。しかし、プログラム内にはこのような要素の削除の処理はありません。したがって穴埋めのどこかにその要素の削除の処理が入ると予想できます。
g に関しては if の条件が入るため、残りの h もしくは i にこの削除処理が入ると考えられます。
ただし、もし h で要素の削除処理を行なったとすると、要素削除後に下記で新たなスタックの末尾の要素の rest 要素の値を 1 を減らすことになります(Python では配列のインデックスに負の値を指定すると末尾側から参照することが可能です。)。
stack[-1]['rest'] -= 1
しかし「実行結果2」では6行目から7行目に遷移するときに rest の値の変化はありませんね。なので h で要素の削除するのはおかしいです。
したがってスタックの末尾要素を削除する処理は i に入ることが分かります。さらに選択肢にはウに「stackの末尾の要素を削除」とコメントされているため i の答えはウであることが分かります。
また i が末尾要素の削除処理であることが分かると、g の答えも見えてきます。具体的には stack[-1][‘rest’] の値(スタックの末尾の要素の rest の値)がどのような時に末尾要素の削除処理が行われていないかを考えると g の答えが分かります。
「実行結果2」を見てみると末尾要素の rest の値が2以上の場合は末尾要素の削除処理が行われていないていないことが分かります。逆に1の場合は末尾要素の削除処理が行われています。
つまり、stack[-1]['rest'] > 1
の場合は末尾要素の削除処理が行われていないことになります(h が含まれる行のプログラムが実行される)。したがって g の答えはオです。
これは g の全選択肢を当てはめてみて「実行結果2」の動きと照らし合わせて考えてみても答えは導けると思います。
h に関しても「実行結果2」から簡単に答えが導けます。末尾要素の削除が行われない場合、変化するのはスタックの末尾要素の rest の値が1減るのみです。
したがって h にはスタックを変化させる処理は入らないと考えられます。ここで h に関する選択肢を眺めてみると、ア以外は全てスタックを変化させる処理になります(オは opno を変化させてしまう)。
これより h の答えはアとなります。opno を変化させるア以外の処理だとループ処理が実現できないことからも答えは導けると思います。
Python 問題の傾向を予想
続いて Python 問題の傾向の予想をしていきたいと思います。あくまでサンプル問題からの予想になりますが、わざわざ IPA が公開したサンプル問題ですので、今後実際に出題される問題も同様の傾向になる可能性は高いと思います。
スポンサーリンク
プログラム自体は Python の特徴を活かした問題になると予想
問題に使用されるプログラム自体は Python ならではのものが出題されるのではないかと予想します。
サンプル問題でも、組み込み関数・リスト・タプル・辞書・内包表記・クラス・スライス・アンパックなどなど、Python で特徴的なもの(C言語ユーザーからするとかなり特徴的)が多数使用されていました。
ですので、実際に出題される問題でも、特にリストやクラスなどがふんだんに使用されたプログラムのものが出題される可能性が高いと予想します。
Python 知識のみで解ける問題は少ないと予想
ただし、これらの Python の知識があるだけで解くことができる問題はほぼ出題されないと予想します。
サンプル問題だと c に関してはスライスの知識があれば解きやすいとは思いますが、それでもプログラムの仕様を理解し、周りのプログラムからしっかり論理的に考えて当てはまる選択肢を選ぶ必要があります。
重要なのは問題文からプログラム仕様をしっかり理解することと、そこから論理立ててプログラムの穴埋めを行うことだと思います。
Python の知識が無くても解ける問題も出題される可能性が高い
逆に問題文からプログラム仕様をしっかり理解し、論理立てて問題を解くことができるのであれば、Python の知識が無くても解ける問題が多数出題されるのではないかと予想しています。
実際にサンプル問題だと、特に a や b に関しては全く Python に関係のない問題になっています。
また他の問題に関しても、何か他のプログラミング言語を使用している方であれば c 以外は解けるのではないかと思います。もちろん Python ならではのコードの記述の仕方などはありますが、なんとなーく推測していけば解くことができる問題だと思います。
スポンサーリンク
数学的な知識・考え方が必要になる問題も出題される可能性が高い
このサンプル問題を解いていて特徴的に感じたのは d です。これってほぼ数学の問題なんですよね。Python の知識があっても、三角関数の知識が無いと解けない問題です。
サンプル問題でわざわざこのような問題が出題されているということは、このような数学的な知識・考え方が必要になる問題が実際の試験で出題される可能性も高いと思います。
Python 問題の対策
続いて上述の問題予想に基づいて Python 問題の対策方法について説明したいと思います。
Python の基礎知識を身につける
とりあえず必要になるのは Python の知識だと思います。プログラムが読めないことには問題が解けませんので…。
ただし高度な知識は不要だと思います。外部ライブラリなどについてはサンプル問題では下記のようにコメントで説明がされていますので、この辺りの知識も不要です(import の仕方などの知識は必要)。
# (x1,y1)と(x2,y2)を結ぶ線分を描画
plt.plot([x1, x2], [y1, y2], color='black', linewidth=2)
ちなみにプログラミング言語で出題される項目は「基本情報技術者試験シラバス」に記載されています。Python 問題の部分を抜粋したものが下記になります。
1. Python の基本的なプログラム
Python の基本的なプログラムを作成する。
[修得項目] インデントによるブロック表現,計算結果の表示,コメント など2. 演算子を用いた式の表現
四則演算や論理演算を用いた式を活用し,プログラムを実行モードや対話モードで利用する。
[修得項目] 整数,浮動小数点,式の表現,四則演算子,代入演算子,比較演算子,論理演算子,代入文 など3. 要素をもつデータ型
シーケンスなど,要素をもつデータ型を使ったプログラムを作成する。
[修得項目] in,リスト,文字列,タプル,辞書,集合,イテレータ,添字,キー,スライス,リスト内包表記 など4. 選択型のプログラム
条件式を使って条件分岐するプログラムを作成する。
[修得項目] if 文 など5. 反復型のプログラム
反復型の制御文を使ったプログラムを作成する。
[修得項目] for 文,while 文 など6. 組込み関数
型,リスト,文字の入出力,ファイル操作などに関する組込み関数の利用場面を理解し,プログラムを作成する。
[修得項目] int,float,str,list,range,enumerate,zip,len,print,input,open など7. 関数の定義
利用者の定義による関数を用いて構造化されたプログラムを作成する。
[修得項目] def 文,return 文,ジェネレータ,yield 文,ラムダ式,再帰呼出し,デコレータ など8. クラスとオブジェクト
クラスを定義し,オブジェクトを生成してプログラムを作成する。
[修得項目] クラス,オブジェクト,class 文,継承,クラス変数,メソッド,特殊メソッド __init__ など9. 変数及び関数の値の取扱い
変数間の代入,オブジェクトの変更,関数の値の受渡しに注意し,プログラムを作成する。
[修得項目] 変数のスコープ,変更可能なオブジェクト,コピー,位置引数,キーワード引数,デフォルト引数,オブジェクトとしての関数 など10. ライブラリの活用
問題解決のために適した代表的な標準ライブラリ又は外部ライブラリを利用し,プログラムを作成する。
[修得項目] import 文,モジュール,パッケージ など
引用元:基本情報技術者試験シラバス
実際にサンプル問題を解くためにもこの範囲の知識しか必要ありませんでした(むしろ無くても殆ど解けた)。例えばオライリーから出版されている「入門 Python 3」であれば、前半部分(P. 1 〜 P. 181)をしっかり理解しておけば、Python 問題を解くために必要な Python の知識は十分だと思います。
おすすめ書籍(PR)
実際にサンプル問題を解くために必要なものは下記に記載されています(第8刷の情報です)。
- タプル、リスト、辞書:P. 53 〜
- 内包表記:P. 104 〜
- split:P. 46
- スライス:P. 43 〜
- アンパック:P. 68
- オブジェクト・クラス:P. 155 〜
スポンサーリンク
他のプログラミング言語の問題やアルゴリズム問題の過去問を解く
ただし、Python の知識があるだけではおそらくほとんどの問題が解けないと思います。
前述の通り問題を解くために重要なのは「問題文からプログラム仕様をしっかり理解することと、そこから論理立ててプログラムの穴埋めを行うこと」です。
実はこれは他のプログラム問題やアルゴリズム問題も同じなんですよね。ですので、「問題文からプログラム仕様をしっかり理解し、そこから論理立ててプログラムの穴埋めを行う」を実践しながら他のプログラム問題やアルゴリズム問題の過去問を解くことで Python 問題の対策も行うことが可能です。
数学の基礎知識も念の為復習しておく
Python 問題で一番厄介なのは数学の基礎知識が必要になる可能性がある点だと思います。時間があれば、念の為、高校数学あたりは復習しておいた方が良いと思います。特に出題されそうなのは確率・統計、三角関数などですかね…。
もちろん数学が得意な人にとってはラッキー問題になる可能性も高いですので、Python を使ったことがない人でも解けそうであれば Python 問題を選択するのもアリだと思います。
まとめ
このページでは IPA から公開されている Python 問題のサンプル問題を実際に解き、問題の傾向や対策について予想してみました。あくまでサンプル問題のみからの予想ですので当たっているかは分かりませんが参考にはなると思います。
いずれにせよ、結局 Python 問題を解くために必要なのは、
Python の基礎知識 +「問題文からプログラム仕様をしっかり理解することと、そこから論理立ててプログラムの穴埋めを行うこと」
だと思います。後者に関しては他のプログラミング言語問題やアルゴリズム問題を解くことで磨くことが出来ますので、Python の基礎知識が身について人に関しては、他のプログラミング言語問題やアルゴリズム問題の過去問を解くことが有効な対策になると思います。
本ページの図・プログラム・問題文について
図やプログラム、問題文はIPA公開のサンプル問題から引用しています。また図やプログラムに関しては説明に必要な部分に関してのみ加工して使用させていただいております。
出典:基本情報技術者試験 Pythonサンプル問題