diff --git a/go/pov/cmd/cmd b/go/pov/cmd/cmd index 09765fd..3e1583d 100755 Binary files a/go/pov/cmd/cmd and b/go/pov/cmd/cmd differ diff --git a/go/pov/cmd/main.go b/go/pov/cmd/main.go index c525c41..1066f1f 100644 --- a/go/pov/cmd/main.go +++ b/go/pov/cmd/main.go @@ -1,13 +1,26 @@ package main -import pov ".." +import ( + "fmt" + + pov ".." +) func main() { g := pov.New() - g.AddNode("sibling") - g.AddNode("x") g.AddNode("parent") - g.AddArc("parent", "sibling") g.AddArc("parent", "x") + g.AddArc("x", "sib-2") + g.AddArc("x", "sib-3") + g.AddArc("x", "sib-4") + g.AddArc("parent", "sibling") + g.AddArc("sibling", "child-1") + g.AddArc("sibling", "child-2") + g.AddArc("sibling", "child-3") + g.AddArc("child-3", "grandchild-1") + g.AddArc("grandchild-1", "greatgrandchild-1") pov.PrintGraph(g) + fmt.Println("== Change Root to child-3 ==") + n := g.ChangeRoot("parent", "child-3") + pov.PrintGraph(n) } diff --git a/go/pov/pov.go b/go/pov/pov.go index 95c943d..c1df882 100644 --- a/go/pov/pov.go +++ b/go/pov/pov.go @@ -7,128 +7,128 @@ type Graph struct { } func New() *Graph { - g := new(Graph) - return g + return new(Graph) } -// GetNode returns the node from the graph with label lbl -func (g *Graph) GetNode(lbl string) *Node { - for i := range g.leaves { - if n := g.leaves[i].GetNode(lbl); n != nil { - return n - } - } - return nil -} - -// AddNode adds a top level leaf with label lbl func (g *Graph) AddNode(lbl string) { + // Make sure that g doesn't already have node lbl + if g.getNode(lbl) != nil { + return + } g.leaves = append(g.leaves, Node{label: lbl}) } -// addRealNode adds the node n to the top level -func (g *Graph) addRealNode(n *Node) { - g.leaves = append(g.leaves, *n) -} - -// AddArc creates a new node after to named from -func (g *Graph) AddArc(from, to string) { - if n := g.GetNode(to); n != nil { - n.AddNode(from) +func (g *Graph) AddArc(fr, to string) { + if frN := g.getNode(fr); frN != nil { + frN.AddNode(to) } } -// ArcList returns a list of all arcs func (g *Graph) ArcList() []string { - var ret []string + var arcList []string for i := range g.leaves { - ret = append(ret, g.leaves[i].ArcList()...) + arcList = append(arcList, g.leaves[i].ArcList()...) } - return ret + return arcList } -// ChangeRoot changes the graph from starting at oldRoot going to newRoot -func (g *Graph) ChangeRoot(oldRoot, newRoot string) *Graph { - // First of all, find the newRoot node - ret := New() - // The new graph will start with newRoot and have newRoot's leaves - var rt *Node - if rt = g.GetNode(newRoot); rt == nil { - return ret +func (g *Graph) GetPath(fr, to string) []string { + if frN := g.getNode(fr); frN != nil { + return frN.GetPath(to) } - // It'll have one more leaf, it's parent node - //rt.addRealNode(g.GetNode(oldRoot)) - ret.addRealNode(rt) - return ret + return []string{} } -func (g *Graph) getPath(from, to string) []string { - var ret []string - // Get the 'from' node - frNode := g.GetNode(from) - if frNode == nil { - // Couldn't find the starting node - return ret - } - // Just in case we got the same value for both - if from == to { - return []string{from} - } - // Found it - return frNode.getPath(to) -} - -type Node struct { - label string - leaves []Node -} - -func (n *Node) AddNode(lbl string) { - n.leaves = append(n.leaves, Node{label: lbl}) -} - -func (n *Node) addRealNode(nd *Node) { - n.leaves = append(n.leaves, *nd) -} - -func (n *Node) GetNode(lbl string) *Node { - if n.label == lbl { - return n - } - for i := range n.leaves { - if r := n.leaves[i].GetNode(lbl); r != nil { +func (g *Graph) getNode(lbl string) *Node { + for i := range g.leaves { + if r := g.leaves[i].getNode(lbl); r != nil { return r } } return nil } +// Return a graph from 'newRoot's POV +func (g *Graph) ChangeRoot(oldRoot, newRoot string) *Graph { + root := g.getNode(newRoot) + if root == nil { + return nil + } + ret := New() + //pth := g.GetPath(oldRoot, newRoot) + if root.parent != nil { + root.parent.removeLeaf(root.label) + root.parent.parent = root + root.addWholeNode(root.parent) + root.parent = nil + } + ret.addWholeNode(root) + return ret +} + +func (g *Graph) addWholeNode(n *Node) { + g.leaves = append(g.leaves, *n) +} + +type Node struct { + label string + leaves []Node + parent *Node +} + +func (n *Node) AddNode(lbl string) { + nn := Node{label: lbl, parent: n} + n.leaves = append(n.leaves, nn) +} + +func (n *Node) addWholeNode(nd *Node) { + n.leaves = append(n.leaves, *nd) +} + +func (n *Node) removeLeaf(lbl string) { + for i := range n.leaves { + if n.leaves[i].label == lbl { + n.leaves = append(n.leaves[:i], n.leaves[i+1:]...) + } + } +} + func (n *Node) ArcList() []string { var ret []string for i := range n.leaves { - ret = append(ret, n.leaves[i].label+" -> "+n.label) + // Append this arc + ret = append(ret, n.label+" -> "+n.leaves[i].label) + // Append all sub-arcs ret = append(ret, n.leaves[i].ArcList()...) } return ret } -func (n *Node) getPath(to string) []string { +// GetPath returns a string slice of all leaves leading to 'to' +func (n *Node) GetPath(to string) []string { ret := []string{n.label} if n.label == to { return ret } - var i int - var found bool - for i = range n.leaves { - if n.leaves[i].GetNode(to) != nil { - found = true - break + for i := range n.leaves { + if toN := n.leaves[i].getNode(to); toN != nil { + // This is the leaf to follow + return append(ret, n.leaves[i].GetPath(to)...) } } - if !found { - // We didn't find a path... :( - return ret - } - // n.leaves[i] should be the right leaf now - return append(ret, n.leaves[i].getPath(to)...) + // Couldn't get there + return []string{} +} + +// Returns the node with label lbl or nil +func (n *Node) getNode(lbl string) *Node { + if n.label == lbl { + return n + } + for i := range n.leaves { + if r := n.leaves[i].getNode(lbl); r != nil { + return r + } + } + return nil } diff --git a/go/pov/pov_helper.go b/go/pov/pov_helper.go index fb3d565..f01b6c9 100644 --- a/go/pov/pov_helper.go +++ b/go/pov/pov_helper.go @@ -12,8 +12,12 @@ func PrintGraph(g *Graph) { } func PrintNode(n *Node, lvl int) { - strings.Repeat(" ", lvl) - fmt.Println(n.label) + fmt.Print(strings.Repeat(" ", lvl)) + if n.parent == nil { + fmt.Println("{label:", n.label, "}") + } else { + fmt.Println("{label:", n.label, ", parent:", n.parent.label, "}") + } for i := range n.leaves { PrintNode(&n.leaves[i], lvl+1) }