Skip to content

Commit

Permalink
Solution careercup#6 + code readability improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
leeorengel committed Nov 29, 2015
1 parent b8238f3 commit 82ba031
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 49 deletions.
8 changes: 5 additions & 3 deletions Clojure/src/chapter_4/chapter_4_q2.clj
Expand Up @@ -6,8 +6,10 @@
half-size (int (/ vec-size 2))
middle (get sorted-vec half-size)]
(cond (= vec-size 1) (map->BinaryTreeNode {:data (first sorted-vec)})
(= vec-size 2) (map->BinaryTreeNode {:data (first sorted-vec)
(= vec-size 2) (map->BinaryTreeNode {:data (first sorted-vec)
:right (map->BinaryTreeNode {:data (second sorted-vec)})})
:else (map->BinaryTreeNode {:data middle
:left (minimal-tree (subvec sorted-vec 0 half-size))
:right (minimal-tree (subvec sorted-vec (inc half-size) vec-size))}))))
:left (minimal-tree
(subvec sorted-vec 0 half-size))
:right (minimal-tree
(subvec sorted-vec (inc half-size) vec-size))}))))
3 changes: 1 addition & 2 deletions Clojure/src/chapter_4/chapter_4_q3.clj
Expand Up @@ -9,5 +9,4 @@
nil))

(defn list-of-depths [tree]
(let [depth-map (list-of-depths-helper tree 0)]
depth-map))
(list-of-depths-helper tree 0))
9 changes: 3 additions & 6 deletions Clojure/src/chapter_4/chapter_4_q4.clj
@@ -1,13 +1,10 @@
(ns chapter-4.chapter-4-q4
(:import (data_structures.tree BinaryTreeNode)))


(defn tree-height [^BinaryTreeNode node]
(if (nil? node)
0
(+ 1 (tree-height (:left node)) (tree-height (:right node)))))
(cond (nil? node) 0
:else (+ 1 (-> node :left tree-height) (-> node :right tree-height))))

(defn tree-balanced? [tree]
(let [root tree
height-delta (- (tree-height (:left root)) (tree-height (:right root)))]
(let [height-delta (- (-> tree :left tree-height) (-> tree :right tree-height))]
(<= (Math/abs height-delta) 1)))
4 changes: 2 additions & 2 deletions Clojure/src/chapter_4/chapter_4_q5.clj
Expand Up @@ -4,8 +4,8 @@
;; O(n)
(defn valid-bst? [tree]
(if (some? tree)
(cond (and (some? (:left tree)) (< (:data tree) (:data (:left tree)))) false
(and (some? (:right tree)) (> (:data tree) (:data (:right tree)))) false
(cond (and (some? (:left tree)) (< (:data tree) (-> tree :left :data))) false
(and (some? (:right tree)) (> (:data tree) (-> tree :right :data))) false
:else (and (valid-bst? (:left tree)) (valid-bst? (:right tree))))
true))

Expand Down
27 changes: 27 additions & 0 deletions Clojure/src/chapter_4/chapter_4_q6.clj
@@ -0,0 +1,27 @@
(ns chapter-4.chapter-4-q6
(:require [clojure.zip :as zip]
[data-structures.tree :refer :all]))

(defn- smallest [zipper-node]
"Returns the smallest node in a zipper of a BST"
(if (-> zipper-node zip/children empty?)
(zip/node zipper-node)
(if (some? (zip-left-child zipper-node))
(smallest (zip-left-child zipper-node))
(smallest (zip-right-child zipper-node)))))

(defn- ancestor-successor [zipper-node node-data]
(let [node (zip/node zipper-node)
parent (zip-parent zipper-node)]
(if (some? parent)
(if (> (:data node) (-> parent zip/node :data))
(ancestor-successor parent node-data)
(zip/node parent))
nil)))

(defn successor [zipper-node]
"Given a zipper structured node reference, returns its successor."
(let [node (zip/node zipper-node)]
(if (some? (:right node))
(smallest (zip-right-child zipper-node))
(ancestor-successor zipper-node (:data node)))))
27 changes: 25 additions & 2 deletions Clojure/src/data_structures/tree.clj
@@ -1,4 +1,5 @@
(ns data-structures.tree)
(ns data-structures.tree
(:require [clojure.zip :as zip]))

(defrecord BinaryTreeNode [data left right])

Expand Down Expand Up @@ -43,4 +44,26 @@
(concat (post-order-walk (:left node))
(post-order-walk (:right node))
[(:data node)])
nil))
nil))

