ainu_utils/numbers/
expr.rs1pub enum Expr {
2 Int(i32),
3 Add { lhs: Box<Expr>, rhs: Box<Expr> },
4 Sub { lhs: Box<Expr>, rhs: Box<Expr> },
5 Mul { lhs: Box<Expr>, rhs: Box<Expr> },
6}
7
8impl ToString for Expr {
9 fn to_string(&self) -> String {
10 match self {
11 Expr::Int(i) => match i {
12 1 => "sine".to_string(),
13 2 => "tu".to_string(),
14 3 => "re".to_string(),
15 4 => "ine".to_string(),
16 5 => "asikne".to_string(),
17 6 => "iwan".to_string(),
18 7 => "arwan".to_string(),
19 8 => "tupesan".to_string(),
20 9 => "sinepesan".to_string(),
21 10 => "wan".to_string(),
22 20 => "hotne".to_string(),
23 _ => panic!("Invalid integer for Ainu number: {}", i),
24 },
25 Expr::Add { lhs, rhs } => format!("{} ikasma {}", lhs.to_string(), rhs.to_string()),
26 Expr::Sub { lhs, rhs } => format!("{} e{}", rhs.to_string(), lhs.to_string()),
27 Expr::Mul { lhs, rhs } => format!("{}{}", lhs.to_string(), rhs.to_string()),
28 }
29 }
30}
31
32pub fn parse(input: i32) -> Result<Expr, String> {
33 if input < 0 || 100 < input {
34 return Err("Input must be between 0 and 100".to_string());
35 }
36
37 if input <= 10 || input == 20 {
38 return Ok(Expr::Int(input));
39 }
40
41 if input % 20 == 0 {
42 return Ok(Expr::Mul {
43 lhs: Box::new(Expr::Int(input / 20)),
44 rhs: Box::new(Expr::Int(20)),
45 });
46 }
47
48 if input % 20 == 10 {
49 return Ok(Expr::Sub {
50 lhs: Box::new(parse(input + 10)?),
51 rhs: Box::new(Expr::Int(10)),
52 });
53 }
54
55 let ones = input % 10;
56 let tens = input - ones;
57
58 return Ok(Expr::Add {
59 lhs: Box::new(parse(ones)?),
60 rhs: Box::new(parse(tens)?),
61 });
62}