Sunday, June 05, 2022

SICP in Clojure: Chapter 2, Exercise 3

This is my Clojure solution to Chapter 2, Exercise 3:

(ns sicp.ch2.ex03
  (:require [sicp.ch2.ex02 :as ch2-ex02]))

(defn- seg-length
  [seg]
  (let [s (ch2-ex02/seg-start seg)
        e (ch2-ex02/seg-end seg)
        x (- (ch2-ex02/point-x e) (ch2-ex02/point-x s))
        y (- (ch2-ex02/point-y e) (ch2-ex02/point-y s))]
    (Math/sqrt (+ (* x x) (* y y)))))

(defn- make-rect-1
  [left-seg bottom-seg]
  [left-seg bottom-seg])

(def ^:private rect-1-left-seg first)

(def ^:private rect-1-bottom-seg second)

(defn- rect-1-width
  [rect-1]
  (seg-length (rect-1-bottom-seg rect-1)))

(defn- rect-1-height
  [rect-1]
  (seg-length (rect-1-left-seg rect-1)))

(defn- rect-1-perimeter
  [rect-1]
  (* 2 (+ (rect-1-width rect-1) (rect-1-height rect-1))))

(defn rect-1-area
  [rect-1]
  (* (rect-1-width rect-1) (rect-1-height rect-1)))

(def ^:private rect-1
  (make-rect-1
   (ch2-ex02/make-seg (ch2-ex02/make-point 1 0)
                      (ch2-ex02/make-point 5 0))
   (ch2-ex02/make-seg (ch2-ex02/make-point 1 0)
                      (ch2-ex02/make-point 1 42))))

(comment
  (rect-1-perimeter rect-1) ; => 92.0

  (rect-1-area rect-1) ; => 168.0
  )

(defn- make-rect-2
  [bottom-left-pt top-right-pt]
  [bottom-left-pt top-right-pt])

(def ^:private rect-2-bottom-left first)

(def ^:private rect-2-top-right second)

(defn- rect-2-bottom-right
  [rect-2]
  (ch2-ex02/make-point
   (ch2-ex02/point-x (rect-2-top-right rect-2))
   (ch2-ex02/point-y (rect-2-bottom-left rect-2))))

(defn- rect-2-width
  [rect-2]
  (seg-length
   (ch2-ex02/make-seg (rect-2-bottom-left rect-2)
                      (rect-2-bottom-right rect-2))))

(defn- rect-2-height
  [rect-2]
  (seg-length
   (ch2-ex02/make-seg (rect-2-bottom-right rect-2)
                      (rect-2-top-right rect-2))))

(defn- rect-2-perimeter
  [rect-2]
  (* 2 (+ (rect-2-width rect-2) (rect-2-height rect-2))))

(defn- rect-2-area
  [rect-2]
  (* (rect-2-width rect-2) (rect-2-height rect-2)))

(comment
  (def rect-2 (make-rect-2 (ch2-ex02/make-point 1 0)
                           (ch2-ex02/make-point 5 42)))

  (rect-2-perimeter rect-2) ; => 92.0

  (rect-2-area rect-2) ; => 168.0
  )

 

SICP in Clojure: Chapter 2, Exercise 2

This is my Clojure solution to Chapter 2, Exercise 2:

(ns sicp.ch2.ex02)

(defn make-point
  [x y]
  [x y])

(def point-x first)

(def point-y second)

(defn- point-print
  [pt]
  (println (str "(" (point-x pt) ", " (point-y pt) ")")))

(defn make-seg
  [start-pt end-pt]
  [start-pt end-pt])

(def seg-start first)

(def seg-end second)

(defn- seg-midpoint
  [seg]
  (let [s (seg-start seg)
        e (seg-end seg)]
    (make-point (/ (+ (point-x s) (point-x e)) 2)
                (/ (+ (point-y s) (point-y e)) 2))))

(comment
  (def seg (make-seg (make-point 1 0) (make-point 5 42)))

  (point-print (seg-midpoint seg)) ; => (3, 21)
  )


SICP in Clojure: Chapter 2, Exercise 1

 This is my Clojure solution to Chapter 2, Exercise 1:

