SICP/ex-1_01-10.scm
2021-04-25 08:57:17 -04:00

242 lines
5.9 KiB
Scheme

(display "ex-1.1 - basic-operations\n")
(display "[see comments]\n")
; 10 -> 10
; (+ 5 3 4) -> 12
; (- 9 1) -> 8
; (/ 6 2) -> 3
; (+ (* 2 4) (- 4 6)) -> 6
; (define a 3) -> a
; (define b (+ a 1)) -> b
; (+ a b (* a b)) -> 19
; (= a b) -> #f
; (if (and (> b a) (< b (* a b))) b a) ; -> b -> 4
; (cond ((= a 4) 6)
; ((= b 4) (+ 6 7 a))
; (else 25)) -> 126
; (+ 2 (if (> b a) b a)) -> 6
; (* (cond ((> a b) a)
; ((< a b) b)
; (else -1))
; (+ a 1)) ->
(display "\nex-1.2 - ")
(display (/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5)))))
(* 3 (- 6 2) (- 2 7))))
(newline)
(display "\nex-1.3 - ")
(define (sum-squares a b) (+ (* a a) (* b b)))
(define (sum-squares-max a b c)
(cond ((and (>= a c) (>= b c)) (sum-squares a b))
((and (>= a b) (>= c b)) (sum-squares a c))
(else (sum-squares b c))))
(display (sum-squares-max 2 -6 1))
(newline)
(display "\nex-1.4 - Operator becomes + or - depending on the value of b\n")
; (define (a-plus-abs-b a b)
; ((if (> b 0) + -) a b))
(display "\nex-1.5 - Only normal-order terminates\n")
;(define (p) (p))
;(define (test x y)
; (if (= x 0) 0 y))
;(display (if (= 0 0) 0 (p)))
; Will not terminate:
;(display (test 0 (p)))
(display "\nexample - Square roots via Newton's Method") (newline)
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
(define (improve guess x)
(average guess (/ x guess)))
(define (average a b) (/ (+ a b) 2))
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.0001))
(define (square a) (* a a))
(define (sqrt x) (sqrt-iter 1.0 x))
(display (sqrt 9))
(newline)
(display (sqrt (+ 100 37)))
(newline)
(display (sqrt (+ (sqrt 2) (sqrt 3))))
(newline)
(display (square (sqrt 1000)))
(newline)
(display "\nex-1.6 - see comment\n")
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
;(define (sqrt-iter guess x)
; (new-if (good-enough? guess x)
; guess
; (sqrt-iter (improve guess x)
; x)))
;(display (sqrt 9))
; sqrt-iter doesn't terminate because new-if is evaluated in applicative
; order which results in an endless recursion of sqrt-iter -> new-if.
(display "\nex-1.7 - see comments for explanation\nwrong behavior:\n")
(display (sqrt 9)) (newline)
; Very small numbers don't work because the delta between the initial
; guess and the expected solution is in a smaller dimension than the
; value used in good-enough?
(display (sqrt 0.0000001)) (newline)
; For very large numbers, good-enough? will never return true because the
; representation of floating point numbers is not accurate enough for their
; difference to ever fall below the tolerance value.
;(display (sqrt 9732402478147293489)) (newline)
(display "better:\n")
(define (good-enough2? guess new-guess)
(< (/ (abs (- new-guess guess)) new-guess) 0.00000000001))
(define (sqrt-iter-precise guess x)
(if (good-enough2? guess (improve guess x))
guess
(sqrt-iter-precise (improve guess x)
x)))
(display (sqrt 9)) (newline)
(display (sqrt 0.00000001)) (newline)
; (display (sqrt 9732402478147293489))
; works with racket and newer MIT Scheme versions
(display "\nex-1.8 - cube-root") (newline)
(define (improve-cubic y x) (/ (+ (/ x (* y y)) (* 2 y)) 3))
(define (cbrt-iter guess x)
(if (good-enough2? guess (improve-cubic guess x))
guess
(cbrt-iter (improve-cubic guess x) x)))
(define (cbrt x) (cbrt-iter 1.0 x))
(display (cbrt 27)) (newline)
(display (cbrt 0.001)) (newline)
(newline) (display "ex-1.9 - see comments in code\n")
;(define (+ a b)
; (if (= a 0)
; b
; (inc (+ (dec a) b))))
; + 3 2
; (inc (+ 2 2))
; (inc (inc (+ 1 2)))
; (inc (inc (inc (+ 0 2)))
; (inc (inc (inc 2)))
; -> recursive process
;(define (+ a b)
; (if (= a 0)
; b
; (+ (dec a) (inc b))))
; (+ 3 2)
; (+ 2 3)
; (+ 1 4)
; (+ 0 5)
; 5
; -> iterative process
(display "\nex-1.10 - Ackermann") (newline)
(define (A x y)
(cond ((= y 0) 0)
((= x 0) (* 2 y))
((= y 1) 2)
(else (A (- x 1)
(A x (- y 1))))))
(display (A 1 10)) (newline)
; (A 1 10)
; (A 0 (A 1 9))
; (* 2 (A 1 9))
; (* 2 (A 0 (A 1 8))
; (* 2 (* 2 (A 1 8))
; -> 2^10 = 1024
(display (A 2 4)) (newline)
; (A 2 4)
; (A 1 (A 2 3))
; (2 ^ (A 2 3))
; (2 ^ (A 1 (A 2 2))
; (2 ^ 2 ^ (A 2 2)
; -> 2^2^2^2 = 65536
(display (A 3 3)) (newline)
; (A 3 3)
; (A 2 (A 3 2))
; (2 ^* (A 3 2))
; (2 ^* (A 2 (A 3 1)))
; (2 ^* 2 ^* 2)
; (2 ^* (2^2))
; (2^2^2^2) = 65536
(define (f n) (A 0 n)) ; f(n)=2*n
(display (f 111)) (newline)
(define (g n) (A 1 n)) ; g(n)=2^n
(display (g 12)) (newline)
(define (h n) (A 2 n)) ; h(n)=2^2^2^... or 2^(h(n-1))
(display (h 4)) (newline)
(newline) (display "example - Couting Change") (newline)
(define (dec x) (- x 1))
(define (counting-change-iter amount current-coin)
(cond ((= amount 0) 1)
((= current-coin 0) 0)
((< amount 0) 0)
(else (+ (counting-change-iter (- amount (list-of-coins current-coin)) current-coin)
(counting-change-iter amount (dec current-coin)))
)))
(define (list-of-coins coin-index)
(cond ((= coin-index 1) 1)
((= coin-index 2) 5)
((= coin-index 3) 10)
((= coin-index 4) 25)
((= coin-index 5) 50)))
(define (count-change amount) (counting-change-iter amount 5))
(display "(count-change 100) = ")
(display (count-change 100)) (newline)
; Try to implement a better version. Worked in Python. See Euler.
;(define (counting-change-iter amount count-coin current-coin)
; (cond ((= current-coin 0) 0)
; ((<= amount 0) 0)
; (else (+ (counting-change-iter (- amount (list-of-coins current-coin)) (+ count-coin 1) current-coin)
; (if (and (= count-coin 0)(= (modulo amount (list-of-coins current-coin)) 0)) 1 0)
; (counting-change-iter amount 0 (- current-coin 1))
; ))))
;(display "(count-change 100) = ")
;(display (counting-change-iter 100 0 5)) (newline)