85 lines
1.8 KiB
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
|
|
}
|