summaryrefslogtreecommitdiff
path: root/src/day25.rs
blob: af5f15ec9d28a82d58073527621dd8db7c9859f1 (plain)
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
fn from_snafu(s: &str) -> i64 {
    // This is the easy bit... 
    let mut i: i64 = 0;
    let mut pow: i64 = 1;
    for ch in s.chars().rev() {
        match ch {
            '2' => i += 2 * pow,
            '1' => i += 1 * pow,
            '0' => {}, // additive identity!
            '-' => i += -1 * pow,
            '=' => i += -2 * pow,
            _ => panic!("unexpected input {}", ch)
        }
        pow *= 5;
    }
    i
}

fn to_snafu(mut i: i64) -> String {
    // how to do this :thinking: add two, mod 5,take away 2? // nope
    let mut res = Vec::<char>::new();
    while i != 0 {
        let d = ((i + 2) % 5) - 2;
        let ch = match d {
            2 => '2',
            1 => '1',
            0 => '0',
            -1 => '-',
            -2 => '=',
            _ => panic!("unexpected digit {}", d)
        };
        res.push(ch);
        i = (i + 2) / 5;
    }
    res.reverse();
    res.into_iter().collect::<String>()    
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_from_snafu() {
        let cases = vec![
        ("1=-0-2",     "1747"),
        ( "12111",      "906"),
        (  "2=0=",      "198"),
        (    "21",       "11"), // works
        (  "2=01",      "201"), // 201,1 > 40,0 > 8,= > 1,1
        (   "111",       "31"), // works
        ( "20012",     "1257"), //works
        (   "112",       "32"), // works
        ( "1=-1=",      "353"), // broke
        (  "1-12",      "107"),
        (    "12",        "7"),
        (    "1=",        "3"),
        (   "122",       "37"),
        ];
        for (snafu, decimal) in cases {
            let x = from_snafu(snafu);
            assert_eq!(x.to_string().as_str(), decimal);
            assert_eq!(to_snafu(x), snafu);
        }
    }
}

pub fn run(input: String) {
    let s: i64 = input.lines()
        .map(from_snafu)
        .sum();
    println!("Day 25: {}", to_snafu(s));
}