exercism/go/pov/pov.go

135 lines
2.5 KiB
Go
Raw Normal View History

2017-08-15 14:55:28 +00:00
package pov
const testVersion = 2
type Graph struct {
leaves []Node
}
func New() *Graph {
2017-08-17 18:12:16 +00:00
return new(Graph)
2017-08-15 14:55:28 +00:00
}
2017-08-17 18:12:16 +00:00
func (g *Graph) AddNode(lbl string) {
// Make sure that g doesn't already have node lbl
if g.getNode(lbl) != nil {
return
2017-08-15 14:55:28 +00:00
}
2017-08-17 18:12:16 +00:00
g.leaves = append(g.leaves, Node{label: lbl})
2017-08-15 14:55:28 +00:00
}
2017-08-17 18:12:16 +00:00
func (g *Graph) AddArc(fr, to string) {
if frN := g.getNode(fr); frN != nil {
frN.AddNode(to)
}
2017-08-15 14:55:28 +00:00
}
2017-08-17 18:12:16 +00:00
func (g *Graph) ArcList() []string {
var arcList []string
for i := range g.leaves {
arcList = append(arcList, g.leaves[i].ArcList()...)
}
return arcList
2017-08-15 14:55:28 +00:00
}
2017-08-17 18:12:16 +00:00
func (g *Graph) GetPath(fr, to string) []string {
if frN := g.getNode(fr); frN != nil {
return frN.GetPath(to)
2017-08-15 14:55:28 +00:00
}
2017-08-17 18:12:16 +00:00
return []string{}
2017-08-15 14:55:28 +00:00
}
2017-08-17 18:12:16 +00:00
func (g *Graph) getNode(lbl string) *Node {
2017-08-15 14:55:28 +00:00
for i := range g.leaves {
2017-08-17 18:12:16 +00:00
if r := g.leaves[i].getNode(lbl); r != nil {
return r
}
2017-08-15 14:55:28 +00:00
}
2017-08-17 18:12:16 +00:00
return nil
2017-08-15 14:55:28 +00:00
}
2017-08-17 18:12:16 +00:00
// Return a graph from 'newRoot's POV
2017-08-15 14:55:28 +00:00
func (g *Graph) ChangeRoot(oldRoot, newRoot string) *Graph {
2017-08-17 18:12:16 +00:00
root := g.getNode(newRoot)
if root == nil {
return nil
}
2017-08-15 14:55:28 +00:00
ret := New()
2017-08-17 18:12:16 +00:00
//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
2017-08-15 14:55:28 +00:00
}
2017-08-17 18:12:16 +00:00
ret.addWholeNode(root)
2017-08-15 22:06:46 +00:00
return ret
2017-08-15 14:55:28 +00:00
}
2017-08-17 18:12:16 +00:00
func (g *Graph) addWholeNode(n *Node) {
g.leaves = append(g.leaves, *n)
2017-08-15 14:55:28 +00:00
}
type Node struct {
label string
leaves []Node
2017-08-17 18:12:16 +00:00
parent *Node
2017-08-15 14:55:28 +00:00
}
func (n *Node) AddNode(lbl string) {
2017-08-17 18:12:16 +00:00
nn := Node{label: lbl, parent: n}
n.leaves = append(n.leaves, nn)
2017-08-15 14:55:28 +00:00
}
2017-08-17 18:12:16 +00:00
func (n *Node) addWholeNode(nd *Node) {
2017-08-15 22:06:46 +00:00
n.leaves = append(n.leaves, *nd)
}
2017-08-17 18:12:16 +00:00
func (n *Node) removeLeaf(lbl string) {
2017-08-15 14:55:28 +00:00
for i := range n.leaves {
2017-08-17 18:12:16 +00:00
if n.leaves[i].label == lbl {
n.leaves = append(n.leaves[:i], n.leaves[i+1:]...)
2017-08-15 14:55:28 +00:00
}
}
}
func (n *Node) ArcList() []string {
var ret []string
for i := range n.leaves {
2017-08-17 18:12:16 +00:00
// Append this arc
ret = append(ret, n.label+" -> "+n.leaves[i].label)
// Append all sub-arcs
2017-08-15 14:55:28 +00:00
ret = append(ret, n.leaves[i].ArcList()...)
}
return ret
}
2017-08-17 18:12:16 +00:00
// GetPath returns a string slice of all leaves leading to 'to'
func (n *Node) GetPath(to string) []string {
2017-08-15 14:55:28 +00:00
ret := []string{n.label}
if n.label == to {
return ret
}
2017-08-17 18:12:16 +00:00
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)...)
2017-08-15 14:55:28 +00:00
}
}
2017-08-17 18:12:16 +00:00
// 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
2017-08-15 14:55:28 +00:00
}
2017-08-17 18:12:16 +00:00
for i := range n.leaves {
if r := n.leaves[i].getNode(lbl); r != nil {
return r
}
}
return nil
2017-08-15 14:55:28 +00:00
}