第7回 制御構造(5月31日)

今日の課題

■ lambda と順接

ラムダ式の形式をよくみると、〈式a〉、〈式b〉・・・〈式n〉 と式の並びを定義することができる。「式の並び」は、通常のプログラミングの考え方でいうところの「順接」に相当する。ラムダ式の評価によって得られる返り値は、最後に評価した式〈式n〉の返り値である。

例題1

Definitions で以下を定義しよう。
(define say
  (lambda (x)
    (write "Hello ")
    (write x)
    (write "World")))

Interactions で以下を実行しよう。
> (say 'scheme)

■ 条件式

条件式は次の2つの書式がある。2つめで、偽の場合、この式全体の返り値は不明である(処理はエラー終了とならずに進む)。
(if <真偽を返す式> <真の際に評価する式> <偽の際に評価する式>)
(if <真偽を返す式> <真の際に評価する式>)

if により同一の処理が可能ではあるが、Lispにおける伝統的な条件式として、cond がある。
(cond (<真偽を返す式1> <真偽を返す式1真の際に評価する式の並び1>)
      (<真偽を返す式2> <真偽を返す式2真の際に評価する式の並び2>)
                  - - - 
      (<真偽を返す式n> <真偽を返す式n真の際に評価する式の並びn>))

例題2

以下にサンプルを示す。Interactions で実行してみよう。
> (if (< 1 2) 'ok 'ng)
> (if (> 1 2) 'ok 'ng)
> (if (< 1 2) 'ok)
> (if (> 1 2) 'ok)

練習1

成績を入力して、ABCラベルを出力する関数 label を作成しよう。もし、成績 s が 90以上ならば "A"、80以上90未満ならば "B"、70以上80未満ならば "C"、60以上70未満ならば"D"、60未満ならば"E"を返り値とせよ。ここで、if 関数を使う場合(label1)と cond 関数を使う場合 (label2) のそれぞれを作成してみよう。

■ 再帰

ある名前で定義した関数の中で、その名前の関数を評価することを再帰呼出しという。

例題2

階乗を計算する関数 factorial を定義しよう.factorial では再帰を終了する条件は,0 の階乗を求めるときであり,その返り値は,1 である.
(define factorial
  (lambda (x)
    (if (= x 0)
        1
        (* x (factorial (- x 1))))))

練習2

以下の問について、再帰を使って回答せよ。

(問1) 2, 4, 6, ... というように、1以上の偶数 n 個を昇順にとりこぼしなくならべたとき、それらの数の和を求める関数 sum_even(n) を定義せよ。

(問2)an+1 = 2an + 2 と定義される式の第n項を計算する関数 prac0703(n) を定義せよ.n は 1 以上の整数,a1 = 2 とする.

(問3)an+1 - 5an + 6 = 0 を満たす数列の第n項を計算する関数 prac0704(n) を定義せよ.n は 1 以上の整数,a1 = 7 とする.

(問4)an+2 - 3an+1 + 4an + 5 = 6 を満たす数列の第n項を計算する関数 prac0705(n) を定義せよ.n は 1 以上の整数,a2 = 7,a1 = 8 とする.


□小レポート

以下の4つの関数を計算するために必要な scheme プログラムリストを印刷し、各行に手書きで説明を書いて、提出せよ。

以下の問題で、お金の計算をするが、小数点数が計算結果に表れて良いことにする。また、再帰を使う練習なので、一般式による回答はしないこと(おまけとして回答に追加しても良い)。

(1) a の n 乗を計算する関数 power(a,n) を定義せよ。n は正の整数とする。

(2) 年複利 r のところに a 円を預けたとき、n 年後の年末の元利を計算する関数 yokin(a,r,n) を定義せよ。ちなみに,複利の計算では、元金 a を一定期間預けたあとの利息 ar を、元金に加えて次の期間の新しい元金とみなす。

ヒント:
1年 元金=a 利息=元金*r = ar
2年 新元金=a+ar 利息=新元金*r=(a+ar)r
3年 新元金=a+ar+(a+ar)r 利息=新元金*r=(a+ar+(a+ar)r)r
: : :

検算:年利1割のところに3,000円を3年預けると、3,993円になる。

(3) 年複利 r のところに毎年 a 円ずつ預ける積立預金の n 年後の年末の元利を計算する関数 tsumitate(a,r,n) を定義せよ。

ヒント:
1年目末 yokin(a,r,n)
2年目末 yokin(a,r,n) + yokin(a,r,n-1)
3年目末 yokin(a,r,n) + yokin(a,r,n-1) + yokin(a,r,n-2)
: : :

検算:年利1割のところに1,000円の積み立てを3年行うと、3,641円になる。

(4) 年複利 r のところから b 円を借りてローンを組み、年末に一定額 a 円を払うことにする。支払いが完了する年数を計算する関数 nenpunen(a,b,r) を定義せよ。

ヒント:
b <= 0のとき完了(0年)
a <= br のとき破産('bankruptcy)
上記以外のとき,「元金 + 利息 - 返済額」円の返済に掛かる年数 + 1年

検算:年利1%のところから100万円借りて、年に12万円ずつ払うことにすると完済に9年かかる。ご利用は計画的に。


(c) 2007.5.29 by tokuhisa