SICP 読み (8)
新年早々、オレオレ 20% ルール適用。
問題 1.20 (gcd の展開)
正規順序評価では if の中のソレ以外は引数展開されず、作用的順序では引数の評価が先、とゆー事で正規順序評価はゆっくり紙に書きたいな。作用的順序な評価は量が少なそうなので以下に。
まず、gcd の定義は以下。
(define (gcd a b) (if (= b 0) a (gcd b (remainder a b))))
(gcd 206 40) (if (= 40 0) 206 (gcd 40 (remainder 206 40))) (gcd 40 (remainder 206 40)) ;; 一回目 (gcd 40 6) (if (= 6 0) 40 (gcd 6 (remainder 40 6))) (gcd 6 (remainder 40 6)) ;; 二回目 (gcd 6 4) (if (= 4 0) 6 (gcd 4 (remainder 6 4))) (gcd 4 (remainder 6 4)) ;; 三回目 (gcd 4 2) (if (= 2 0)) 4 (gcd 2 (remainder 4 2)) (gcd 2 (remainder 4 2)) ;; 四回目 (gcd 2 0) (if (= 0 0)) 2 (gcd 0 (remainder 2 0)) 2
で、四回となりました。これでも十分長い。これ、正規順序なナニはもの凄いコトになりそうです。ワケがわからなくなりそう。(アセらず、一日一題を目処にした方が良いかなぁ。スルー多いし)
問題 1.22
1.21 はスルー。で、1.22 ですが、runtime 手続きは guile では未定義な模様。get-internal-run-time 手続きで取得可能なのかなぁ。get-internal-real-time なんてのもある。とりあえず get-internal-real-time で試してみたのが以下。コードが長い。要リファクタリングとゆー感じッス。(変数名とか微妙スギ)
(define (test-timed-prime-test) (let f ((l (reverse (search-for-prime '(100000000 1000000000 10000000000))))) (cond ((not (null? l)) (let ff ((prime-list (car l))) (cond ((null? prime-list) (f (cdr l))) (else (timed-prime-test (car prime-list)) (ff (cdr prime-list))))))))) (define (search-for-prime l) (let f ((l l) (result '())) (cond ((null? l) result) (else (f (cdr l) (let ff ((n (car l)) (r result) (primes '())) (if (= (length primes) 3) (cons primes r) (cond ((prime? n) (ff (+ n 1) r (append primes (cons n '())))) (else (ff (+ n 1) r primes)))))))))) (define (timed-prime-test n) (newline) (display n) (start-prime-test n (get-internal-real-time))) (define (start-prime-test n start-time) (if (prime? n) (report-prime (- (get-internal-real-time) start-time)) (newline))) (define (report-prime elapsed-time) (display " *** ") (display elapsed-time) (newline)) (define (square n) (* n n)) (define (smallest-divisor n) (find-divisor n 2)) (define (find-divisor n test-divisor) (cond ((> (square test-divisor) n) n) ((divides? test-divisor n) test-divisor) (else (find-divisor n (+ test-divisor 1))))) (define (divides? a b) (= (remainder b a) 0)) (define (prime? n) (= n (smallest-divisor n)))
で、test-timed-prime-test 内の search-for-prime の引数なリストですが、0 を 4 桁くらい増やさないとちゃんとした数字が出てきませんでした。実行結果は以下。
guile> (test-timed-prime-test) 100000007 *** 13 100000037 *** 13 100000039 *** 14 1000000007 *** 42 1000000009 *** 44 1000000021 *** 43 10000000019 *** 161 10000000033 *** 160 10000000061 *** 161 guile>
大体 √10 倍くらいの数値になっているのか。