From e3d678b04f6c4a24f49dd55ac46224b5f8607208 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Tue, 30 Aug 2016 02:32:55 +0200 Subject: Solve strain --- go/strain/strain_test.go | 170 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 go/strain/strain_test.go (limited to 'go/strain/strain_test.go') diff --git a/go/strain/strain_test.go b/go/strain/strain_test.go new file mode 100644 index 0000000..dd3da5a --- /dev/null +++ b/go/strain/strain_test.go @@ -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) + } + } +} -- cgit v1.2.3