Skip to content

Commit

Permalink
Make "Spelling Numbers" exhaustive
Browse files Browse the repository at this point in the history
Should hopefully fix this hole being cheeseable.

Updates code-golf#448
  • Loading branch information
JRaspass committed Jul 5, 2021
1 parent a278864 commit 77e130e
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 57 deletions.
85 changes: 28 additions & 57 deletions hole/spelling-numbers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package hole
import (
"math/rand"
"strconv"
"strings"
)

var teens = [][]byte{
Expand Down Expand Up @@ -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()
}
9 changes: 9 additions & 0 deletions hole/spelling-numbers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package hole

import "testing"

func BenchmarkSpellingNumbers(b *testing.B) {
for n := 0; n < b.N; n++ {
spellingNumbers()
}
}

0 comments on commit 77e130e

Please sign in to comment.