Some more progress
This commit is contained in:
		
							
								
								
									
										12
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
									
									
									
									
								
							@@ -1,13 +1,11 @@
 | 
				
			|||||||
# hello
 | 
					# SICP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This repository is where I keep my solutions to the problems in SICP
 | 
					This repository is where I keep my solutions to the problems in SICP.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
I'm currently working through the book and wanted to keep track of my progress somewhere.
 | 
					I'm currently working through the book and wanted to keep track of my progress somewhere.
 | 
				
			||||||
Note: I won't be solving ***ALL*** problems. I just solve *most*, I will probably ignore
 | 
					Note: I won't be solving ***ALL*** problems. I just solve *most*, I will probably ignore
 | 
				
			||||||
those that seem like they would take too long (or ones that require several PhD's to solve).
 | 
					those that seem like they would take too long (or ones that require several PhD's to solve).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Note: these are all racket files, I am also learning racket at the same time (and using
 | 
					Note that some of the solutions were done in racket. I started with racket, but eventually
 | 
				
			||||||
DrRacket) so beware of that. I will mostly try to stick to racket, but there may be 
 | 
					I switched to common lisp. Right now I'm using Emacs with SLIME, and will hopefully be
 | 
				
			||||||
times where I switch to `#lang r5rs` or `#lang sicp` for compatability with the book.
 | 
					continuing with that for the rest of the book.
 | 
				
			||||||
 | 
					 | 
				
			||||||
Also, I will put related-seeming or close-together problems in the same file.
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -183,6 +183,7 @@
 | 
				
			|||||||
;; to the table as well.
 | 
					;; to the table as well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
;; Note: this problem is sometimes referred to as the "expression problem."
 | 
					;; Note: this problem is sometimes referred to as the "expression problem."
 | 
				
			||||||
 | 
					;; especially within compiler development.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										60
									
								
								sec-2-5.lisp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								sec-2-5.lisp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					;; 2.77
 | 
				
			||||||
 | 
					;; obviously magnitude isn't defined yet on the complex type,
 | 
				
			||||||
 | 
					;; it is only defined in the internal types, i.e. the secondary types.
 | 
				
			||||||
 | 
					;; this means that the first apply-generic will immediately fail.
 | 
				
			||||||
 | 
					;; the reason Alyssa's fix works, is because this makes the
 | 
				
			||||||
 | 
					;; maginute function dispatch to itself when seing the type
 | 
				
			||||||
 | 
					;; '(complex). Then, magnitude will be called with the
 | 
				
			||||||
 | 
					;; internal type - e.g. '(rectangular 3 4), which gives
 | 
				
			||||||
 | 
					;; the correct answer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; 2.78
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun type-tag (datum)
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((consp datum) (car datum))
 | 
				
			||||||
 | 
					    ((numberp datum) 'number)
 | 
				
			||||||
 | 
					    (t (error "unkown type"))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun contents (datum)
 | 
				
			||||||
 | 
					  (cond
 | 
				
			||||||
 | 
					    ((consp datum) (cdr datum))
 | 
				
			||||||
 | 
					    ((numberp datum) datum)
 | 
				
			||||||
 | 
					    (t (error "unknown type"))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; assuming the dispatch function actually calls the function with
 | 
				
			||||||
 | 
					;; the contents of each datum, then you should now be able to just
 | 
				
			||||||
 | 
					;; insert #'+, #'*, #'- and #'/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; 2.79
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; 2.81
 | 
				
			||||||
 | 
					;; First, apply-generic is called.
 | 
				
			||||||
 | 
					;; 'exp is not defined on complex numbers. Therefore, the apply-generic
 | 
				
			||||||
 | 
					;; function somewhat mistakenly enters the second branch, and first tries
 | 
				
			||||||
 | 
					;; to find a coercion from the first argument's type to the second argument's
 | 
				
			||||||
 | 
					;; type. It finds this coercion function. But then it calls:
 | 
				
			||||||
 | 
					;; (apply-generic op (t1->t2 a1) a2)
 | 
				
			||||||
 | 
					;; this is a problem, because it now enters an infinite loop. Every time,
 | 
				
			||||||
 | 
					;; apply-generic will try to find the 'exp method, not find it, and try
 | 
				
			||||||
 | 
					;; to coerce the first argument to the second argument's type.
 | 
				
			||||||
 | 
					;; It will succeed, and call itself again.
 | 
				
			||||||
 | 
					;; Since this is a tail call, it will be optimised and this will be reduced
 | 
				
			||||||
 | 
					;; to an infinite loop.
 | 
				
			||||||
 | 
					;;
 | 
				
			||||||
 | 
					;; Something can be done about it. We can simply compare the tags of
 | 
				
			||||||
 | 
					;; the objects before trying to coerce - and we can simply raise an error
 | 
				
			||||||
 | 
					;; if both objects have been coerced to the same type and there is still
 | 
				
			||||||
 | 
					;; no function found. Coincidentally, this would also prevent Louis Reasouner's
 | 
				
			||||||
 | 
					;; previous infinite loop.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; In order to be extra spicy, I will be completing the exercises in
 | 
				
			||||||
 | 
					;; the symbolic algebra section through the use of CLOS.
 | 
				
			||||||
 | 
					;; I.e. I will actually build an AST of these objects, and use
 | 
				
			||||||
 | 
					;; methods to parse, interpret and modify them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; Tomorrow. I will do that tomorrow.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										134
									
								
								sec-3-3.scm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								sec-3-3.scm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,134 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					;; I am not drawing box-and-pointer diagrams lmao
 | 
				
			||||||
 | 
					;; still, to answer 3.12:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; first:
 | 
				
			||||||
 | 
					;; (cdr x)
 | 
				
			||||||
 | 
					;; => '(b)
 | 
				
			||||||
 | 
					;; because x is not modified in the call to append
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; however, append! modifies the underlying data structure
 | 
				
			||||||
 | 
					;; held in x, hence the second (cdr x) returns:
 | 
				
			||||||
 | 
					;; => '(b c d)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(define (append! x y)
 | 
				
			||||||
 | 
					  (set-cdr! (last-pair x) y)
 | 
				
			||||||
 | 
					  x)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(define (last-pair x)
 | 
				
			||||||
 | 
					  (if (null? (cdr x)) x (last-pair (cdr x))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; don't run these twice, you'll create a circular list.
 | 
				
			||||||
 | 
					;; I lost a good many REPL's to this.
 | 
				
			||||||
 | 
					(define x '(a b))
 | 
				
			||||||
 | 
					(define y '(c d))
 | 
				
			||||||
 | 
					(append! x y)
 | 
				
			||||||
 | 
					x ; => '(a b c d)
 | 
				
			||||||
 | 
					(cdr x) ; => '(b c d)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; 3.13:
 | 
				
			||||||
 | 
					;; oh! how very nice - a question about the very thing I just
 | 
				
			||||||
 | 
					;; wrote about.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; the REPL hangs. It tries to traverse to the end of a list
 | 
				
			||||||
 | 
					;; that doesn't have an end. Like most human lives, it dies
 | 
				
			||||||
 | 
					;; a meaningless death in search of that which does not exist,
 | 
				
			||||||
 | 
					;; a search that goes round and round and round forever.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; I.e. we constructed a cyclical list.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; 3.14:
 | 
				
			||||||
 | 
					;; This is a list reversal procedure.
 | 
				
			||||||
 | 
					;; The input list is destructively reversed in-place, i.e. with
 | 
				
			||||||
 | 
					;; no allocations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; v will still refer to the same cons cell, so its value is
 | 
				
			||||||
 | 
					;; '(a)
 | 
				
			||||||
 | 
					;; w will refer to the new head of the (now-reversed) list.
 | 
				
			||||||
 | 
					;; '(d c b a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(define (mystery x)
 | 
				
			||||||
 | 
					  (define (loop x y)
 | 
				
			||||||
 | 
					    (if (null? x)
 | 
				
			||||||
 | 
						y
 | 
				
			||||||
 | 
						(let ((temp (cdr x)))
 | 
				
			||||||
 | 
						  (set-cdr! x y)
 | 
				
			||||||
 | 
						  (loop temp x))))
 | 
				
			||||||
 | 
					  (loop x '()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; this procedure is useful because its sometimes very convenient
 | 
				
			||||||
 | 
					;; to generate data into a list through cons cells, then reverse
 | 
				
			||||||
 | 
					;; it at the end (through an efficient reversal procedure like this)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; 3.16:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(define (count-pairs x)
 | 
				
			||||||
 | 
					  (if (not (pair? x))
 | 
				
			||||||
 | 
					      0
 | 
				
			||||||
 | 
					      (+ (count-pairs (car x))
 | 
				
			||||||
 | 
						 (count-pairs (cdr x))
 | 
				
			||||||
 | 
						 1)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(count-pairs '(a b c)) ; => 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(define fourbase (cons 1 '()))
 | 
				
			||||||
 | 
					(define four (cons fourbase (cons fourbase '())))
 | 
				
			||||||
 | 
					(count-pairs four) ; => 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(define sevenbase (cons 1 '()))
 | 
				
			||||||
 | 
					(define sevenmid (cons sevenbase sevenbase))
 | 
				
			||||||
 | 
					(define seven (cons sevenmid sevenmid))
 | 
				
			||||||
 | 
					(count-pairs seven) ; => 7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; and for the great finale...
 | 
				
			||||||
 | 
					(define finale-a (cons 'a '()))
 | 
				
			||||||
 | 
					(define finale-b (cons 'b finale-a))
 | 
				
			||||||
 | 
					(define finale-c (cons 'c finale-b))
 | 
				
			||||||
 | 
					(set-cdr! finale-a finale-c)
 | 
				
			||||||
 | 
					;; (you can do this with a single cons cell, actually)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; 3.17
 | 
				
			||||||
 | 
					;; it seems that eq? really does simply check for
 | 
				
			||||||
 | 
					;; pointer equality - if literally the same cons
 | 
				
			||||||
 | 
					;; cell is passed twice it returns #t but if two
 | 
				
			||||||
 | 
					;; cons cells with the same values are created
 | 
				
			||||||
 | 
					;; they measure #f.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; it's honestly very convenient to know this
 | 
				
			||||||
 | 
					;; it simplifies and clarifies a lot of things.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; we can use this to essentially build a list of
 | 
				
			||||||
 | 
					;; all pairs we have ever visited. We can have this
 | 
				
			||||||
 | 
					;; list behave like a set - which we defined before.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; I used a hash table instead because they were available.
 | 
				
			||||||
 | 
					;; and efficient, I guess.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; You can count the number of pairs without falling
 | 
				
			||||||
 | 
					;; for cycles by just refusing to traverse a cell
 | 
				
			||||||
 | 
					;; that has already been traversed, though this
 | 
				
			||||||
 | 
					;; requires extra storage.
 | 
				
			||||||
 | 
					;; I'm gonna count this for 3.18, as the logic
 | 
				
			||||||
 | 
					;; is incredibly similar.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(define (count-pairs-2 x)
 | 
				
			||||||
 | 
					  (define table (make-eq-hashtable))
 | 
				
			||||||
 | 
					  (define (mark-visited! c)
 | 
				
			||||||
 | 
					    (set-cdr! (hashtable-cell table c #t) #t)
 | 
				
			||||||
 | 
					    #t)
 | 
				
			||||||
 | 
					  (define (visited? x)
 | 
				
			||||||
 | 
					    (eq-hashtable-ref table x #f))
 | 
				
			||||||
 | 
					  (define (loop x)
 | 
				
			||||||
 | 
					    (when (and (pair? x) (not (visited? x)))
 | 
				
			||||||
 | 
					      (mark-visited! x)
 | 
				
			||||||
 | 
					      (loop (car x))
 | 
				
			||||||
 | 
					      (loop (cdr x))))
 | 
				
			||||||
 | 
					  (loop x)
 | 
				
			||||||
 | 
					  (vector-length (hashtable-values table)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Reference in New Issue
	
	Block a user