2章【1】 整数を一つ読み込み，その階乗を計算する RAM プログラムを書け。
f (n) =[解答]n! （ n ≥ 0 ）何でもよい （ n < 0 ）RAM プログラム
load #1
store 1

コメント
{ y= 1; }read 2loop: load 2
jgtz skip
jump exit
skip: load 1
mult 2store 1load 2sub #1store 2jump loop{x = n; }{if ( x>0 ) goto skip ;}{ y= y*x ;}{x=x-1;}

exit: write 1【2】 整数を一つ読み込み，素数かどうか判定する RAM プログラムを書け。
g (n) =1 （ n は素数である）
0( n は素数でない）[解答] のヒント。次の C プログラムと同等の RAM プログラムを書く。
int main(void) {int x, y, out;
out= 0;scanf ("%d", &x);
if (x == 0) goto exit;
if (x >0 ) goto skip;
x= x* (- 1) ;skip: if (x= =1) goto exit;
y =x -1 ;loop : if (y = =1) {out= 1; goto exit;}
if (x% y == 0) goto exit ;y =y -1;
goto loop ;exit: printf ("ans %d╲n", out) ;1

【3】 pred, iszero, true, 0, 1 を 2.3.2 項で定義した式 λ とする。つぎの書換え系列が存在することを示せ。
(1) iszero 0 →* true

[解答] (1)iszero 0 = (λ x .x (true (false) ) true) 0→β 0 (true (false) ) true = (λ x.λ y .y) (true (false) ) true→β (λ y .y) true→β true
従って，iszero 0 →* true

【4】 S = λx.λy.λz.xz(yz)K = λx.λy.x
B = λx.λy.λz.x(yz)I = λx.xとするとき，つぎの書換え系列が存在することを示せ。
S(KI) →* I
BI →* I
S(KS)K →* B
SKK →* I[解答]S(KI) = (λ x .λ y.λ z.xz(yz) ) (KI)→β λ y.λ z.(KI) z(yz) =λ y.λ z.(λ x.λ y.x)I z(yz)→β λ y.λ z.(λ y .I ) z(yz) =λ y.λ z.(λ y.λ x.x) z(yz)→β λ y.λ z.(λ x.x) (yz)→β λ y.λ z.yz
→η λ y. y →α λ x .x =I
従って，S(KI) →* IBI→β λ y.λ z.I (yz)→β λ y.λ z.yz
→η λ y. y →α I

S(KS)KSKK→* λ z.(KS) z(Kz)→* λ z. (λ y .S) z(λ y . z)→β λ z.S(λ y. z)→* λ z.λ y′.λ z′. (λ y .z)z′(y′z′)→β λ z.λ y′.λ z′. z(y′z′) →α *B→* λ z.Kz(Kz)→* λ z. (λ y . z) (λ y. z)→β λ z.z →α I2

【6】 二つのリスト(S1 S2 …Sm), (T1 T2 …Tn)を入力として受け取り，合成したリスト(S1 S2 …Sm T1 T2 …Tn)を返す関数 APPEND を LISP で書け。

[解答]

(APPEND (LAMBDA (x y)(COND ( (NULL x) y)(T (CONS (CAR x) (APPEND (CDR x) y))))))【7】 f (X, g(X))と f (3, g(Y))を単一化をしなさい。
[解答] 単一化代入θ={3 /X, 3 /Y}【8】 Prolog でフィボナッチ数を計算するプログラムを作成しなさい。ただし，フィボナッチ数とはfib(0)=fib(1)=1, fib(n)=fib(n-1)+fib(n-2)となる関数 fib で返される数である。ただし，n は 2 以上の整数である。

[解答]

fib(0, 1).
fib(1, 1).
fib(N, A) :- N >= 2,
N1 is N -1, fib(N, a1),
N2 is N -2, fib(N2, A2),
A is A1+ A2 .

【9】 差分プログラムの利点と欠点は何か。
[解答] 利点：差分のみの作成なので，プログラムの作成量が減少する。プログラミングの指針として，差分化することを与える。
欠点：差分化を制御する部分はオブジェクト指向言語の処理系によって暗黙的に動作する部分があるため，人間にとって動作が把握しにくい。

3

3章【1】 L1={an bm | n≥m≥1}とする。L1 を生成する CF 文法を与えよ。
[解答]

G1 = (N= {S}, Σ= {a, b}, P={S→aS, S→aSb, S→ab}, S)【2】L2={ω |ω∈{0, 1}*,ω中に現れる 0 と 1 の個数は等しい}は CF 言語であることを示せ｡[解答]

G2 = (N= {S}, Σ= {0, 1}, P={S→ε, S → 0S1S, S → 1S0S}, S)
L(G2 )=L2 の証明は省略【3】 L3={an bm cm, an bn cm | n, m≥1}とする。L3 を生成する CF 文法を与え，つぎに終端記号列 abc の解析木をすべて求めよ。

[解答]

G= ({S, A, B, C, D}, {a, b, c}, P, S)
ただし，P= {S → AB
S → CDA → aAC → aCb
A→ a
C → ab
B → bBc D → cD
B → bcD→ cSSABab

CcaDbc【4】例 3.4 の式（3.6）の生成規則を用いて,num1-num2*num3↑num4↑num5 の解析木を与えよ｡[解答]

E1E2E2-E3E3E3*E4E4E4E5E5E5num3

num1num2

↑

E4E5

↑

num4E4E5num5【5】および【6】[解答]31)などのコンパイラの文献を参照されたい。

44章【2】 C 言語のプログラム中で i と a はつぎのように宣言されている。
int i, a[10][5] ;つぎの式は左辺値を持つか否かを調べよ。
(1)[解答]i++

(2)

(i)

(3)

a(4)

a[0]

(5)

(a[3]+2)[1](1)のみ左辺値を持たない。

【5】 例 4.15 中の文の並び i:=2 ; A[2]:=3 ; A[3]:=4 ; swap(i, A[i]) ; の実行において，手続きを値呼出し，変数呼出し，名前呼出しで実行したとき，実行結果を比較せよ。

[解答]

値呼出しのとき，(i, A[2], A[3]) = (2, 3, 4)
変数呼出しのとき，(i, A[2], A[3]) = (3, 2, 4)
名前呼出しのとき，(i, A[2], A[3]) = (3, 3, 2) となる。

【6】 例 4.18 の C プログラム中の関数 f の定義の 2 行目をつぎのように代入文 n=n+1; を追加して得られたプログラムの実行結果を求めよ。
int x ;

[解答]

出力値→

int x ; n=n+1;

19【7】 つぎの C プログラムの実行結果を示せ。また，その理由を説明せよ。
int x, y;void f (int *a) {*a=*a+3; }void g (int *b) {f(b); x=x+1; }void h (int y) {if (y>1) {h(y-1); x=(x+3)*y; }}int main (void) {x=1; y=2; h (y+1);
printf ("%d╲t%d╲n", x, y);x=3; y=4; g (&y);
printf ("%d╲t%d╲n", x, y);
}

[解答]

出力値

332475

【8】 つぎの C プログラムの実行結果を示せ。
int x;
void f (int y) {int a;
if (y>0) {a=x+y; f (y-1); x=(a-2)*x; }}int main (void) {x=3; f (3);printf ("%d╲n", x); }[解答]

出力値7265章【1】 5.2 節のスタック IStack を Java の Vector を使って実装しなさい。Vector はパッケージ java.utilにあり，メソッドとして最後に要素 element を加える add(Object element)，Vector のサイズを返す
size([解答])，指定された位置 position の要素を削除する remove(int position)がある。

import java. util .Vector;
class VectorStack implements IStack {Vector <Object> vector;
VectorStack ( ) {vector= new Vector <Object> ( );}public void push (Object element) {vector. add (element) ;}public Object pop ( ) {return vector .remove (vector.size ( )-1) ;}}【2】 オブジェクト指向のクラスと継承を使って，円 Circle と楕円 Ellipse を操作するプログラムを作成しなさい。操作として面積を求める操作 getAreaSize を定義しなさい。

[解答]

class Ellipse {int radius1;
int radius2;
Ellipse ( ) { }Ellipse (int radius1, int radius2) {this.radius1 =radius1;
this.radius2 =radius2;}
double getAreaSize ( ) {return java.lang .Math. PI * radius1 * radius2;}}
public class Circle extends Ellipse {Circle (int radius) {radius1=radius2 =radius;}}7【3】 コンポジションの考えを用いて，楕円と円のプログラムを作成しなさい。操作として面積を求める
操作 getAreaSize を定義しなさい。

[解答]

class Ellipse {int radius1;
int radius2;Ellipse ( ) { }Ellipse (int radius1, int radius2) {this .radius1 =radius1 ;this .radius2 =radius2 ;}double getAreaSize ( ) {return java.lang .Math. PI * radius1 * radius2;}}
public class Circle {Ellipse ellipse;
Circle (int radius) {ellipse= new Ellipse (radius, radius);}
double getAreaSize ( ) {return ellipse .getAreaSize ( );}}【4】 つぎの Java プログラムでクラス C から直接アクセスできるフィールドは，どのクラスのどのフィールドか。
class A {int x; int y; int z; }class B extends A {int y; }class C extends B {int x; }[解答] クラス C の x，クラス B の y，クラス A の z。

8

【5】 つぎの Java プログラムで返される値はどれか。
class A {int x = 1;
int getX ( ) {return x ; }}public class B extends A {int x= 2 ;public static void main (String [ ] args) {System . out . println (new C( ) . getX ( ) ) ;}
}

[解答]

1
クラス A のフィールドが返される。

【6】 つぎの Java プログラムで返される値はどれか。
class A {void foo( ) {System . out . println ("A . foo( )") ; }}public class B extends A {void foo( ) {System . out . println ("B . foo( )") ; }public static void main (String [ ] args) {A a = new B ( );System . out . println (a . foo( ) ) ;}}[解答]

B.foo( )96章【2】 N を非負整数の集合とする。N⊥ = N ∪{⊥N} とする。関係 ⊑N⊥⊆ N⊥×N⊥ はつぎの条件(a)～(c)をみたす。
(a) ∀x∈N⊥⊥N ⊑N x⊥(b) ∀x, y∈Nx ⊑N y ⇔ x =y⊥(c) ∀x∈N⊥x ⊑N ⊥N ⇒ x =⊥N⊥
そのとき，つぎの問いに答えよ。
(4) ( ⊔ {f i | i≥0}) (x)= x ! （ただし，x∈N ）であることを示せ。ここで，f i は(3)で定義された関数である。

[解答](4)の解答の概略
i, x∈N に対して，f i (x) =x!
（x < i のとき）⊥N（x ≥ i のとき）であることを数学的帰納法で証明する。

【3】 Hoare の論理を用いて，つぎの表明が定理であることを示せ。
{n≥0} x=n; y=n; while (y>0) {y=y-1; x=x+y; } {x=n*(n+1)/2}[解答の概略]

ループ不変表明 A をつぎのように定義する。
y (y-1)n (n +1)
A=( x+ *= *)∧(y≥0)
22
つぎの表明が定理であることを示す。
{A} while (y> 0) {y= y-1; x =x+ y ; } {A∧y≤0}10