Add solutions to exercises 2.53-57

This commit is contained in:
Petar Kapriš 2025-03-06 21:31:04 +01:00
parent 2a278157ad
commit f5131b16db
5 changed files with 219 additions and 0 deletions

7
ex-2.53.txt Normal file
View file

@ -0,0 +1,7 @@
(list 'a 'b 'c) -> (a b c)
(list (list 'george)) -> ((george))
(cdr '((x1 x2) (y1 y2))) -> ((y1 y2))
(cadr '((x1 x2) (y1 y2))) -> (y1 y2)
(pair? (car '(a short list))) -> #f
(memq 'red '((red shoes) (blue socks))) -> #f
(memq 'red '(red shoes blue socks)) -> (red shoes blue socks)

8
ex-2.54.scm Normal file
View file

@ -0,0 +1,8 @@
#lang sicp
(define (equal? a b)
(cond ((and (pair? a) (pair? b))
(and (equal? (car a) (car b)) (equal? (cdr a) (cdr b))))
((and (not (pair? a)) (not (pair? b)))
(and (eq? a b)))
(else #f)))

6
ex-2.55.txt Normal file
View file

@ -0,0 +1,6 @@
When typing (car ''abracadabra), the interpreter will transform the expression
into: (car (quote (quote abracadabra))), then it will evaluate.
First the symbol car becomes the car procedure, then quote gets evaluated as a
special form, which means the surrounded expression should be left
unevaluated, so we get something like: (#<car:procedure> (quote abracadabra)),
now car gets applied, and we get the expected result.

78
ex-2.56.scm Normal file
View file

@ -0,0 +1,78 @@
#lang sicp
(define (variable? x) (symbol? x))
(define (same-variable? v1 v2)
(and (variable? v1) (variable? v2) (eq? v1 v2)))
(define (=number? exp num) (and (number? exp) (= exp num)))
(define (make-sum a1 a2)
(cond ((=number? a1 0) a2)
((=number? a2 0) a1)
((and (number? a1) (number? a2))
(+ a1 a2))
(else (list '+ a1 a2))))
(define (make-product m1 m2)
(cond ((or (=number? m1 0) (=number? m2 0)) 0)
((=number? m1 1) m2)
((=number? m2 1) m1)
((and (number? m1) (number? m2)) (* m1 m2))
(else (list '* m1 m2))))
(define (sum? x) (and (pair? x) (eq? (car x) '+)))
(define (addend s) (cadr s))
(define (augend s) (caddr s))
(define (product? x) (and (pair? x) (eq? (car x) '*)))
(define (multiplier p) (cadr p))
(define (multiplicand p) (caddr p))
; for the purposes of our exponentiation exercise, we need to determine whether
; the exponent is constant so that we can apply the rule correctly
(define (constant? x var)
(or (number? x)
(and (variable? x) (not (same-variable? x var)))
(and (sum? x)
(constant? (addend x) var)
(constant? (augend x) var))
(and (product? x)
(constant? (multiplier x) var)
(constant? (multiplicand x) var))
(and (exponentiation? x)
(constant? (base x) var)
(constant? (exponent x) var))))
(define (make-exponentiation b e)
(cond ((=number? e 0) 1)
((=number? e 1) b)
((=number? b 0) 0)
((and (number? b) (number? e)) (expt b e))
(else (list '** b e))))
(define (exponentiation? x) (and (pair? x) (eq? (car x) '**)))
(define (base e) (cadr e))
(define (exponent e) (caddr e))
(define (deriv exp var)
(cond ((number? exp) 0)
((variable? exp) (if (same-variable? exp var) 1 0))
((sum? exp) (make-sum (deriv (addend exp) var)
(deriv (augend exp) var)))
((product? exp)
(make-sum
(make-product (multiplier exp)
(deriv (multiplicand exp) var))
(make-product (deriv (multiplier exp) var)
(multiplicand exp))))
((exponentiation? exp)
(if (constant? (exponent exp) var)
(make-product (make-product (exponent exp)
(make-exponentiation (base exp)
(make-sum
(exponent exp)
-1)))
(deriv (base exp) var))
(error "non-constant exponents not yet supported: DERIV" exp)))
(else
(error "unknown expression type: DERIV" exp))))

120
ex-2.57.scm Normal file
View file

@ -0,0 +1,120 @@
#lang sicp
; For these exercises, where I'm adding extra functionality to the deriv
; system. I chose to build each new feature off of the results of the previous
; exercises, rather than the unmodified code.
; This might make the solutions a bit more complicated than they have to be
(define (variable? x) (symbol? x))
(define (same-variable? v1 v2)
(and (variable? v1) (variable? v2) (eq? v1 v2)))
(define (=number? exp num) (and (number? exp) (= exp num)))
(define (not-number? x) (not (number? x)))
(define (filter predicate sequence)
(cond ((null? sequence) nil)
((predicate (car sequence))
(cons (car sequence)
(filter predicate (cdr sequence))))
(else (filter predicate (cdr sequence)))))
; only folds the beginning constants of the top-level expression
; e.g. (+ 2 3 5 x) becomes (+ 10 x)
; (+ x y z) -> (+ x y z)
; (* 2 0 3 x) -> 0
; (+ 3 -3 x) -> x
(define (fold exp)
(if (and (not (sum? exp)) (not (product? exp)))
exp ; if you don't know how to fold the exp, just leave it
(let* ((op (car exp))
(consts (filter number? (cdr exp)))
(rest (filter not-number? (cdr exp)))
(folded-const (if (eq? op '+)
(apply + consts)
(apply * consts)))
(args (cond ((and (eq? op '*) (= folded-const 0)) '(0))
((and (eq? op '*) (= folded-const 1)) rest)
((and (eq? op '+) (= folded-const 0)) rest)
(else (append (list folded-const) rest)))))
(cond ((and (eq? op '+) (= (length args) 0)) 0)
((and (eq? op '*) (= (length args) 0)) 1)
((= (length args) 1) (car args))
(else (append (list op) args))))))
; make-sum and make-product will be changed so that any arguments which are
; sums themselves will be spliced into the list, and all numbers will be placed
; in the front and folded
(define (make-sum a1 a2)
; l1 and l2 are lists to be spliced, if they're not sums, we make them lists
; of a list, so effectively, they don't get spliced
(let ((l1 (if (sum? a1) (cdr a1) (list a1)))
(l2 (if (sum? a2) (cdr a2) (list a2))))
(fold (append '(+) l1 l2))))
(define (make-product m1 m2)
(let ((l1 (if (product? m1) (cdr m1) (list m1)))
(l2 (if (product? m2) (cdr m2) (list m2))))
(fold (append '(*) l1 l2))))
(define (sum? x) (and (pair? x) (eq? (car x) '+)))
(define (addend s) (cadr s))
(define (augend s) (if (= (length s) 3)
(caddr s)
(cons '+ (cddr s))))
(define (product? x) (and (pair? x) (eq? (car x) '*)))
(define (multiplier p) (cadr p))
(define (multiplicand p) (if (= (length p) 3)
(caddr p)
(cons '* (cddr p))))
; for the purposes of our exponentiation exercise, we need to determine whether
; the exponent is constant so that we can apply the rule correctly
(define (constant? x var)
(or (number? x)
(and (variable? x) (not (same-variable? x var)))
(and (sum? x)
(constant? (addend x) var)
(constant? (augend x) var))
(and (product? x)
(constant? (multiplier x) var)
(constant? (multiplicand x) var))
(and (exponentiation? x)
(constant? (base x) var)
(constant? (exponent x) var))))
(define (make-exponentiation b e)
(cond ((=number? e 0) 1)
((=number? e 1) b)
((=number? b 0) 0)
((and (number? b) (number? e)) (expt b e))
(else (list '** b e))))
(define (exponentiation? x) (and (pair? x) (eq? (car x) '**)))
(define (base e) (cadr e))
(define (exponent e) (caddr e))
(define (deriv exp var)
(cond ((number? exp) 0)
((variable? exp) (if (same-variable? exp var) 1 0))
((sum? exp) (make-sum (deriv (addend exp) var)
(deriv (augend exp) var)))
((product? exp)
(make-sum
(make-product (multiplier exp)
(deriv (multiplicand exp) var))
(make-product (deriv (multiplier exp) var)
(multiplicand exp))))
((exponentiation? exp)
(if (constant? (exponent exp) var)
(make-product (make-product (exponent exp)
(make-exponentiation (base exp)
(make-sum
(exponent exp)
-1)))
(deriv (base exp) var))
(error "non-constant exponents not yet supported: DERIV" exp)))
(else
(error "unknown expression type: DERIV" exp))))