This is my Clojure solution to Chapter 1, Exercise 14:
(ns sicp.ch1.ex14
(:require [clojure.java.io :as io]
[clojure.shell :as shell]
[clojure.string :as s]))
(defn first-denomination
[kinds-of-coins]
(condp = kinds-of-coins
1 1
2 5
3 10
4 25
5 50))
(def ^{:dynamic true :private true} *writer* nil)
(defn- cc
[amount kinds-of-coins prev-call calls]
(let [this-call (inc (count @calls))
step [prev-call this-call]]
(when (some? *writer*)
(.write *writer* (str (s/join " -> " step) \newline)))
(swap! calls conj step)
(cond (zero? amount) 1
(or (neg? amount) (zero? kinds-of-coins)) 0
:else (+ (cc amount
(dec kinds-of-coins)
this-call
calls)
(cc (- amount
(first-denomination kinds-of-coins))
kinds-of-coins
this-call
calls)))))
(defn count-change
[amount & {:keys [dot-file] :or [dot-file false]}]
(let [calls (atom [])]
(if dot-file
(with-open [writer (io/writer "/tmp/cc.dot")]
(binding [*writer* writer]
(.write *writer* "digraph {\n")
(let [answer (cc amount 5 0 calls)]
(.write *writer* "}\n")
answer)))
(cc amount 5 0 calls))))
(count-change 100) ; => 292
(count-change 11 :dot-file true) ; => 4
;; draw the call graph
(shell/sh "/usr/local/bin/dot" "-Kdot" "-Tsvg" "/tmp/cc.dot" "-O")
(shell/sh "/usr/bin/open" "/tmp/cc.dot.svg")
;; if n is the amount to be changed and k is the number of
;; denominations then: the space complexity (or the maximum height of
;; the tree) is O(n + k) the time complexity (or the number of nodes
;; in the tree) is O(n^k)
(ns sicp.ch1.ex14
(:require [clojure.java.io :as io]
[clojure.shell :as shell]
[clojure.string :as s]))
(defn first-denomination
[kinds-of-coins]
(condp = kinds-of-coins
1 1
2 5
3 10
4 25
5 50))
(def ^{:dynamic true :private true} *writer* nil)
(defn- cc
[amount kinds-of-coins prev-call calls]
(let [this-call (inc (count @calls))
step [prev-call this-call]]
(when (some? *writer*)
(.write *writer* (str (s/join " -> " step) \newline)))
(swap! calls conj step)
(cond (zero? amount) 1
(or (neg? amount) (zero? kinds-of-coins)) 0
:else (+ (cc amount
(dec kinds-of-coins)
this-call
calls)
(cc (- amount
(first-denomination kinds-of-coins))
kinds-of-coins
this-call
calls)))))
(defn count-change
[amount & {:keys [dot-file] :or [dot-file false]}]
(let [calls (atom [])]
(if dot-file
(with-open [writer (io/writer "/tmp/cc.dot")]
(binding [*writer* writer]
(.write *writer* "digraph {\n")
(let [answer (cc amount 5 0 calls)]
(.write *writer* "}\n")
answer)))
(cc amount 5 0 calls))))
(count-change 100) ; => 292
(count-change 11 :dot-file true) ; => 4
;; draw the call graph
(shell/sh "/usr/local/bin/dot" "-Kdot" "-Tsvg" "/tmp/cc.dot" "-O")
(shell/sh "/usr/bin/open" "/tmp/cc.dot.svg")
;; if n is the amount to be changed and k is the number of
;; denominations then: the space complexity (or the maximum height of
;; the tree) is O(n + k) the time complexity (or the number of nodes
;; in the tree) is O(n^k)
No comments:
Post a Comment