shad-go/speller/speller.go

85 lines
1.8 KiB
Go

//go:build !solution
package speller
import (
"strings"
)
var (
digits = []string{
"", "one", "two", "three", "four", "five",
"six", "seven", "eight", "nine",
}
teens = []string{
"ten", "eleven", "twelve", "thirteen", "fourteen",
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen",
}
decs = []string{
"", "", "twenty", "thirty", "forty", "fifty",
"sixty", "seventy", "eighty", "ninety",
}
large = []string{
"billion", "million", "thousand",
}
)
func digitsReversedSlice(n int64) []uint8 {
digits := make([]uint8, 12)
for i := 0; i < len(digits); i, n = i+1, n/10 {
digits[i] = uint8(n % 10)
}
return digits
}
func Spell(n int64) string {
if n == 0 {
return "zero"
}
sign := n < 0
if sign {
n = -n
}
num, numDigits := strings.Builder{}, digitsReversedSlice(n)
// 35 is the optimal number which gives approx needed
// space for the number in 1 allocation
num.Grow(len(numDigits) * 35)
if sign {
num.WriteString("minus ")
}
for i, largeIndex := len(numDigits)-1, 0; i >= 0; i, largeIndex = i-3, largeIndex+1 {
hundreds, tens, ones := numDigits[i], numDigits[i-1], numDigits[i-2]
hundredsPresent, tensPesent, onesPresent := hundreds != 0, tens != 0, ones != 0
if !hundredsPresent && !tensPesent && !onesPresent {
continue
}
if hundredsPresent {
num.WriteString(digits[hundreds])
num.WriteString(" hundred")
if tensPesent || onesPresent {
num.WriteRune(' ')
}
}
if tensPesent {
if tens == 1 {
num.WriteString(teens[ones])
} else {
num.WriteString(decs[tens])
if onesPresent {
num.WriteRune('-')
}
}
}
if onesPresent && tens != 1 {
num.WriteString(digits[ones])
}
if largeIndex < len(large) {
num.WriteRune(' ')
num.WriteString(large[largeIndex])
}
num.WriteRune(' ')
}
output := num.String()
output = output[:len(output)-1]
return output
}