package pov const testVersion = 2 type Graph struct { leaves []Node } func New() *Graph { return new(Graph) } 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}) } func (g *Graph) AddArc(fr, to string) { if frN := g.getNode(fr); frN != nil { frN.AddNode(to) } } func (g *Graph) ArcList() []string { var arcList []string for i := range g.leaves { arcList = append(arcList, g.leaves[i].ArcList()...) } return arcList } func (g *Graph) GetPath(fr, to string) []string { if frN := g.getNode(fr); frN != nil { return frN.GetPath(to) } return []string{} } 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 { // 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 } // 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 } 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)...) } } // 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 }