/
util.go
219 lines (186 loc) · 6.87 KB
/
util.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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
package lmd
import (
"strconv"
)
// next_lettering will iterate a given string to give the next logical lettering point
// please note this only works with english language letters "a" to "z" and "A" to "Z"
// this is not meant to be a general purpose letter iterator, but rather is purpose
// built for legal documents which use letter based denotations.
//
// if the final code point (converted to integer type) is 90 or 122, that means
// that the final letter is "Z" or "z" in which case we subtract 25 from the code
// point and then double the letter which will return the final bit as "AA" or "aa"
// in keeping with fairly typical legal syntax.
func next_lettering(previous string) string {
codepoint := []byte(previous)
finlpoint := codepoint[len(codepoint)-1]
if int(finlpoint) == 90 || int(finlpoint) == 122 {
codepoint[len(codepoint)-1] = finlpoint - 25
codepoint = append(codepoint, codepoint[len(codepoint)-1])
} else {
codepoint[len(codepoint)-1] = finlpoint + 1
}
return string(codepoint)
}
// prev_lettering is the opposite of next_lettering.
func prev_lettering(previous string) string {
codepoint := []byte(previous)
finlpoint := codepoint[len(codepoint)-1]
var penlpoint byte
if len(codepoint) >= 2 {
penlpoint = codepoint[len(codepoint)-2]
} else {
penlpoint = byte(0)
}
if finlpoint == penlpoint {
if int(finlpoint) == 65 || int(finlpoint) == 97 {
codepoint[len(codepoint)-2] = finlpoint + 25
codepoint = codepoint[:len(codepoint)-1]
} else {
codepoint[len(codepoint)-1] = finlpoint - 1
}
} else {
if !(int(finlpoint) == 65 || int(finlpoint) == 97) {
codepoint[len(codepoint)-1] = finlpoint - 1
}
}
return string(codepoint)
}
// next_roman_upper increases a roman number by one position for upper cased roman
// numerals by using the from_roman_to_arabic function which returns an integer
// that is subsequently increased by one and then changed back to a roman number
// via the from_arabic_to_roman function.
func next_roman_upper(previous string) string {
prev_as_digit := from_roman_to_arabic_upper(previous)
next_as_digit := prev_as_digit + 1
return from_arabic_to_roman_upper(next_as_digit)
}
// prev_roman_upper is the opposite of next_roman_upper
func prev_roman_upper(previous string) string {
prev_as_digit := from_roman_to_arabic_upper(previous)
next_as_digit := prev_as_digit - 1
return from_arabic_to_roman_upper(next_as_digit)
}
// next_roman_lower increases a roman number by one position for lower cased roman
// numerals by using the from_roman_to_arabic function which returns an integer
// that is subsequently increased by one and then changed back to a roman number
// via the from_arabic_to_roman function.
func next_roman_lower(previous string) string {
prev_as_digit := from_roman_to_arabic_lower(previous)
next_as_digit := prev_as_digit + 1
return from_arabic_to_roman_lower(next_as_digit)
}
// prev_roman_lower isthe opposite of next_roman_lower
func prev_roman_lower(previous string) string {
prev_as_digit := from_roman_to_arabic_lower(previous)
next_as_digit := prev_as_digit - 1
return from_arabic_to_roman_lower(next_as_digit)
}
// next_numbering increases numbers which are presented as strings for the package
// the function uses the strconv package first to convert the string to an integer
// then it increases the integer by one and then converts it back to a string.
func next_numbering(previous string) string {
prev_as_digit, _ := strconv.Atoi(previous)
next_as_digit := prev_as_digit + 1
return strconv.Itoa(next_as_digit)
}
// prev_numbering is the opposite of next_numbering
func prev_numbering(previous string) string {
prev_as_digit, _ := strconv.Atoi(previous)
next_as_digit := prev_as_digit - 1
return strconv.Itoa(next_as_digit)
}
// from_roman_to_arabic_upper is a convenience function which converts upper cased
// roman numerals to integers.
//
// via: http://rosettacode.org/wiki/Roman_numerals/Decode#Go
func from_roman_to_arabic_upper(romans string) int {
var arabic int
// set a map from the roman runes to arabic integers
var roman_to_arabic_map = map[rune]int{
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000,
}
// loop through the roman string which is passed by rune
last_digit := 1000
for _, roman := range romans {
digit := roman_to_arabic_map[roman]
if last_digit < digit {
arabic -= 2 * last_digit
}
last_digit = digit
arabic += digit
}
return arabic
}
// from_arabic_to_roman_upper is a convenience function which converts upper cased
// integers to roman numerals.
//
// via: http://rosettacode.org/wiki/Roman_numerals/Encode#Go
func from_arabic_to_roman_upper(arabic int) string {
var (
m0 = []string{"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}
m1 = []string{"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}
m2 = []string{"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}
m3 = []string{"", "M", "MM", "MMM", "IV", "V", "VI", "VII", "VIII", "IX"}
m4 = []string{"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}
m5 = []string{"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}
m6 = []string{"", "M", "MM", "MMM"}
)
if arabic < 1 || arabic >= 4e6 {
return ""
}
return m6[arabic/1e6] + m5[arabic%1e6/1e5] + m4[arabic%1e5/1e4] + m3[arabic%1e4/1e3] + m2[arabic%1e3/1e2] + m1[arabic%100/10] + m0[arabic%10]
}
// from_roman_to_arabic_lower is a convenience function which converts lower cased
// roman numerals to integers.
//
// via: http://rosettacode.org/wiki/Roman_numerals/Decode#Go
func from_roman_to_arabic_lower(romans string) int {
var arabic int
// set a map from the roman runes to arabic integers
var roman_to_arabic_map = map[rune]int{
'i': 1,
'v': 5,
'x': 10,
'l': 50,
'c': 100,
'd': 500,
'm': 1000,
}
// loop through the roman string which is passed by rune
last_digit := 1000
for _, roman := range romans {
digit := roman_to_arabic_map[roman]
if last_digit < digit {
arabic -= 2 * last_digit
}
last_digit = digit
arabic += digit
}
return arabic
}
// from_arabic_to_roman_upper is a convenience function which converts lower cased
// integers to roman numerals.
//
// via: http://rosettacode.org/wiki/Roman_numerals/Encode#Go
func from_arabic_to_roman_lower(arabic int) string {
var (
m0 = []string{"", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix"}
m1 = []string{"", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"}
m2 = []string{"", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"}
m3 = []string{"", "m", "mm", "mmm", "iv", "v", "vi", "vii", "viii", "xi"}
m4 = []string{"", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc"}
m5 = []string{"", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm"}
m6 = []string{"", "m", "mm", "mmm"}
)
if arabic < 1 || arabic >= 4e6 {
return ""
}
return m6[arabic/1e6] + m5[arabic%1e6/1e5] + m4[arabic%1e5/1e4] + m3[arabic%1e4/1e3] + m2[arabic%1e3/1e2] + m1[arabic%100/10] + m0[arabic%10]
}