135 lines
2.5 KiB
Go
135 lines
2.5 KiB
Go
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
|
|
}
|