Python サンプル

Python サンプル

https://www.jitec.ipa.go.jp/1_00topic/topic_20191028.html

 問題 https://www.jitec.ipa.go.jp/1_13download/fe_python_sample.pdf


出典:基本情報技術者試験 Pythonサンプル問題

基本情報技術者試験(FE)午後試験 Python のサンプル問題

------------------------------------------------------------------------

 Pythonプログラムに関する次の記述を読んで,設問 1,2 に答えよ。

 命令列を解釈実行することによって様々な図形を描くプログラムである。

(1) 描画キャンバスの座標は,x 軸の範囲が -320~320,y 軸の範囲が -240~240

 である。描画キャンバスの座標系を,図 1 に示す。描画キャンバス上にはマーカ

 があり,マーカを移動させることによって描画する。マーカは,現在の位置座標

 と進行方向の角度を情報としてもつ。マーカの初期状態の位置座標は (0,0)

 であり,進行方向は x 軸の正方向である。

(図 1 描画キャンバスの座標系 あり)

 y軸

(-320,240)

(320,240)

(0,0)

x軸

(-320,-240)

(320,-240) 図 1 描画キャンバスの座標系

(2) 命令列は,命令を“;”で区切った文字列である。命令は,1 文字の命令コード

 と数値パラメタの対で構成される。命令には,マーカに対して移動を指示する

 命令,マーカに対して回転を指示する命令,及び命令列中のある範囲の繰返し

 を指示する命令がある。繰り返す範囲を,繰返し区間という。命令は,命令列

 の先頭から順に 実行する。命令とその説明を,表 1 に示す。

(表 1 命令とその説明 あり)

命令 命令コード 数値パラメタ

説明 F 長さ

マーカを現在の進行方向に数値パラメタで指定した長さだけ進 め,移動元から移動先までの線分を描く。数値パラメタは,1 以 上の整数値である。

T 角度

マーカの進行方向を,現在の進行方向から数値パラメタが正の場 合は反時計回りに,負の場合は時計回りに,数値パラメタの絶対 値の角度だけ回転する。数値パラメタが 0 の場合は回転しない。 数値パラメタは,単位を度数法とする任意の整数値である。

R 繰返し回数

繰返し区間の開始を示す。この命令と対となる命令コード E の命 令との間を,数値パラメタで指定した回数だけ繰り返す。繰返し 区間は,入れ子にすることができる。数値パラメタは 1 以上の整 数値である。

E 0 繰返し区間の終了を示す。数値パラメタは,参照しない。

 (3) 命令列 R3;R4;F100;T90;E0;F100;E0(以下,命令列αという)の繰返し区間を,

図 2 に示す。マーカが初期状態にあるときに,命令列αを実行した場合の描画結果 を,図 3 に示す。

なお,図 3 中の描画キャンバスの枠,目盛りとその値,1,2 及び矢印は,説

明のために加えたものである。

(図 2 命令列αの繰返し区間 あり)

命令0 命令1 命令2 命令3 命令4 命令5 命令6

R 3

; R 4 ; F 1 0 0 ; T 9 0 ; E 0 ; F 1 0 0 ; E 0

繰返し区間

繰返し区間

200

100

0

  • 1001 2
  • 200
  • 300
  • 200 -200 -100 0 100 200 300

(図 3 命令列αを実行した場合の描画結果 あり)

------------------------------------------------------------------------

設問 1

 次の記述中の【 】に入れる正しい答えを,解答群の中から選べ。ここで,a1

と a2 に入れる答えは,a に関する解答群の中から組合せとして正しいものを選ぶ

ものとする。

(1) 命令列 α の実行が終了した時点でのマーカの位置は,図 3 中の【 a1 】が

 指す位置にあり,進行方向は【 a2 】である。

(2) マーカが初期状態にあるときに,図 4 に示す 1 辺の長さが 100 の正五角形

 を描くことができる命令列は,【 b 】である。ここで,図 4 中の描 画キャンバス

