SICP LEARNING


(defun square (n) (* n n))
(defun fast-pow (x n)
"this is a fast version of power function"
  (cond ((= n 0) 1)
	((evenp n) (square (fast-pow x (/ n 2))))
	(t (* x (fast-pow x (1- n))))))

(defun my-gcd (a b )
"calculate the gcd of two numbers using Euclid's Algorithm"
  (if (zerop b)
      a
    (my-gcd b (mod a b))))

Counting Change

the number of ways to change amount a using n kinds of coins equals
the number of ways to change amount a using all but first kind of coin plus
the number of ways to change the amount a -d using all kinds of coins,
where d is the denomination of the coin

(defun cc (amount kind-of-coin)
	   (cond ((= amount 0) 1)
		 ((or (< amount 0) (= kind-of-coin 0)) 0)
		 (t (+ (cc amount (1- kind-of-coin))
		       (cc (- amount (denom-of kind-of-coin)) kind-of-coin)))))

(defun denom-of (coin)
	   (cond ((= coin 1) 1)
		 ((= coin 2) 5)
		 ((= coin 3) 10)
		 ((= coin 4) 25)
		 ((= coin 5) 50)))

Exercise 1.11. A function f is defined by the rule that f(n) = n if n 3.
Write a procedure that computes f by means of a recursive process.
Write a procedure that computes f by means of an iterative process.