(ns sicp.ch2.ex01
 (:require [sicp.ch1.ex20 :as ch1-ex20]))

(defn- make-rat
  [n d]
  (let [g (Math/abs (long (ch1-ex20/gcd n d)))
        h (if (neg? d) (- g) g)]
    [(/ n h) (/ d h)]))

(comment
  (make-rat 10 -30) ; => [-1 3]
  #__)


Sunday, September 05, 2021

SICP in Clojure: Chapter 1, Exercise 46

This is my Clojure solution to Chapter 1, Exercise 46:

(ns sicp.ch1.ex46
  (:require [sicp.ch1.ex06 :as ch1-ex06]
            [sicp.ch1.ex35 :as ch1-ex35]))

(defn iterative-improve
  [good-enough? improve]
  (fn f [guess]
    (if (good-enough? guess)
      guess
      (f (improve guess)))))

(defn sqrt
  [x]
  ((iterative-improve #(ch1-ex06/good-enough? % x)
                      #(ch1-ex06/improve % x))
   1.0))

(defn fixed-point
  [f first-guess]
  ((iterative-improve #(ch1-ex35/close-enough? % (f %))
                      #(f %))
   first-guess))

(comment
  (sqrt 16) ; => ~4.0

  (sqrt 10000) ; => ~100.0

  (fixed-point #(+ 1 (/ 1 %)) 2.0) ; => ~1.618
  #__)

 

SICP in Clojure: Chapter 1, Exercise 45

This is my Clojure solution to Chapter 1, Exercise 45:

(ns sicp.ch1.ex45
  (:require [sicp.ch1.ex35 :as ch1-ex35]
            [sicp.ch1.ex43 :as ch1-ex43]))

(defn expt
  [x n]
  (loop [acc 1 n n]
    (if (zero? n) acc
        (recur (* x acc) (dec n)))))

(defn log2
  [n]
  (/ (Math/log n) (Math/log 2)))

(defn average-damp
  [f]
  #(/ (+ % (f %)) 2))

(defn fixed-point
  [f guess]
  (let [next-guess (f guess)]
    (if (ch1-ex35/close-enough? guess next-guess)
      next-guess
      (fixed-point f next-guess))))

(defn nth-root
  [n x]
  (fixed-point ((ch1-ex43/repeated average-damp (Math/ceil (log2 n)))
                #(/ x (expt % (dec n))))
               1.0))

(comment
  (nth-root 2 100)

  (nth-root 3 1000)

  (nth-root 4 10000)

  (nth-root 5 100000)

  (nth-root 15 (expt 10 15))
  #__)

 

Monday, May 03, 2021

EtherFreakers

EtherFreakers is a decentralised game on the Ethereum blockchain. To play, an account must birth a freaker, an ERC-721 token. This requires a payment in ether to the EtherFreakers smart contract that is greater than 1.005 times the price paid for the n/2-th birthed freaker where n is the current number of freakers. For the first freaker, any price greater than zero will do.

Each freaker is randomly assigned to one of eight species: mercury, venus, mars, jupiter, saturn, uranus, neptune, and pluto. Each freaker is randomly assigned numeric values for a set of five attributes: agility, stamina, fortune, offence and defence. Both probabilty distributions are non-uniform, and the probability distribution for the attributes depends on the species.

Each freaker has energy. Before a freaker is birthed, half of the price is distributed to the existing freakers as energy and the other half is assigned directly to the new freaker as energy. Furthermore, an account can deposit or withdraw ether to increase (charge) or decrease (discharge) the energy of a freaker.

Each account has a combat multiplier with two components: offence and defense. When an account receives or sends a freaker, its combat multiplier increases or decreases respectively based on the offence and defence attributes of the freaker. A transfer also triggers a redistribution of some energy to all existing freakers.

A freaker can attack another freaker. The outcome is either a miss, a thwart or a capture. The outcome is random but is based on the attributes and energy of the freakers and the combat multiplier of the controlling accounts. An attack also triggers a redistribution of some energy to all existing freakers. In the case of a capture, the ERC-721 token of the loser is transferred to the winner. If an account has at least one freaker from each species, those freakers cannot attack or be attacked. 

Additionally, there are eight creators, a special type of token, that cannot attack or be attacked. These were created when the smart contract was first deployed and serve to siphon energy (and hence, ether) from the game.

Sunday, December 27, 2020

SICP in Clojure: Chapter 1, Exercise 44

This is my Clojure solution to Chapter 1, Exercise 44:

(ns sicp.ch1.ex44
  (:require [sicp.ch1.ex16 :as ch1-ex16]
            [sicp.ch1.ex40 :as ch1-ex40]
            [sicp.ch1.ex43 :as ch1-ex43]))

(defn smooth
  [f]
  #(/ (+ (f (- % ch1-ex40/dx))
         (f %)
         (f (+ % ch1-ex40/dx)))
      3))

(defn n-fold-smooth
  [f n]
  ((ch1-ex43/repeated smooth n) f))

(comment
  ((smooth ch1-ex16/square) 5) ; => ~25

  ((n-fold-smooth ch1-ex16/square 2) 5) ; => ~25
  #__)

 

SICP in Clojure: Chapter 1, Exercise 43

This is my Clojure solution to Chapter 1, Exercise 43:

(ns sicp.ch1.ex43
  (:require [sicp.ch1.ex16 :as ch1-ex16]
            [sicp.ch1.ex42 :as ch1-ex42]))

(defn repeated
  [f n]
  (loop [g identity n n]
    (if (zero? n)
      g
      (recur (ch1-ex42/compose f g) (dec n)))))

(comment
  ((repeated ch1-ex16/square 2) 5) ; => 625
  #__)

 

Wednesday, December 23, 2020

SICP in Clojure: Chapter 1, Exercise 42

This is my Clojure solution to Chapter 1, Exercise 42:

(ns sicp.ch1.ex42
  (:require [sicp.ch1.ex16 :as ch1-ex16]))

(defn compose
  [f g]
  #(f (g %))) ; could use comp

(comment
  ((compose ch1-ex16/square inc) 6)
  #__)

 

SICP in Clojure: Chapter 1, Exercise 41

 This is my Clojure solution to Chapter 1, Exercise 41:

(ns sicp.ch1.ex41)

(defn double-it
  [f]
  #(f (f %))) ; could use comp

(comment
  (((double-it (double-it double-it)) inc) 5) ; => 21
  #__)
 

Sunday, November 29, 2020

SICP in Clojure: Chapter 1, Exercise 40

This is my Clojure solution to Chapter 1, Exercise 40:

(ns sicp.ch1.ex40
  (:require [sicp.ch1.ex15 :as ch1-ex15]
            [sicp.ch1.ex16 :as ch1-ex16]
            [sicp.ch1.ex35 :as ch1-ex35]))

(def dx 0.00001)

(defn deriv
  [f]
  #(/ (- (f (+ % dx)) (f %)) dx))

(defn newton-transform
  [f]
  #(- % (/ (f %) ((deriv f) %))))

(defn newtons-method
  [f guess]
  (ch1-ex35/fixed-point (newton-transform f) guess))

(defn cubic
  [a b c]
  #(+ (ch1-ex15/cube %)
      (* a (ch1-ex16/square %) (* b %) c)))

(comment
  (< ((cubic 1 2 3) (newtons-method (cubic 1 2 3) 1.0)) dx)
  #__)
 

Tuesday, September 01, 2020

SICP in Clojure: Chapter 1, Exercise 39

  This is my Clojure solution to Chapter 1, Exercise 39:

 (ns sicp.ch1.ex39
  (:require [sicp.ch1.ex16 :as ch1-ex16]
            [sicp.ch1.ex37 :as ch1-ex37]))

(defn tan-cf
  [x k]
  (/
   (ch1-ex37/cont-frac (constantly (- (ch1-ex16/square x)))
                       #(inc (* 2 (dec %)))
                       k)
   (- x)))

(comment
  (double (tan-cf (/ Math/PI 6) 10)) ; => 0.5773502691896257
  #__)