//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 }