More progress. Got up to 2.65
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,2 +1,3 @@
 | 
				
			|||||||
\#*
 | 
					\#*
 | 
				
			||||||
*~
 | 
					*~
 | 
				
			||||||
 | 
					*.fasl
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										54
									
								
								ex-2-40.rkt
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								ex-2-40.rkt
									
									
									
									
									
								
							@@ -133,6 +133,7 @@
 | 
				
			|||||||
  (make-vect (* (vect-xcoor v) n)
 | 
					  (make-vect (* (vect-xcoor v) n)
 | 
				
			||||||
             (* (vect-ycoor v) n)))
 | 
					             (* (vect-ycoor v) n)))
 | 
				
			||||||
;; 2.47
 | 
					;; 2.47
 | 
				
			||||||
 | 
					;; a list-of-three representation
 | 
				
			||||||
(define (make-frame1 origin edge1 edge2)
 | 
					(define (make-frame1 origin edge1 edge2)
 | 
				
			||||||
  (list origin edge1 edge2))
 | 
					  (list origin edge1 edge2))
 | 
				
			||||||
(define (frame-origin1 f)
 | 
					(define (frame-origin1 f)
 | 
				
			||||||
@@ -142,8 +143,61 @@
 | 
				
			|||||||
(define (frame-edge2-1 f)
 | 
					(define (frame-edge2-1 f)
 | 
				
			||||||
  (list-ref f 2))
 | 
					  (list-ref f 2))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					; two cons representation
 | 
				
			||||||
(define (make-frame2 origin edge1 edge2)
 | 
					(define (make-frame2 origin edge1 edge2)
 | 
				
			||||||
  (cons origin (cons edge1 edge2)))
 | 
					  (cons origin (cons edge1 edge2)))
 | 
				
			||||||
(define frame-origin2 car)
 | 
					(define frame-origin2 car)
 | 
				
			||||||
(define frame-edge1-2 cadr)
 | 
					(define frame-edge1-2 cadr)
 | 
				
			||||||
(define frame-edge2-2 cddr)
 | 
					(define frame-edge2-2 cddr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					; choose one impl
 | 
				
			||||||
 | 
					(define origin-frame frame-origin2)
 | 
				
			||||||
 | 
					(define edge1-frame frame-edge1-2)
 | 
				
			||||||
 | 
					(define edge2-frame frame-edge2-2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; 2.48
 | 
				
			||||||
 | 
					;; decided to stop using define-struct for this, as it kinda
 | 
				
			||||||
 | 
					;; screws with the naming conventions
 | 
				
			||||||
 | 
					(define make-segment cons)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(define start-segment car)
 | 
				
			||||||
 | 
					(define end-segment cdr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; 2.49
 | 
				
			||||||
 | 
					(define (draw-line x y) #f)
 | 
				
			||||||
 | 
					(define (frame-coord-map frame)
 | 
				
			||||||
 | 
					  (lambda (v)
 | 
				
			||||||
 | 
					    (add-vect
 | 
				
			||||||
 | 
					     (origin-frame frame)
 | 
				
			||||||
 | 
					     (add-vect (scale-vect (xcoor-vect v) (edge1-frame frame))
 | 
				
			||||||
 | 
					               (scale-vect (ycoor-vect v) (edge2-frame frame))))))
 | 
				
			||||||
 | 
					(define (segments->painter segment-list)
 | 
				
			||||||
 | 
					  (lambda (frame)
 | 
				
			||||||
 | 
					    (for-each
 | 
				
			||||||
 | 
					     (lambda (segment)
 | 
				
			||||||
 | 
					       (draw-line
 | 
				
			||||||
 | 
					        ((frame-coord-map frame)
 | 
				
			||||||
 | 
					         (start-segment segment))
 | 
				
			||||||
 | 
					        ((frame-coord-map frame)
 | 
				
			||||||
 | 
					         (end-segment segment))))
 | 
				
			||||||
 | 
					     segment-list)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					; I really should have thought of making a better
 | 
				
			||||||
 | 
					; notation for these things, it would have been super easy too.
 | 
				
			||||||
 | 
					; but I've already written it, so it stays, I guess.
 | 
				
			||||||
 | 
					(define outline-painter
 | 
				
			||||||
 | 
					  (segments->painter
 | 
				
			||||||
 | 
					   (list (make-segment (make-vect 0 0) (make-vect 0 1))
 | 
				
			||||||
 | 
					         (make-segment (make-vect 0 0) (make-vect 1 0))
 | 
				
			||||||
 | 
					         (make-segment (make-vect 1 0) (make-vect 1 1))
 | 
				
			||||||
 | 
					         (make-segment (make-vect 0 1) (make-vect 1 1)))))
 | 
				
			||||||
 | 
					(define x-painter
 | 
				
			||||||
 | 
					  (segments->painter
 | 
				
			||||||
 | 
					   (list (make-segment (make-vect 0 0) (make-vect 1 1))
 | 
				
			||||||
 | 
					         (make-segment (make-vect 1 0) (make-vect 0 1)))))
 | 
				
			||||||
 | 
					(define diamond
 | 
				
			||||||
 | 
					  (segments->painter
 | 
				
			||||||
 | 
					   (list (make-segment (make-vect 0.5 0) (make-vect 0 0.5))
 | 
				
			||||||
 | 
					         (make-segment (make-vect 0.5 0) (make-vect 1 0.5))
 | 
				
			||||||
 | 
					         (make-segment (make-vect 0 0.5) (make-vect 0.5 1))
 | 
				
			||||||
 | 
					         (make-segment (make-vect 1 0.5) (make-vect 0.5 1)))))
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										212
									
								
								ex-2-53.lisp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								ex-2-53.lisp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,212 @@
 | 
				
			|||||||
 | 
					;; I'm using common lisp from this point on,
 | 
				
			||||||
 | 
					;; I honestly kind of got bored with scheme.
 | 
				
			||||||
 | 
					;; CL is pretty good though. using scheme now.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; well, this means we gotta reimplement
 | 
				
			||||||
 | 
					;; a lot of the things in the book, because we can't
 | 
				
			||||||
 | 
					;; just copy&paste them. but that's fine.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; as an aside, I probably could get pretty close
 | 
				
			||||||
 | 
					;; to being able to copy-paste with this macro:
 | 
				
			||||||
 | 
					(defun rest-symbol (param-list)
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((null param-list)
 | 
				
			||||||
 | 
					     nil)
 | 
				
			||||||
 | 
					    ((consp param-list)
 | 
				
			||||||
 | 
					     (cons (car param-list) (rest-symbol (cdr param-list))))
 | 
				
			||||||
 | 
					    ((symbolp param-list)
 | 
				
			||||||
 | 
					     (list '&rest param-list))
 | 
				
			||||||
 | 
					    (t (error "non-symbol as tail element of parameter list."))))
 | 
				
			||||||
 | 
					(defmacro define (name &body body)
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((symbolp name) `(defparameter ,name ,@body))
 | 
				
			||||||
 | 
					    ((listp name) `(defun ,(first name)
 | 
				
			||||||
 | 
							       ,(rest-symbol (rest name))
 | 
				
			||||||
 | 
							     ,@body))
 | 
				
			||||||
 | 
					    (t (error "Whoops, cannot expand define"))))
 | 
				
			||||||
 | 
					;; This essentially allows us to use scheme-style
 | 
				
			||||||
 | 
					;; define syntax for defining variables and
 | 
				
			||||||
 | 
					;; procedures.
 | 
				
			||||||
 | 
					;; I won't be using this for every single exercise though,
 | 
				
			||||||
 | 
					;; cuz that's kinda boring.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun memq (item l)
 | 
				
			||||||
 | 
					  "This definition doesn't have many differences from the book."
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((null l) nil)
 | 
				
			||||||
 | 
					    ((eq item (car l)) l)
 | 
				
			||||||
 | 
					    (t (memq item (cdr l)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(memq 'apple '(pear banana prune)) ;; => NIL
 | 
				
			||||||
 | 
					(memq 'apple '(x (apple sauce) y apple pear)) ;; = (APPLE PEAR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; EX 2.54
 | 
				
			||||||
 | 
					(defun my-equal? (a b)
 | 
				
			||||||
 | 
					  "fun fact: when I first began common lisp, I used to be kind of annoyed/afraid
 | 
				
			||||||
 | 
					of defining functions recursively like this. I thought this would be less efficient
 | 
				
			||||||
 | 
					than using a loop like in C.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Now I know better of course. On SBCL, this is fully tail call optimised,
 | 
				
			||||||
 | 
					and therefore can be used on lists of any length with no fear for
 | 
				
			||||||
 | 
					stack overflow. It generates an iterative process, despite being \"recursive\"
 | 
				
			||||||
 | 
					so this is actually as efficient as can be."
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((eq a b)  t)
 | 
				
			||||||
 | 
					    ((and (listp a) (listp b))
 | 
				
			||||||
 | 
					     (if (my-equal? (car a) (car b))
 | 
				
			||||||
 | 
						 (my-equal? (cdr a) (cdr b))
 | 
				
			||||||
 | 
						 nil))
 | 
				
			||||||
 | 
					    (t nil)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; Wooooo! symbolic derivation.
 | 
				
			||||||
 | 
					;; ex 2.56 is inside here somewhere
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun var= (v1 v2)
 | 
				
			||||||
 | 
					  (and (symbolp v1) (symbolp v2) (eq v1 v2)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun var!= (v1 v2)
 | 
				
			||||||
 | 
					  (and (symbolp v1) (symbolp v2) (not (eq v1 v2))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun sump (e)
 | 
				
			||||||
 | 
					  (and (listp e) (eq '+ (car e))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun addend (e)
 | 
				
			||||||
 | 
					  (second e))
 | 
				
			||||||
 | 
					(defun augend (e)
 | 
				
			||||||
 | 
					  ;; 2.57
 | 
				
			||||||
 | 
					  (if (> (length e) 3)
 | 
				
			||||||
 | 
					      `(+ ,@(cddr e))
 | 
				
			||||||
 | 
					      (third e)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun productp (e)
 | 
				
			||||||
 | 
					  (and (listp e) (eq '* (car e))))
 | 
				
			||||||
 | 
					(defun multiplier (e)
 | 
				
			||||||
 | 
					  (second e))
 | 
				
			||||||
 | 
					(defun multiplicand (e)
 | 
				
			||||||
 | 
					  ;; 2.57
 | 
				
			||||||
 | 
					  (if (> (length e) 3)
 | 
				
			||||||
 | 
					      `(* ,@(cddr e))
 | 
				
			||||||
 | 
					      (third e)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun number= (a b)
 | 
				
			||||||
 | 
					  (and (numberp a) (numberp b) (= a b)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun make-sum (a b)
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((and (numberp a) (numberp b)) (+ a b))
 | 
				
			||||||
 | 
					    ((number= a 0) b)
 | 
				
			||||||
 | 
					    ((number= b 0) a)
 | 
				
			||||||
 | 
					    (t `(+ ,a ,b))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun make-product (a b)
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((and (numberp a) (numberp b)) (* a b))
 | 
				
			||||||
 | 
					    ((number= a 0) 0)
 | 
				
			||||||
 | 
					    ((number= a 1) b)
 | 
				
			||||||
 | 
					    ((number= b 0) 0)
 | 
				
			||||||
 | 
					    ((number= b 1) a)
 | 
				
			||||||
 | 
					    (t (append (list '*)
 | 
				
			||||||
 | 
						       (if (productp a) (cdr a) (list a))
 | 
				
			||||||
 | 
						       (if (productp b) (cdr b) (list b))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun expt-p (e)
 | 
				
			||||||
 | 
					  (and (listp e) (eq '** (car e))))
 | 
				
			||||||
 | 
					(defun base (e)
 | 
				
			||||||
 | 
					  (second e))
 | 
				
			||||||
 | 
					(defun exponent (e)
 | 
				
			||||||
 | 
					  (third e))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun make-expt (b e)
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((number= b 0) 0)
 | 
				
			||||||
 | 
					    ((number= b 1) 1)
 | 
				
			||||||
 | 
					    ((number= e 0) 1)
 | 
				
			||||||
 | 
					    ((number= e 1) b)
 | 
				
			||||||
 | 
					    (t `(** ,b ,e))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun deriv (expr var)
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((numberp expr) 0)	;; c/dx = 0
 | 
				
			||||||
 | 
					    ((var= expr var) 1)	;; dx/dx = 1
 | 
				
			||||||
 | 
					    ((and (symbolp expr) (var!= expr var)) 0)
 | 
				
			||||||
 | 
					    ((sump expr)
 | 
				
			||||||
 | 
					     (make-sum (deriv (addend expr) var)
 | 
				
			||||||
 | 
						       (deriv (augend expr) var)))
 | 
				
			||||||
 | 
					    ((productp expr)
 | 
				
			||||||
 | 
					     (make-sum (make-product (multiplier expr) (deriv (multiplicand expr) var))
 | 
				
			||||||
 | 
						       (make-product (multiplicand expr) (deriv (multiplier expr) var))))
 | 
				
			||||||
 | 
					    ;; EX 2.56 - exponentiaton derived.
 | 
				
			||||||
 | 
					    ((expt-p expr)
 | 
				
			||||||
 | 
					     (make-product (exponent expr)
 | 
				
			||||||
 | 
							   (make-product (make-expt (base expr) (make-sum -1 (exponent expr)))
 | 
				
			||||||
 | 
									 (deriv (base expr) var))))
 | 
				
			||||||
 | 
					    (t (error "unknown"))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; 2.58 - okay, so we *could* modify the selectors and stuff
 | 
				
			||||||
 | 
					;; above to make this work, but I kinda wanna keep those.
 | 
				
			||||||
 | 
					;; instead, I'll just make a function that transforms the new
 | 
				
			||||||
 | 
					;; input into the old input format (this is trivial for the
 | 
				
			||||||
 | 
					;; case with fully parenthesized input)
 | 
				
			||||||
 | 
					(defun transform-input (expr)
 | 
				
			||||||
 | 
					  (if (listp expr)
 | 
				
			||||||
 | 
					      (list (second expr) (transform-input (first expr)) (transform-input (third expr)))
 | 
				
			||||||
 | 
					      expr))
 | 
				
			||||||
 | 
					(defun deriv-infix (e v)
 | 
				
			||||||
 | 
					  (deriv (transform-input e) v))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; ... and also kind of doable for the more general case.
 | 
				
			||||||
 | 
					;; requires more work though, but I guess that's the point.
 | 
				
			||||||
 | 
					(defparameter op-precedence (make-hash-table))
 | 
				
			||||||
 | 
					(loop for i in '((+ 1) (* 3) (** 5))
 | 
				
			||||||
 | 
					      do (setf (gethash (car i)  op-precedence) (second i)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun prec (op)
 | 
				
			||||||
 | 
					  (gethash op op-precedence))
 | 
				
			||||||
 | 
					(defun collapse (ops items)
 | 
				
			||||||
 | 
					  (if (null ops)
 | 
				
			||||||
 | 
					      (car items)
 | 
				
			||||||
 | 
					      (collapse (cdr ops)
 | 
				
			||||||
 | 
							(cons (list (first ops) (second items) (first items))
 | 
				
			||||||
 | 
							      (cddr items)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; (3 + 5 * 6 + 2)
 | 
				
			||||||
 | 
					;; (helper 0 expr nil)
 | 
				
			||||||
 | 
					;; (helper 1 '(5 * 6 + 2) '(+) '(3))
 | 
				
			||||||
 | 
					;; (helper 3 '(6 + 2) '(* +) '(5 3))
 | 
				
			||||||
 | 
					;; (helper 1 '(2) '() '(+ (* 6 5) 3))
 | 
				
			||||||
 | 
					;; (+ 3 (* 5 6) 2)
 | 
				
			||||||
 | 
					;; Fuckkkkkkk
 | 
				
			||||||
 | 
					;; this took way longer than it needed to.
 | 
				
			||||||
 | 
					;; not a good-looking implementation at all, really ugly.
 | 
				
			||||||
 | 
					;; but it works! correctly transforms infix notation
 | 
				
			||||||
 | 
					;; to prefix. (output can be directly used by deriv)
 | 
				
			||||||
 | 
					(defun transform-infix (expr)
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((null expr) nil)
 | 
				
			||||||
 | 
					    ((or (numberp expr) (symbolp expr)) expr)
 | 
				
			||||||
 | 
					    (t (labels ((helper (expr ops items)
 | 
				
			||||||
 | 
							  (format t "~a ~a ~a~%" expr ops items)
 | 
				
			||||||
 | 
							  (cond
 | 
				
			||||||
 | 
							    ((null expr) items)
 | 
				
			||||||
 | 
							    ((null (cdr expr))
 | 
				
			||||||
 | 
							     (collapse ops (cons (transform-infix
 | 
				
			||||||
 | 
										  (car expr))
 | 
				
			||||||
 | 
										 items)))
 | 
				
			||||||
 | 
							    ((>= (prec (second expr)) (or (prec (car ops)) 0))
 | 
				
			||||||
 | 
							     (helper (cddr expr)
 | 
				
			||||||
 | 
								     (cons (second expr) ops)
 | 
				
			||||||
 | 
								     (cons (transform-infix (first expr))
 | 
				
			||||||
 | 
									   items)))
 | 
				
			||||||
 | 
							    (t
 | 
				
			||||||
 | 
							     (helper (cddr expr)
 | 
				
			||||||
 | 
								     (cons (second expr) nil)
 | 
				
			||||||
 | 
								     (list (collapse ops
 | 
				
			||||||
 | 
										 (cons (transform-infix
 | 
				
			||||||
 | 
											(first expr))
 | 
				
			||||||
 | 
										       items))))))))
 | 
				
			||||||
 | 
						 (helper expr '() '())))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun deriv-real-infix (e v)
 | 
				
			||||||
 | 
					  (deriv (transform-infix e) v))
 | 
				
			||||||
							
								
								
									
										112
									
								
								ex-2-59.lisp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								ex-2-59.lisp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					;; not gonna bother copy-pasting the rest of the implementation.
 | 
				
			||||||
 | 
					;; ex 2.59
 | 
				
			||||||
 | 
					(defun adjoin-set (s i)
 | 
				
			||||||
 | 
					  (if (element-of-set? s i)
 | 
				
			||||||
 | 
					      s
 | 
				
			||||||
 | 
					      (cons i s)))
 | 
				
			||||||
 | 
					(defun union-set (s1 s2)
 | 
				
			||||||
 | 
					  (labels ((rec (s1 s2)
 | 
				
			||||||
 | 
						     (if (null s1)
 | 
				
			||||||
 | 
							 s2
 | 
				
			||||||
 | 
							 (rec (cdr s1) (adjoin-set s2 (car s1))))))
 | 
				
			||||||
 | 
					    (rec s1 s2)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; ex 2.60
 | 
				
			||||||
 | 
					;; element-of-set? doesn't change I'm pretty sure.
 | 
				
			||||||
 | 
					(defun element-of-set? (s e)
 | 
				
			||||||
 | 
					  (if (null s)
 | 
				
			||||||
 | 
					      nil
 | 
				
			||||||
 | 
					      (element-of-set? (cdr s) e)))
 | 
				
			||||||
 | 
					;; adjoin becomes more efficient, as it is now an O(1) operation
 | 
				
			||||||
 | 
					(defun adjoin-set-duppy (s e)
 | 
				
			||||||
 | 
					  (cons e s))
 | 
				
			||||||
 | 
					;; union-set becomes a linear-time algorithm as it relies on adjoin-set.
 | 
				
			||||||
 | 
					;; doesn't really change in logic otherwise, though.x
 | 
				
			||||||
 | 
					(defun union-set-duppy (s1 s2)
 | 
				
			||||||
 | 
					  (labels ((rec (s1 s2)
 | 
				
			||||||
 | 
						     (if (null s1)
 | 
				
			||||||
 | 
							 s2
 | 
				
			||||||
 | 
							 (rec (cdr s1) (adjoin-set s2 (car s1))))))
 | 
				
			||||||
 | 
					    (rec s1 s2)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; ex 2.61
 | 
				
			||||||
 | 
					;; Note: NOT tail recursive. not gonna work for too long lists.
 | 
				
			||||||
 | 
					;; though the book's given intersection-list is also not tail
 | 
				
			||||||
 | 
					;; recursive, so this is probably intended.
 | 
				
			||||||
 | 
					(defun adjoin-set-ordered (s1 i)
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((null s1) (cons i nil))
 | 
				
			||||||
 | 
					    ((= i (car s1)) s1)
 | 
				
			||||||
 | 
					    ((< i (car s1))
 | 
				
			||||||
 | 
					     (cons i s1))
 | 
				
			||||||
 | 
					    (t (cons (car s1) (adjoin-set-ordered (cdr s1) i)))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; ex 2.62
 | 
				
			||||||
 | 
					;; same with 2.61, not tail recursive
 | 
				
			||||||
 | 
					;; both could be translated fairly easily though
 | 
				
			||||||
 | 
					(defun union-set-ordered (s1 s2)
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((null s1) s2)
 | 
				
			||||||
 | 
					    ((null s2) s1)
 | 
				
			||||||
 | 
					    ((= (car s1) (car s2))
 | 
				
			||||||
 | 
					     (cons (car s1)
 | 
				
			||||||
 | 
						   (union-set-ordered (cdr s1) (cdr s2))))
 | 
				
			||||||
 | 
					    ((> (car s1) (car s2))
 | 
				
			||||||
 | 
					     (cons (car s2)
 | 
				
			||||||
 | 
						   (union-set-ordered s1 (cdr s2))))
 | 
				
			||||||
 | 
					    ((< (car s1) (car s2))
 | 
				
			||||||
 | 
					     (cons (car s1)
 | 
				
			||||||
 | 
						   (union-set-ordered (cdr s1) s2)))
 | 
				
			||||||
 | 
					    (t (error "asd"))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; ex 2.63
 | 
				
			||||||
 | 
					;; a) it looks like the result should be the same.
 | 
				
			||||||
 | 
					;; tried the code, couldn't get them to give different results.
 | 
				
			||||||
 | 
					;; on the figure 2.16 trees, they all give the same results.
 | 
				
			||||||
 | 
					;; b) At first glance they might look equivalent. However,
 | 
				
			||||||
 | 
					;; the first algorithm has a hidden cost in the append operation.
 | 
				
			||||||
 | 
					;; because the fastest way to append two linked lists is an O(N)
 | 
				
			||||||
 | 
					;; operation: so eventually it becomes O(N/2 + 2N/4 + 4N/8 + ... + logN)
 | 
				
			||||||
 | 
					;; or something like that, which is O(N + logn) or O(N).
 | 
				
			||||||
 | 
					;; the second algorithm doesn't waste time with that, and is therefore
 | 
				
			||||||
 | 
					;; a flat O(logN). The second one takes less time.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; damn, raw lisp code can be hard to read. might be a skill issue.
 | 
				
			||||||
 | 
					;; ex 2.64
 | 
				
			||||||
 | 
					;; "short" paragraph. yeah.
 | 
				
			||||||
 | 
					;; Okay, so...
 | 
				
			||||||
 | 
					;; partial-tree takes a list of elements and n.
 | 
				
			||||||
 | 
					;; in the base case, i.e. n = 0, the result is trivially just (cons nil elts)
 | 
				
			||||||
 | 
					;; otherwise, the function calculates the length of the left half of the tree,
 | 
				
			||||||
 | 
					;; recursively calls itself with that "left half". As partial-tree returns
 | 
				
			||||||
 | 
					;; the rest of the elements, we take the "right half" from this rest of the elements
 | 
				
			||||||
 | 
					;; (of course making sure to save and exclude the center element, as that is
 | 
				
			||||||
 | 
					;; the root of the tree).
 | 
				
			||||||
 | 
					;; This way, we create a tree by recursively creating the left subtree, then the right
 | 
				
			||||||
 | 
					;; subtree, then we simply combine these to create the final tree.
 | 
				
			||||||
 | 
					;; b) O(N) each element is visited exactly once.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; ex 2.65
 | 
				
			||||||
 | 
					;; assuming the union and intersection don't have to maintain
 | 
				
			||||||
 | 
					;; balance (or that's handled by something else)
 | 
				
			||||||
 | 
					(defstruct btree elt left right)
 | 
				
			||||||
 | 
					(defun adjoin-set-tree (s i)
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((null s) (make-btree :elt i :left nil :right nil))
 | 
				
			||||||
 | 
					    ((= (btree-elt s) i) s)
 | 
				
			||||||
 | 
					    ((< (btree-elt s) i)
 | 
				
			||||||
 | 
					     (make-btree :elt (btree-elt s)
 | 
				
			||||||
 | 
							 :left (btree-left s)
 | 
				
			||||||
 | 
							 :right (adjoin-set-tree (btree-right s) i)))
 | 
				
			||||||
 | 
					    ((> (btree-elt s) i)
 | 
				
			||||||
 | 
					     (make-btree :elt (btree-elt s)
 | 
				
			||||||
 | 
							 :left (adjoin-set-tree (btree-left s) i)
 | 
				
			||||||
 | 
							 :right (btree-right s)))))
 | 
				
			||||||
 | 
					(defun union-set-tree (s1 s2)
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((null s1) s2)
 | 
				
			||||||
 | 
					    ((null s2) s1)
 | 
				
			||||||
 | 
					    (t (union-set-tree (union-set-tree (btree-left s1) (btree-right s2))
 | 
				
			||||||
 | 
							       (adjoin-set-tree s2 (btree-elt s1))))))
 | 
				
			||||||
 | 
					;; yeah, okay. this looks good enough, didn't test it at all, but whatevs.
 | 
				
			||||||
		Reference in New Issue
	
	Block a user