(defun f (n)
       (cond ((= elem

(defun p-elem (height elem)
	   (cond ((= elem 0) 1)
		 ((= elem height) 1)
		 (t (+ (p-elem (1- height) (1- elem))
			  (p-elem (1- height) elem)))))

Half-interval method to find roots


(defun average (x y) (/ (+ x y) 2))
(defun close-enough? (a b)
	   ( a b)
	       0
	       (+ (funcall term a)
		  (sum term (funcall next a) next b))))

(defun cube (x ) (* x x x ))

(defun integral (f a b dx)
  (labels((add-dx (x) (+ x dx)))
  (* (sum f (+ a (/ dx 2.0)) #'add-dx b)
     dx)))

(defun deriv (g)
	   #'(lambda (x)
	       (/ (- (funcall g (+ x 0.0001)) (funcall g x))
	       0.0001)))

Rational Numbers Example

(defun make-rat (n d)
  (let ((g (gcd n d)))
    (cons (/ n g) (/ d g))))

(defun numer (x) (car x))
(defun denom (x) (cdr x))

(defun add-rat (x y)
  (make-rat (+ (* (numer x) (denom y))
	       (* (numer y) (denom x)))
	    (* (denom x) (denom y))))

(defun sub-rat (x y)
  (make-rat (- (* (numer x) (denom y))
	       (* (numer y) (denom x)))
	    (* (denom x) (denom y))))

(defun mul-rat (x y)
  (make-rat (* (numer x) (numer y))
	    (* (denom x) (denom y))))

(defun div-rat (x y)
  (make-rat (* (numer x) (denom y))
	    (* (denom x) (numer y))))
(defun equal-rat? (x y)
  (= (* (numer x) (denom y))
     (* (numer y) (denom x))))

Define our own cons,car and cdr functions.
Notice that the “data” is actually a function.

(defun our-cons (x y)
	   #'(lambda (m)
	     (cond ((= m 0) x)
		   ((= m 1) y)
		   (t (error "Argument not 0 or 1")))))
(defun our-car (z) (funcall z 0))
(defun our-cdr (z) (funcall z 1))

Interval Arithmetic

(defun make-interval (a b) (cons a b))

(defun lower-bound (x) (min (car x) (cdr x)))
(defun upper-bound (x) (max (car x) (cdr x)))

(defun add-interval (x y)
  (make-interval (+ (lower-bound x) (lower-bound y))
		 (+ (upper-bound x) (upper-bound y))))

(defun mul-interval (x y)
  (let ((p1 (* (lower-bound x) (lower-bound y)))
	(p2 (* (lower-bound x) (upper-bound y)))
	(p3 (* (upper-bound x) (lower-bound y)))
	(p4 (* (upper-bound x) (upper-bound y))))
    (make-interval (min p1 p2 p3 p4)
		   (max p1 p2 p3 p4))))

(defun div-interval (x y)
  (mul-interval x
		(make-interval (/ 1.0 (upper-bound y))
			       (/ 1.0 (lower-bound y)))))

(defun sub-interval (x y)
  (make-interval (- (lower-bound x) (lower-bound y))
		 (- (upper-bound x) (upper-bound y))))

(defun width-interval (x)
  (/ (- (upper-bound x) (lower-bound x)) 2.0))

(= (width-interval (add-interval (make-interval 2 4) (make-interval 2 7)))
	    (+ (width-interval (make-interval 2 4))
	       (width-interval (make-interval 2 7))))

(defun div-interval (x y)
  (if (and (>= (upper-bound y) 0) (<= (lower-bound y) 0))
      (error "Invalid interval for dividing")
    (mul-interval x
		  (make-interval (/ 1.0 (upper-bound y))
				 (/ 1.0 (lower-bound y))))))
(defun eq-interval? (x y)
  (and (= (upper-bound x) (upper-bound y))
       (= (lower-bound x) (lower-bound y))))

Divide into 9 different cases

(defun mul-interval (x y)
  (let ((xl (lower-bound x)) (xu (upper-bound x))
	(yl (lower-bound y)) (yu (upper-bound y)))
    (cond ((and (minusp xu) (minusp yu))
                 (make-interval (* xl yl) (* xu yu)))
	  ((and (minusp xu) (minusp yl) (plusp yu))
                 (make-interval (* xl yl) (* xl yu)))
	  ((and (minusp xu) (plusp yl))
                 (make-interval (* xl yu) (* xu yl)))
	  ((and (minusp xl) (plusp xu) (minusp yu))
                 (make-interval (* xl yl) (* xu yl)))
	  ((and (minusp xl) (plusp xu) (minusp yl) (plusp yu))
                 (make-interval (max (* xu yu) (* xl yl)) (min (* xl yu) (* xu yl))))
	  ((and (minusp xl) (plusp xu) (plusp yu))
                  (make-interval (* xu yu) (* xl yu)))
	  ((and (plusp xl)  (minusp yu))
                  (make-interval (* xl yu) (* xu yl)))
	  ((and (plusp xl) (minusp yl) (plusp yu))
                  (make-interval (* xu yl) (* xu yu)))
	  ((and (plusp xl) (plusp yl))
                  (make-interval (* xl yl) (* xu yu))))))

test with different intervals here

(dolist (x-val  '((-2 . -1) (-1 . 3) (3 . 4)))
  (dolist (y-val '((-5 . -3) (-3 . 2) (2 . 6)))
    (let ((xl (car x-val)) (xu (cdr x-val)) (yl (car y-val)) (yu (cdr y-val)))
      (let ((org-val (mul-org-interval (make-interval xl xu) (make-interval yl yu)))
	    (new-val (mul-interval (make-interval xl xu) (make-interval yl yu))))
	(format t "~a ~a : ~a ~a ~%"
		(lower-bound org-val) (upper-bound org-val)
		(lower-bound new-val) (upper-bound new-val))
	(if (eq-interval? org-val new-val)
	    t
	  (error "Error in multiplication"))))))

2.2

(defun list-ref (items n)
  (if (= n 0)
      (car items)
      (list-ref (cdr items) (- n 1))))

(defparameter *squares* (list 1 4 9 16 25))

(defun mylength (items)
  (if (null items)
      0
      (+ 1 (length (cdr items)))))

(defun myappend (list1 list2)
  (if (null list1)
      list2
      (cons (car list1) (append (cdr list1) list2))))

;; ex 2.17
(defun last-pair (list)
  (if (null (cdr list))
      list
      (last-pair (cdr list))))

(last-pair '(1 2 3 4))

;; ex 2.18

(defun myreverse-aux  (list acc)
  (if (null list)
      acc
      (myreverse-aux (cdr list) (cons (car list) acc))))

(defun myreverse (list)
  (myreverse-aux list '()))

(myreverse (list 1 2 3 4 5 ))

;;2.19 revisited

Counting Change

the number of ways to change amount a using n kinds of coins equals
the number of ways to change amount a using all but first kind of coin plus
the number of ways to change the amount a -d using all kinds of coins,
where d is the denomination of the coin

(defun cc (amount kind-of-coin)
	   (cond ((= amount 0) 1)
		 ((or (< amount 0) (= kind-of-coin 0)) 0)
		 (t (+ (cc amount (1- kind-of-coin))
		       (cc (- amount (denom-of kind-of-coin)) kind-of-coin)))))

(defun denom-of (coin)
	   (cond ((= coin 1) 1)
		 ((= coin 2) 5)
		 ((= coin 3) 10)
		 ((= coin 4) 25)
		 ((= coin 5) 50)))

(defun cc (amount coin-values)
  (cond ((= amount 0) 1)
	((or (< amount 0) (no-more? coin-values)) 0)
	(else
	 (+ (cc amount
		(except-first-denomination coin-values))
	    (cc (- amount
		   (first-denomination coin-values))
		coin-values)))))

(defun first-denomination (list))
(defun except-first-denomination (list))
(defun no-more? (list))

;; ex 2.20

(defun same-parity (&rest args)
  (when args
    (if (evenp (car args))
	(remove-if-not #'evenp args)
	(remove-if-not #'oddp  args))))

(same-parity  2 3 4 5 6 7)

;; ex 2.21

(defun square-list (list)
  (mapcar #'(lambda (x) (* x x )) list))

(square-list (list 1 2 3 4))

;; ex 2.22

(defun square (x) (* x x))

(defun iter (things answer)
  (if (null things)
      (reverse answer)
      (iter (cdr things)
	    (cons (square (car things)) answer))))

(defun sq-list-error (items)
  (iter items nil))

(sq-list-error '(1 2 3 4))

;; ex 2.23
(for-each (lambda (x)
	    (format t "~a" x))
	  (list 4 5 6))

(defun for-each (fn lst)
  (if (null lst)
      'true
      (progn
	(funcall fn (car lst))
	(for-each fn (cdr lst)))))

;;2.2.2 Hierarchial Structures

(defparameter *x* (cons (list 1 2) (list 3 4)))

(length *x*)

(count-leaves *x*)

(length (list *x* *x*))

(defun count-leaves (x)
  (cond ((null x) 0)
	((not (consp x)) 1)
	(t (+ (count-leaves (car x))
		 (count-leaves (cdr x))))))

(count-leaves *x*)
(count-leaves (list *x* *x*))

;; 2.27

there are three conditions
when the given list is empty, return back the accumulator

when the given list is a fringe,
then append the value in front of the accumulator

when the list is not empty or a fringe,
then the accumulator will be the appended list of the
deep-reverse of the car of the value and the accumulator
and the result is the deep reverse of the cdr of the

(defun deep-reverse-aux  (val acc)
  (cond ((null val) acc)
	((not (consp val)) (cons val acc))
	 (t (deep-reverse-aux (cdr val)
			       (deep-reverse-aux (car val) acc)))))

(defun deep-reverse (list)
  (deep-reverse-aux list '()))

(deep-reverse (list (list 1 2 3) (list 4 5 6)))

;; 2.28

(defun single (x)
  (not (consp x)))

(defun fringe-aux  (list acc )
  (cond ((null list) acc)
	((single list) (append acc (list list)))
	(t (fringe-aux (cdr list)
		       (fringe-aux
			(car list)
			acc)))))
(defun fringe (list)
  (fringe-aux list '()))

(fringe *x*)

;;2.29

(defun make-mobile (left right)
  (list left right))

(defun make-branch (length structure)
  (list length structure))

(defun left-branch (mobile)
  (first mobile))

(defun right-branch (mobile)
  (second mobile))

(defun branch-length (branch)
  (first branch))

(defun branch-structure(branch)
  (second branch))

(defparameter *mobile* (make-mobile
			(make-branch 5
				     (make-mobile
				      (make-branch 2 5)
				      (make-branch 4 3)))
			(make-branch 4
				     (make-mobile
				      (make-branch 5 2)
				      (make-branch 7 9)))))

A mobile is structually a tree alternates between a mobile and a mobile structure. Thus the total-weight function calls total-branch-weight and vice versa.

(defun is-simple-branch (mobile)
  (numberp (branch-structure mobile)))

(defun total-branch-weight  (mobile-branch acc)
  (cond ((null mobile-branch) acc)
	((is-simple-branch mobile-branch) (+ acc (branch-structure mobile-branch)))

	(t (+ acc (total-weight (branch-structure mobile-branch))))))

(defun total-weight (mobile)
  (+
   (total-branch-weight (left-branch  mobile) 0)
   (total-branch-weight (right-branch mobile) 0)))

;;MAPPING OVER TREES
(defun scale-tree (tree factor)
  (cond ((not tree) nil)
	((single tree) (* tree factor))
	(t (cons (scale-tree (car tree) factor)
		 (scale-tree (cdr tree) factor)))))

(defun scale-tree (tree factor)
  (mapcar #'(lambda (sub-tree)
	      (if (consp sub-tree)
		  (scale-tree2 sub-tree factor)
		(* sub-tree factor)))
	  tree))
;;NOTE: use M-/ to auto-complete word

;;ex 2.30

(defun square-tree (list)
  (mapcar #'(lambda (sub-list)
	      (if (consp sub-list)
		  (square-tree sub-list)
		(* sub-list sub-list)))
	  list))
(square-tree
 (list 1
       (list 2 (list 3 4) 5)
       (list 6 7)))

;;ex 2.31

(defun tree-map (fn tree)
  (mapcar #'(lambda (sub-tree)
	      (if (consp sub-tree)
		  (tree-map fn sub-tree)
		(funcall fn sub-tree)))
	  tree))

(tree-map #'(lambda (x) (* x x ))
	  (list 1
		(list 2 (list 3 4) 5)
		(list 6 7)))

;;ex 2.32

(defun subsets (s)
  (if (null s)
      (list nil)
    (let ((rest (subsets (cdr s))))
      (append rest (mapcar
		    #'(lambda (x)
			(if (null x)
			    (list (car s))
			  (append x (list  (car s)))))
		    rest)))))

(subsets '(1 2 3))

;;2.2.3 Sequeces
(defun single (x)
  (not (consp x)))

Post a Comment

*
*