이번에는 코드안짜구 말로 설명하는 문제들만 따로풀어보려구한다.
ch1 에서 딴거보다 쉬워보이는
exer 1.1, 1.2,, 1.4, 1.5, 1.6, 1.9, 1.10, 1.21, 1.34 만 풀어보았다.
역시 말로 설명하는건 코드짜는거보다 괜히 조금 귀찮다-_-
따로 문제는적지않는다.
무엇보다 일단 귀찮으며--;;, 문제는 책보면은 있는 내용이라서 쓸 이유를 못 느끼겠다.
경우에 따라서는 풀이에 꼭 필요한 경우에만 적겠다.
exercise 1.1
가. 10 => 10; 나. (+ 5 3 4) => 12; 다. (- 9 1) => 8; 라. (/ 6 2) => 3
마. (+ (* 2 4) (- 4 6)) 괄호안을 계산하면 (+ 8 -2) => 6
바. (+ a b (* a b)) 괄호안의 a를 3으로 대치, b를 4로 대치하면 (+ 3 4 (* 3 4)) = (+ 7 12) => 19
사. (= a b) 는 (= 3 4) => #f
아.
괄호안의 a, b를 3, 4로 대치시키구나면
(if (and (> 4 3) (< 4 (* 4 3))) 4 3) 두 조건다 참이므로 => 4
자. (= b 4)가 참이니까 (+ 6 7 3) 하면 => 16
차. (+ 2 (if (> b a) b a)) => (> b a)가 참이므로 (+ 2 b) => 6
카.
cond부터 풀면은 (< a b)가 참이니 cond를 eval하구 난 값은 4가된다.
거기에 * (+ a 1)을 하면 (* 4 (+ 3 1)) = (* 4 4) => 16
exercise 1.2
(/ (+ 5 (+ 4 (- 2 (- 3 (+ 6 (/ 4 5)))))) (* 3 (- 6 2) (- 2 7)))
exercise 1.4
(a-plus-abs-b 3 -4)로 호출했다구 치면 ((if (> -4 0) + -) 3 -4))이다. if가 거짓이다.
그래서 (- 3 -4) 가 되서 중위표기식으로 하면은 (3 - (-4)) = 3 + 4 => 7
exercise 1.5
인자 먼저 계산하는 식으로 하면 무한루프에 빠진다 왜냐하면 y자리에 (p)가 가는데 계속 자신을 호출하니까
만약 정의한대로 계산하면 if(= 0 0)이 참이 되어서 0을 리턴을 할것임 y값을 eval하지도 않으니까
무한루프에빠질일도없음
exercise 1.6
무한 루프에 빠지는데, new-if에 매개변수로 전달된 then-clause랑 else-clause가 둘다 전달되면서 evaluate되기 때문이다.
exercise 1.9
위의것 되도는프로시져, 아래것은 반복프로시져다
왜냐하면 위의건 곧바로 계산을 하지 않구 계속 미루어 놓다가 재귀호출이 끝나면 리턴값들을
계산을 하구, 밑의것은 그때그때에 계산을 한다
exercise 1.10
(A 1 10) => 1024
(A 2 4) => 65536
(A 3 3) => 65536
n > 0 임
(f n) : 2n
(g n) : 2 ^ n
(h n) : 2 ^ h (n - 1)
h는 n에 좀만 큰 수를 넣으면은 답이 졸라 커진다.
exercise 1.21
199 => 199, 1999 => 1999, 19999 => 7
exercise 1.34
procedure application: expected procedure, given: 2; arguments were: 2
라는 에러메세지 나옴.
f는 인자로 받아온 프로시져에 2를 인자로 하여 호출하는 프로시져다.
(f f) 하면은 일단 인자로 받은 f에 2를 인자로 하여 호출하려고 한다.
그럼 (f 2)를 하려하는데 (f 2)하면 인자로 받은 2에 2를 인자로 하여 호출하는
(2 2)라는 이상한짓을 하게 된다. 2는 프로시져가 아니므로 에러가되는것임
'exercise'에 해당되는 글 4건
- 2008/01/30 스킴 걸음마의 말 - sicp 연습문제 1장 (설명하는 문제들중 9문제)
- 2008/01/29 스킴 걸음마의 코드 - sicp 연습문제 1장 (코드짜는 문제중 14문제)
- 2008/01/18 스킴 걸음마의 코드 - sicp 연습문제 3장 (코드짜는문제중 7개)
; sicp의 ch1 중 설명하는 문제는 빼놓구 코드를 짜는 문제중에서
; exercise 1.3, 1.8, 1.11, 1.12, 1.17, 1.18, 1.23, 1.30, 1.32, 1.33,
; 1.35, 1.41, 1.42, 1.43만 품
; 쉬워보이는것만 골라서 함--;;
; 12월에 포스팅했던것을 문제 몇문제 좀 더 풀구
; 정리좀해서 다시포스팅한것
; 이제 문제더 풀면 이 글에 그냥 수정해 계속해 붙여갈계획
; (plt scheme 의 개발환경 DrScheme에서 language를 standard(R5RS)로 맞춘후 테스트)
; exercise 1.3, 1.8, 1.11, 1.12, 1.17, 1.18, 1.23, 1.30, 1.32, 1.33,
; 1.35, 1.41, 1.42, 1.43만 품
; 쉬워보이는것만 골라서 함--;;
; 12월에 포스팅했던것을 문제 몇문제 좀 더 풀구
; 정리좀해서 다시포스팅한것
; 이제 문제더 풀면 이 글에 그냥 수정해 계속해 붙여갈계획
; (plt scheme 의 개발환경 DrScheme에서 language를 standard(R5RS)로 맞춘후 테스트)
; exercise 1.3
(define (square n) (* n n))
(define (sum-of-larger-square i j k)
(let ((m (min i j k)))
(cond ((= m i) (+ (square j) (square k)))
((= m j) (+ (square i) (square k)))
(else (+ (square i) (square j))))))
(display "\nexer 1.3\n")
(sum-of-larger-square 10 30 40)
(sum-of-larger-square 10 40 30)
(sum-of-larger-square 30 10 40)
(sum-of-larger-square 30 40 10)
(sum-of-larger-square 40 10 30)
(sum-of-larger-square 40 30 10)
; exercise 1.8
(define (square n) (* n n))
(define (cube n) (* n n n))
(define (cbrt-iter guess x)
(if (good-enough? guess x) guess
(cbrt-iter (improve guess x) x)))
(define (improve guess x)
(+ (/ x (* 3 (square guess))) (/ (* 2 guess) 3)))
(define (average x y)
(/ (+ x y) 2))
(define (good-enough? guess x)
(< (abs (- (cube guess) x)) 0.001))
(define (cbrt x)
(cbrt-iter 1.0 x))
(display "\nexer 1.8\n")
(cbrt 9)
(cbrt 10)
(cbrt 125)
; exercise 1.11
(define (f n)
(if (< n 3) n
(+ (- n 1) (* 2 (f (- n 2))) (* 3 (f (- n 3))))))
(define (f-iter n)
(define (iter i j k result)
(cond ((> i n) result)
((< i 3) (iter (+ i 1) (- i 1) (- i 2) i))
(else (iter (+ i 1) result j (+ (- i 1) (* 2 j) (* 3 k))))))
(iter 1 0 0 0))
(define (test proc)
(define (iter i)
(cond ((<= i 10) (display "f(") (display i)
(display ") = ") (display (proc i)) (newline)
(iter (+ i 1)))
(else (newline))))
(iter 0))
(display "\nexer 1.11\n")
(test f)
(test f-iter)
; exercise 1.12
(define (invalid? row col)
(or (< row 0) (< col 0) (< row col)))
(define (pascal row col)
(cond ((invalid? row col) 'wrong)
((or (= col 0) (= row col))1)
(else (+ (pascal (- row 1) (- col 1)) (pascal (- row 1) col)))))
(display "\nexer 1.12\n")
(pascal 9 7)
; exercise 1.17
; 짝수면은 그 값의 두배, 홀수면 그냥 더하는 식으로 곱셈을 만드는것
(define (double n) (+ n n))
(define (halve n) (/ n 2))
(define (fast-mul a b)
(cond ((or (= a 0) (= b 0)) 0)
((= b 1) a)
((= a 1) b)
((even? b) (double (fast-mul a (halve b))))
(else (+ a (fast-mul a (- b 1))))))
(display "\nexer 1.17\n")
(fast-mul 2 3)
(fast-mul 2 4)
(fast-mul 2 5)
(fast-mul 100 20)
; exercise 1.18
; even일때 a를 double하는게 중요
(define (fast-mul-iter a b)
(define (iter a b result)
(cond ((or (= a 0) (= b 0)) 0)
((= b 1) (+ result a))
((even? b) (iter (double a) (halve b) result))
(else (iter a (- b 1) (+ result a)))))
(iter a b 0))
(display "\nexer 1.18\n")
(fast-mul-iter 2 3)
(fast-mul-iter 2 4)
(fast-mul-iter 2 5)
(fast-mul-iter 100 20)
; exercise 1-23
(define (next n)
(if (= n 2) 3
(+ n 2)))
(define (find-divisor n test-div)
(cond ((> (* test-div test-div) n) n)
((= 0 (remainder n test-div)) test-div)
(else (find-divisor n (next test-div)))))
(define (smallest-divisor n)
(find-divisor n 2))
(define (prime? n)
(if(>= 1 n) #f
(= n (smallest-divisor n))))
(display "\nexer 1.23\n")
(prime? 17)
(prime? 561)
; exercise 1.30
(define (inc n) (+ n 1))
(define (cube n) (* n n n))
(define (sum-cubes a b)
(sum cube a inc b))
(define (sum term a next b)
(define (iter a result)
(if (> a b) result
(iter (next a) (+ result (term a)))))
(iter a 0))
(display "\nexer 1.30\n")
(sum-cubes 1 10)
; exercise 1.32
(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-iter combiner null-value term a next b)
(define (iter a result)
(if (> a b) result
(iter (next a) (combiner (term a) result))))
(iter a null-value))
(define (sum term a next b)
(accumulate + 0 term a next b))
(define (product term a next b)
(accumulate * 1 term a next b))
(define (sum-iter term a next b)
(accumulate-iter + 0 term a next b))
(define (product-iter term a next b)
(accumulate-iter * 1 term a next b))
(display "\nexer 1.32\n")
(define (sum-squares a b)
(sum square a inc b))
(define (sum-squares-iter a b)
(sum-iter square a inc b))
(define (product-squares a b)
(product square a inc b))
(define (product-squares-iter a b)
(product-iter square a inc b))
(sum-squares 1 5)
(sum-squares-iter 1 5)
(product-squares 1 5)
(product-squares-iter 1 5)
; exercise 1.33
(define (filtered-accumulate predicate combiner null-value term a next b)
(cond ((> a b) null-value)
((predicate a)
(combiner (term a) (filtered-accumulate predicate combiner
null-value term (next a) next b)))
(else (filtered-accumulate
predicate combiner null-value term (next a) next b))))
(define (sum-prime-squares a b)
(filtered-accumulate prime? + 0 square a inc b))
(define (mutual-prime? a b)
(= 1 (gcd a b)))
(define (identity. x) x)
(define (product-mutual-primes n)
(filtered-accumulate (lambda (x) (mutual-prime? x n)) * 1 identity. 1 inc (- n 1)))
(display "\nexercise 1.33\n")
(sum-prime-squares 1 20)
(product-mutual-primes 10)
; exercise 1.35
(define tolerance 0.00001)
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(define (try guess)
(let ((next (f guess)))
(if (close-enough? guess next) next
(try next))))
(try first-guess))
(define (golden-ratio)
(fixed-point (lambda (x) (+ 1 (/ 1 x))) 1.0))
(display "\nexercise 1.35\n")
(golden-ratio)
; exercise 1.41
(define (double proc)
(lambda (x) (proc (proc x))))
(display "\nexer 1.41\n")
;((double inc) 3)
(((double (double double)) inc) 5)
; exercise 1.42
; lambda로 만드는 프로시져는
; x를 인자로 받아서 (g x)를 호출 후 리턴값으로 f를 호출
(define (compose. f g)
(lambda (x) (f (g x))))
(display "\nexer 1.42\n")
((compose. square inc) 6)
; exercise 1.43
(define (identity. x) x)
(define (repeated f n)
(if (= n 0) identity.
(compose. f (repeated f (- n 1)))))
(display "\nexer 1.43\n")
((repeated square 2) 5)
((repeated square 1) 2)
((repeated square 2) 2)
((repeated square 3) 2)
((repeated square 4) 2)
(define (square n) (* n n))
(define (sum-of-larger-square i j k)
(let ((m (min i j k)))
(cond ((= m i) (+ (square j) (square k)))
((= m j) (+ (square i) (square k)))
(else (+ (square i) (square j))))))
(display "\nexer 1.3\n")
(sum-of-larger-square 10 30 40)
(sum-of-larger-square 10 40 30)
(sum-of-larger-square 30 10 40)
(sum-of-larger-square 30 40 10)
(sum-of-larger-square 40 10 30)
(sum-of-larger-square 40 30 10)
; exercise 1.8
(define (square n) (* n n))
(define (cube n) (* n n n))
(define (cbrt-iter guess x)
(if (good-enough? guess x) guess
(cbrt-iter (improve guess x) x)))
(define (improve guess x)
(+ (/ x (* 3 (square guess))) (/ (* 2 guess) 3)))
(define (average x y)
(/ (+ x y) 2))
(define (good-enough? guess x)
(< (abs (- (cube guess) x)) 0.001))
(define (cbrt x)
(cbrt-iter 1.0 x))
(display "\nexer 1.8\n")
(cbrt 9)
(cbrt 10)
(cbrt 125)
; exercise 1.11
(define (f n)
(if (< n 3) n
(+ (- n 1) (* 2 (f (- n 2))) (* 3 (f (- n 3))))))
(define (f-iter n)
(define (iter i j k result)
(cond ((> i n) result)
((< i 3) (iter (+ i 1) (- i 1) (- i 2) i))
(else (iter (+ i 1) result j (+ (- i 1) (* 2 j) (* 3 k))))))
(iter 1 0 0 0))
(define (test proc)
(define (iter i)
(cond ((<= i 10) (display "f(") (display i)
(display ") = ") (display (proc i)) (newline)
(iter (+ i 1)))
(else (newline))))
(iter 0))
(display "\nexer 1.11\n")
(test f)
(test f-iter)
; exercise 1.12
(define (invalid? row col)
(or (< row 0) (< col 0) (< row col)))
(define (pascal row col)
(cond ((invalid? row col) 'wrong)
((or (= col 0) (= row col))1)
(else (+ (pascal (- row 1) (- col 1)) (pascal (- row 1) col)))))
(display "\nexer 1.12\n")
(pascal 9 7)
; exercise 1.17
; 짝수면은 그 값의 두배, 홀수면 그냥 더하는 식으로 곱셈을 만드는것
(define (double n) (+ n n))
(define (halve n) (/ n 2))
(define (fast-mul a b)
(cond ((or (= a 0) (= b 0)) 0)
((= b 1) a)
((= a 1) b)
((even? b) (double (fast-mul a (halve b))))
(else (+ a (fast-mul a (- b 1))))))
(display "\nexer 1.17\n")
(fast-mul 2 3)
(fast-mul 2 4)
(fast-mul 2 5)
(fast-mul 100 20)
; exercise 1.18
; even일때 a를 double하는게 중요
(define (fast-mul-iter a b)
(define (iter a b result)
(cond ((or (= a 0) (= b 0)) 0)
((= b 1) (+ result a))
((even? b) (iter (double a) (halve b) result))
(else (iter a (- b 1) (+ result a)))))
(iter a b 0))
(display "\nexer 1.18\n")
(fast-mul-iter 2 3)
(fast-mul-iter 2 4)
(fast-mul-iter 2 5)
(fast-mul-iter 100 20)
; exercise 1-23
(define (next n)
(if (= n 2) 3
(+ n 2)))
(define (find-divisor n test-div)
(cond ((> (* test-div test-div) n) n)
((= 0 (remainder n test-div)) test-div)
(else (find-divisor n (next test-div)))))
(define (smallest-divisor n)
(find-divisor n 2))
(define (prime? n)
(if(>= 1 n) #f
(= n (smallest-divisor n))))
(display "\nexer 1.23\n")
(prime? 17)
(prime? 561)
; exercise 1.30
(define (inc n) (+ n 1))
(define (cube n) (* n n n))
(define (sum-cubes a b)
(sum cube a inc b))
(define (sum term a next b)
(define (iter a result)
(if (> a b) result
(iter (next a) (+ result (term a)))))
(iter a 0))
(display "\nexer 1.30\n")
(sum-cubes 1 10)
; exercise 1.32
(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-iter combiner null-value term a next b)
(define (iter a result)
(if (> a b) result
(iter (next a) (combiner (term a) result))))
(iter a null-value))
(define (sum term a next b)
(accumulate + 0 term a next b))
(define (product term a next b)
(accumulate * 1 term a next b))
(define (sum-iter term a next b)
(accumulate-iter + 0 term a next b))
(define (product-iter term a next b)
(accumulate-iter * 1 term a next b))
(display "\nexer 1.32\n")
(define (sum-squares a b)
(sum square a inc b))
(define (sum-squares-iter a b)
(sum-iter square a inc b))
(define (product-squares a b)
(product square a inc b))
(define (product-squares-iter a b)
(product-iter square a inc b))
(sum-squares 1 5)
(sum-squares-iter 1 5)
(product-squares 1 5)
(product-squares-iter 1 5)
; exercise 1.33
(define (filtered-accumulate predicate combiner null-value term a next b)
(cond ((> a b) null-value)
((predicate a)
(combiner (term a) (filtered-accumulate predicate combiner
null-value term (next a) next b)))
(else (filtered-accumulate
predicate combiner null-value term (next a) next b))))
(define (sum-prime-squares a b)
(filtered-accumulate prime? + 0 square a inc b))
(define (mutual-prime? a b)
(= 1 (gcd a b)))
(define (identity. x) x)
(define (product-mutual-primes n)
(filtered-accumulate (lambda (x) (mutual-prime? x n)) * 1 identity. 1 inc (- n 1)))
(display "\nexercise 1.33\n")
(sum-prime-squares 1 20)
(product-mutual-primes 10)
; exercise 1.35
(define tolerance 0.00001)
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(define (try guess)
(let ((next (f guess)))
(if (close-enough? guess next) next
(try next))))
(try first-guess))
(define (golden-ratio)
(fixed-point (lambda (x) (+ 1 (/ 1 x))) 1.0))
(display "\nexercise 1.35\n")
(golden-ratio)
; exercise 1.41
(define (double proc)
(lambda (x) (proc (proc x))))
(display "\nexer 1.41\n")
;((double inc) 3)
(((double (double double)) inc) 5)
; exercise 1.42
; lambda로 만드는 프로시져는
; x를 인자로 받아서 (g x)를 호출 후 리턴값으로 f를 호출
(define (compose. f g)
(lambda (x) (f (g x))))
(display "\nexer 1.42\n")
((compose. square inc) 6)
; exercise 1.43
(define (identity. x) x)
(define (repeated f n)
(if (= n 0) identity.
(compose. f (repeated f (- n 1)))))
(display "\nexer 1.43\n")
((repeated square 2) 5)
((repeated square 1) 2)
((repeated square 2) 2)
((repeated square 3) 2)
((repeated square 4) 2)
; sicp ch3 의 코드짜는 문제중 쉬워보이는것만 골라서 좀 품
; exer 3.1, 3.2, 3.3, 3.4, 3.7, 3.8, 3.18
; 12월에 포스팅했던것을 문제 몇문제 좀 더 풀구
; 정리좀해서 다시포스팅한것
; 이제 문제더 풀면 이 글에 그냥 수정해 계속해 붙여갈계획
;(plt scheme 의 개발환경 DrScheme에서 language를 standard(R5RS)로 맞춘후 테스트)
(define (error s . args)
(display s) (display " ")
(for-each (lambda(x) (display x) (display " ")) args)
(newline))
; exercise 3.1
(define (make-accumulator val)
(lambda (n)
(set! val (+ n val))
val))
(display "exer 3.1\n")
(define A (make-accumulator 5))
(define B (make-accumulator 5))
(A 10)
(A 10)
(B 10)
; exercise 3.2
(define (make-monitored f)
(let ((count 0))
(define (mf arg)
(cond ((eq? arg 'how-many-calls?) count)
((eq? arg 'reset-count) (set! count 0))
(else (set! count (+ count 1)) (f arg))))
mf))
(display "exer 3.2\n")
(define s (make-monitored sqrt))
(s 100)
(s 100)
(s 100)
(s 'how-many-calls?)
(s 'reset-count)
(s 'how-many-calls?)
; exercise 3.3
(define (make-account balance pass)
(let ((password pass))
(define (withdraw amount)
(cond ((>= balance amount) (set! balance (- balance amount)) balance)
(else 'Insufficient-funds)))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(define (incorrect-pass arg) 'Incorrect-password)
(define (dispatch pass m)
(cond ((not (eq? password pass)) incorrect-pass)
((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
(else (error "Unknown request - make-account" m))))
dispatch))
(display "\nexer 3.3\n")
(define acc (make-account 100 'secret-password))
((acc 'secret-password 'withdraw) 40)
((acc 'some-other-password 'deposit) 50)
; exercise 3.4
(define (make-account balance pass)
(let ((password pass) (incorrect-count 0))
(define (withdraw amount)
(cond ((>= balance amount) (set! balance (- balance amount)) balance)
(else 'Insufficient-funds)))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(define (incorrect-pass arg)
(set! incorrect-count (+ incorrect-count 1))
(if (> incorrect-count 7) (call-the-cops)
'Incorrect-password))
(define (call-the-cops)
'CALL-THE-COPS)
(define (dispatch pass m)
(cond ((not (eq? password pass)) incorrect-pass)
((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
(else (error "Unknown request - make-account" m))))
dispatch))
(display "\nexer 3.4\n")
(define acc (make-account 100 'secret-password))
((acc 'secret-password 'withdraw) 40)
(define (wrong-pass)
((acc 'some-other-password 'deposit) 50))
(wrong-pass)
(wrong-pass)
(wrong-pass)
(wrong-pass)
(wrong-pass)
(wrong-pass)
(wrong-pass)
(wrong-pass)
; exercise 3.7
(define (make-account balance pass)
(let ((password pass) (joint-password pass))
(define (withdraw amount)
(cond ((>= balance amount) (set! balance (- balance amount))
balance)
(else 'Insufficient-funds)))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(define (correct-pass? pass)
(eq? password pass))
(define (incorrect-pass arg)
'Incorrect-password)
(define (set-joint-pass joint-pass)
(set! joint-password joint-pass))
(define (correct-joint? joint)
(eq? joint-password joint))
(define (dispatch pass m)
(cond ((and (not (correct-pass? pass)) (not (correct-joint? pass))) incorrect-pass)
((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
((eq? m 'correct-pass?) correct-pass?)
((eq? m 'set-joint-pass) set-joint-pass)
(else (error "Unknown request - make-account" m))))
dispatch))
(define (make-joint acc pass joint-pass)
(if (not ((acc pass 'set-joint-pass) joint-pass))
'Cannot-make-joint)
acc)
(display "\nexer 3.7\n")
(define peter-acc (make-account 100 'open-sesame))
;(define paul-acc (make-joint peter-acc 'incorrect 'rosebud))
(define paul-acc (make-joint peter-acc 'open-sesame 'rosebud))
((paul-acc 'incorrect 'withdraw) 10)
((peter-acc 'open-sesame 'withdraw) 10)
((paul-acc 'rosebud 'withdraw) 10)
((paul-acc 'open-sesame 'withdraw) 10)
((peter-acc 'rosebud 'withdraw) 10)
; exercise 3.8
; 두번 테스트할때 앞의 테스트때문에 state가 변해있으니까는
; 초기화 할수있게 'init도 받을수있게한것이다.
(define f
(let ((state 1))
(lambda (x)
(cond ((number? x) (set! state (* state x)) state)
((eq? x 'init ) (set! state 1))
(else (error "invalid\n" x))))))
(display "\nexer 3.8\n")
; 왼쪽에서 오른쪽으로 평가했다구 볼때
; 1 * 0 = 0; 0 * 1 = 0; 0 + 0 = 0;
(+ (f 0) (f 1))
; 초기화
(f 'init)
;오른쪽에서왼쪽으로 평가했다구 볼때에
; 1 * 1 = 1; 1 * 0 = 0; 1 + 0 = 1
(+ (f 1) (f 0))
; exercise 3.18
(define (last-pair ls)
(if (or (null? ls) (null? (cdr ls))) ls
(last-pair (cdr ls))))
; 마지막 요소 cdr을 리스트 맨첨을가리키게함
; tail의 cdr을 head로 한것 원형 연결리스트가된다.
(define (make-cycle x)
(set-cdr! (last-pair x) x)
x)
; 일단 slow, fast를 두는데
; fast는 slow보다 한발 앞서서 출발해서
; slow는 한칸식, fast는 두칸씩 이동을 한다
; fast가 한바퀴돌구 다시 slow를 따라 잡으면 싸이클이 있는것이구
; 따라잡지 못하구 null이 있으면 싸이클이 없는것
(define (cycle? ls)
(define (loop slow fast)
(cond ((eq? slow fast) #t)
((or (null? slow) (null? fast)) #f)
((or (null? (cdr slow)) (null? (cdr fast))) #f)
(else (loop (cdr slow) (cddr fast)))))
(if (and (pair? ls) (pair? (cdr ls))) (loop (cdr ls) (cddr ls))
#f))
(define (test ls)
(for-each (lambda (x) (display x)
(if (cycle? x) (display " has a cycle\n")
(display " does not have a cycle\n"))) ls))
(display "\nexer 3-18\n")
(test (list (make-cycle '(a b c)) (make-cycle '(a b b))
'(a a a) '(a) '(a b b) '() '(a b a b)))
; exer 3.1, 3.2, 3.3, 3.4, 3.7, 3.8, 3.18
; 12월에 포스팅했던것을 문제 몇문제 좀 더 풀구
; 정리좀해서 다시포스팅한것
; 이제 문제더 풀면 이 글에 그냥 수정해 계속해 붙여갈계획
;(plt scheme 의 개발환경 DrScheme에서 language를 standard(R5RS)로 맞춘후 테스트)
(define (error s . args)
(display s) (display " ")
(for-each (lambda(x) (display x) (display " ")) args)
(newline))
; exercise 3.1
(define (make-accumulator val)
(lambda (n)
(set! val (+ n val))
val))
(display "exer 3.1\n")
(define A (make-accumulator 5))
(define B (make-accumulator 5))
(A 10)
(A 10)
(B 10)
; exercise 3.2
(define (make-monitored f)
(let ((count 0))
(define (mf arg)
(cond ((eq? arg 'how-many-calls?) count)
((eq? arg 'reset-count) (set! count 0))
(else (set! count (+ count 1)) (f arg))))
mf))
(display "exer 3.2\n")
(define s (make-monitored sqrt))
(s 100)
(s 100)
(s 100)
(s 'how-many-calls?)
(s 'reset-count)
(s 'how-many-calls?)
; exercise 3.3
(define (make-account balance pass)
(let ((password pass))
(define (withdraw amount)
(cond ((>= balance amount) (set! balance (- balance amount)) balance)
(else 'Insufficient-funds)))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(define (incorrect-pass arg) 'Incorrect-password)
(define (dispatch pass m)
(cond ((not (eq? password pass)) incorrect-pass)
((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
(else (error "Unknown request - make-account" m))))
dispatch))
(display "\nexer 3.3\n")
(define acc (make-account 100 'secret-password))
((acc 'secret-password 'withdraw) 40)
((acc 'some-other-password 'deposit) 50)
; exercise 3.4
(define (make-account balance pass)
(let ((password pass) (incorrect-count 0))
(define (withdraw amount)
(cond ((>= balance amount) (set! balance (- balance amount)) balance)
(else 'Insufficient-funds)))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(define (incorrect-pass arg)
(set! incorrect-count (+ incorrect-count 1))
(if (> incorrect-count 7) (call-the-cops)
'Incorrect-password))
(define (call-the-cops)
'CALL-THE-COPS)
(define (dispatch pass m)
(cond ((not (eq? password pass)) incorrect-pass)
((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
(else (error "Unknown request - make-account" m))))
dispatch))
(display "\nexer 3.4\n")
(define acc (make-account 100 'secret-password))
((acc 'secret-password 'withdraw) 40)
(define (wrong-pass)
((acc 'some-other-password 'deposit) 50))
(wrong-pass)
(wrong-pass)
(wrong-pass)
(wrong-pass)
(wrong-pass)
(wrong-pass)
(wrong-pass)
(wrong-pass)
; exercise 3.7
(define (make-account balance pass)
(let ((password pass) (joint-password pass))
(define (withdraw amount)
(cond ((>= balance amount) (set! balance (- balance amount))
balance)
(else 'Insufficient-funds)))
(define (deposit amount)
(set! balance (+ balance amount))
balance)
(define (correct-pass? pass)
(eq? password pass))
(define (incorrect-pass arg)
'Incorrect-password)
(define (set-joint-pass joint-pass)
(set! joint-password joint-pass))
(define (correct-joint? joint)
(eq? joint-password joint))
(define (dispatch pass m)
(cond ((and (not (correct-pass? pass)) (not (correct-joint? pass))) incorrect-pass)
((eq? m 'withdraw) withdraw)
((eq? m 'deposit) deposit)
((eq? m 'correct-pass?) correct-pass?)
((eq? m 'set-joint-pass) set-joint-pass)
(else (error "Unknown request - make-account" m))))
dispatch))
(define (make-joint acc pass joint-pass)
(if (not ((acc pass 'set-joint-pass) joint-pass))
'Cannot-make-joint)
acc)
(display "\nexer 3.7\n")
(define peter-acc (make-account 100 'open-sesame))
;(define paul-acc (make-joint peter-acc 'incorrect 'rosebud))
(define paul-acc (make-joint peter-acc 'open-sesame 'rosebud))
((paul-acc 'incorrect 'withdraw) 10)
((peter-acc 'open-sesame 'withdraw) 10)
((paul-acc 'rosebud 'withdraw) 10)
((paul-acc 'open-sesame 'withdraw) 10)
((peter-acc 'rosebud 'withdraw) 10)
; exercise 3.8
; 두번 테스트할때 앞의 테스트때문에 state가 변해있으니까는
; 초기화 할수있게 'init도 받을수있게한것이다.
(define f
(let ((state 1))
(lambda (x)
(cond ((number? x) (set! state (* state x)) state)
((eq? x 'init ) (set! state 1))
(else (error "invalid\n" x))))))
(display "\nexer 3.8\n")
; 왼쪽에서 오른쪽으로 평가했다구 볼때
; 1 * 0 = 0; 0 * 1 = 0; 0 + 0 = 0;
(+ (f 0) (f 1))
; 초기화
(f 'init)
;오른쪽에서왼쪽으로 평가했다구 볼때에
; 1 * 1 = 1; 1 * 0 = 0; 1 + 0 = 1
(+ (f 1) (f 0))
; exercise 3.18
(define (last-pair ls)
(if (or (null? ls) (null? (cdr ls))) ls
(last-pair (cdr ls))))
; 마지막 요소 cdr을 리스트 맨첨을가리키게함
; tail의 cdr을 head로 한것 원형 연결리스트가된다.
(define (make-cycle x)
(set-cdr! (last-pair x) x)
x)
; 일단 slow, fast를 두는데
; fast는 slow보다 한발 앞서서 출발해서
; slow는 한칸식, fast는 두칸씩 이동을 한다
; fast가 한바퀴돌구 다시 slow를 따라 잡으면 싸이클이 있는것이구
; 따라잡지 못하구 null이 있으면 싸이클이 없는것
(define (cycle? ls)
(define (loop slow fast)
(cond ((eq? slow fast) #t)
((or (null? slow) (null? fast)) #f)
((or (null? (cdr slow)) (null? (cdr fast))) #f)
(else (loop (cdr slow) (cddr fast)))))
(if (and (pair? ls) (pair? (cdr ls))) (loop (cdr ls) (cddr ls))
#f))
(define (test ls)
(for-each (lambda (x) (display x)
(if (cycle? x) (display " has a cycle\n")
(display " does not have a cycle\n"))) ls))
(display "\nexer 3-18\n")
(test (list (make-cycle '(a b c)) (make-cycle '(a b b))
'(a a a) '(a) '(a b b) '() '(a b a b)))