;;
;; Zipper implementation for parent navigation
;; See: http://tech.puredanger.com/2010/10/22/zippers-with-records-in-clojure/
;;

(defn- branch? [_] true)
(defn- children [node] (remove nil? (seq [(:left node) (:right node)])))
(defn- make-node [node children] (->BinaryTreeNode (:data node) (first children) (second children)))

(defn create-tree-zipper [tree-spec]
(let [root (create-tree tree-spec)]
(zip/zipper branch? children make-node root)))

(defn zip-left-child [zipper-node]
(-> zipper-node zip/down))

(defn zip-right-child [zipper-node]
(-> zipper-node zip/down zip/right))

(defn zip-parent [zipper-node]
(-> zipper-node zip/up))
15 changes: 9 additions & 6 deletions Clojure/test/chapter_4/chapter_4_q2_test.clj
Expand Up @@ -12,29 +12,32 @@
(testing "base-case even"
(let [arr [1 2]
expected-bst (create-tree [1
[] [2]])]
[]
[2]])]
(is (= expected-bst (minimal-tree arr)))))

(testing "base-case odd"
(let [arr [1 2 3]
expected-bst (create-tree [2
[1] [3]])]
[1]
[3]])]
(is (= expected-bst (minimal-tree arr)))))

(testing "even-numbered array"
(let [arr [1 2 3 4]
expected-bst (create-tree [3
[1
[] [2]] [4]])]
[] [2]]
[4]])]
(is (= expected-bst (minimal-tree arr)))))

(testing "odd-numbered array"
(let [arr [1 2 3 4 5]
expected-bst (create-tree [3
[1
[] [2]] [4
[] [5]]])]
[] [2]]
[4
[] [5]]])]
(is (= expected-bst (minimal-tree arr))))))


(run-tests)
14 changes: 11 additions & 3 deletions Clojure/test/chapter_4/chapter_4_q3_test.clj
Expand Up @@ -4,19 +4,23 @@
[chapter-4.chapter-4-q3 :refer :all]))

(deftest list-of-depths-test

(let [tree (create-tree [1])
actual (list-of-depths tree)]
(is (= {0 '(1)} actual)))

(let [tree (create-tree [1 [2] [3]])
(let [tree (create-tree [1
[2]
[3]])
actual (list-of-depths tree)]
(is (= {0 '(1)
1 '(2 3)} actual)))

(let [tree (create-tree [1
[2
[5
[1]]] [3]])
[1]]]
[3]])
actual (list-of-depths tree)]
(is (= {0 '(1)
1 '(2 3)
Expand All @@ -26,7 +30,11 @@
(let [tree (create-tree [1
[2
[5
[1]]] [3 [6 [23]] [10]]])
[1]]]
[3
[6
[23]]
[10]]])
actual (list-of-depths tree)]
(is (= {0 '(1)
1 '(2 3)
Expand Down
29 changes: 20 additions & 9 deletions Clojure/test/chapter_4/chapter_4_q4_test.clj
Expand Up @@ -9,30 +9,41 @@
(is (tree-balanced? tree))))

(testing "two nodes"
(let [tree-1 (create-tree [1 [2]])
tree-2 (create-tree [1 [] [2]])]
(let [tree-1 (create-tree [1
[2]])
tree-2 (create-tree [1
[]
[2]])]
(is (tree-balanced? tree-1))
(is (tree-balanced? tree-2))))

(testing "balanced > 2 nodes"
(let [tree-1 (create-tree [1 [2] [3]])
(let [tree-1 (create-tree [1
[2]
[3]])
tree-2 (create-tree [1
[2] [3
[4]]])]
[2]
[3
[4]]])]
(is (tree-balanced? tree-1))
(is (tree-balanced? tree-2))))

(testing "not balanced"
(let [tree-1 (create-tree [1 [2
[3]]])
(let [tree-1 (create-tree [1
[2
[3]]])
tree-2 (create-tree [1
[2
[5
[1]]] [3]])
[1]]]
[3]])
tree-3 (create-tree [1
[2
[5
[1] [15]] [45]] [3]])]
[1]
[15]]
[45]]
[3]])]
(is (not (tree-balanced? tree-1)))
(is (not (tree-balanced? tree-2)))
(is (not (tree-balanced? tree-3))))))
Expand Down
48 changes: 32 additions & 16 deletions Clojure/test/chapter_4/chapter_4_q5_test.clj
Expand Up @@ -9,21 +9,29 @@
(is (valid-bst? tree))))

