Very Secure

Nightmare

May 18th, 2019

Vivid dreams are one of the most beautiful aspects of living. I go to sleep every night1 knowing that I have a chance to have an experience akin to an acid trip.

This is not my first nightmare since I started _actually_ dreaming. But it had one moment that was so creepy and disturbing that it surpassed the realm of fear into the realm of beauty and awe.

The nightmare was long and involved, and I don't quite remember the storyline. What I do remember was there was some conflict between two groups of two people, and one person from one group set out to kill one from the other. The victim was sitting in a parked car, on a dark street near my high school. He was not paying attention, when all of the sudden his brains were blown out by a bullet that went through the driver's seat window.

My perspective was from ~5 meters outside the car looking into the driver's seat window at my friend. The bullet had gone straight through the center, leaving the pane of glass intact. But it was difficult to see my dead buddy, since the window had lost most of its transparency due to the cracks branching in all directions from the bullet hole.

The image of my dead friend through the cracked window then slowly began to morph. The window started slowly swirling counter clockwise, turning into a large eyeball as it spiraled. The bullet hole became the pupil, the white cracks the sclera. And the blood from my friend became red veins going every which way.

After a few seconds of morphing, the image froze on the completed transformation. The large eyeball stared at me in all of its magnificent horror.

  1. To do this I gave up smoking weed and started writing down my dreams []

SICP 2.1 Solutions - Introduction to Data Abstraction

May 17th, 2019

The chapters seem to get progressively harder, so I plan to break my future posts into subchapters like this one. So far no problem has proven itself to be particularly difficult, save 1.15 and 2.16. 1.15 requires reviewing how to solve runtimes for recursive solutions, which is only slightly touched on in the book. 2.16 is a whole project in and of itself, so I've chosen to skip that problem for now.

 
;; Functions needed from Chapter 1.
(defun average (a b) (/ (+ a b) 2))

;; 2.1
(defun make-rat (a b)
  (defun negate (x) (- x))
  (if (< b 0)
      (cons (negate a) (negate b))
      (cons a b)))

;; 2.2

