Given the following...
(def inTree
\'((1 2)
(1 2 3)
(1 2 4 5 9)
(1 2 4 10 15)
(1 2 4 20 25)))
How would you transform it to this t
I'm sure there is a prettier way (there was! see Brian's answer it is better):
(defn find-in-trie
"Finds a sub trie that matches an item, eg:
user=> (find-in-trie '(1 (2) (3 (2))) 3)
(3 (2))"
[tr item]
(first (for [ll (rest tr) :when (= (first ll) item)] ll)))
(defn add-to-trie
"Returns a new trie, the result of adding se to tr, eg:
user=> (add-to-trie nil '(1 2))
(1 (2))"
[tr se]
(cond
(empty? se) tr
(empty? tr) (add-to-trie (list (first se)) (rest se))
:else (if-let [st (find-in-trie tr (first se))]
(cons (first tr)
(cons (add-to-trie st (rest se))
(filter (partial not= st) (rest tr))))
(cons (first tr)
(cons (add-to-trie (list (first se)) (rest se))
(rest tr))))))
(def in '((1 2)
(1 2 3)
(1 2 4 5 9)
(1 2 4 10 15)
(1 2 4 20 25)))
(reduce add-to-trie '(nil) in)
-> (nil (1 (2 (4 (20 (25)) (10 (15)) (5 (9))) (3))))
Note that I've chosen to use nil as the root node and have not bothered keeping empty lists to signify no children. Actually doing it this way is not correct as it does not preserve substring identity.