第12夜:ピタゴラスの宮殿
数の悪魔*1を題材にSchemeの勉強の最終回です。三角数の計算方法です。
よろしい、ドリス。じゃ、よく聞いて。前に座ってる1番目の生徒が、ええっと、アルバートだよね、そう、アルバートがパンを1個もらうことにする。つぎに2番目の生徒のベッティーナは、パンを2個もらうことにする。チャーリーは3個、ドリスは4個、という具合にして、38番目の生徒までいくことにしよう。じゃ、いいかな、計算して。こんなふうにして教室のみんなにパンを配るには、パンは何個いりますか - ボッケル先生
三角数の計算です。本の中ではn*(n+1)/2
の式を変形させて、n/2*(n+1)
で計算しています。
(define (show-triangler-number n) (define (answer n h) (format #f "~% ~D x ~D = ~D~%" h (+ n 1) (* h (+ n 1)))) (define (number v) (format #f " ~3D" v)) (define (dot-join proc l) (define (dot-iter l nl) (if (null? l) (string-join (reverse nl) "") (dot-iter (cdr l) (cons (apply proc (car l)) (cons " ..." nl))))) (dot-iter (cdr l) (cons (apply proc (car l)) '()))) (define (dup-number n v) (do ((i n (- i 1)) (l '() (cons (number v) l))) ((< i 1) (string-join l "")))) (define (format-number n v op) (define (format-number-iter n v l) (if (< n 1) (string-join (reverse l) "") (format-number-iter (- n 1) (op v 1) (cons (number v) l)))) (format-number-iter n v '())) (define (some-numbers n h) (string-join (list (format-number h 1 +) (format-number h n -) (make-string (* 4 h) #\-) (dup-number h (+ n 1)) (answer n h) ) "\n")) (define (many-numbers n h) (string-join (list (dot-join format-number (list (list 3 1 +) (list 2 (- h 1) +))) (dot-join format-number (list (list 3 n -) (list 2 (+ h 2) -))) (make-string (* 4 6) #\-) (dot-join dup-number (list (list 3 (+ n 1)) (list 2 (+ n 1)))) (answer n h) ) "\n")) (if (odd? n) "Sorry, please even number." ((if (< n 12) some-numbers many-numbers) n (/ n 2))) ) (define (main args) (print (show-triangler-number 38)) 0)
抽象化するスタイルが良く分からなくて、中途半端に抽象化しています。要修練です。結果はこちら。
1 2 3 ... 18 19 38 37 36 ... 21 20 ------------------------ 39 39 39 ... 39 39 19 x 39 = 741
本はこれで終わりです。ありがとうございました。
参考にさせていただきました:三角数 - Wikipedia