Initial upload

This commit is contained in:
2022-08-24 14:28:45 +02:00
parent c67653ddee
commit 57bc7b0289
370 changed files with 18479 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
{
"blurb": "Refactor a tree building algorithm.",
"authors": [
"pminten"
],
"contributors": [
"alebaffa",
"bitfield",
"Daveed9",
"devillexio",
"dvrkps",
"ekingery",
"ferhatelmas",
"hilary",
"jeffguorg",
"kytrinyx",
"leenipper",
"object88",
"petertseng",
"robphoenix",
"sebito91",
"soniakeys",
"tbrisker",
"tleen"
],
"files": {
"solution": [
"tree_building.go"
],
"test": [
"tree_building_test.go"
],
"example": [
".meta/example.go"
]
}
}

View File

@@ -0,0 +1 @@
{"track":"go","exercise":"tree-building","id":"41954e1ca66440f899c639278975f0d2","url":"https://exercism.org/tracks/go/exercises/tree-building","handle":"halfdan","is_requester":true,"auto_approve":false}

40
go/tree-building/HELP.md Normal file
View File

@@ -0,0 +1,40 @@
# Help
## 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` and `--benchmem`
flags:
go test -v --bench . --benchmem
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.
## Submitting your solution
You can submit your solution using the `exercism submit tree_building.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

View File

@@ -0,0 +1,56 @@
# Tree Building
Welcome to Tree Building on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
## Instructions
Some web-forums have a tree layout, so posts are presented as a tree. However
the posts are typically stored in a database as an unsorted set of records. Thus
when presenting the posts to the user the tree structure has to be
reconstructed.
Your job will be to implement the tree building logic for these records. The
records only contain an ID number and a parent ID number. The ID number is
always between 0 (inclusive) and the length of the record list (exclusive). All
records have a parent ID lower than their own ID, except for the root record,
which has a parent ID that's equal to its own ID.
An example tree:
```text
root (ID: 0, parent ID: 0)
|-- child1 (ID: 1, parent ID: 0)
| |-- grandchild1 (ID: 2, parent ID: 1)
| +-- grandchild2 (ID: 4, parent ID: 1)
+-- child2 (ID: 3, parent ID: 0)
| +-- grandchild3 (ID: 6, parent ID: 3)
+-- child3 (ID: 5, parent ID: 0)
```
## Source
### Created by
- @pminten
### Contributed to by
- @alebaffa
- @bitfield
- @Daveed9
- @devillexio
- @dvrkps
- @ekingery
- @ferhatelmas
- @hilary
- @jeffguorg
- @kytrinyx
- @leenipper
- @object88
- @petertseng
- @robphoenix
- @sebito91
- @soniakeys
- @tbrisker
- @tleen

3
go/tree-building/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module tree
go 1.13

View File

@@ -0,0 +1,12 @@
package tree
// Define the Record type
struct Node {
}
// Define the Node type
func Build(records []Record) (*Node, error) {
panic("Please implement the Build function")
}

View File

@@ -0,0 +1,351 @@
package tree
import (
"fmt"
"math/rand"
"reflect"
"testing"
)
// Define a function Build(records []Record) (*Node, error)
// where Record is a struct containing int fields ID and Parent
// and Node is a struct containing int field ID and []*Node field Children.
var successTestCases = []struct {
name string
input []Record
expected *Node
}{
{
name: "empty input",
input: []Record{},
expected: nil,
},
{
name: "one node",
input: []Record{
{ID: 0},
},
expected: &Node{
ID: 0,
},
},
{
name: "three nodes in order",
input: []Record{
{ID: 0},
{ID: 1, Parent: 0},
{ID: 2, Parent: 0},
},
expected: &Node{
ID: 0,
Children: []*Node{
{ID: 1},
{ID: 2},
},
},
},
{
name: "three nodes in reverse order",
input: []Record{
{ID: 2, Parent: 0},
{ID: 1, Parent: 0},
{ID: 0},
},
expected: &Node{
ID: 0,
Children: []*Node{
{ID: 1},
{ID: 2},
},
},
},
{
name: "three levels of nesting",
input: []Record{
{ID: 2, Parent: 1},
{ID: 1, Parent: 0},
{ID: 3, Parent: 2},
{ID: 0},
},
expected: &Node{
ID: 0,
Children: []*Node{
{
ID: 1,
Children: []*Node{
{
ID: 2,
Children: []*Node{
{ID: 3},
},
},
},
},
},
},
},
{
name: "more than two children",
input: []Record{
{ID: 3, Parent: 0},
{ID: 2, Parent: 0},
{ID: 1, Parent: 0},
{ID: 0},
},
expected: &Node{
ID: 0,
Children: []*Node{
{ID: 1},
{ID: 2},
{ID: 3},
},
},
},
{
name: "binary tree",
input: []Record{
{ID: 5, Parent: 1},
{ID: 3, Parent: 2},
{ID: 2, Parent: 0},
{ID: 4, Parent: 1},
{ID: 1, Parent: 0},
{ID: 0},
{ID: 6, Parent: 2},
},
expected: &Node{
ID: 0,
Children: []*Node{
{
ID: 1,
Children: []*Node{
{ID: 4},
{ID: 5},
},
},
{
ID: 2,
Children: []*Node{
{ID: 3},
{ID: 6},
},
},
},
},
},
{
name: "unbalanced tree",
input: []Record{
{ID: 5, Parent: 2},
{ID: 3, Parent: 2},
{ID: 2, Parent: 0},
{ID: 4, Parent: 1},
{ID: 1, Parent: 0},
{ID: 0},
{ID: 6, Parent: 2},
},
expected: &Node{
ID: 0,
Children: []*Node{
{
ID: 1,
Children: []*Node{
{ID: 4},
},
},
{
ID: 2,
Children: []*Node{
{ID: 3},
{ID: 5},
{ID: 6},
},
},
},
},
},
}
var failureTestCases = []struct {
name string
input []Record
}{
{
name: "root node has parent",
input: []Record{
{ID: 0, Parent: 1},
{ID: 1, Parent: 0},
},
},
{
name: "no root node",
input: []Record{
{ID: 1, Parent: 0},
},
},
{
name: "duplicate node",
input: []Record{
{ID: 0, Parent: 0},
{ID: 1, Parent: 0},
{ID: 1, Parent: 0},
},
},
{
name: "duplicate root",
input: []Record{
{ID: 0, Parent: 0},
{ID: 0, Parent: 0},
},
},
{
name: "non-continuous",
input: []Record{
{ID: 2, Parent: 0},
{ID: 4, Parent: 2},
{ID: 1, Parent: 0},
{ID: 0},
},
},
{
name: "cycle directly",
input: []Record{
{ID: 5, Parent: 2},
{ID: 3, Parent: 2},
{ID: 2, Parent: 2},
{ID: 4, Parent: 1},
{ID: 1, Parent: 0},
{ID: 0},
{ID: 6, Parent: 3},
},
},
{
name: "cycle indirectly",
input: []Record{
{ID: 5, Parent: 2},
{ID: 3, Parent: 2},
{ID: 2, Parent: 6},
{ID: 4, Parent: 1},
{ID: 1, Parent: 0},
{ID: 0},
{ID: 6, Parent: 3},
},
},
{
name: "higher id parent of lower id",
input: []Record{
{ID: 0},
{ID: 2, Parent: 0},
{ID: 1, Parent: 2},
},
},
}
func (n Node) String() string {
return fmt.Sprintf("%d:%s", n.ID, n.Children)
}
func TestMakeTreeSuccess(t *testing.T) {
for _, tt := range successTestCases {
t.Run(tt.name, func(t *testing.T) {
actual, err := Build(tt.input)
if err != nil {
var _ error = err
t.Fatalf("Build for test case %q returned error %q. Error not expected.",
tt.name, err)
}
if !reflect.DeepEqual(actual, tt.expected) {
t.Fatalf("Build for test case %q returned %s but was expected to return %s.",
tt.name, actual, tt.expected)
}
})
}
}
func TestMakeTreeFailure(t *testing.T) {
for _, tt := range failureTestCases {
t.Run(tt.name, func(t *testing.T) {
actual, err := Build(tt.input)
if err == nil {
t.Fatalf("Build for test case %q returned %s but was expected to fail.",
tt.name, actual)
}
})
}
}
func shuffleRecords(records []Record) []Record {
gen := rand.New(rand.NewSource(42))
newRecords := make([]Record, len(records))
for i, idx := range gen.Perm(len(records)) {
newRecords[i] = records[idx]
}
return newRecords
}
// Binary tree
func makeTwoTreeRecords() []Record {
records := make([]Record, 1<<16)
for i := range records {
if i == 0 {
records[i] = Record{ID: 0}
} else {
records[i] = Record{ID: i, Parent: i >> 1}
}
}
return shuffleRecords(records)
}
var twoTreeRecords = makeTwoTreeRecords()
func BenchmarkTwoTree(b *testing.B) {
if testing.Short() {
b.Skip("skipping benchmark in short mode.")
}
for i := 0; i < b.N; i++ {
Build(twoTreeRecords)
}
}
// Each node but the root node and leaf nodes has ten children.
func makeTenTreeRecords() []Record {
records := make([]Record, 10000)
for i := range records {
if i == 0 {
records[i] = Record{ID: 0}
} else {
records[i] = Record{ID: i, Parent: i / 10}
}
}
return shuffleRecords(records)
}
var tenTreeRecords = makeTenTreeRecords()
func BenchmarkTenTree(b *testing.B) {
if testing.Short() {
b.Skip("skipping benchmark in short mode.")
}
for i := 0; i < b.N; i++ {
Build(tenTreeRecords)
}
}
func makeShallowRecords() []Record {
records := make([]Record, 10000)
for i := range records {
records[i] = Record{ID: i, Parent: 0}
}
return shuffleRecords(records)
}
var shallowRecords = makeShallowRecords()
func BenchmarkShallowTree(b *testing.B) {
if testing.Short() {
b.Skip("skipping benchmark in short mode.")
}
for i := 0; i < b.N; i++ {
Build(shallowRecords)
}
}