第2夜:0はえらい
5の1乗、5の2乗、5の3乗。これをな、5をホップさせる、と言うんじゃ。わかったかな。おなじことを10でやると、もっと簡単だ。計算機なんかなくったって、すらすらできる。10を1回ホップさせれば、そのまま10だ - 数の悪魔
(define (hop b n) (define (hop-iter v n) (if (< n 1) v (hop-iter (* b v) (- n 1)))) (hop-iter 1 n) ) (define (main args) (print (hop 10 0)) (print (hop 10 1)) (print (hop 10 5)) (print (hop 10 10)) 0)
結果はこちら。
1 10 100000 10000000000
直球だとこんな感じになりました。ここで、ちょっとトラウマになりかけたSICP*2を思い出して。
(define (hop b n) (define (hop-iter a b n) (if (< n 1) a (if (even? n) (hop-iter a (* b b) (/ n 2)) (hop-iter (* b a) b (- n 1))))) (hop-iter 1 b n) ) (define (main args) (print (hop 10 0)) (print (hop 10 1)) (print (hop 10 5)) (print (hop 10 10)) 0)
おまけでローマ数字変換。効率のいい書き方がありそう。nとキャラクタをconsセルでまとめて返して、lambda式で受ける部分は完全に自己流。もっといい方法あるかも。
(define (roman-numeral n) (define (roman-num n) (cond ((>= n 1000) (cons (- n 1000) "M")) ((>= n 900) (cons (+ n 100) "C")) ((>= n 500) (cons (- n 500) "D")) ((>= n 400) (cons (+ n 100) "C")) ((>= n 100) (cons (- n 100) "C")) ((>= n 90) (cons (+ n 10) "X")) ((>= n 50) (cons (- n 50) "L")) ((>= n 40) (cons (+ n 10) "X")) ((>= n 10) (cons (- n 10) "X")) ((>= n 9) (cons (+ n 1) "I")) ((>= n 5) (cons (- n 5) "V")) ((>= n 4) (cons (+ n 1) "I")) ((>= n 1) (cons (- n 1) "I")))) (define (roman-iter n l) (if (< n 1) (reverse l) ((lambda (x) (roman-iter (car x) (cons (cdr x) l))) (roman-num n)))) (if (> n 3999) "Please less than 4000." (roman-iter n '())) ) (define (main args) (print (roman-numeral 1986)) 0)
実行結果はこちら。
(M C M L X X X V I)
SICPは26ページで挫折中。いつか続きをやりたいです。
*1:Hans Magnus Enzensberger,1997,Der Zahlenteufel,エンツェンスベルガー 丘沢静也(訳),2000,数の悪魔,晶文社
*2:Harold Abelson and Gerald Jay Sussman with Julie Sussman,1996,Structure and Interpretation of Computer Programs -- 2nd ed.,ジェラルド・ジェイ・サスマン ハロルド・エイブルソン ジュリー・サスマン 和田英一(訳),2000,計算機プログラムの構造と解釈 第二版,ピアソン・エデュケーション