1use std::fmt::Display;
2
3use num_traits::AsPrimitive;
4
5#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
6pub struct Numeral(String);
14
15impl Display for Numeral {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 write!(f, "{}", self.0)
18 }
19}
20
21impl<T: AsPrimitive<usize>> From<T> for Numeral {
22 fn from(num: T) -> Self {
23 let mut n: usize = num.as_();
24
25 assert!(n < 4000);
26
27 let mut string = String::new();
28
29 fn digit(n: usize, one: char, five: char, ten: char) -> String {
30 match n {
31 0 => String::new(),
32 1 => format!("{0}", one),
33 2 => format!("{0}{0}", one),
34 3 => format!("{0}{0}{0}", one),
35 4 => format!("{0}{1}", one, five),
36 5 => format!("{0}", five),
37 6 => format!("{1}{0}", one, five),
38 7 => format!("{1}{0}{0}", one, five),
39 8 => format!("{1}{0}{0}{0}", one, five),
40 9 => format!("{0}{1}", one, ten),
41 _ => panic!(),
42 }
43 }
44
45 string = digit(n % 10, 'I', 'V', 'X') + &string;
46 n /= 10;
47
48 string = digit(n % 10, 'X', 'L', 'C') + &string;
49 n /= 10;
50
51 string = digit(n % 10, 'C', 'D', 'M') + &string;
52 n /= 10;
53
54 string = match n % 10 {
55 0 => String::new(),
56 1 => format!("{0}", 'M'),
57 2 => format!("{0}{0}", 'M'),
58 3 => format!("{0}{0}{0}", 'M'),
59 _ => panic!(),
60 } + &string;
61
62 Self(string)
63 }
64}