1const LOWER: &[u8] = b"abcdefghijklmnopqrstuvwxyz";
7const UPPER: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
8
9const GREEK_LOWER: &[char] = &[
10 '\u{03B1}', '\u{03B2}', '\u{03B3}', '\u{03B4}', '\u{03B5}', '\u{03B6}', '\u{03B7}', '\u{03B8}',
11 '\u{03B9}', '\u{03BA}', '\u{03BB}', '\u{03BC}', '\u{03BD}', '\u{03BE}', '\u{03BF}', '\u{03C0}',
12 '\u{03C1}', '\u{03C3}', '\u{03C4}', '\u{03C5}', '\u{03C6}', '\u{03C7}', '\u{03C8}', '\u{03C9}',
13];
14
15const GREEK_UPPER: &[char] = &[
16 '\u{0391}', '\u{0392}', '\u{0393}', '\u{0394}', '\u{0395}', '\u{0396}', '\u{0397}', '\u{0398}',
17 '\u{0399}', '\u{039A}', '\u{039B}', '\u{039C}', '\u{039D}', '\u{039E}', '\u{039F}', '\u{03A0}',
18 '\u{03A1}', '\u{03A3}', '\u{03A4}', '\u{03A5}', '\u{03A6}', '\u{03A7}', '\u{03A8}', '\u{03A9}',
19];
20
21fn radix_format_chars(mut number: u32, symbols: &[char]) -> String {
27 let mut result = String::new();
28 let base = symbols.len() as u32;
29 while number > 0 {
30 let idx = ((number - 1) % base) as usize;
31 result.insert(0, symbols[idx]);
32 number = (number - 1) / base;
33 }
34 result
35}
36
37fn radix_format_bytes(mut number: u32, symbols: &[u8]) -> String {
38 let mut result = Vec::new();
39 let base = symbols.len() as u32;
40 while number > 0 {
41 let idx = ((number - 1) % base) as usize;
42 result.insert(0, symbols[idx]);
43 number = (number - 1) / base;
44 }
45 String::from_utf8(result).unwrap()
46}
47
48pub fn radix_alpha(n: u32) -> String { radix_format_bytes(n, LOWER) }
50
51pub fn radix_alpha_upper(n: u32) -> String { radix_format_bytes(n, UPPER) }
53
54pub fn radix_greek(n: u32) -> String { radix_format_chars(n, GREEK_LOWER) }
56
57pub fn radix_greek_upper(n: u32) -> String { radix_format_chars(n, GREEK_UPPER) }
59
60pub fn radix_roman(mut n: u32) -> String {
62 let letters = ['i', 'v', 'x', 'l', 'c', 'd', 'm'];
63 let mut s = String::new();
64 let mut div: u32 = 1000;
65
66 if n >= div {
68 for _ in 0..(n / div) {
69 s.push('m');
70 }
71 }
72 let mut p: i32 = 4;
73
74 loop {
75 n %= div;
76 if n == 0 {
77 break;
78 }
79 div /= 10;
80 if div == 0 {
81 break;
82 }
83 let mut d = n / div;
84 if d % 5 == 4 {
85 s.push(letters[p as usize]);
86 d += 1;
87 }
88 if d > 4 {
89 s.push(letters[(p + (d / 5) as i32) as usize]);
90 d %= 5;
91 }
92 for _ in 0..d {
93 s.push(letters[p as usize]);
94 }
95 p -= 2;
96 if p < 0 {
97 break;
98 }
99 }
100 s
101}
102
103pub fn radix_roman_upper(n: u32) -> String { radix_roman(n).to_uppercase() }
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109
110 #[test]
111 fn test_radix_alpha() {
112 assert_eq!(radix_alpha(1), "a");
113 assert_eq!(radix_alpha(2), "b");
114 assert_eq!(radix_alpha(26), "z");
115 assert_eq!(radix_alpha(27), "aa");
116 assert_eq!(radix_alpha(28), "ab");
117 assert_eq!(radix_alpha(52), "az");
118 assert_eq!(radix_alpha(53), "ba");
119 assert_eq!(radix_alpha(702), "zz");
120 assert_eq!(radix_alpha(703), "aaa");
121 }
122
123 #[test]
124 fn test_radix_roman() {
125 assert_eq!(radix_roman(1), "i");
126 assert_eq!(radix_roman(4), "iv");
127 assert_eq!(radix_roman(9), "ix");
128 assert_eq!(radix_roman(14), "xiv");
129 assert_eq!(radix_roman(42), "xlii");
130 assert_eq!(radix_roman(1000), "m"); assert_eq!(radix_roman(1999), "mcmxcix");
132 assert_eq!(radix_roman(2000), "mm");
133 assert_eq!(radix_roman(3999), "mmmcmxcix");
134 }
135
136 #[test]
137 fn test_radix_alpha_upper() {
138 assert_eq!(radix_alpha_upper(1), "A");
139 assert_eq!(radix_alpha_upper(26), "Z");
140 assert_eq!(radix_alpha_upper(27), "AA");
141 assert_eq!(radix_alpha_upper(703), "AAA");
142 }
143
144 #[test]
145 fn test_radix_alpha_upper_vs_lower_case() {
146 for n in 1..100 {
148 assert_eq!(
149 radix_alpha_upper(n),
150 radix_alpha(n).to_uppercase(),
151 "divergence at n={n}"
152 );
153 }
154 }
155
156 #[test]
157 fn test_radix_greek_basic() {
158 assert_eq!(radix_greek(1), "α");
159 assert_eq!(radix_greek(2), "β");
160 assert_eq!(radix_greek(24), "ω");
162 assert_eq!(radix_greek(25), "αα");
164 }
165
166 #[test]
167 fn test_radix_greek_upper_basic() {
168 assert_eq!(radix_greek_upper(1), "Α");
169 assert_eq!(radix_greek_upper(24), "Ω");
170 assert_eq!(radix_greek_upper(25), "ΑΑ");
171 }
172
173 #[test]
174 fn test_radix_roman_upper() {
175 assert_eq!(radix_roman_upper(1), "I");
176 assert_eq!(radix_roman_upper(4), "IV");
177 assert_eq!(radix_roman_upper(1999), "MCMXCIX");
178 }
179
180 #[test]
181 fn test_radix_alpha_zero_is_empty() {
182 assert_eq!(radix_alpha(0), "");
184 assert_eq!(radix_alpha_upper(0), "");
185 assert_eq!(radix_greek(0), "");
186 assert_eq!(radix_roman(0), "");
187 }
188}