From 77e130ec340ad1af53bdeb099ddf768f8bca4a1b Mon Sep 17 00:00:00 2001 From: James Raspass Date: Mon, 5 Jul 2021 22:35:23 +0100 Subject: [PATCH] Make "Spelling Numbers" exhaustive Should hopefully fix this hole being cheeseable. Updates #448 --- hole/spelling-numbers.go | 85 ++++++++++++----------------------- hole/spelling-numbers_test.go | 9 ++++ 2 files changed, 37 insertions(+), 57 deletions(-) create mode 100644 hole/spelling-numbers_test.go diff --git a/hole/spelling-numbers.go b/hole/spelling-numbers.go index e8d35e888..f6a83e8c3 100644 --- a/hole/spelling-numbers.go +++ b/hole/spelling-numbers.go @@ -3,6 +3,7 @@ package hole import ( "math/rand" "strconv" + "strings" ) var teens = [][]byte{ @@ -41,77 +42,47 @@ var tens = [][]byte{ []byte("ninety"), } -func wordify(i uint16) []byte { +func wordify(out *strings.Builder, i int) { if i == 1000 { - return []byte("one thousand") + out.WriteString("one thousand") } else if i < 20 { - return teens[i] + out.Write(teens[i]) } else if i < 100 { + out.Write(tens[i/10]) + if j := i % 10; j > 0 { - return append(append(append([]byte(nil), tens[i/10]...), '-'), teens[j]...) + out.WriteRune('-') + out.Write(teens[j]) } + } else { + out.Write(teens[i/100]) + out.WriteString(" hundred") - return tens[i/10] - } - - hundred := append(append([]byte(nil), teens[i/100]...), []byte(" hundred")...) - - if j := i % 100; j > 0 { - hundred = append(append(hundred, []byte(" and ")...), wordify(j)...) + if j := i % 100; j > 0 { + out.WriteString(" and ") + wordify(out, j) + } } - - return hundred } -func spellingNumbers() (args []string, out string) { - // Always test the low and high end. - numbers := []uint16{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 29, 31, - 901, 910, 911, 919, 920, 921, - 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, - } - - tens := []uint16{20, 30, 40, 50, 60, 70, 80, 90} +func spellingNumbers() ([]string, string) { + const max = 1000 - rand.Shuffle(len(tens), func(i, j int) { - tens[i], tens[j] = tens[j], tens[i] - }) + args := make([]string, max+1) + var out strings.Builder - // Add on random numbers to each ten except the first, to ensure at least - // one non hyphen answer. - for i := 1; i < len(tens); i++ { - tens[i] += 1 + uint16(rand.Intn(8)) - } - - numbers = append(numbers, tens...) - - hundreds := []uint16{100, 200, 300, 400, 500, 600, 700, 800, 900} - - rand.Shuffle(len(hundreds), func(i, j int) { - hundreds[i], hundreds[j] = hundreds[j], hundreds[i] - }) + // The strings "zero" to "one thousand", newline delimited, are this len. + out.Grow(25531) - // Add on random numbers to each hundred except the first, to ensure at - // least one non and answer. - for i := 1; i < len(hundreds); i++ { - hundreds[i] += 1 + uint16(rand.Intn(98)) - } - - numbers = append(numbers, hundreds...) + for i, n := range rand.Perm(max + 1) { + args[i] = strconv.Itoa(n) - rand.Shuffle(len(numbers), func(i, j int) { - numbers[i], numbers[j] = numbers[j], numbers[i] - }) + wordify(&out, n) - for _, n := range numbers { - args = append(args, strconv.Itoa(int(n))) - out += string(wordify(n)) + "\n" + if i < max { + out.WriteRune('\n') + } } - // Drop the trailing newline. - out = out[:len(out)-1] - - return + return args, out.String() } diff --git a/hole/spelling-numbers_test.go b/hole/spelling-numbers_test.go new file mode 100644 index 000000000..856547db3 --- /dev/null +++ b/hole/spelling-numbers_test.go @@ -0,0 +1,9 @@ +package hole + +import "testing" + +func BenchmarkSpellingNumbers(b *testing.B) { + for n := 0; n < b.N; n++ { + spellingNumbers() + } +}