の枠,目盛りとその値は,説明のために加えたものである。

(図 4 1 辺の長さが 100 の正五角形 あり)

200

100

0

  • 100-200
  • 300
  • 200 -200 -100 0 100 200 300

------------------------------------------------------------------------

 a に関する解答群

 ===========================

    a1     a2

 ===========================

 ア  (1)  x 軸の正方向

 ---------------------------

 イ  (1)  y 軸の正方向

 ---------------------------

 ウ  (2)  x 軸の正方向

 ---------------------------

 エ  (2)  y 軸の正方向

 ===========================

 b に関する解答群

 ア R5;F100;T-108;E0

 イ R5;F100;T-75;E0

 ウ R5;F100;T-72;E0

 エ R5;F100;T-60;E0

 オ R5;F100;T60;E0

 カ R5;F100;T72;E0

 キ R5;F100;T75;E0

 ク R5;F100;T108;E0

------------------------------------------------------------------------

プログラムの説明〕

(1) 関数 parse は,引数として与えられた命令列を,タプルを要素とするリスト

変換する。ここで,命令列は,少なくとも一つの命令をもち,誤りはないものとす

る。1 タプルは,1 命令に相当し,命令コード及び数値パラメタから構成される。

関数 parse が定義された状態での,対話モードによる実行例を,実行結果 1 に示す。

実行結果 1

>>> parse('R4;F100;T90;E0') [('R',4),('F',100),('T',90),('E',0)]

(2) クラス Marker は,マーカの現在の位置座標を属性 x,y に,進行方向を x 軸正方

向から反時計回りに測った角度で属性 angle に保持する。オブジェクトの生成時に,

描画キャンバスの表示範囲を設定し,属性 x,y を 0,0 に,属性 angle を 0 に設定

する。クラス Marker に,マーカの操作をする次のメソッドを定義する。

forward(val)

 マーカの位置座標を,現在の進行方向に val で指定された長さだけ進め,線分

を描く。

引数: val 長さ

turn(val)

 マーカの進行方向を,反時計回りに val で指定された角度だけ回転させる。

 引数: val 度数法で表した角度

(3) 関数 draw は,引数として与えられた命令列の各命令を解釈実行し,描画結果を

表示する。ここで,命令列は,少なくとも一つの命令をもち,誤りはないものとす

る。関数 draw の概要を,次に示す。

1 命令列を,関数 parse を利用してタプルを要素とするリストに変換する。

2 マーカの操作は,クラス Marker を利用する。

3 繰返し区間の入れ子を扱うために,スタックを用いる。

4 スタックリストで表現され,各要素は繰返しの開始位置 opno と残り回数

rest をもつ辞書である。

5 プログラムの位置βにある print 関数を使って,スタックの状態変化を出力す

る。

 2 重の繰返し区間をもつ命令列について,関数 draw が定義された状態での,対

話モードによる実行例を,実行結果 2 に示す。

実行結果 2

>>> draw('R2;R3;E0;E0')

[]

[{'opno': 0,'rest': 2}]

[{'opno': 0,'rest': 2},{'opno': 1,'rest': 3}]

[{'opno': 0,'rest': 2},{'opno': 1,'rest': 2}]

[{'opno': 0,'rest': 2},{'opno': 1,'rest': 1}]

[{'opno': 0,'rest': 2}]

[{'opno': 0,'rest': 1}]

[{'opno': 0,'rest': 1},{'opno': 1,'rest': 3}]

[{'opno': 0,'rest': 1},{'opno': 1,'rest': 2}]

[{'opno': 0,'rest': 1},{'opno': 1,'rest': 1}]

[{'opno': 0,'rest': 1}]


プログラム

import math # 数学関数標準ライブラリ 
import matplotlib.pyplot as plt # グラフ描画の外部ライブラリ 