(defun make-point (x y) (cons x y))
(defun x-point (point) (car point))
(defun y-point (point) (cdr point))
(defun make-segment (a b) (cons a b))
(defun start-segment (segment) (car segment))
(defun end-segment   (segment) (cdr segment))
(defun midpoint-segment (segment)
  (defun average-two-points (get-point)
    (average (funcall get-point (start-segment segment))
	     (funcall get-point (end-segment   segment))))
  (make-point
   (average-two-points #'x-point)
   (average-two-points #'y-point)))

(defun print-point (point)
  (princ "(")
  (princ (x-point point))
  (princ ", ")
  (princ (y-point point))
  (princ ")")
  nil)

;; 2.3

(defun square (x) (* x x))
(defun distance (p1 p2)
  (sqrt (+ (square (- (x-point p1) (x-point p2)))
	   (square (- (y-point p1) (y-point p2))))))
(defun length-segment (segment)
  (distance (start-segment segment) (end-segment segment)))

;; Rectangle Abstraction 1
;; Requires user to give p1 p2 p3 so <(p1 p2 p3) = pi/2
(defun make-rectangle (p1 p2 p3)
  (cons (make-segment p1 p2) (make-segment p2 p3)))
(defun width  (rectangle) (length-segment (car rectangle)))
(defun height (rectangle) (length-segment (cdr rectangle)))

(defun make-rectangle-2 (bottom-left width height)
  (cons bottom-left (cons width height)))
(defun width-2  (rectangle) (cadr rectangle))
(defun height-2 (rectangle) (cddr rectangle))

;; End Rectangle Abstraction
(defun perimeter (rectangle) (* 2 (+ (width rectangle) (height rectangle))))
(defun area (rectangle) (* (width rectangle) (height rectangle)))

;; 2.4
(defun mycons (x y)
  (lambda (m) (funcall m x y)))

(defun mycar (z)
  (funcall z (lambda (p q) (declare (ignore q)) p)))

(defun mycdr (z)
  (funcall z (lambda (p q) (declare (ignore p)) q)))

;; Substitution Model, same for mycdr
;; (mycar (mycons 1 2))
;; (funcall (mycons 1 2) (lambda (p q) (declare ignore q) p))
;; (funcall (lambda (m) (funcall m 1 2)) (lambda (p q) (declare ignore q) p))
;; (funcall (lambda (p q) (declare ignore q) p) 1 2)
;; ( (declare ignore 2) 1)
;; 1

;; 2.5

(defun num-cons (x y) (* (expt 2 x) (expt 3 y)))

(defun num-car (z)
  (if (equal (mod z 2) 1)
      0
      (+ 1 (num-car (/ z 2)))))

(defun num-cdr (z)
  (if (not (equal (mod z 3) 0))
      0
      (+ 1 (num-cdr (/ z 3)))))

;; 2.6

(defun church-zero () (lambda (f) (declare (ignore f)) (lambda (x) x)))

(defun church-add-one (n)
  (lambda (f) (lambda (x) (funcall f (funcall (funcall n f) x)))))

;; Substitution method
(lambda (f) (lambda (x) (funcall f (funcall (funcall (my-zero) f) x))))

(lambda (f)
  (lambda (x)
    (funcall f
	     (funcall
	      (funcall (lambda (f) (declare (ignore f)) (lambda (x) x)) f) x))))

(lambda (f)
  (lambda (x)
    (funcall
     f
     (funcall (lambda (x) x) x))))

(lambda (f)
  (lambda (x)
    (funcall f x)))

(defun church-one ()
  (lambda (f) (lambda (x) (funcall f x))))

;; add one to church-one to get church-two

(lambda (f)
  (lambda (x)
    (funcall
     f
     (funcall (funcall (lambda (f) (lambda (x) (funcall f x))) f) x))))

(lambda (f)
  (lambda (x)
    (funcall
     f
     (funcall (lambda (x) (funcall f x)) x))))

(defun church-two ()
  (lambda (f) (lambda (x) (funcall f (funcall f x)))))

;; church zero returns a function that takes a function f,
;; and returns an identity function. It does nothing with f.

;; church one returns a function that takes a function f, and then creates a
;; new function that takes a function x and calls f on x.

;; church two returns a function that takes a function f, and then creates a
;; new function that takes a function x, and calls f twice on x.

;; church two, takes a function f, returns a function that calls f on a
;;
(defun church-add (a b)
  (lambda (f) (lambda (x) (funcall (funcall a f) (funcall (funcall b f) x)))))

;; example

(church-add #'church-one #'church-zero)

(lambda (f)
  (lambda (x)
    (funcall
     (funcall (church-one) f)
     (funcall (funcall (church-zero) f) x))))

(lambda (f)
  (lambda (x)
    (funcall
     (funcall (church-one) f)
     (funcall (lambda (x) x) x))))

(lambda (f)
  (lambda (x)
    (funcall
     (funcall (church-one) f)
     x)))

(lambda (f)
  (lambda (x)
    (funcall
     (lambda (x) (funcall f x))
     x)))

(lambda (f) (lambda (x) (funcall f x)))

;; 2.7

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

(defun lower-bound (interval) (car interval))
(defun upper-bound (interval) (cdr interval))

;; 2.8

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

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

;; 2.9

;; width =  (upper-bound - lower-bound)/2
;; addition:
;; 2w1 = u1 - l1
;; 2w2 = u2 - l2
;; 2w3 = (u1 + u2) - (l1 + l2)
;; 2w3 = (u1 - l1) + (u2 - l2)
;; w3 = w1 + w2

;; subtraction:
;; 2w1 = u1 - l1
;; 2w2 = u2 - l2
;; 2w3 = (u1 - l2) - (l1 - u2)
;; 2w3 = (u1 - l1) + (u2 - l2)
;; w3 = w1 + w2

;; multiplication counterexample:
;; i1 = -5 5
;; i2 =  5 10
;; i3 =  -5 0
;; i2 and i3 have the same width, but:
;; width of i1 * i2 (-50, 50) = 100
;; width of i1 * i3 (-25, 25) = 50

;; division counterexample:
;; i1 = 1 3
;; i2 = 1 3
;; i3 = -1 1
;; width of i1 / i2 (1/3, 3) = 10/3
;; width of i1 / i3 (-3, 3)  = 6

;; 2.10

(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-fixed (x y)
  (if (or (equal x 0) (equal y 0))
      (error "Division by zero")
      (mul-interval
       x
       (make-interval (/ 1.0 (upper-bound y))
		      (/ 1.0 (lower-bound y))))))

;; 2.11

(defun mul-interval-fast (x y)
  (defun posp (x) (>= x 0))
  (defun negp (x) (not (posp x)))
  (let ( (lx (lower-bound x))
	(ux (upper-bound x))
	(ly (lower-bound y))
	(uy (upper-bound y)))
    (cond
      ( (posp lx)
       (cond
	 ( (posp ly)                 (make-interval (* lx ly) (* ux uy)))
	 ( (and (negp ly) (posp uy)) (make-interval (* ux ly) (* ux uy)))
	 (t                         (make-interval (* ux ly) (* lx uy)))))
      ( (and (negp lx) (posp ux))
       (cond
	 ( (posp ly)                 (make-interval (* lx uy) (* ux uy)))
	 ( (and (negp ly) (posp uy)) (make-interval (min (* lx uy) (* ux ly))
						   (max (* lx ly) (* ux uy))))
	 (t                         (make-interval (* ux ly) (* lx ly)))))
      (t ;; first interval is completely negative
       (cond
	 ( (posp ly)                 (make-interval (* lx uy) (* ux ly)))
	 ( (and (negp ly) (posp uy)) (make-interval (* uy lx) (* ly lx)))
	 (t                         (make-interval (* ux uy) (* lx ly))))))))

(defun test-mult-interval-fast ()
  ;; I rushed through checking for errors with zeros.

    (defun assert-mults-correctly (lx ux ly uy le ue)
      (let ( (new-interval (mul-interval-fast (make-interval lx ux) (make-interval ly uy))))
	(assert (equal le (lower-bound new-interval)))
	(assert (equal ue (upper-bound new-interval)))))

    (assert-mults-correctly 0 0   0 0   0 0)

    (assert-mults-correctly 2 4    3  5     6 20)
    (assert-mults-correctly 2 4    0 0   0 0)
    (assert-mults-correctly 2 4   -3  5   -12 20)
    (assert-mults-correctly 2 4   -5 -3   -20 -6)

    (assert-mults-correctly -2 5    3  4    -8   20)
    (assert-mults-correctly -2 5    0 0   0 0)
    (assert-mults-correctly -2 5   -3  5    -15  25)
    (assert-mults-correctly -9 3   -9  10   -90  81)
    (assert-mults-correctly -2 5   -4  -3   -20   8)

    (assert-mults-correctly -4 -2    0 0        0 0)
    (assert-mults-correctly -4 -2    3  5    -20 -6)
    (assert-mults-correctly -4 -2   -3  5    -20 12)

    ;; this last one caught a bug.
    (assert-mults-correctly -4 -2   -5 -3     6  20))

;; 2.12

(defun make-center-percent (center percent)
  (make-interval (- center (* (/ percent 100) center)) (+ center (* (/ percent 100) center))))

(defun center-i (i)
  (/ (+ (lower-bound i) (upper-bound i)) 2))

(defun width-i (i)
  (/ (- (upper-bound i) (lower-bound i)) 2))

(defun percent (i)
  (if (equal (center-i i) 0)
      (error "division by 0")
      (* (/ (width-i i) (center-i i)) 100)))

;; 2.13

;; first interval is  [C1 - (p1*C1) , C1 + (p1 * C1)]
;; second interval is [C2 - (p2*C2) , C2 + (p2 * C2)]
;; Since they're both positive the new min is min x min and new max is max x max
;; We will show work for the min x min.
;; ( C1 - (p1 * C1) ) * ( C2 - (p2 * C2) )
;; C1C2 + p1c1p2c2 - p1c1c2 - p2c1x2
;; c1c2 + p1p2c1c2 - (p1 + p2)c1c2
;; c1c2 (p1p2 - (p1+p2)) c1c2.
;; Since p1 and p2 are small p1p2 is ~0 so this reduces to c1c2 - (p1+p2)c1c2
;; So the new percentage is p1 + p2.

;; 2.14
;; Everytime you multiply or divide something with error bounds, the error increases. So if you
;; make an interval by taking A / A, it is going to have more of an error than simply making
;; the interval 1.

(defun par1 (r1 r2)
  (div-interval-fixed (mul-interval r1 r2)
		      (add-interval r1 r2)))

(defun par2 (r1 r2)
  (let ( (one (make-interval 1 1)))
    (div-interval-fixed one
			(add-interval (div-interval-fixed one r1)
				      (div-interval-fixed one r2)))))

;; 2.15
;; par2 is indeed better because we are not unnecessarily compounding our error.

;; 2.16 I believe requires writing a library that has a large set of algebraic identities used for reducing algebraic expression. Possibly a TODO, but I probably will not do this exercise.

Chapter 1 SICP Answers in Common Lisp

April 8th, 2019

As I move towards a proper computer science education, I figure it'd be worthwhile to document my work. Perhaps someone in the future learning SICP will find an answer key written in CL helpful. The code provided is not polished nor checked very thoroughly. But I did see that most of my answers matched with the ones provided here. (link dead at time of writing)

NB: I realize I'm missing answers for 1.14 and 1.15 . They should be uploaded shortly.


;; answers for 1.1
;; 10
;; 12
;; 8
;; 3
;; -16
;; switched define->defparameter
;; A
;; B
;; nil
;; 4
;; 16
;; 6
;; 16
=
;; 1.2
(defparameter *ans2* (/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5))))) (* 3 (- 6 2) (- 2 7))))

