2

I have the following vector, [-1 1 2 -1 3 0 -1 2 -1 4 0 3 0 0]

which represents the tree [[1 2 [3] [2 [4] 3]]]

where -1 begins a new branch and 0 ends it. How can I convert the original vector into a usable tree-like clojure structure (nested vector, nested map)? I think clojure.zip/zipper might do it but I'm not sure how to build those function args.

calopter
  • 67
  • 2

3 Answers3

7

Zippers are a good tool for this: 

(require '[clojure.zip :as zip])

(def in [-1 1 2 -1 3 0 -1 2 -1 4 0 3 0 0])
(def out [[1 2 [3] [2 [4] 3]]])

(defn deepen [steps]
  (->> steps
       (reduce (fn [loc step]
                 (case step
                   -1 (-> loc
                          (zip/append-child [])
                          (zip/down)
                          (zip/rightmost))
                   0 (zip/up loc)
                   (zip/append-child loc step)))
         (zip/vector-zip []))
       (zip/root)))

(assert (= (deepen in) out))
nberger
  • 3,659
  • 17
  • 19
Francis Avila
  • 31,233
  • 6
  • 58
  • 96
4

Somehow this feels like cheating:

[(read-string
  (clojure.string/join " "
                       (replace {-1 "[" 0 "]"}
                                [-1 1 2 -1 3 0 -1 2 -1 4 0 3 0 0])))]
bsvingen
  • 2,699
  • 14
  • 18
2

This is not too hard with some recursion:

(defn numbers->tree [xs]
  (letfn [(step [xs]
            (loop [ret [], remainder xs]
              (if (empty? remainder)
                [ret remainder]
                (let [x (first remainder)]
                  (case x
                    0 [ret (next remainder)]
                    -1 (let [[ret' remainder'] (step (next remainder))]
                         (recur (conj ret ret'), remainder'))
                    (recur (conj ret x) (next remainder)))))))]
    (first (step xs))))

The idea is to have a function (step) that finds a sub-tree, and returns that tree as well as what numbers are left to be processed. It proceeds iteratively (via loop) for most inputs, and starts a recursive instance of itself when it runs into a -1. The only tricky part is making sure to use the remainder returned from these recursive invocations, rather than proceeding on with the list you were in the middle of.

amalloy
  • 89,153
  • 8
  • 140
  • 205