From acbc22c498a5e58b810f6a3838fa85e597b7f4d9 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Fri, 26 Aug 2016 14:44:10 +0200 Subject: Solve sum of multiples --- go/sum-of-multiples/README.md | 29 +++++++++++ go/sum-of-multiples/sum_of_multiples.go | 34 +++++++++++++ go/sum-of-multiples/sum_of_multiples_test.go | 73 ++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 go/sum-of-multiples/README.md create mode 100644 go/sum-of-multiples/sum_of_multiples.go create mode 100644 go/sum-of-multiples/sum_of_multiples_test.go (limited to 'go') diff --git a/go/sum-of-multiples/README.md b/go/sum-of-multiples/README.md new file mode 100644 index 0000000..621777b --- /dev/null +++ b/go/sum-of-multiples/README.md @@ -0,0 +1,29 @@ +# Sum Of Multiples + +Write a program that, given a number, can find the sum of all the multiples of particular numbers up to but not including that number. + +If we list all the natural numbers up to but not including 20 that are +multiples of either 3 or 5, we get 3, 5, 6 and 9, 10, 12, 15, and 18. + +The sum of these multiples is 78. + +Write a program that can find the sum of the multiples of a given set of +numbers. + +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 variation on Problem 1 at Project Euler [http://projecteuler.net/problem=1](http://projecteuler.net/problem=1) + +## 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/sum-of-multiples/sum_of_multiples.go b/go/sum-of-multiples/sum_of_multiples.go new file mode 100644 index 0000000..c99cdd7 --- /dev/null +++ b/go/sum-of-multiples/sum_of_multiples.go @@ -0,0 +1,34 @@ +package summultiples + +import "sync" + +func MultipleSummer(n ...int) func(top int) int { + return func(top int) int { + c := make(chan int) + wg := sync.WaitGroup{} + // spawn worker + for _, v := range n { + wg.Add(1) + go func(m int) { + for i := m; i < top; i += m { + c <- i + } + wg.Done() + }(v) + } + go func() { + wg.Wait() + close(c) + }() + // collect, uniq and sum up values + var sum int + seen := make(map[int]bool) + for v := range c { + if !seen[v] { + seen[v] = true + sum += v + } + } + return sum + } +} diff --git a/go/sum-of-multiples/sum_of_multiples_test.go b/go/sum-of-multiples/sum_of_multiples_test.go new file mode 100644 index 0000000..9ab0bb2 --- /dev/null +++ b/go/sum-of-multiples/sum_of_multiples_test.go @@ -0,0 +1,73 @@ +package summultiples + +import "testing" + +var test35 = []struct { + limit int + sum int +}{ + {1, 0}, + {4, 3}, + {10, 23}, + {100, 2318}, + {1000, 233168}, +} + +var varTests = []struct { + divisors []int + limit int + sum int +}{ + {[]int{7, 13, 17}, 20, 51}, + {[]int{43, 47}, 10000, 2203160}, + {[]int{5, 10, 12}, 10000, 13331672}, + {[]int{1, 1}, 10000, 49995000}, + // Note: The following test case deviates from the README. + // The README specifies some rather odd defaults, whereas + // this has the more logical approach of not implementing any + // defaults, which causes the resulting sum to be zero. + // See discussion in: + // https://github.com/exercism/xgo/issues/256 and + // https://github.com/exercism/x-common/issues/198 + {[]int{}, 10000, 0}, +} + +func Test35(t *testing.T) { + sum35 := MultipleSummer(3, 5) + for _, test := range test35 { + s := sum35(test.limit) + if s != test.sum { + t.Fatalf("Sum to %d returned %d, want %d.", test.limit, s, test.sum) + } + } +} + +func TestVar(t *testing.T) { + for _, test := range varTests { + sv := MultipleSummer(test.divisors...) + s := sv(test.limit) + if s != test.sum { + t.Fatalf("Sum of multiples of %v to %d returned %d, want %d.", + test.divisors, test.limit, s, test.sum) + } + } +} + +func Benchmark35(b *testing.B) { + sum35 := MultipleSummer(3, 5) + b.ResetTimer() // bench just the sum function + for i := 0; i < b.N; i++ { + for _, test := range test35 { + sum35(test.limit) + } + } +} + +func BenchmarkVar(b *testing.B) { + // bench combined time to bind sum function and call it. + for i := 0; i < b.N; i++ { + for _, test := range varTests { + MultipleSummer(test.divisors...)(test.limit) + } + } +} -- cgit v1.2.3