package main import ( "fmt" "strings" ) const ( treeIndentStep = 2 treeStemWidth = treeIndentStep - 1 treeVertical = '\u2502' treeThisAndMore = "\u251c" treeJustThis = "\u2514" treeStem = "\u2500" ) type treeNode struct { left, right string notes []string } func selectRoot(nodes []treeNode) string { children := make(map[string][]string) areChildren := make(map[string]bool) for _, node := range nodes { areChildren[node.right] = true if childlist, ok := children[node.left]; ok { children[node.left] = append(childlist, node.right) } else { children[node.left] = []string{node.right} } } favorite := "" for left, right := range children { if areChildren[left] { continue } if favorite == "" { favorite = left } else if len(right) < len(children[favorite]) { favorite = left } } return favorite } func printSubTree(root string, nodes []treeNode, indent int, continued []int) []treeNode { leftovers := []treeNode{} children := []treeNode{} for _, node := range nodes { if node.left != root { leftovers = append(leftovers, node) continue } children = append(children, node) } for n, child := range children { istring := []rune(strings.Repeat(" ", indent)) for _, column := range continued { istring[column] = treeVertical } subc := continued[:] header := treeJustThis noteHeader := " " if n < len(children)-1 { subc = append(subc, indent) header = treeThisAndMore noteHeader = string(treeVertical) } fmt.Printf("%s%s%s%s\n", string(istring), header, strings.Repeat(treeStem, treeStemWidth), child.right) for _, note := range child.notes { fmt.Printf("%s%s%s%s\n", string(istring), noteHeader, strings.Repeat(" ", treeStemWidth), note) } leftovers = printSubTree(child.right, leftovers, indent+treeIndentStep, subc) } return leftovers } func printTree(nodes []treeNode) { for len(nodes) > 0 { root := selectRoot(nodes) fmt.Printf("%s\n", root) oldLength := len(nodes) nodes = printSubTree(root, nodes, 0, []int{}) newLength := len(nodes) if oldLength == newLength { break } } }