From 5905c68a1fbae71682ff2edea7c009ad0355e9fb Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Fri, 26 Aug 2016 09:21:31 +0200 Subject: Solve series --- go/series/README.md | 38 ++++++++++++++++++ go/series/asktoomuch_test.go | 29 ++++++++++++++ go/series/first_test.go | 23 +++++++++++ go/series/series.go | 25 ++++++++++++ go/series/series_test.go | 94 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 209 insertions(+) create mode 100644 go/series/README.md create mode 100644 go/series/asktoomuch_test.go create mode 100644 go/series/first_test.go create mode 100644 go/series/series.go create mode 100644 go/series/series_test.go (limited to 'go/series') diff --git a/go/series/README.md b/go/series/README.md new file mode 100644 index 0000000..6474366 --- /dev/null +++ b/go/series/README.md @@ -0,0 +1,38 @@ +# Series + +Write a program that will take a string of digits and give you all the contiguous substrings of length `n` in that string. + +For example, the string "49142" has the following 3-digit series: + +- 491 +- 914 +- 142 + +And the following 4-digit series: + +- 4914 +- 9142 + +And if you ask for a 6-digit series from a 5-digit string, you deserve +whatever you get. + +Note that these series are only required to occupy *adjacent positions* +in the input; the digits need not be *numerically consecutive*. + +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 + +A subset of the Problem 8 at Project Euler [http://projecteuler.net/problem=8](http://projecteuler.net/problem=8) + +## Submitting Incomplete Problems +It's possible to submit an incomplete solution so you can see how others have completed the exercise. + diff --git a/go/series/asktoomuch_test.go b/go/series/asktoomuch_test.go new file mode 100644 index 0000000..e29703a --- /dev/null +++ b/go/series/asktoomuch_test.go @@ -0,0 +1,29 @@ +// +build asktoomuch + +package slice + +import "testing" + +func TestAskTooMuch(t *testing.T) { + test := allTests[0] + defer func() { + if recover() != nil { + t.Fatalf("Yikes, UnsafeFirst(%d, %s) panicked!", test.n, test.s) + } + }() + for _, test = range allTests { + switch res := UnsafeFirst(test.n, test.s); { + case len(test.out) > 0: // well, this should work + if res != test.out[0] { + t.Fatalf("Yikes, UnsafeFirst(%d, %s) = %q, want %q.", + test.n, test.s, res, test.out[0]) + } + case len(res) != test.n: + t.Fatalf("Yikes, UnsafeFirst(%d, %s) = %q, but %q doesn't have %d characters.", + test.n, test.s, res, res, test.n) + default: + t.Fatalf("Yikes, UnsafeFirst(%d, %s) = %q, but %q isn't in %q", + test.n, test.s, res, res, test.s) + } + } +} diff --git a/go/series/first_test.go b/go/series/first_test.go new file mode 100644 index 0000000..cbe524b --- /dev/null +++ b/go/series/first_test.go @@ -0,0 +1,23 @@ +// +build first + +package slice + +import "testing" + +func TestFirst(t *testing.T) { + for _, test := range allTests { + switch res, ok := First(test.n, test.s); { + case !ok: + if len(test.out) > 0 { + t.Fatalf("First(%d, %s) returned !ok, want ok.", + test.n, test.s) + } + case len(test.out) == 0: + t.Fatalf("First(%d, %s) = %s, %t. Expected ok == false", + test.n, test.s, res, ok) + case res != test.out[0]: + t.Fatalf("First(%d, %s) = %s. Want %s.", + test.n, test.s, res, test.out[0]) + } + } +} diff --git a/go/series/series.go b/go/series/series.go new file mode 100644 index 0000000..55f7eb2 --- /dev/null +++ b/go/series/series.go @@ -0,0 +1,25 @@ +package slice + +// All returns a list of all substrings of s with length n. +func All(n int, s string) []string { + var ret []string + for i, j := 0, n; j <= len(s); i, j = i+1, j+1 { + ret = append(ret, s[i:j]) + } + return ret +} + +// UnsafeFirst returns the first substring of s with length n. +func UnsafeFirst(n int, s string) string { + if len(s) >= n { + return s[:n] + } + return "" +} + +func First(n int, s string) (string, bool) { + if len(s) >= n { + return s[:n], true + } + return "", false +} diff --git a/go/series/series_test.go b/go/series/series_test.go new file mode 100644 index 0000000..682d78f --- /dev/null +++ b/go/series/series_test.go @@ -0,0 +1,94 @@ +// Define two functions: (Two? Yes, sometimes we ask more out of Go.) +// +// // All returns a list of all substrings of s with length n. +// All(n int, s string) []string +// +// // UnsafeFirst returns the first substring of s with length n. +// UnsafeFirst(n int, s string) string +// +// At this point you could consider this exercise complete and move on. +// But wait, maybe you ask a reasonable question: +// Why is the function called **Unsafe** First? +// If you are interested, read on for a bonus exercise. +// +// Bonus exercise: +// +// Once you get `go test` passing, try `go test -tags asktoomuch`. +// This uses a *build tag* to enable a test that wasn't enabled before. +// You can read more about those at https://golang.org/pkg/go/build/#hdr-Build_Constraints +// +// You may notice that you can't make this asktoomuch test happy. +// We need a way to signal that in some cases you can't take the first N characters of the string. +// UnsafeFirst can't do that since it only returns a string. +// +// To fix that, let's add another return value to the function. Define +// +// First(int, string) (first string, ok bool) +// +// and test with `go test -tags first`. + +package slice + +import ( + "reflect" + "testing" +) + +var allTests = []struct { + n int + s string + out []string +}{ + {1, "01234", + []string{"0", "1", "2", "3", "4"}}, + {1, "92834", + []string{"9", "2", "8", "3", "4"}}, + {2, "01234", + []string{"01", "12", "23", "34"}}, + {2, "98273463", + []string{"98", "82", "27", "73", "34", "46", "63"}}, + {2, "37103", + []string{"37", "71", "10", "03"}}, + {3, "01234", + []string{"012", "123", "234"}}, + {3, "31001", + []string{"310", "100", "001"}}, + {3, "982347", + []string{"982", "823", "234", "347"}}, + {4, "01234", + []string{"0123", "1234"}}, + {4, "91274", + []string{"9127", "1274"}}, + {5, "01234", + []string{"01234"}}, + {5, "81228", + []string{"81228"}}, + {6, "01234", nil}, + {len(cx) + 1, cx, nil}, +} + +var cx = "01032987583" + +func TestAll(t *testing.T) { + for _, test := range allTests { + switch res := All(test.n, test.s); { + case len(res) == 0 && len(test.out) == 0: + case reflect.DeepEqual(res, test.out): + default: + t.Fatalf("All(%d, %s) = %v, want %v.", + test.n, test.s, res, test.out) + } + } +} + +func TestUnsafeFirst(t *testing.T) { + for _, test := range allTests { + if len(test.out) == 0 { + continue + } + if res := UnsafeFirst(test.n, test.s); res != test.out[0] { + t.Fatalf("UnsafeFirst(%d, %s) = %s, want %s.", + test.n, test.s, res, test.out[0]) + } + } +} -- cgit v1.2.3