diff --git a/ex-2.53.txt b/ex-2.53.txt new file mode 100644 index 0000000..d7a47fc --- /dev/null +++ b/ex-2.53.txt @@ -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) diff --git a/ex-2.54.scm b/ex-2.54.scm new file mode 100644 index 0000000..a2d82ac --- /dev/null +++ b/ex-2.54.scm @@ -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))) \ No newline at end of file diff --git a/ex-2.55.txt b/ex-2.55.txt new file mode 100644 index 0000000..cedaebd --- /dev/null +++ b/ex-2.55.txt @@ -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: (# (quote abracadabra)), +now car gets applied, and we get the expected result. diff --git a/ex-2.56.scm b/ex-2.56.scm new file mode 100644 index 0000000..947ed3a --- /dev/null +++ b/ex-2.56.scm @@ -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)))) \ No newline at end of file diff --git a/ex-2.57.scm b/ex-2.57.scm new file mode 100644 index 0000000..bb2c91a --- /dev/null +++ b/ex-2.57.scm @@ -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)))) \ No newline at end of file