//go:build !solution package speller import ( "strings" ) var numToDigits = []string{ "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", } var teens = []string{ "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", } var decs = []string{ "", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety", } var 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, digits := strings.Builder{}, digitsReversedSlice(n) // 35 is the optimal number which gives approx needed // space for the number in 1 allocation num.Grow(len(digits) * 35) if sign { num.WriteString("minus ") } largeIndex, iters := 0, 0 for i := len(digits) - 1; i >= 0; i, largeIndex = i-3, largeIndex+1 { first, second, third := digits[i-2], digits[i-1], digits[i] if first == 0 && second == 0 && third == 0 { continue } if iters != 0 { num.WriteRune(' ') } hundreds := numToDigits[third] if hundreds != "" { num.WriteString(hundreds) num.WriteString(" hundred") if second != 0 || first != 0 { num.WriteRune(' ') } } if second > 1 { num.WriteString(decs[second]) if first > 0 { num.WriteRune('-') num.WriteString(numToDigits[first]) } } else if second == 1 { num.WriteString(teens[first]) } else { if first > 0 { num.WriteString(numToDigits[first]) } } if largeIndex < len(large) { num.WriteRune(' ') num.WriteString(large[largeIndex]) } iters++ } return num.String() }