Skip to main content

ainu_utils/numbers/
expr.rs

1pub 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}