summaryrefslogtreecommitdiff
path: root/go/say/say.go
blob: 4fdc5b418598aa57fb9c5327775b1ab46443bcb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package say

import "strings"

var small = []string{
	"", "one", "two", "three", "four", "five",
	"six", "seven", "eight", "nine", "ten",
	"eleven", "twelve", "thirteen", "fourteen", "fifteen",
	"sixteen", "seventeen", "eighteen", "nineteen",
}

var tens = []string{
	"", "", "twenty", "thirty", "forty", "fifty",
	"sixty", "seventy", "eighty", "ninety",
}

var scale = []string{
	"", "thousand", "million", "billion", "trillion",
	"quadrillion", "quintillion",
}

type Group struct {
	Value uint64
	Power int
}

func (g Group) String() string {
	var s []string
	if h := g.Value / 100; h > 0 {
		s = append(s, small[h]+" hundred")
	}
	if t := g.Value % 100; t > 0 {
		if tns := t / 10; tns >= 2 {
			if sml := t % 10; sml > 0 {
				s = append(s, tens[tns]+"-"+small[sml])
			} else {
				s = append(s, tens[tns])
			}
		} else if t > 0 {
			s = append(s, small[t])
		}
	}
	if p := scale[g.Power]; p != "" && len(s) > 0 {
		s = append(s, p)
	}
	return strings.Join(s, " ")
}

func split(n uint64) []Group {
	var g []Group
	for i := 0; n > 0; i++ {
		r := n % 1e3
		n /= 1e3
		g = append(g, Group{
			Value: r,
			Power: i,
		})
	}
	return g
}

func Say(n uint64) string {
	if n <= 0 {
		return "zero"
	}
	g := split(n)
	var s []string
	for i := len(g) - 1; i >= 0; i-- {
		if str := g[i].String(); str != "" {
			s = append(s, str)
		}
	}
	return strings.Join(s, " ")
}