Merge Go Work

This commit is contained in:
2016-08-23 15:47:19 -05:00
parent b8814259b5
commit 9e58d17c5c
25 changed files with 941 additions and 50 deletions

53
go/strain/README.md Normal file
View File

@@ -0,0 +1,53 @@
# Strain
Implement the `keep` and `discard` operation on collections. Given a collection and a predicate on the collection's elements, `keep` returns a new collection containing those elements where the predicate is true, while `discard` returns a new collection containing those elements where the predicate is false.
Write two functions that each take a function and a list. One of them will
return the list of items for which the passed in function is true, and the
other will return the items for which it is false.
For example, given the collection of numbers:
- 1, 2, 3, 4, 5
And the predicate:
- is the number even?
Then your keep operation should produce:
- 2, 4
While your discard operation should produce:
- 1, 3, 5
Note that the union of keep and discard is all the elements.
The functions may be called `keep` and `discard`, or they may need different
names in order to not clash with existing functions or concepts in your
language.
## Restrictions
Keep your hands off that filter/reject/whatchamacallit functionality
provided by your standard library! Solve this one yourself using other
basic tools instead.
To run the tests simply run the command `go test` in the exercise directory.
If the test suite contains benchmarks, you can run these with the `-bench`
flag:
go test -bench .
For more detailed info about the Go track see the [help
page](http://exercism.io/languages/go).
## Source
Conversation with James Edward Gray II [https://twitter.com/jeg2](https://twitter.com/jeg2)
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

54
go/strain/strain.go Normal file
View File

@@ -0,0 +1,54 @@
package strain
// Ints is a slice of int
type Ints []int
// Lists is a slice of int slices
type Lists [][]int
// Strings is a slice of strings
type Strings []string
// Keep runs the Ints through a function and returns the ones that succeed
func (i Ints) Keep(kf func(int) bool) Ints {
var ret Ints
for idx := range i {
if kf(i[idx]) {
ret = append(ret, i[idx])
}
}
return ret
}
// Discard runs the Ints through a function and returns the ones that fail
func (i Ints) Discard(df func(int) bool) Ints {
var ret Ints
for idx := range i {
if !df(i[idx]) {
ret = append(ret, i[idx])
}
}
return ret
}
// Keep runs the Lists through a function and returns the ones that succeed
func (l Lists) Keep(kf func([]int) bool) Lists {
var ret Lists
for idx := range l {
if kf(l[idx]) {
ret = append(ret, l[idx])
}
}
return ret
}
// Keep runs the Strings through a function and returns the ones that succeed
func (s Strings) Keep(kf func(string) bool) Strings {
var ret Strings
for idx := range s {
if kf(s[idx]) {
ret = append(ret, s[idx])
}
}
return ret
}

170
go/strain/strain_test.go Normal file
View File

@@ -0,0 +1,170 @@
// Collections, hm? For this exercise in Go you'll work with slices as
// collections. Define the following in your solution:
//
// type Ints []int
// type Lists [][]int
// type Strings []string
//
// Then complete the exercise by implementing these methods:
//
// (Ints) Keep(func(int) bool) Ints
// (Ints) Discard(func(int) bool) Ints
// (Lists) Keep(func([]int) bool) Lists
// (Strings) Keep(func(string) bool) Strings
package strain
import (
"reflect"
"testing"
)
func lt10(x int) bool { return x < 10 }
func gt10(x int) bool { return x > 10 }
func odd(x int) bool { return x&1 == 1 }
func even(x int) bool { return x&1 == 0 }
var keepTests = []struct {
pred func(int) bool
list Ints
want Ints
}{
{lt10,
nil,
nil},
{lt10,
Ints{1, 2, 3},
Ints{1, 2, 3}},
{odd,
Ints{1, 2, 3},
Ints{1, 3}},
{even,
Ints{1, 2, 3, 4, 5},
Ints{2, 4}},
}
func TestKeepInts(t *testing.T) {
for _, test := range keepTests {
// setup here copies test.list, preserving the nil value if it is nil
// and making a fresh copy of the underlying array otherwise.
cp := test.list
if cp != nil {
cp = append(Ints{}, cp...)
}
switch res := cp.Keep(test.pred); {
case !reflect.DeepEqual(cp, test.list):
t.Fatalf("Ints%v.Keep() should not modify its reciever. "+
"Found %v, reciever should stay %v",
test.list, cp, test.list)
case !reflect.DeepEqual(res, test.want):
t.Fatalf("Ints%v.Keep() = %v, want %v",
test.list, res, test.want)
}
}
}
var discardTests = []struct {
pred func(int) bool
list Ints
want Ints
}{
{lt10,
nil,
nil},
{gt10,
Ints{1, 2, 3},
Ints{1, 2, 3}},
{odd,
Ints{1, 2, 3},
Ints{2}},
{even,
Ints{1, 2, 3, 4, 5},
Ints{1, 3, 5}},
}
func TestDiscardInts(t *testing.T) {
for _, test := range discardTests {
cp := test.list
if cp != nil {
cp = append(Ints{}, cp...) // dup underlying array
}
switch res := cp.Discard(test.pred); {
case !reflect.DeepEqual(cp, test.list):
t.Fatalf("Ints%v.Discard() should not modify its reciever. "+
"Found %v, reciever should stay %v",
test.list, cp, test.list)
case !reflect.DeepEqual(res, test.want):
t.Fatalf("Ints%v.Discard() = %v, want %v",
test.list, res, test.want)
}
}
}
func TestKeepStrings(t *testing.T) {
zword := func(s string) bool { return len(s) > 0 && s[0] == 'z' }
list := Strings{"apple", "zebra", "banana", "zombies", "cherimoya", "zelot"}
want := Strings{"zebra", "zombies", "zelot"}
cp := append(Strings{}, list...) // make copy, as with TestInts
switch res := cp.Keep(zword); {
case !reflect.DeepEqual(cp, list):
t.Fatalf("Strings%v.Keep() should not modify its reciever. "+
"Found %v, reciever should stay %v",
list, cp, list)
case !reflect.DeepEqual(res, want):
t.Fatalf("Strings%v.Keep() = %v, want %v",
list, res, want)
}
}
func TestKeepLists(t *testing.T) {
has5 := func(l []int) bool {
for _, e := range l {
if e == 5 {
return true
}
}
return false
}
list := Lists{
{1, 2, 3},
{5, 5, 5},
{5, 1, 2},
{2, 1, 2},
{1, 5, 2},
{2, 2, 1},
{1, 2, 5},
}
want := Lists{
{5, 5, 5},
{5, 1, 2},
{1, 5, 2},
{1, 2, 5},
}
cp := append(Lists{}, list...)
switch res := cp.Keep(has5); {
case !reflect.DeepEqual(cp, list):
t.Fatalf("Lists%v.Keep() should not modify its reciever. "+
"Found %v, reciever should stay %v",
list, cp, list)
case !reflect.DeepEqual(res, want):
t.Fatalf("Lists%v.Keep() = %v, want %v",
list, res, want)
}
}
func BenchmarkKeepInts(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range keepTests {
test.list.Keep(test.pred)
}
}
}
func BenchmarkDiscardInts(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range discardTests {
test.list.Discard(test.pred)
}
}
}