def parse(s): 
    return [(x[0],【 c 】) for x in s.split(';')] 

class Marker: 
    def __init__(self): 
        self.x,self.y,self.angle = 0,0,0 
        plt.xlim(-320,320) # x 軸の表示範囲を設定 
        plt.ylim(-240,240) # y 軸の表示範囲を設定 

    def forward(self,val): 
        # 度数法で表した角度を,ラジアンで表した角度に変換 
        rad = math.radians(self.angle) 
        dx = val * d1 
        dy = val * d2 
        x1,y1,x2,y2 = e ,self.x + dx,self.y + dy 
        # (x1,y1)と(x2,y2)を結ぶ線分を描画 
        plt.plot([x1,x2],[y1,y2],color='black',linewidth=2) 
        self.x,self.y = x2,y2 

    def turn(self,val): 
        self.angle = (self.angle + val) % 360 

    def show(self): 
        plt.show() # 描画結果を表示 

    def draw(s): 
        insts = parse(s) 
        marker = Marker() 
        stack = [] 
        opno = 0 
        while opno < len(insts): 
            print(stack) 
            codeval = insts[opno] 
            if code == 'F': 
                marker.forward( ) 
            elif code == 'T': 
                marker.turn( f) 
            elif code == 'R':
                stack.append({'opno': opno,'rest': ( )}) 
            elif code == 'E': 
                if stack[-1]['rest'] ( ): 
                    stack[-1]['rest'] -= 1 
                else:
                    ( )
            opno += 1 
        marker.show() 


(以下,整理中)

設問2 プログラム中の に入れる正しい答えを,解答群の中から選べ。

ここで,d1 と d2 に入れる答えは,d に関する解答群の中から組合せとして正

しいものを選ぶものとする。d に関する解答群の中で使用される標準ライブラ

リの仕様は,次のとおりである。

math.sin(x)

指定された角度の正弦(sin)を返す。

引数: x ラジアンで表した角度

戻り値:引数の正弦(sin)

math.cos(x)

指定された角度の余弦(cos)を返す。

引数: x ラジアンで表した角度

戻り値:引数の余弦(cos)

β

f

f

f

g

h

i

c に関する解答群

ア int(x[1]) イ int(x[1:]) ウ int(x[:1])

エ int(x[2]) オ int(x[2:]) カ int(x[:2])

d に関する解答群

d1 d2

ア math.cos(rad) -math.sin(rad)

イ math.cos(rad) math.sin(rad)

ウ math.sin(rad) -math.cos(rad)

エ math.sin(rad) math.cos(rad)

e に関する解答群

ア 0,0 イ dx,dy

ウ self.x,self.y エ self.x - dx,self.y - dy

f に関する解答群

ア 0 イ code

ウ len(insts) エ val

g に関する解答群

ア < 0 イ < 1 ウ == 0

エ > 0 オ > 1

h,i に関する解答群

ア opno = stack[-1]['opno']

stack.clear() # stack をクリア

stack.pop() # stack の末尾の要素を削除

stack.pop(0) # stack の先頭の要素を削除

stack[-1]['opno'] = opno


基本情報技術者試験(FE)午後試験 Python のサンプル問題 解答例

設問番号 正解

設問 1 a ウ

b カ

設問 2 c イ

d イ

e ウ

f エ

g オ

h ア

i ウ

出題趣旨

命令列の解釈実行を行うインタプリタを作成することは,プログラミング技法の習得の点でも,プログラムの動作原理を理解する点でも,意義深い取組である。 本問は,簡易な描画処理の命令列を解釈実行することを主題としている。 本問では,繰返しの入れ子構造をもつ命令列の解釈実行について問うことによって,スタックを用いて実装する能力を評価する。また,マーカの移動及び回転を指示する命令の実行について問うことによって,プログラム言語 Python の外部ライブラリや,三角 関数などの数値計算を行う標準ライブラリを活用する能力を評価する。