2014年10月13日月曜日

[SICP] 問題 1.03 : 三つの数を引数として取り、大きい二つの数の二乗の和を返す手続き

三つの数を引数としてとり, 大きい二つの数の二乗の和を返す手続きを定義せよ.
問題文を計算する手続きを定義します.
  1. 手続きは, 三つの引数x, y, zを取ることとします.
  2. xが最小であればyとzをそれぞれ二乗し,その和を返します.
  3. 同様に, yが最小である場合, zが最小である場合もそれぞれ計算します.
これを手続きとして定義します.
(define (square x)
  (* x x))

(define (sum-square-large-2 x y z)
  (cond ((and (<= x y) (<= x z)) (+ (square y) (square z)))
        ((and (<= y z) (<= y x)) (+ (square z) (square x)))
        ((and (<= z x) (<= z y)) (+ (square x) (square y)))))
計算してみます.
ようこそ DrRacket, バージョン 6.1 [3m].
言語: Pretty Big; memory limit: 2048 MB.
> (sum-square-large-2 1 2 3)
13
> (sum-square-large-2 4 2 3)
25
> (sum-square-large-2 1 5 3)
34
> (sum-square-large-2 1 3 3)
18
> (sum-square-large-2 2 2 2)
8
> 
計算結果から, 手続きはうまく定義できているようです.
手続きの定義をよく眺めると, 同じような構造が繰り返されており, 引数が循環していることが分かります. この構造に着目することで, 手続きの定義をもっと簡潔にできます. 手続名をsum-square-large-2-rとして定義します.
(define (square x)
  (* x x))

(define (sum-square-large-2-r x y z)
  (if (and (<= x y) (<= x z))
      (+ (square y) (square z))
      (sum-square-large-2-r y z x)))
この手続定義で何をしているかを説明します.
  1. 引数xの値が最も小さい場合は, yの2乗とzの2乗の和を求めます.
  2. それ以外の場合は, 引数の順序を入替えて自分自身を呼び出します.
  3. 引数x, y, zのどれかが最小になるので, 残りの引数のそれぞれを2乗し, その和を返します.
手続きのテストをするため, 同じ条件で計算してみます.
ようこそ DrRacket, バージョン 6.1 [3m].
言語: Pretty Big; memory limit: 2048 MB.
(13 25 34 18 8)
> (sum-square-large-2-r 1 2 3)
13
> (sum-square-large-2-r 4 2 3)
25
> (sum-square-large-2-r 1 5 3)
34
> (sum-square-large-2-r 1 3 3)
18
> (sum-square-large-2-r 2 2 2)
8
> 
結果は一致しています.

0 件のコメント:

コメントを投稿