Fauler Druck eines Baumes im Newick-Format
Ich möchte einen binären Baum in druckenNewick-FormatZeigt die Entfernung jedes Knotens zu seinem Elternknoten an. Im Moment habe ich kein Problem mit dem folgenden Code gehabt, der eine regelmäßige Rekursion verwendet, aber ein zu tiefer Baum kann einen Stapelüberlauf erzeugen.
(defn tree->newick
[tree]
(let [{:keys [id children to-parent]} tree
dist (double to-parent)] ; to-parent may be a rational
(if children
(str "(" (tree->newick (first children))
"," (tree->newick (second children))
"):" dist)
(str (name id) ":" dist))))
(def example {:id nil :to-parent 0.0
:children [{:id nil :to-parent 0.5
:children [{:id "A" :to-parent 0.3 :children nil}
{:id "B" :to-parent 0.2 :children nil}]}
{:id "C" :to-parent 0.8 :children nil}]})
(tree->newick example)
;=> "((A:0.3,B:0.2):0.5,C:0.8):0.0"
(def linear-tree (->> {:id "bottom" :to-parent 0.1 :children nil}
(iterate #(hash-map :id nil :to-parent 0.1
:children [% {:id "side" :to-parent 0.1 :children nil}]))
(take 10000)
last))
(tree->newick linear-tree)
;=> StackOverflowError
Das Problem habe ich mit aktuellen Dienstprogrammen gefunden, wie ztree-seq
undclojure.walk
, ist, dass ich mehr als einmal einen inneren Knoten aufsuchen muss, um das Komma einzufügen und die Klammer zu schließen. Ich habe benutztclojure.zip
, aber es ist mir nicht gelungen, eine Lazy / Tail-rekursive Implementierung zu schreiben, da ich für jeden inneren Knoten speichern müsste, wie oft sie bereits besucht wurden.