Compare commits
No commits in common. "6fb03cda1c299ee674daff468cd1c06d369d369c" and "2a278157adeed91d716f4c0fc55df484d3b79d2f" have entirely different histories.
6fb03cda1c
...
2a278157ad
113 changed files with 0 additions and 706 deletions
|
@ -1,7 +0,0 @@
|
||||||
(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)
|
|
|
@ -1,8 +0,0 @@
|
||||||
#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)))
|
|
|
@ -1,6 +0,0 @@
|
||||||
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.
|
|
|
@ -1,78 +0,0 @@
|
||||||
#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))))
|
|
|
@ -1,120 +0,0 @@
|
||||||
#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)))))
|
|
||||||
|
|
||||||
; folds the constants of the top-level expression
|
|
||||||
; e.g. (+ 2 3 x 5) becomes (+ 10 x)
|
|
||||||
; (+ x y z) -> (+ x y z)
|
|
||||||
; (* 2 x 0 3) -> 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))))
|
|
|
@ -1,272 +0,0 @@
|
||||||
#lang sicp
|
|
||||||
|
|
||||||
; Thoughts before the exercise:
|
|
||||||
; The first thing that I think might be an issue here is unnecessarily nested
|
|
||||||
; expressions:
|
|
||||||
; example: (((1 + 2 * 3))). We didn't have to think about these when we were simply
|
|
||||||
; using Lisp notation, since every list was basically guarranteed to have an
|
|
||||||
; operator. In our new case, every list with a length > 1 is going to have to
|
|
||||||
; have an operator, but we need a way to deal naturally with expressions of the
|
|
||||||
; form (x), where the result of the expression is obviously x.
|
|
||||||
|
|
||||||
; One idea would be to have a function that tries to access the innermost list.
|
|
||||||
; And then use it throughout all the other functions. But this would be quite
|
|
||||||
; painful. A better idea might be to consider this list to be a new kind of
|
|
||||||
; expression, called a grouping, we could have a predicate "grouping?", a
|
|
||||||
; selector "group-mem", and a constructor "group" (but there's no reason to ever
|
|
||||||
; use the constructor.)
|
|
||||||
|
|
||||||
; Okay, once we know how to deal with those, everything else should be clear: a
|
|
||||||
; sum is simply a list that contains +, a product is a list that contains * but
|
|
||||||
; not +, an exponentiation is a list which contains only the ** operator
|
|
||||||
; (speaking at the top level for all of these, of course).
|
|
||||||
|
|
||||||
; It's clear how to construct a sum, it's also clear how to get the addend and
|
|
||||||
; augend, and construction, in essence, is not complicated. However, if we want
|
|
||||||
; to try and keep the expressions somewhat simplified, like we did in previous
|
|
||||||
; exercises, we may need to do more work on the constructors.
|
|
||||||
|
|
||||||
(define op-order '(+ * **))
|
|
||||||
|
|
||||||
(define (list-index lst elem)
|
|
||||||
(define (li-rec lst elem index)
|
|
||||||
(cond ((null? lst) -1)
|
|
||||||
((eq? (car lst) elem) index)
|
|
||||||
(else (li-rec (cdr lst) elem (+ index 1)))))
|
|
||||||
(li-rec lst elem 0))
|
|
||||||
|
|
||||||
;compares precedence of ops
|
|
||||||
(define (lower-or-eq-op op1 op2)
|
|
||||||
(<= (list-index op-order op1)
|
|
||||||
(list-index op-order op2)))
|
|
||||||
|
|
||||||
; finds the-top-level op for an expression list:
|
|
||||||
; e.g. (1 + (2 * 4) * 3) => +
|
|
||||||
(define (top-op exp)
|
|
||||||
(define (top-op-rec exp op-order)
|
|
||||||
(cond ((null? op-order) nil)
|
|
||||||
((memq (car op-order) exp) (car op-order))
|
|
||||||
(else (top-op-rec exp (cdr op-order)))))
|
|
||||||
(top-op-rec exp op-order))
|
|
||||||
|
|
||||||
(define (make-group exp)
|
|
||||||
(list exp))
|
|
||||||
|
|
||||||
; a group is just a list of length 1
|
|
||||||
(define (group? exp)
|
|
||||||
(and (pair? exp) (null? (cdr exp))))
|
|
||||||
|
|
||||||
(define (degroup exp)
|
|
||||||
(car exp))
|
|
||||||
|
|
||||||
; not the real deconstructor, but very useful
|
|
||||||
(define (degroup-repeated exp)
|
|
||||||
(if (group? exp)
|
|
||||||
(degroup-repeated (degroup exp))
|
|
||||||
exp))
|
|
||||||
|
|
||||||
; We're gonna be doing this, a lot
|
|
||||||
; turns a list such as (1 (2 * 4) 3) into (1 + (2 * 4) + 3)
|
|
||||||
(define (splice-op arglist op)
|
|
||||||
(cond ((null? arglist) nil) ; 0 args
|
|
||||||
((null? (cdr arglist)) arglist) ; 1 arg
|
|
||||||
(else (cons (car arglist)
|
|
||||||
(cons op
|
|
||||||
(splice-op (cdr arglist) op))))))
|
|
||||||
|
|
||||||
; This does the opposite, assumes op is the top-op of the expression
|
|
||||||
; eg. (1 + 2 * 4 + 3) => (1 (2 * 4) 3)
|
|
||||||
(define (extract-op exp op)
|
|
||||||
(cond ((null? exp) nil)
|
|
||||||
((null? (cdr exp)) exp)
|
|
||||||
((null? (cddr exp)) (error "Extract-op from two-member list" exp))
|
|
||||||
((not (memq (cadr exp) op-order)) (error "Extract-op, second element not an op" exp))
|
|
||||||
((eq? (cadr exp) op) (cons (car exp)
|
|
||||||
(extract-op (cddr exp) op)))
|
|
||||||
(else (cons (grab-subexp exp op)
|
|
||||||
(extract-op (drop-subexp exp op))))))
|
|
||||||
|
|
||||||
; two helper functions for extract-op, extract a beginning subexpression, which uses a
|
|
||||||
; higher precedence op
|
|
||||||
; e.g. exp. (2 * 4 + 3 + 5), op: +
|
|
||||||
; (grab-subexp exp op) => (2 * 4)
|
|
||||||
; (drop-subexp exp op) => (3 + 5)
|
|
||||||
;
|
|
||||||
; exp. (2 * 4 + 3), op: +
|
|
||||||
; (grab-subexp exp op) => (2 * 4)
|
|
||||||
; (drop-subexp exp op) => (3)
|
|
||||||
;
|
|
||||||
; exp. (2 * 4), op: +
|
|
||||||
; (grab-subexp exp op) => (2 * 4)
|
|
||||||
; (drop-subexp exp op) => ()
|
|
||||||
(define (grab-subexp exp op)
|
|
||||||
(if (or (null? exp) (eq? op (car exp)))
|
|
||||||
nil
|
|
||||||
; if we reach the end of the list, or the top-level op, we stop adding elements
|
|
||||||
(cons (car exp)
|
|
||||||
(grab-subexp (cdr exp) op))))
|
|
||||||
|
|
||||||
(define (drop-subexp exp op)
|
|
||||||
(let ((list-from-op (memq op exp)))
|
|
||||||
(if (not list-from-op)
|
|
||||||
nil
|
|
||||||
(cdr list-from-op))))
|
|
||||||
|
|
||||||
; accepts a complex expression containing at least one operations
|
|
||||||
; removes parentheses around subexpressions which use an operator with higher
|
|
||||||
; precedence
|
|
||||||
(define (remove-parens list op)
|
|
||||||
(cond ((null? list) nil)
|
|
||||||
((or (number? (car list))
|
|
||||||
(variable? (car list))
|
|
||||||
; we don't want to remove parentheses around ops of the same precedence
|
|
||||||
; since we did that while extracting argument lists. And if our operation
|
|
||||||
; is not associative (e.g. **) this could cause an error
|
|
||||||
(lower-or-eq-op (top-op (car list)) op))
|
|
||||||
(cons (car list) (remove-parens (cdr list) op)))
|
|
||||||
; in any other case, it's either a grouping, or a higher-precedence op
|
|
||||||
; and we can get rid of the parens
|
|
||||||
(else (append (car list) (remove-parens (cdr list) op)))))
|
|
||||||
|
|
||||||
(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)))))
|
|
||||||
|
|
||||||
; instead of the "fold" function in the previous exercise, here we have several
|
|
||||||
; "optimize" functions for arglists
|
|
||||||
(define (optimize-+ args)
|
|
||||||
(let* ((consts (filter number? args))
|
|
||||||
(rest (filter not-number? args))
|
|
||||||
(folded-const (apply + consts)))
|
|
||||||
(if (= folded-const 0)
|
|
||||||
rest
|
|
||||||
(append (list folded-const) rest))))
|
|
||||||
|
|
||||||
(define (optimize-* args)
|
|
||||||
(let* ((consts (filter number? args))
|
|
||||||
(rest (filter not-number? args))
|
|
||||||
(folded-const (apply * consts)))
|
|
||||||
(cond ((= folded-const 1) rest)
|
|
||||||
((= folded-const 0) '(0))
|
|
||||||
(else (append (list folded-const) rest)))))
|
|
||||||
|
|
||||||
(define (optimize-** args)
|
|
||||||
(cond ((null? args) (error "Empty arg list for ** in optimize-**"))
|
|
||||||
((null? (cdr args)) args)
|
|
||||||
(else
|
|
||||||
(let* ((new-args (cons (car args) ; if len(args)>=2, we first try to
|
|
||||||
; compute the right hand side recursively
|
|
||||||
; if afterwards len(args)==2, we try that too
|
|
||||||
(optimize-** (cdr args))))
|
|
||||||
(len=2 (null? (cddr new-args)))
|
|
||||||
(fst (car new-args))
|
|
||||||
(snd (cadr new-args)))
|
|
||||||
(cond ((and len=2 (number? fst) (number? snd)) ; both constant
|
|
||||||
(list (expt (car new-args) (cadr new-args))))
|
|
||||||
((and len=2 (=number? snd 1))
|
|
||||||
(list fst))
|
|
||||||
(else new-args))))))
|
|
||||||
|
|
||||||
(define (make-op op x1 x2)
|
|
||||||
(let* ((ux1 (degroup-repeated x1)) ; now we know our args are either simple nums/vars or
|
|
||||||
(ux2 (degroup-repeated x2)) ; they're an operation (+,*,**)
|
|
||||||
(exp->arglist
|
|
||||||
(lambda (exp) ; as long as our subexpression: exp. is not an operation of the exact
|
|
||||||
; same type as the one we're creating, the list of extracted args
|
|
||||||
; should just look like (exp). Otherwise, we need to extract the
|
|
||||||
; operators from the list
|
|
||||||
; e.g. op=+, x1 = (2 + 3 + 2 * 4) -> result=(2 3 (2 * 4))
|
|
||||||
; x2 = (2 * 4) -> result=((2 * 4))
|
|
||||||
; then we simply append the lists
|
|
||||||
(if (or (variable? exp)
|
|
||||||
(number? exp)
|
|
||||||
(not (eq? op (top-op exp))))
|
|
||||||
(list exp)
|
|
||||||
(extract-op exp op))))
|
|
||||||
(arglist1 (if (and (eq? op '**) ; if both the op we're making, and the left-hand side
|
|
||||||
(exponentiation? ux1)) ; are an exponentiation, we need to simply
|
|
||||||
(list ux1) ; parenthesise the left-hand side, don't extract args,
|
|
||||||
(exp->arglist ux1))) ; because ** is right-associative
|
|
||||||
(arglist2 (exp->arglist ux2))
|
|
||||||
(args (append arglist1 arglist2))
|
|
||||||
(opt-args (cond ((eq? op '+) (optimize-+ args))
|
|
||||||
((eq? op '*) (optimize-* args))
|
|
||||||
((eq? op '**) (optimize-** args)))))
|
|
||||||
; keep in mind, after this step ** must have at least 1 argument,
|
|
||||||
; +,* can have 0
|
|
||||||
(cond ((and (eq? op '+) (= (length opt-args) 0)) 0)
|
|
||||||
((and (eq? op '*) (= (length opt-args) 0)) 1)
|
|
||||||
((= (length opt-args) 1) (car opt-args))
|
|
||||||
(else (remove-parens (splice-op opt-args op) op)))))
|
|
||||||
|
|
||||||
(define (make-sum a1 a2)
|
|
||||||
(make-op '+ a1 a2))
|
|
||||||
|
|
||||||
(define (make-product m1 m2)
|
|
||||||
(make-op '* m1 m2))
|
|
||||||
|
|
||||||
(define (sum? x) (and (pair? x) (eq? (top-op x) '+)))
|
|
||||||
; when we split the list using grab/drop-subexp, we might get a list of length
|
|
||||||
; 1 on either end
|
|
||||||
(define (addend s) (degroup-repeated (grab-subexp s '+)))
|
|
||||||
(define (augend s) (degroup-repeated (drop-subexp s '+)))
|
|
||||||
|
|
||||||
(define (product? x) (and (pair? x) (eq? (top-op x) '*)))
|
|
||||||
(define (multiplier p) (degroup-repeated (grab-subexp p '*)))
|
|
||||||
(define (multiplicand p) (degroup-repeated (drop-subexp 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)
|
|
||||||
(make-op '** b e))
|
|
||||||
|
|
||||||
(define (exponentiation? x) (and (pair? x) (eq? (top-op x) '**)))
|
|
||||||
(define (base e) (car 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))))
|
|
|
@ -1,15 +0,0 @@
|
||||||
#lang sicp
|
|
||||||
|
|
||||||
(define (element-of-set? x set)
|
|
||||||
(cond ((null? set) false)
|
|
||||||
((equal? x (car set)) true)
|
|
||||||
(else (element-of-set? x (cdr set)))))
|
|
||||||
|
|
||||||
; we will simply adjoin elements of set1 to set2 if they are not there
|
|
||||||
; and drop them if they are there
|
|
||||||
(define (union-set set1 set2)
|
|
||||||
(cond ((null? set1) set2)
|
|
||||||
((null? set2) set1)
|
|
||||||
((element-of-set? (car set1) set2)
|
|
||||||
(union-set (cdr set1) set2))
|
|
||||||
(else (union-set (cdr set1) (cons (car set1) set2)))))
|
|
|
@ -1,24 +0,0 @@
|
||||||
#lang sicp
|
|
||||||
|
|
||||||
; element-of-set? is the exact same
|
|
||||||
; O(n)
|
|
||||||
(define (element-of-set? x set)
|
|
||||||
(cond ((null? set) false)
|
|
||||||
((equal? x (car set)) true)
|
|
||||||
(else (element-of-set? x (cdr set)))))
|
|
||||||
|
|
||||||
; O(1)
|
|
||||||
(define (adjoin-set x set)
|
|
||||||
(cons x set)) ; we don't have to check anymore
|
|
||||||
|
|
||||||
; O(n), where n is the length of set1
|
|
||||||
(define (union-set set1 set2)
|
|
||||||
(append set1 set2))
|
|
||||||
|
|
||||||
; intersection-set can still be the exact same
|
|
||||||
; O(n^2)
|
|
||||||
(define (intersection-set set1 set2)
|
|
||||||
(cond ((or (null? set1) (null? set2)) '())
|
|
||||||
((element-of-set? (car set1) set2)
|
|
||||||
(cons (car set1) (intersection-set (cdr set1) set2)))
|
|
||||||
(else (intersection-set (cdr set1) set2))))
|
|
|
@ -1,7 +0,0 @@
|
||||||
#lang sicp
|
|
||||||
|
|
||||||
(define (adjoin-set x set)
|
|
||||||
(cond ((null? set) (list x))
|
|
||||||
((< x (car set)) (cons x set))
|
|
||||||
((= x (car set)) set)
|
|
||||||
((> x (car set)) (cons (car set) (adjoin-set x (cdr set))))))
|
|
|
@ -1,11 +0,0 @@
|
||||||
#lang sicp
|
|
||||||
|
|
||||||
(define (union-set set1 set2)
|
|
||||||
(cond ((null? set1) set2)
|
|
||||||
((null? set2) set1)
|
|
||||||
((< (car set1) (car set2)) (cons (car set1)
|
|
||||||
(union-set (cdr set1) set2)))
|
|
||||||
((= (car set1) (car set2)) (cons (car set1)
|
|
||||||
(union-set (cdr set1) (cdr set2))))
|
|
||||||
((> (car set1) (car set2)) (cons (car set2)
|
|
||||||
(union-set set1 (cdr set2))))))
|
|
|
@ -1,16 +0,0 @@
|
||||||
a)
|
|
||||||
From my understanding, yes, the lists produced are always going to be equal?
|
|
||||||
given the same tree
|
|
||||||
|
|
||||||
b)
|
|
||||||
No, they don't, remember than when we `append` two lists, the cons cells for
|
|
||||||
the first list have to all be reconstructed, which is an additional O(n)
|
|
||||||
steps, where n is len(first-list).
|
|
||||||
|
|
||||||
This means that when we break up a tree in (tree->list-1 tree) T(n) = T(n/2) +
|
|
||||||
O(n) + T(n/2)
|
|
||||||
|
|
||||||
tree->list-2 has one cons operation, which is constant, for each entry, which
|
|
||||||
means the order of growth is O(n)
|
|
||||||
|
|
||||||
On the other hand, tree->list-1 has order of growth: O(n log n)
|
|
|
@ -1,22 +0,0 @@
|
||||||
a)
|
|
||||||
partial-tree takes a list elts, and n, a number of starting elements which it
|
|
||||||
will process, it arranges these n elements into a tree and returns a list with
|
|
||||||
2 elements. The first is a tree of the first n elements, the second is a list
|
|
||||||
of the remaining elements. The arrangement is done by making a tree out of
|
|
||||||
(n-1)/2 elements recursively, then adding the one element at the start of the
|
|
||||||
remainder-list as the current entry, then taking the other half of the n
|
|
||||||
elements, and recursively arranging them as well.
|
|
||||||
|
|
||||||
(list->tree '(1 3 5 7 9 11))
|
|
||||||
==
|
|
||||||
5
|
|
||||||
/ \
|
|
||||||
1 9
|
|
||||||
\ / \
|
|
||||||
3 7 11
|
|
||||||
|
|
||||||
b)
|
|
||||||
Since only the top-level list has its length calculated O(n), while all the
|
|
||||||
lower ones have theirs calculated in constant time. And in general, every
|
|
||||||
specific call of partial-tree has a number of constant operations, the total
|
|
||||||
would be O(n)
|
|
|
@ -1,101 +0,0 @@
|
||||||
#lang sicp
|
|
||||||
|
|
||||||
; the helper functions:
|
|
||||||
|
|
||||||
(define (entry tree) (car tree))
|
|
||||||
(define (left-branch tree) (cadr tree))
|
|
||||||
(define (right-branch tree) (caddr tree))
|
|
||||||
(define (make-tree entry left right)
|
|
||||||
(list entry left right))
|
|
||||||
|
|
||||||
(define (element-of-set? x set)
|
|
||||||
(cond ((null? set) false)
|
|
||||||
((= x (entry set)) true)
|
|
||||||
((< x (entry set))
|
|
||||||
(element-of-set? x (left-branch set)))
|
|
||||||
((> x (entry set))
|
|
||||||
(element-of-set? x (right-branch set)))))
|
|
||||||
|
|
||||||
(define (adjoin-set x set)
|
|
||||||
(cond ((null? set) (make-tree x '() '()))
|
|
||||||
((= x (entry set)) set)
|
|
||||||
((< x (entry set))
|
|
||||||
(make-tree (entry set)
|
|
||||||
(adjoin-set x (left-branch set))
|
|
||||||
(right-branch set)))
|
|
||||||
((> x (entry set))
|
|
||||||
(make-tree (entry set) (left-branch set)
|
|
||||||
(adjoin-set x (right-branch set))))))
|
|
||||||
|
|
||||||
(define (tree->list-2 tree)
|
|
||||||
(define (copy-to-list tree result-list)
|
|
||||||
(if (null? tree)
|
|
||||||
result-list
|
|
||||||
(copy-to-list (left-branch tree)
|
|
||||||
(cons (entry tree)
|
|
||||||
(copy-to-list
|
|
||||||
(right-branch tree)
|
|
||||||
result-list)))))
|
|
||||||
(copy-to-list tree '()))
|
|
||||||
|
|
||||||
(define tree->list tree->list-2)
|
|
||||||
|
|
||||||
(define (list->tree elements)
|
|
||||||
(car (partial-tree elements (length elements))))
|
|
||||||
|
|
||||||
(define (partial-tree elts n)
|
|
||||||
(if (= n 0)
|
|
||||||
(cons '() elts)
|
|
||||||
(let ((left-size (quotient (- n 1) 2)))
|
|
||||||
(let ((left-result
|
|
||||||
(partial-tree elts left-size)))
|
|
||||||
(let ((left-tree (car left-result))
|
|
||||||
(non-left-elts (cdr left-result))
|
|
||||||
(right-size (- n (+ left-size 1))))
|
|
||||||
(let ((this-entry (car non-left-elts))
|
|
||||||
(right-result
|
|
||||||
(partial-tree
|
|
||||||
(cdr non-left-elts)
|
|
||||||
right-size)))
|
|
||||||
(let ((right-tree (car right-result))
|
|
||||||
(remaining-elts
|
|
||||||
(cdr right-result)))
|
|
||||||
(cons (make-tree this-entry
|
|
||||||
left-tree
|
|
||||||
right-tree)
|
|
||||||
remaining-elts))))))))
|
|
||||||
|
|
||||||
|
|
||||||
; the exercise itself
|
|
||||||
|
|
||||||
(define (union-olist set1 set2)
|
|
||||||
(cond ((null? set1) set2)
|
|
||||||
((null? set2) set1)
|
|
||||||
((< (car set1) (car set2)) (cons (car set1)
|
|
||||||
(union-olist (cdr set1) set2)))
|
|
||||||
((= (car set1) (car set2)) (cons (car set1)
|
|
||||||
(union-olist (cdr set1) (cdr set2))))
|
|
||||||
((> (car set1) (car set2)) (cons (car set2)
|
|
||||||
(union-olist set1 (cdr set2))))))
|
|
||||||
|
|
||||||
(define (intersection-olist set1 set2)
|
|
||||||
(if (or (null? set1) (null? set2))
|
|
||||||
'()
|
|
||||||
(let ((x1 (car set1)) (x2 (car set2)))
|
|
||||||
(cond ((= x1 x2)
|
|
||||||
(cons x1 (intersection-olist (cdr set1)
|
|
||||||
(cdr set2))))
|
|
||||||
((< x1 x2)
|
|
||||||
(intersection-olist (cdr set1) set2))
|
|
||||||
((< x2 x1)
|
|
||||||
(intersection-olist set1 (cdr set2)))))))
|
|
||||||
|
|
||||||
(define (union-set set1 set2)
|
|
||||||
(list->tree
|
|
||||||
(union-olist (tree->list set1)
|
|
||||||
(tree->list set2))))
|
|
||||||
|
|
||||||
(define (intersection-set set1 set2)
|
|
||||||
(list->tree
|
|
||||||
(intersection-olist (tree->list set1)
|
|
||||||
(tree->list set2))))
|
|
|
@ -1,19 +0,0 @@
|
||||||
#lang sicp
|
|
||||||
|
|
||||||
(define (entry tree) (car tree))
|
|
||||||
(define (left-branch tree) (cadr tree))
|
|
||||||
(define (right-branch tree) (caddr tree))
|
|
||||||
(define (make-tree entry left right)
|
|
||||||
(list entry left right))
|
|
||||||
|
|
||||||
(define (key record)
|
|
||||||
(car record))
|
|
||||||
|
|
||||||
(define (lookup given-key set-of-records)
|
|
||||||
(cond ((null? set-of-records) false)
|
|
||||||
((= given-key (key (entry set-of-records)))
|
|
||||||
(entry set-of-records))
|
|
||||||
((< given-key (key (entry set-of-records)))
|
|
||||||
(lookup given-key (left-branch set-of-records)))
|
|
||||||
((> given-key (key (entry set-of-records)))
|
|
||||||
(lookup given-key (right-branch set-of-records)))))
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue