ウォンツテック

そでやまのーと

SICPの問題を解こう17

問題 1.31

product(積)版を書いて\piを計算せよという問題

(define (product term a next b)                                                 
  (if (> a b)                                                                   
      1                                                                         
    (* (term a)                                                                 
       (exact->inexact (product term (next a) next b)))))                       
(define (getpi n)                                                               
  (define (pi-term x)                                                           
    (if (even? x)                                                               
        (/ (+ x 2) (+ x 1))                                                     
      (/ (+ x 1) (+ x 2))))                                                     
  (define (pi-next x) (+ x 1))                                                  
  (* 4 (product pi-term 1 pi-next n)))                                          
                                                                                
(print (getpi 10))                                                              
(print (getpi 100))                                                             
(print (getpi 1000))                                                            
(print (getpi 10000))                                                           
(print (getpi 100000))                                                          
(print (getpi 1000000)) 

結果

n pi
10 3.275101041334807
100 3.1570301764551645
1000 3.143160705532257
10000 3.1417497057379746
100000 3.1416083612780903
1000000 3.141594224382829

recursive process版

(define (product term a next b)                                                 
  (define (itr a result)                                                        
    (if (> a b)                                                                 
        result                                                                  
      (itr (next a) (exact->inexact (* (term a) result)))))                     
  (itr a 1))                                                                    
(define (getpi n)                                                               
  (define (pi-term x)                                                           
    (if (even? x)                                                               
        (/ (+ x 2) (+ x 1))                                                     
      (/ (+ x 1) (+ x 2))))                                                     
  (define (pi-next x) (+ x 1))                                                  
  (* 4 (product pi-term 1 pi-next n)))                                          
                                                                                
(print (getpi 10))                                                              
(print (getpi 100))                                                             
(print (getpi 1000))                                                            
(print (getpi 10000))                                                           
(print (getpi 100000))                                                          
(print (getpi 1000000))

有理数を小数にするのに exact->inexactを使用

問題 1.32

sumとproductはもっと抽象化出来、それをaccumulateとして実装せよという問題。
iterativeとrecursiveなprocessを両方書く

(define (accumulate combiner null-value term a next b)                          
  (if (> a b)                                                                   
      null-value                                                                
    (combiner (term a) (accumulate combiner null-value term (next a) next b)))) 
(define (accumulate-recursive combiner null-value term a next b)                
  (define (itr x result)                                                        
    (if (> a b)                                                                 
        result                                                                  
      (itr (next x)                                                             
           (combiner result (term x)))))                                        
  (itr a null-value))                                                           
                                                                                
(define (term x) x)                                                             
(define (next x) (+ x 1))                                                       
                                                                                
(define (sum n)                                                                 
  (accumulate + 0 term 1 next n))                                               
(define (product n)                                                             
  (accumulate * 1 term 1 next n))                                               
(define (sum-recursive n)                                                       
  (accumulate + 0 term 1 next n))                                               
(define (product-recursive n)                                                   
  (accumulate * 1 term 1 next n))                                               
                                                                                
(print (sum 10))                                                                
(print (product 5))                                                             
(print (sum-recursive 10))                                                      
(print (product-recursive 5))

問題 1.33

accumulateの改良でfilter条件を満たすもののみaccumulateしていく

(define (filtered-accumulate filter combiner null-value term a next b)          
  (cond ((> a b) null-value)                                                    
        ((filter a b)                                                           
         (combiner (term a)                                                     
                   (filtered-accumulate                                         
                    filter combiner null-value term (next a) next b)))          
        (else (combiner null-value                                              
                        (filtered-accumulate                                    
                         filter combiner null-value term (next a) next b)))))   
(define (gcd a b)                                                               
  (if (= b 0)                                                                   
      a                                                                         
    (gcd b (remainder a b))))                                                   
                                                                                
(define (relative-prime? a b)                                                   
  (= (gcd a b) 1))                                                              
                                                                                
(define (product-b n)                                                           
  (define (term x) x)                                                           
  (define (next x) (+ x 1))                                                     
  (filtered-accumulate relative-prime? * 1 term 2 next n))                      
                                                                                
(display (product-b 5))                                                         
(newline) 

問題 1.34

(define (f g)
  (g 2))
(f f)

interpreterが(f f)をどのようにevaluateするかという問題。

(f f)
(f 2)
(2 2)

となって「2」という定義がないという結論になると思う。
GuileのBacktrace

Backtrace:
In unknown file:
   ?: 0* [primitive-load "1-34.sc"]
In 1-34.sc:
   4: 1* [display ...
   4: 2*  [f #]
   2: 3   [f 2]
   2: 4   [2 2]

1-34.sc:2:9: In expression (g 2):
1-34.sc:2:9: Wrong type to apply: 2

GaucheでGuileのBacktraceのようなデバッグ情報吐き出すにはどうすればいいんだろう・・?
ないのかな?