New Fetch

This commit is contained in:
2017-08-12 09:01:07 -05:00
parent ba838ca4fb
commit a9630f6ee8
58 changed files with 2530 additions and 0 deletions

64
go/pov/README.md Normal file
View File

@@ -0,0 +1,64 @@
# Pov
Reparent a graph on a selected node.
# Tree Reparenting
This exercise is all about re-orientating a graph to see things from a different
point of view. For example family trees are usually presented from the
ancestor's perspective:
```
+------0------+
| | |
+-1-+ +-2-+ +-3-+
| | | | | |
4 5 6 7 8 9
```
But the same information can be presented from the perspective of any other node
in the graph, by pulling it up to the root and dragging its relationships along
with it. So the same graph from 6's perspective would look like:
```
6
|
+-----2-----+
| |
7 +-----0-----+
| |
+-1-+ +-3-+
| | | |
4 5 8 9
```
This lets us more simply describe the paths between two nodes. So for example
the path from 6-9 (which in the first graph goes up to the root and then down to
a different leaf node) can be seen to follow the path 6-2-0-3-9
This exercise involves taking an input graph and re-orientating it from the point
of view of one of the nodes.
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `-bench`
flag:
go test -bench .
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Further information
For more detailed information about the Go track, including how to get help if
you're having trouble, please visit the exercism.io [Go language page](http://exercism.io/languages/go/about).
## Source
Adaptation of exercise from 4clojure [https://www.4clojure.com/](https://www.4clojure.com/)
## Submitting Incomplete Solutions
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

298
go/pov/pov_test.go Normal file
View File

@@ -0,0 +1,298 @@
package pov
import (
"reflect"
"sort"
"testing"
)
const targetTestVersion = 2
// POV / reparent / change root of a tree
//
// API:
// type Graph
// func New() *Graph
// func (*Graph) AddNode(nodeLabel string)
// func (*Graph) AddArc(from, to string)
// func (*Graph) ArcList() []string
// func (*Graph) ChangeRoot(oldRoot, newRoot string) *Graph
//
// The type name is Graph because you'll probably be implementing a general
// directed graph representation, although the test program will only use
// it to create a tree. The term "arc" is used here to mean a directed edge.
//
// The test program will create a graph with New, then use AddNode to add
// leaf nodes. After that it will use AddArc to construct the rest of the tree
// from the bottom up. That is, the `to` argument will aways specify a node
// that has already been added.
//
// ArcList is a dump method to let the test program see your graph. It must
// return a list of all arcs in the graph. Format each arc as a single string
// like "from -> to". The test program can then easily sort the list and
// compare it to an expected result. You do not need to bother with sorting
// the list yourself.
//
// All this graph construction and dumping must be working before you start
// on the interesting part of the exercise, so it is tested separately as
// a first test.
//
// API function ChangeRoot does the interesting part of the exercise.
// OldRoot is passed (as a convenience) and you must return a graph with
// newRoot as the root. You can modify the original graph in place and
// return it or create a new graph and return that. If you return a new
// graph you are free to consume or destroy the original graph. Of course
// it's nice to leave it unmodified.
type arc struct{ fr, to string }
type testCase struct {
description string
leaves []string
arcPairs []arc
root string
arcStrings []string
reRooted []string
}
var testCases = []testCase{
{
description: "singleton",
leaves: []string{"x"},
arcPairs: nil,
root: "x",
arcStrings: nil,
reRooted: nil,
},
{
description: "simple tree",
leaves: []string{"sibling", "x"},
arcPairs: []arc{
{"parent", "sibling"},
{"parent", "x"},
},
root: "parent",
arcStrings: []string{
"parent -> sibling",
"parent -> x",
},
reRooted: []string{
"parent -> sibling",
"x -> parent",
},
},
{
description: "large flat",
leaves: []string{"sib-a", "sib-b", "x", "sib-c", "sib-d"},
arcPairs: []arc{
{"parent", "sib-a"},
{"parent", "sib-b"},
{"parent", "x"},
{"parent", "sib-c"},
{"parent", "sib-d"},
},
root: "parent",
arcStrings: []string{
"parent -> sib-a",
"parent -> sib-b",
"parent -> sib-c",
"parent -> sib-d",
"parent -> x",
},
reRooted: []string{
"parent -> sib-a",
"parent -> sib-b",
"parent -> sib-c",
"parent -> sib-d",
"x -> parent",
},
},
{
description: "deeply nested",
leaves: []string{"x"},
arcPairs: []arc{
{"level-4", "x"},
{"level-3", "level-4"},
{"level-2", "level-3"},
{"level-1", "level-2"},
{"level-0", "level-1"},
},
root: "level-0",
arcStrings: []string{
"level-0 -> level-1",
"level-1 -> level-2",
"level-2 -> level-3",
"level-3 -> level-4",
"level-4 -> x",
},
reRooted: []string{
"level-1 -> level-0",
"level-2 -> level-1",
"level-3 -> level-2",
"level-4 -> level-3",
"x -> level-4",
},
},
{
description: "cousins",
leaves: []string{"sib-1", "x", "sib-2", "cousin-1", "cousin-2"},
arcPairs: []arc{
{"parent", "sib-1"},
{"parent", "x"},
{"parent", "sib-2"},
{"aunt", "cousin-1"},
{"aunt", "cousin-2"},
{"grand-parent", "parent"},
{"grand-parent", "aunt"},
},
root: "grand-parent",
arcStrings: []string{
"aunt -> cousin-1",
"aunt -> cousin-2",
"grand-parent -> aunt",
"grand-parent -> parent",
"parent -> sib-1",
"parent -> sib-2",
"parent -> x",
},
reRooted: []string{
"aunt -> cousin-1",
"aunt -> cousin-2",
"grand-parent -> aunt",
"parent -> grand-parent",
"parent -> sib-1",
"parent -> sib-2",
"x -> parent",
},
},
{
description: "target with children",
leaves: []string{"child-1", "child-2", "nephew", "niece",
"2nd-cousin-1", "2nd-cousin-2", "2nd-cousin-3", "2nd-cousin-4"},
arcPairs: []arc{
{"x", "child-1"},
{"x", "child-2"},
{"sibling", "nephew"},
{"sibling", "niece"},
{"cousin-1", "2nd-cousin-1"},
{"cousin-1", "2nd-cousin-2"},
{"cousin-2", "2nd-cousin-3"},
{"cousin-2", "2nd-cousin-4"},
{"parent", "x"},
{"parent", "sibling"},
{"aunt", "cousin-1"},
{"aunt", "cousin-2"},
{"grand-parent", "parent"},
{"grand-parent", "aunt"},
},
root: "grand-parent",
arcStrings: []string{
"aunt -> cousin-1",
"aunt -> cousin-2",
"cousin-1 -> 2nd-cousin-1",
"cousin-1 -> 2nd-cousin-2",
"cousin-2 -> 2nd-cousin-3",
"cousin-2 -> 2nd-cousin-4",
"grand-parent -> aunt",
"grand-parent -> parent",
"parent -> sibling",
"parent -> x",
"sibling -> nephew",
"sibling -> niece",
"x -> child-1",
"x -> child-2",
},
reRooted: []string{
"aunt -> cousin-1",
"aunt -> cousin-2",
"cousin-1 -> 2nd-cousin-1",
"cousin-1 -> 2nd-cousin-2",
"cousin-2 -> 2nd-cousin-3",
"cousin-2 -> 2nd-cousin-4",
"grand-parent -> aunt",
"parent -> grand-parent",
"parent -> sibling",
"sibling -> nephew",
"sibling -> niece",
"x -> child-1",
"x -> child-2",
"x -> parent",
},
},
}
func (tc testCase) graph() *Graph {
g := New()
for _, l := range tc.leaves {
g.AddNode(l)
}
for _, a := range tc.arcPairs {
g.AddArc(a.fr, a.to)
}
return g
}
func (tc testCase) testResult(got, want []string, msg string, t *testing.T) {
if len(got)+len(want) == 0 {
return
}
gs := append([]string{}, got...)
sort.Strings(gs)
if reflect.DeepEqual(gs, want) {
return
}
// test has failed
t.Log(tc.description, "test case")
t.Log(msg)
t.Logf("got %d arcs:", len(got))
for _, s := range got {
t.Log(" ", s)
}
t.Logf("that result sorted:")
for _, s := range gs {
t.Log(" ", s)
}
t.Logf("want %d arcs:", len(want))
for _, s := range want {
t.Log(" ", s)
}
t.FailNow()
}
func TestTestVersion(t *testing.T) {
if testVersion != targetTestVersion {
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
}
}
func TestConstruction(t *testing.T) {
for _, tc := range testCases {
got := tc.graph().ArcList()
want := tc.arcStrings
tc.testResult(got, want, "incorrect graph construction", t)
}
}
func TestChangeRoot(t *testing.T) {
for _, tc := range testCases {
got := tc.graph().ChangeRoot(tc.root, "x").ArcList()
want := tc.reRooted
tc.testResult(got, want, "incorrect root change", t)
}
}
func BenchmarkConstructOnlyNoChange(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tc := range testCases {
tc.graph()
}
}
}
func BenchmarkConstructAndChangeRoot(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tc := range testCases {
tc.graph().ChangeRoot(tc.root, "x")
}
}
}