-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgoCardinal.go
162 lines (141 loc) · 4.24 KB
/
goCardinal.go
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package goCardinal
import (
"strings"
)
// Slices for units and tens
var units = []string{
"", "one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten", "eleven", "twelve", "thirteen",
"fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen",
}
var unitsOrdinals = []string{
"", "first", "second", "third", "fourth", "fifth", "sixth", "seventh",
"eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth",
"fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteenth", "nineteenth",
}
var tens = []string{
"", "", "twenty", "thirty", "forty", "fifty", "sixty",
"seventy", "eighty", "ninety",
}
var tensOrdinals = []string{
"", "", "twentieth", "thirtieth", "fortieth", "fiftieth", "sixtieth",
"seventieth", "eightieth", "ninetieth",
}
var magnitudes = []struct {
value int64
singular string
singularOrdinal string
}{
{1e18, "quintillion", "quintillionth"},
{1e15, "quadrillion", "quadrillionth"},
{1e12, "trillion", "trillionth"},
{1e9, "billion", "billionth"},
{1e6, "million", "millionth"},
{1e3, "thousand", "thousandth"},
{1e2, "hundred", "hundredth"},
}
// NumberToOrdinal converts an integer to its ordinal word form.
// Supports numbers up to 9,223,372,036,854,775,807 (max int64 value).
func NumberToOrdinal(n int64) string {
if n == 0 {
return "Zeroth"
}
var words []string
remainder := n
ordinalAlreadySet := false // Flag to indicate if ordinal conversion has been done
// Process magnitudes (quintillion, quadrillion, etc.)
for _, magnitude := range magnitudes {
if remainder >= magnitude.value {
count := remainder / magnitude.value
remainder %= magnitude.value
// Get the word for the count (e.g., "one", "two")
var countWord string
if count < 20 {
countWord = units[count]
} else if count < 100 {
if count%10 == 0 {
countWord = tens[count/10]
} else {
countWord = tens[count/10] + "-" + units[count%10]
}
} else {
// For counts >= 100, recursively process
countWord = numberToWords(count)
}
// Append the magnitude word
words = append(words, countWord, magnitude.singular)
if remainder == 0 {
// Convert magnitude to its ordinal form
words[len(words)-1] = magnitude.singularOrdinal
ordinalAlreadySet = true // Set the flag
break
}
}
}
// Process tens and units
if remainder > 0 {
if remainder < 20 {
// For numbers less than 20
words = append(words, unitsOrdinals[remainder])
} else if remainder%10 == 0 {
// Exact tens (e.g., 20, 30)
words = append(words, tensOrdinals[remainder/10])
} else {
// Numbers between tens (e.g., 21, 47)
words = append(words, tens[remainder/10]+"-"+unitsOrdinals[remainder%10])
}
} else if len(words) > 0 && !ordinalAlreadySet {
// If remainder is zero and words exist, and ordinal not already set
lastIndex := len(words) - 1
lastWord := words[lastIndex]
if strings.HasSuffix(lastWord, "y") {
words[lastIndex] = lastWord[:len(lastWord)-1] + "ieth"
} else {
words[lastIndex] = lastWord + "th"
}
}
// Capitalize the first letter
result := strings.Join(words, " ")
if len(result) > 0 {
result = strings.ToUpper(result[:1]) + result[1:]
}
return result
}
// Helper function to convert numbers to words without ordinal suffixes.
func numberToWords(n int64) string {
var words []string
remainder := n
// Process magnitudes (quintillion, quadrillion, etc.)
for _, magnitude := range magnitudes {
if remainder >= magnitude.value {
count := remainder / magnitude.value
remainder %= magnitude.value
// Get the word for the count
var countWord string
if count < 20 {
countWord = units[count]
} else if count < 100 {
if count%10 == 0 {
countWord = tens[count/10]
} else {
countWord = tens[count/10] + "-" + units[count%10]
}
} else {
// For counts >= 100, recursively process
countWord = numberToWords(count)
}
words = append(words, countWord, magnitude.singular)
}
}
// Process tens and units
if remainder > 0 {
if remainder < 20 {
words = append(words, units[remainder])
} else if remainder%10 == 0 {
words = append(words, tens[remainder/10])
} else {
words = append(words, tens[remainder/10]+"-"+units[remainder%10])
}
}
return strings.Join(words, " ")
}