From 91edc6cab191413ec1ad61921aac24babd3171ba Mon Sep 17 00:00:00 2001 From: Lee Nipper Date: Wed, 15 Nov 2017 21:41:50 -0600 Subject: [PATCH] sieve: add generator Add .meta/gen.go to generate cases_test.go. Update test program to use generated test case array. Update example solution to pass test which includes limit as prime. For #605. --- exercises/sieve/.meta/gen.go | 48 +++++++++++++++++++++++++++++++++++ exercises/sieve/cases_test.go | 37 +++++++++++++++++++++++++++ exercises/sieve/example.go | 10 ++++---- exercises/sieve/sieve_test.go | 33 +++++++++--------------- 4 files changed, 102 insertions(+), 26 deletions(-) create mode 100644 exercises/sieve/.meta/gen.go create mode 100644 exercises/sieve/cases_test.go diff --git a/exercises/sieve/.meta/gen.go b/exercises/sieve/.meta/gen.go new file mode 100644 index 000000000..0fd38c1bc --- /dev/null +++ b/exercises/sieve/.meta/gen.go @@ -0,0 +1,48 @@ +package main + +import ( + "log" + "text/template" + + "../../../gen" +) + +func main() { + t, err := template.New("").Parse(tmpl) + if err != nil { + log.Fatal(err) + } + var j js + if err := gen.Gen("sieve", &j, t); err != nil { + log.Fatal(err) + } +} + +type OneCase struct { + Description string + Limit int + Expected []int +} + +// The JSON structure we expect to be able to unmarshal into +type js struct { + Cases []OneCase +} + +// template applied to above data structure generates the Go test cases +var tmpl = `package sieve + +{{.Header}} + +var testCases = []struct { + description string + limit int + expected []int +}{ +{{range .J.Cases}}{ + "{{.Description}}", + {{.Limit}}, + {{printf "%#v" .Expected}}, +}, +{{end}}} +` diff --git a/exercises/sieve/cases_test.go b/exercises/sieve/cases_test.go new file mode 100644 index 000000000..38327f811 --- /dev/null +++ b/exercises/sieve/cases_test.go @@ -0,0 +1,37 @@ +package sieve + +// Source: exercism/problem-specifications +// Commit: f2b2693 sieve: Fix canonical-data.json formatting +// Problem Specifications Version: 1.0.0 + +var testCases = []struct { + description string + limit int + expected []int +}{ + { + "no primes under two", + 1, + []int{}, + }, + { + "find first prime", + 2, + []int{2}, + }, + { + "find primes up to 10", + 10, + []int{2, 3, 5, 7}, + }, + { + "limit is prime", + 13, + []int{2, 3, 5, 7, 11, 13}, + }, + { + "find primes up to 1000", + 1000, + []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997}, + }, +} diff --git a/exercises/sieve/example.go b/exercises/sieve/example.go index 71bacb68a..e713e0795 100644 --- a/exercises/sieve/example.go +++ b/exercises/sieve/example.go @@ -1,15 +1,15 @@ package sieve func Sieve(limit int) (primes []int) { - c := make([]bool, limit) - for p := 2; p < limit; { - for i := p + p; i < limit; i += p { + c := make([]bool, limit+1) + for p := 2; p <= limit; { + for i := p + p; i <= limit; i += p { c[i] = true } - for p++; p < limit && c[p]; p++ { + for p++; p <= limit && c[p]; p++ { } } - for i := 2; i < limit; i++ { + for i := 2; i <= limit; i++ { if !c[i] { primes = append(primes, i) } diff --git a/exercises/sieve/sieve_test.go b/exercises/sieve/sieve_test.go index 1eec072bb..52ffc3e0b 100644 --- a/exercises/sieve/sieve_test.go +++ b/exercises/sieve/sieve_test.go @@ -5,32 +5,23 @@ import ( "testing" ) -var p10 = []int{2, 3, 5, 7} -var p1000 = []int{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, - 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, - 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, - 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, - 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, - 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, - 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, - 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, - 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, - 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, - 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997} - func TestSieve(t *testing.T) { - p := Sieve(10) - if !reflect.DeepEqual(p, p10) { - t.Fatalf("Sieve(10) = %v, want %v", p, p10) - } - p = Sieve(1000) - if !reflect.DeepEqual(p, p1000) { - t.Fatalf("Sieve(1000) = %v, want %v", p, p1000) + for _, tc := range testCases { + p := Sieve(tc.limit) + if len(p) != 0 || len(tc.expected) != 0 { + if !reflect.DeepEqual(p, tc.expected) { + t.Fatalf("FAIL: %s\nSieve(%d)\nExpected %v\nActual %v", + tc.description, tc.limit, tc.expected, p) + } + } + t.Logf("PASS: %s", tc.description) } } func BenchmarkSieve(b *testing.B) { for i := 0; i < b.N; i++ { - Sieve(1000) + for _, tc := range testCases { + Sieve(tc.limit) + } } }