(testing "two nodes"
(let [tree-1 (create-tree [1 [2]])
tree-2 (create-tree [1 [0]])
tree-3 (create-tree [1 [] [2]])]
(let [tree-1 (create-tree [1
[2]])
tree-2 (create-tree [1
[0]])
tree-3 (create-tree [1
[]
[2]])]
(is (not (valid-bst? tree-1)))
(is (valid-bst? tree-2))
(is (valid-bst? tree-3))))

(testing "balanced > 2 nodes"
(let [tree-1 (create-tree [2 [1] [3]])
(let [tree-1 (create-tree [2
[1]
[3]])
tree-2 (create-tree [2
[1] [4
[3]]])
[1]
[4
[3]]])
tree-3 (create-tree [2
[1] [3
[4]]])]
[1]
[3
[4]]])]
(is (valid-bst? tree-1))
(is (valid-bst? tree-2))
(is (not (valid-bst? tree-3))))))
Expand All @@ -34,21 +42,29 @@
(is (alt-valid-bst? tree))))

(testing "two nodes"
(let [tree-1 (create-tree [1 [2]])
tree-2 (create-tree [1 [0]])
tree-3 (create-tree [1 [] [2]])]
(let [tree-1 (create-tree [1
[2]])
tree-2 (create-tree [1
[0]])
tree-3 (create-tree [1
[]
[2]])]
(is (not (alt-valid-bst? tree-1)))
(is (alt-valid-bst? tree-2))
(is (alt-valid-bst? tree-3))))

(testing "balanced > 2 nodes"
(let [tree-1 (create-tree [2 [1] [3]])
(let [tree-1 (create-tree [2
[1]
[3]])
tree-2 (create-tree [2
[1] [4
[3]]])
[1]
[4
[3]]])
tree-3 (create-tree [2
[1] [3
[4]]])]
[1]
[3
[4]]])]
(is (alt-valid-bst? tree-1))
(is (alt-valid-bst? tree-2))
(is (not (alt-valid-bst? tree-3))))))
Expand Down
54 changes: 54 additions & 0 deletions Clojure/test/chapter_4/chapter_4_q6_test.clj
@@ -0,0 +1,54 @@
(ns chapter-4.chapter-4-q6-test
(:require [clojure.test :refer :all]
[data-structures.tree :refer :all]
[chapter-4.chapter-4-q6 :refer :all]
[clojure.zip :as zip]))

(deftest sucessor-test
(let [tree (create-tree-zipper [4
[3
[2]]
[6
[5]
[8]]])
left-child (zip-left-child tree)
right-child (zip-right-child tree)
right-left-child (-> right-child zip/down)
lowest (-> left-child zip/down)
highest (-> right-child zip/down zip/right)]
(is (= 5 (-> tree successor :data)))
(is (= 4 (-> left-child successor :data)))
(is (= 8 (-> right-child successor :data)))
(is (= 6 (-> right-left-child successor :data)))
(is (= 3 (-> lowest successor :data)))
(is (nil? (-> highest successor :data))))

(let [largest-right-subtree-node (create-tree-zipper [6
[3
[2] [4
[]
[5]]]
[]])
lowest-left (-> largest-right-subtree-node
zip-left-child
zip-right-child
zip-left-child)]
(is (= 6 (-> lowest-left successor :data))))

(let [largest-right-subtree-node-2 (create-tree-zipper [10
[2
[0] [4
[3]
[5
[6]
[8]]]]
[12]])
lowest-left (-> largest-right-subtree-node-2
zip-left-child
zip-right-child
zip-right-child
zip-right-child)]
(is (= 10 (-> lowest-left successor :data))))
)

(run-tests)

0 comments on commit 82ba031

Please sign in to comment.