;; 1.3

(defun ans3 (a b c)
(defun square (x) (* x x))
(defun sum-of-squares (a b) (+ (square a) (square b)))
(cond
((and (<= c a) (<= c b)) (sum-of-squares a b))
((and (<= b c) (<= b a)) (sum-of-squares a c))
('t                      (sum-of-squares b c))))

;; 1.4

;; describe the following function
;; ( (if (> b 0) + -) a b) )
;; Adds a plus the absolute value of b. in CL would need explicit funcall.

;; 1.5
;; infinite loop if applicative order, 0 if normal order

(defun p () (p))

(defun test (x y) (if (equal x 0) 0 y))

;; 1.6
;; The function gets caught in an infinite loop, because all the parameters are evaluated
;; first so it doesn't have a base case.

(defun square (x) (* x x))
(defun good-enough? (guess x) (< (abs (- (square guess) x)) .0001))
(defun average (a b) (/ (+ a b) 2))
(defun improve (guess x) (average guess (/ x guess)))
(defun sqrt-itr (guess x)
(if (good-enough? guess x)
guess
(sqrt-itr (improve guess x) x)))

;; 1.7
(defun new-sqrt-itr (guess x)
(if (< ( / (abs (- (improve guess x) guess)) guess) (* guess .0001))
guess
(new-sqrt-itr (improve guess x) x)))

;; 1.8
(defun cube (x) (* x x x))
(defun cube-good-enough?
(guess x)
(<= (abs (- (cube-improve guess x) guess)) (abs (* .0001 guess))))

(defun cube-improve (guess x) (/ (+ (/ x (square guess)) (* 2 guess)) 3))
(defun cube-root-itr (guess x)
(print (float guess))
(if (cube-good-enough? guess x)
guess
(cube-root-itr (cube-improve guess x) x)))

;; 1.9
;; First one is recursive process
;; Second one is iterative process

;; 1.10
;; (A 1 10) = 2^10
;; (A 2 4) = 2^16
;; (A 3 3) = (A 2 4) = 2^16

;; (f n) = 2n
;; (g n) = 2^n
;; (h n) = 2 ^ h(n-1) h(0) = 0

;; 1.11
(defun f-recursive (n)
(if (< n 3)
n
(+ (f-recursive (- n 1)) (* 2 (f-recursive (- n 2))) (* 3 (f-recursive (- n 3))))))

(defun f-iterative (n)
(defun f-iterative-helper (f1 f2 f3 count final)
(if (equal count final)
f3
(f-iterative-helper f2 f3 (+ (* f1 3) (* f2 2) f3) (+ count 1) final)))
(if (< n 3) n
(f-iterative-helper 0 1 2 2 n)))

;; 1.12
(defun pascals-triangle (n)
(defun get-harmonic-addition (n) (/ (- (sqrt (+ 1 (* 8 n))) 1) 2))
(defun is-on-edge? (n)
(defun is-mod-addition-whole-integer (x)
(equal (mod (get-harmonic-addition x) 1) 0.0))
(or (is-mod-addition-whole-integer n) (is-mod-addition-whole-integer (+ n 1))))
(defun get-current-level (n) (floor (get-harmonic-addition n)))
(if (is-on-edge? n)
1
(+ (pascals-triangle (- n (get-current-level n) 1))
(pascals-triangle (- n (get-current-level n))))))







fibproof1







fibproof2







1.14 -> 1.15 coming soon


;; 1.16
(defun iterative-repeated-squaring (b n)
"page 46"
(defun square   (x) (* x x))
(defun is-evenp (x) (equal (mod x 2) 0))
(defun iter-expt (b n a)
(cond
((equal n 0)  a)
((is-evenp n) (iter-expt (square b) (- (/ n 2) 1) (* a (square b))))
('t           (iter-expt b (- n 1) (* a b)))))
(iter-expt b n 1))
(defun is-evenp (x) (equal (mod x 2) 0))

;; 1.17
(defun my-multiply (a b)
(defun my-double (x) (* x 2))
(defun half   (x) (/ x 2))
(cond
((equal b 0)  0)
((is-evenp b) (my-multiply (my-double a) (half b)))
(t            (+ a (my-multiply a (- b 1))))))

;; 1.18
(defun my-mult-iterative (a b)
(defun my-double (x) (* x 2))
(defun half   (x) (/ x 2))
(defun my-mult-itr (a b c)
(cond
((equal b 0)  c)
((is-evenp b) (my-mult-itr (my-double a) (half b) c))
(t            (my-mult-itr a (- b 1)  (+ c a)))))
(my-mult-itr a b 0))

;; 1.19
(defun fib (n) (fast-fib 1 0 0 1 n))
(defun fast-fib (a b p q count)
(defun square (x) (* x x))
(cond ( (equal count 0) b)
((is-evenp count)
(fast-fib a b (+ (square p) (square q)) (+ (* 2 p q) (square q)) (/ count 2)))
(t (fast-fib (+ (* b q) (* a q) (* a p))
(+ (* b p) (* a q))
p
q
(- count 1)))))

;; 1.20 18 / 4 (the big thing here is that the if statement is where the actual reduction of the gcd happens)

;; 1.21 199, 1999, 7
(defun smallest-divisor (n)
(defun dividesp (a b) (equal (mod b a) 0))
(defun find-divisor (n test-divisor)
(cond ( (> (square test-divisor) n) n)
((dividesp test-divisor n) test-divisor)
(t (find-divisor n (+ test-divisor 1)))))
(find-divisor n 2))

(defun primep (n)
(equal (smallest-divisor n) n))

(defun timed-prime-test (n)
(defun prime-test (n start-time)
(if (primep n)
(progn
(princ n)
(princ "*****")
(princ (- (get-internal-run-time) start-time))
(print "")
)))
(prime-test n (get-internal-run-time)))

;; 1.22
;; 1013, 1019, 1021 (0 seconds all)
;; 10009, 10037, 10039 (0 seconds all)
;; 100019, 100043, 100049, (0 seconds)
;; 1000033, 1000037, 1000039, (0 seconds)
(defun search-for-primes (n limit)
(if (< n limit)
(progn (timed-prime-test n) (search-for-primes (+ n 2) limit))))

;; 1.25 problem is that the number gets super big, should be taking mod m along the way.
;; 1.26  logn height but number of leaves are doubling every round since u call expmod recursively twice.

(defun expmod (base exp m)
(cond ( (equal exp 0) 1)
((evenp exp) 	 (mod (square (expmod base (/ exp 2) m)) m))
(t               (mod (* base (expmod base (- exp 1) m)) m))))

(defun expmod-miller (base exp m)
;; i had a bug where i wasn't checking > exp 0...caused issues for a bit with infinite loop
(let ( (mod-of-half-exp (if (and (> exp 0) (evenp exp)) (expmod-miller base (/ exp 2) m))))
(cond ( (equal exp 0) 1)
((and (evenp exp)
(not (or (equal mod-of-half-exp 1) (equal mod-of-half-exp (- m 1))))
(equal (mod (square mod-of-half-exp) m) 1)) 0)
((evenp exp) 	 (mod (square mod-of-half-exp) m))
(t               (mod (* base (expmod-miller base (- exp 1) m)) m)))))

(defun fermat-full-test (n)
(defun fermat-test (a n)
(if (>= a n) t (and (equal (expmod a n n) a) (fermat-test (+ a 1) n))))
(fermat-test 2 n))

(defun miller-rabin-full-test (n)
(defun miller-rabin-test (a n)
(if (>= a n) t (and (equal (expmod-miller a n n) a) (miller-rabin-test (+ a 1) n))))
(miller-rabin-test 2 n))

;; 1.29
(defun simpson-integrate (f a b n)
(defun get-h () (/  (- b a) n))
(defun simpson-integrate-itr (h k current-sum)
(defun current-step-value ()  (funcall f (+ a (* h k))))
(cond
((equal k n) (+ current-sum (current-step-value)))
((equal k 0) (simpson-integrate-itr h (+ k 1) (current-step-value)))
((evenp k)   (simpson-integrate-itr h (+ k 1) (+ current-sum (* 2 (current-step-value)))))
(t           (simpson-integrate-itr h (+ k 1) (+ current-sum (* 4 (current-step-value)))))))
(* (/ (get-h) 3) (simpson-integrate-itr (get-h) 0 0)))

;; 1.30
(defun my-sum (term a next b)
(defun iter (a result)
(if (> a b)
result
(iter (funcall next a) (+ result (funcall term a)))))
(iter a 0))

;; 1.31 recursive process

(defun pi-over-4-term (a)
(/  (+ (* (floor a       2) 2) 2)
(+ (* (floor (+ a 1) 2) 2) 1)))

(defun pi-over-4-next (a) (+ a 1))
;; a

(defun my-product (term a next b)
(if (> a b)
1
(* (funcall term a) (my-product term (funcall next a) next b))))

;; b

(defun my-product-itr (term a next b)
(defun iter (a result)
(if (> a b)
result
(iter (funcall next a) (* result (funcall term a)))))
(iter a 1))

;; 1.32 accumulate

;; a
;; (accumulate-recursive #'+ 0 (lambda (x) x) 0 (lambda (x) (+ x 1)) 10)
;; (accumulate-recursive #'* 1 (lambda (x) x) 1 (lambda (x) (+ x 1)) 4)
(defun accumulate-recursive (combiner null-value term a next b)
(if (> a b)
null-value
(funcall combiner (funcall term a)
(accumulate-recursive combiner null-value term (funcall next a) next b))))

;; b
;; (accumulate-iterative #'* 1 (lambda (x) x) 1 (lambda (x) (+ x 1)) 4)
;; (accumulate-iterative #'+ 0 (lambda (x) x) 0 (lambda (x) (+ x 1)) 10)
(defun accumulate-iterative (combiner null-value term a next b)
(defun iter (a result)
(if (> a b)
result
(iter (funcall next a) (funcall combiner result (funcall term a)))))
(iter a null-value))

;; 1.33
;; (filter-accumulate #'primep #'+ 0 #'square 2 (lambda (x) (+ x 1)) 5)

;; kept to show error i made. notice how i accidently call accumulate-recursive
;; because i was copying and pasting the previous code without fully changing it.
;; i also didn't notice the bug because it was hard to tell for low values, since it filters
;; the first value correctly.
(defun filter-accumulate-broken (filter combiner null-value term a next b)
(if (> a b)
null-value
(cond
((funcall filter a)
(funcall combiner (funcall term a)
(accumulate-recursive combiner null-value term (funcall next a) next b)))
(t (funcall combiner
null-value
(accumulate-recursive combiner null-value term (funcall next a) next b))))))

(defun filter-accumulate (filter combiner null-value term a next b)
(if (> a b)
null-value
(funcall combiner (if (funcall filter a) (funcall term a) null-value)
(filter-accumulate filter combiner null-value term (funcall next a) next b))))

(defun sum-of-squares-of-primes (n)
(filter-accumulate #'primep #'+ 0 #'square 2 (lambda (x) (+ x 1)) n))

(defun product-of-relative-primes-less-than-n (n)
(filter-accumulate
(lambda (x) (equal (gcd n x) 1)) #'* 1 (lambda (x) x) 2 (lambda (x) (+ x 1)) (- n 1)))

;; 1.34
;; (f f) -> (f 2) -> (2 2)

;; 1.35
;; x -> 1 + 1 / x
;; x^2 = 1 + x

(defun average-damp (f) (lambda (x) (average x (funcall f x))))

;; This originally had (average-damp f) in the if statement, but it was removed after doing the q.
(defun fixed-point (f &optional (first-guess 1))
(defun iter (old new)
(if (< (abs (- new old)) .0001)
new
(iter new (funcall f new))))
(iter first-guess (funcall f first-guess)))

;; 1.36
;; = 30 iterations with tolerance .0001 and no average damping.
;; =  9 iterations with tolerance .0001 and average damping.
(defun fixed-point-expanded (f &optional (first-guess 1))
(defun iter (old new)
(print new)
(if (< (abs (- new old)) .0001)
new
(iter new (funcall (average-damp f) new))))
(iter first-guess (funcall f first-guess)))

;; 1.37
;; a)
;; it takes k=11  to get it right to 4 decimal places.
;; recursive version
(defun infinite-continued-fraction (n d k)
(defun iter (i)
(/ (funcall n i) (+ (funcall d i) (if (equal i k) 0 (iter (+ i 1))))))
(iter 1))

;; b)
;; iterative version
(defun infinite-continued-fraction-iterative (n d k)
;; work backwards for iterative process
(defun iter (i current-denominator)
(cond
((equal i 1) (/ (funcall n i) current-denominator))
(t           (iter (- i 1) (+ (funcall d (- i 1)) (/ (funcall n i) current-denominator))))))
(iter k (funcall d k)))

;; euler expansion e - 2
;; 1.38 infinite continued fraction with ni = 1 and di = 1,2,1,1,4,6,1,1,8
(defun euler-e-expanion (&optional (steps 10))
(defun ni (i) 1.0)
(defun di (i)
(if (equal (mod i 3) 2)
(* (+ (floor i 3) 1) 2)
1.0))
(infinite-continued-fraction #'ni #'di steps))

;; 1.39 Lambert tanx

(defun tan-cf (x k)
(defun ni (i) (if (equal i 1) x (- (square x))))
(defun di (i) (+ (* 2 (- i 1)) 1))
(infinite-continued-fraction #'ni #'di k))

;; 1.40

(defun deriv (f &optional (dx .0001))
(lambda (x) (/ (- (funcall f (+ x dx)) (funcall f x)) dx)))

(defun newton-transform (f)
(lambda (x) ( - x (/ (funcall f x) (funcall (deriv f) x)))))

(defun newtons-method (g guess)
(fixed-point (newton-transform g) guess))

(defun cubic (a b c)
(lambda (x) (+ (expt x 3) (* a (expt x 2)) (* b x) c)))

;; 1.41
(defun inc (x) (+ x 1))

(defun double-compose (f)
(lambda (x) (funcall f (funcall f x))))
; (funcall (funcall (double-compose (double-compose #'double-compose)) #'inc) 5) = 21

;; 1.42

(defun compose (f g)
(lambda (x) (funcall f (funcall g x))))

;; 1.43

(defun repeated-composition (f n)
(if (equal n 1)
f
(compose f (repeated-composition f (- n 1)))))

;; 1.44

(defun smooth (f)
(lambda (x)
(let ( (dx .0001))
(/ (+ (funcall f (- x dx))
(funcall f x)
(funcall f (+ x dx)))
3))))

(defun n-fold-smooth (f n)
(funcall (repeated-composition #'smooth n) f))

;; 1.45

(defun fixed-point-of-transform (g transform guess)
(fixed-point (funcall transform g) guess))

;;

;; I had issues with this because it was running out of memory for a different reason-namely from
;; display huge fractions. It only works consistently if you make sure that n is a float!
(defun nth-root (x n)
(fixed-point-of-transform
(lambda (y) (/ x (iterative-repeated-squaring y (- n 1))))
(repeated-composition #'average-damp (floor (log n 2)))
1))

;; 1.46

(defun iterative-improve (improve-guess good-enoughp)
(defun iter (guess)
(if (funcall good-enoughp guess)
guess
(iter (funcall improve-guess guess))))
#'iter)

(defun sqrt-iter-improve (n)
(funcall (iterative-improve
(average-damp (lambda (guess) (/ n guess)))
(lambda (guess) (< (abs (- (square guess) n)) .0001))) 1))

(defun fixed-point-iter-improve (f)
(funcall (iterative-improve
(lambda (guess) (funcall f guess))
(lambda (guess) (< (abs (- (funcall f guess) guess)) .0001))) 1))


Fixing My Affliction of Monolingualism

March 22nd, 2019

It's tough to come to terms with the idea that my "internal software" may be broken. I know I am handicapped day in and day out by being ESL - English as a Single Language.

Spanish is similar to English. But certain aspects of Spanish, such as verb conjugation rendering pronouns unnecessary, make it more concise than English. If I could think in Spanish, perhaps I would be able to compactly store certain concepts in my head.

..

I'm at the point in my journey of learning Spanish where I need to make some changes in my study habits to break the barrier that lies between me and basic fluency. Without a methodical process I likely will stay stagnant or even regress. A strategy with a set of goals over a specific timeline is to be established.

I've learned all of the verb conjugations. There are six main categories (moods) of verbs:

el indicativo
el subjuntivo
el imperativo
el presente progresivo
el pretérito perfecto compuesto
el pretérito perfecto de subjuntivo
Within those are various tenses, listed below:

el indicativo - el presente, el pretérito, el imperfecto, el condicional, el futuro simple
el subjuntivo - el presente, el imperfecto (2 versions), el futuro
el imperativo - afirmativo, negativo
el presente progresivo - el presente, el pretérito, el imperfecto, el condicional, el futuro simple
el pretérito perfecto compuesto - (presente) el pretérito perfecto compuesto, el pretérito anterior, el pretérito pluscuamperfecto, el condicional compuesto, el futuro compuesto
el pretérito perfecto de subjuntivo - (presesnte) el pretérito perfecto de subjuntivo, el pluscuamperfecto de subjuntivo, el futuro compuesto del subjuntivo
So all in all there are about 24 total ways you can conjugate a verb. When I first started learning Spanish in middle school, learning each conjugation seemed daunting. Once they've been fully enumerated, it doesn't really seem like so much work. There are a few hundred irregular verbs, which I will have to list in another blog post. Even though I have studied each and every conjugation possible, I am still shaky. Goal (1) is:

1. Obtain absolute mastery of verb conjugation.

The second major task is building up a vocabulary. I would guesstimate my personal Spanish dictionary to contain 2,000 words. My problem is that many of these words I have mapped to an English word in my head. Instead of thining in Spanish, I am basically running a shitty Spanish virtual machine on English XP. So the (2)nd step of learning Spanish is to increase my Spanish word count to roughly 8,000 by creating a Spanish->Spanish mapping Instead of defining the Spanish words in English, I have to close the loop. So I may have a graph of 6,000 words pointing to definitions in my 2,000 fundamental Spanish words, whose concepts are mapped to English words. As I learn new words in Spanish by defining them in Spanish, I will slowly replace the middle man in my mappings of | Spanish word -> English word -> concept |

2. Build a 8,000 word + vocabulary, where new words are defined in Spanish

To learn a new language one must also be aware of how words are put together naturally by native speakers. Among other things, this means learning a large set of idioms. While speaking to Spanish speakers will help, one can process information much faster by reading. So the third step is clearly to read more books. This can be combined with step 2, by adding new words to my Spanish vocabulary study list while I read.

3. Read a minimum of 12 books in Spanish over the course of the year. Improve my vocabulary by adding new words to my study list

The final two steps are to be able to pronounce words correctly and parse spoken Spanish. Pronouncing words should is a matter of getting vocal tract used to making the shapes that are used to say certain words. Practicing this can be combined with (3) and thus combined with (2)

4. Pronounce the words as I read them.

Listening to Spanish is a tad bit tricky since it doesn't combine well with goals (2) (3) and (4). The best course of action is likely to listen to some Spanish music and simply have conversations when available. Parsing rapidly spoken Spanish is difficult but should become easier as my vocabulary expands.

5. Practice parsing spoken Spanish by listening to Spanish music and engaging in conversation when possible.

Combining all of these goals, my study plan is as follows:

Dedicate 1.5 hours to learning Spanish five days a week.

1. 30 minutes is spent working on conjugating verbs. For the fist few days I will be obtaining a list of all the irregular Spanish verbs. Then I will create a small little CL program that conjugates verbs. If they are in the irregular list, their conjugation is either further subcategorized (ala "boot" verbs) or is hard coded in. Then the Spanish program will test me on the various conjugations used spacing repetition.

2. 40 minutes is spent reading a Spanish book each day. As the book is read, each word is pronounced out loud. Words or phrases that are unknown are marked. At the end of the chapter / towards the end of 40 mins, the words are loaded into an SRS and then reviewed for 20 mins. The words, of course, are defined in Spanish.

3. Time spent on the subway/etc is spent listening to Spanish music/podcasts/etc.

Time spent on (1) will likely shift into time time spent on (2) or be switched to a more general study of Spanish grammar.

To be continued.

What Bad Writing Reveals

March 19th, 2019

This past week I attempted to write a few blog posts. I only managed to produce gibberish that won’t be published. It is frustrating to have nothing to show for the time I had put into writing. But after I transformed my thoughts into characters, I could see those thoughts for what they were: nonsense.

I never learned to write powerfully. The standard for English in my high school was... abysmal. I was taught to make essays with a basic structure, to create somewhat grammatically correct sentences, to employ “persuasive" techniques. I learned how to comply with various bureaucracies by learning standardization's such as "MLA format" for references. In essence, I was shown how to write just well enough to keep me employed at some government job.

But I wasn't taught how to punch with my pen. Nor was I shown how to trim down the fat that hides the message behind my words. Missing from my curriculum: How to Write a Manifesto that Starts a War.

That I cannot write with impact is not a problem in and of itself. I never aspired to be a journalist or novelist or anything of the sort. The issue is that words written are a projection of one's internal dialogue. The same words that go down on paper are circulating in the head just moments before.

Knowing this, I decided to read The Elements of Style by William Shrunk Jr. and E.b. White. That ~70 page booklet contains a long list of common errors that contaminate my essays. I learned that I misallocate my relative pronouns, overuse the word “not”, group words incorrectly, etc. But reading Shrunk and White’s work convinced me that I can fix my superfluous writing. And fixing bloated writing may be a key to thinking efficiently.

Apollo Music Update

February 26th, 2019

After a month or so hiatus i am back to working on Apollo. Right now Apollo has two main features

(1) The Ability to Synthesize Sound

(2) The Ability to Compose Music easily with ASCII Characters

Apollo's main focus is on (2) but I want it to be a piece of code that makes music "all by itself" so using samples of instruments recorded in a studio will only be a side feature, if it ever even gets implemented. The nice part of having all your music synth'd yourself is that for every instrument you can usually easily pre-generate sound waves of different lengths with different notes.

Today I fixed a few bugs:

1. An error calculating the equation for an exponential based envelope (which involved solving the system of equations y1 = ab^(zx1) y2 = ab^(zx2) for a and b where z is a chosen parameter by the user and the two points are the points where you want to draw an exponential curve between.

2. Fixed a bug where I called (apply #'max a-huge-list) . Common Lisp has a limit on the number of arguments you can pass to a function, so the correct way to do what I was trying to do was (reduce #'max a-huge-list)

3. Fixed a performance bug where I was iterating through a list and each time trying to get the nth element using the function nth, which caused the computation to be n^2.

Now I need to add a feature where I create two different types of instruments - ones that have a sustain such as wind instruments vs. those that peak and die off (piano, guitar, drums). The former needs a way to have a variable envelope function.

Coming of Age

February 24th, 2019

mircea_popescu: there's this common tendency among noob bloggers to regard the blog as some sort of trophycase/showcase. they miss out on their own youth, as the lived story of their own personal path through life, consisting as such always does of failure, and tribulation.

Reading your own writing is akin to looking at yourself in the mirror. If you haven’t done it in a long time (or ever) you are going to be quite unhappy when you look. You'll notice all the blemishes and faults that everyone else can see but are invisible to you. The childish approach to dealing with this is to never look in the mirror. But not looking into the mirror does not make those imperfections disappear.

In reality writing for a blog is much more daunting than looking in the mirror, because instead of just seeing your reflection you are taking a snapshot of your mind and posting it for yourself and the world to see. When I take a look back at my previous writings I often cringe from reading what I wrote. I read my writing about goals I still haven’t made progress into, let alone accomplished. I read world views that not only seem ridiculous now, but were written in broken English. And I know that in the future I will likely feel the same way reading the post I’m writing today.

But I take solace knowing that there is more honesty in blogging frequently and keeping a record of one’s development than there is in showing only a very curated “trophy case” of thoughts. Everyone save naive children knows that in-between the highlight reel of a millennial’s antisocial media posts are painful and embarrassing moments. The crime of erasing one’s past and cherry-picking content to display on your blog is not that your lying to everyone else. It’s that you’re lying to yourself. It prevents you from confronting your inner hayseed.

In You Know Me Al by Ring Lardner, Jack writes to his friend Al constantly updating him about his life. Reading Jack’s letters is amusing not only because you see how foolish he is and how he can’t keep any of his commitments, but also because Jack manages to remain complete oblivious to his own character. One wonders if had the fictional character Jack written blog posts instead of writing letters, he perhaps would have been able to see his ridiculousness and improve himself.

Here’s to finishing Apollo, starting my game Zylon, staying healthy, avoiding my bad habits, and most importantly using every minute of my time wisely.

Still In The Big Apple

January 29th, 2019

It’s been well over a month since my last post; a new piece of writing is very much due. My life trajectory has changed dramatically between my last publication and now. Before I had plans to return to Costa Rica on January 2nd, but today I am still here in New York City. The reasons for this are numerous - but the primary cause of me staying here is to be with the people who I love and have known the longest in my life.

At times I feel that I am regressing by staying in New York. My time spent in Costa Rica was nothing short of heavenly. Nearly every day consisted of waking up to a chorus of birds chirping, surfing magnificent waves, and enjoying the company of close friends. I had a wonderful three bedroom apartment that I was very proud to invite people over to. I was picking up, however slowly, my second language Spanish and finally starting to have enjoyable conversations with locals in their tongue. Although I wasn’t working when at the moment I left, I had previously succeeded in obtaining well paying jobs where I could work remotely and support myself. And now that I’m back in the city, just about all of this is gone. I’m back to the cold concrete jungle of the city. I have my closest friends and family here - but making new friendships is much harder than it was in Costa Rica. As for my living situation - I’m back to crashing my parent's house. I can’t even begin to fathom sacrificing my time spent reading, coding, learning the guitar, etc. to work a boring 9-5 to sustain a shoebox of an apartment in the city. But this day will have to come soon..

Another great pain of leaving Costa Rica is the feeling that the friendships I made there will fade away quickly. Given that I don’t have accounts with the normal antisocial media websites, it can be a bit tricky maintaing certain relationships. The fact that I lost my phone and subsequently my phone number does not help either. There are many people I miss terribly, and I apologize to them for not having put in the time to message them.

New York being home is not the only thing that draws me back here. In Central America I felt that my days were being spent well since I was thoroughly enjoying my youth, yet I couldn’t help but think that I was not pushing my career forward like I should be. Even though I picked up two wonderful hobbies that will last me a lifetime - guitar and surfing - I felt that most of my hours were spent were only going to give me pleasure at the specific moment I spent them. I had fears of becoming an adult that had little to show for his earlier years. The one educational reason - or should I say excuse - for being in Costa Rica was to learn Spanish. This, however, was not progressing at the rate it should have been since I had enclosed myself in an English speaking bubble within Costa Rica. My friends spoke Spanish as their primary language, but with me the conversation always was in English. I believe I still have learned more Spanish in America than I have in Costa Rica. So I felt, and feel currently, that I needed to stay in New York to develop a lifestyle that allows me to soak up knowledge and build a career.

I hope to return to Costa Rica within the year, but when I do it will likely be for only a relatively short period of time. As for now, it's great to be back home.

The price of btc will be $13337 by the time you're done reading this.

December 20th, 2018

This morning, according to the publicized fiat exchanges, bitcoin was trading at 3.8k USD. This price is up from 3.3k or something, which now appears to be the valley of some dip after a long stable 6k price.

When these fiat-reported major price shifts occur, a whole lot of technical analysis voodoo and faulty logic gets used to explain what happened that caused the change in price. A common explanation for a price dip is "X government banned bitcoin" or "the block size debate is causing doubts.” For a rising price, the explanation is some blah blah about how new X feature from the power ranger bitcoin team has caused increased confidence in the chain, upgrade your nodes today!

But the question of why and especially why now with regards to the price is generally too complicated to get answered. The last-traded-price is based off an equation with millions of variables, and for the lay person it is impossible to discover. Perhaps the DO”J” just seized a new batch of bitcoins, and the price goes down because they are dumping the stolen coins onto the market. Perhaps an exchange was hacked and their reserves were stolen, causing the supply to drop, and thus the price to increase. Perhaps there is a group psychology phenomena at play. No one really knows.

We can make statements about the price from recent trades, but the price of bitcoin for an individual is in something akin to a quantum superposition until the very moment when an exchange occurs. At the instant a transfer is made, that price superposition collapses to the value for the parties involved in the exchange. But until that moment, the price is a Fugazzi. "Fugayzzi? Fuggazi? it’s a wazy it’s a woosy it’s a .. fairy dust, it doesn’t exist, it’s never landed, it is no matter, it’s not on the elemental chart, it’s not fucking real."

Yet with a very real cap of 21,000,000 btc and no cap on the USD, there is little hope that the ability to buy btc for price P can stay at P <= C for any constant C when C is denominated in dollars. So when a company is saying that the price is at some peculiarly low value - $3.5k or so - an eyebrow must be raised in suspicion.

Coinbase selling btc for 4k is the same thing as children selling lemonade for less than the price of the supplies they used to buy the lemonade. The point of the kids selling lemonade is not to make money. It is to have social interactions and receive the dopamine hit from the smile on their customers’ faces. They are eating the cost to obtain an ulterior goal. Likewise, Coinbase, in typical SV fashion, is not concerned about turning a profit. And especially not a profit denominated in bitcoin. Their job is to sell btc at the lowest price to the greatest number of people. Preferably young ones just entering the work force. When a whale (i.e. someone with like >$10k dollars) comes to Coinbase and says, “$4k a btc? i’d like all the lemonade please” they are either turned away or are given bitcoin IOUs.

If Coinbase were really a profit oriented company, they would have taken their $100mil+ investment (read: access to write permission to the USD db) and used it to acquire more btc. They were in a better position than anyone to know that the price of btc was going to go up. Same thing with 21.co with their 116mil+ investment into hamster powered miners. (Does anyone even remember them?)

At the end of the day, you have to pay for the privilege of knowing what the price is for btc at a certain volume. It’s a world of lies out there - and the only thing that’s for certain is the real game is being played by high rollers off of the exchanges.

The Fundamentals of Learning

December 16th, 2018

There is a rule of thumb that applies to nearly everything you are trying to learn.

For every skill, there is a finite set of fundamentals whose application and combination will allow you to perform that skill.

Thus to succeed at your goal you must:

1. figure out what those fundamentals are
2. figure out what is the correct way to execute those fundamentals
3. Devise and perform a training program to be able to perform said execution from (2) consistently
The usefulness of this advice relies heavily on a clear understanding of the word fundamental in this context. A fundamental is a technique in a finite -but possibly quite large- set of "the fundamentals of skill y." A fundamental is always something that can be trained or improved upon. So, while being tall may be quite important to succeeding at playing basketball, "being tall" is not by our definition a fundamental. In addition, a fundamental cannot be the combination of two or more different fundamentals. The pragmatic reason for this is that if a fundamental is the combination of two other fundamentals, it would be incorrect to train that technique. It would be better to isolate the the two distinct fundamentals that comprise that technique and train them separately. Needless to say, some fundamentals build upon each other in a way that you cannot learn fundamental b without learning fundamental a. Also, while the combination of two fundamentals cannot be a fundamental, the act of combining two fundamentals may very well be a fundamental in and of itself.

With that being clear, we need guidelines on how to perform tasks (1) (2) and (3). Step (1) is often the hardest.

(1)

To figure out the fundamentals of a skill, there are two principal methods that must be combined.

(A) Figuring out the authority on the subject. This is either the best person in the field you can be in contact with, or preferably a book. Then simply inquire from that authority what the fundamentals are.

(B) Reasoning must be used to confirm that a technique is indeed a fundamental of a skill. Of course if you the pioneer of a skill, then this is the only method you can use. This is much harder than simply "downloading" all the fundamentls from an authority, since it can be difficult to figure out the different elements that comprise a technique.

(2)

Once you know what the fundamentals are, then you can begin to judge what is the correct execution of those fundamentals. This is effectively the same process as step one. You consult an authority and combine their advice with rational analysis.

For the sake of example, let us consider the skill of playing tennis. Within that skill is the technique of a serve. We know that a serve, itself, is not a fundamental. This is because a serve is at least the combination of two different fundamentals - an overhead shot and a toss. So let's examine how we would determine the correct way to perform a toss, for our serve, using logic alone.

Of course we want to create the best possible angle for us to hit the ball into our opponents service area, which would mean we want to toss the ball as high as possible. We want to maximize the time the ball stays in the "sweet spot," i.e. the best position for us to hit our overhead shot. This is the highest point at which we can make contact with the ball, so that we can hit the ball at the moment it switches directions (i.e. when its velocity is zero) with the best angle. (etc, etc)

(3)

Once you are aware of what is the correct execution of the fundamentals, you must devise an efficient and regular training plan/schedule to be able to perform all of the fundamentals correctly. From our previous example, this may be something such as:

Toss the ball 10 times trying to hit the height as indicated by a line marked on a wall. Do this with a camera recording your tosses. Review the video and fix mistakes. Repeat 3x 4 days a week.

It is important to remember that when training, mindlessly repeating an action does not help you towards your goal. Only when you are self analytic, by doing an action like recording yourself with a camera and fixing your mistakes, do you make progress. Once again, consulting an authority figure on how to train is often wise. A secret code in the title of books that help you with this stage of learning is "training manual."