summaryrefslogtreecommitdiff
path: root/d02/src/main.rs
blob: 33c7ec012dfb22d8d1396dee14adc787a54fad16 (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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use std::fs;

fn solve_part1(lines: &Vec<&str>) -> String {
    let mut result = String::new();

    let mut num = 5;
    for line in lines {
        for c in line.chars() {
            num = match c {
                'U' => if num - 3 >  0 { num - 3 } else { num },
                'D' => if num + 3 < 10 { num + 3 } else { num },
                'L' => if num % 3 != 1 { num - 1 } else { num },
                'R' => if num % 3 != 0 { num + 1 } else { num },
                _   => num, // shouldn't happen
            }
        }
        result.push_str(&num.to_string());
    }

    result
}

fn solve_part2(lines: &Vec<&str>) -> String {
    let mut result = String::new();

    // Part 2's keypad is a bit more exotic
    let keypad = [
        [0,  0,  1,  0,  0],
        [0,  2,  3,  4,  0],
        [5,  6,  7,  8,  9],
        [0, 10, 11, 12,  0],
        [0,  0, 13,  0,  0],
    ];
    let mut pos = (2, 0); // (row, col) index

    for line in lines {
        for c in line.chars() {
            let mut new = pos;
            match c {
                'U' => new.0 = if pos.0 > 0 { pos.0 - 1 } else { pos.0 },
                'D' => new.0 = if pos.0 < 4 { pos.0 + 1 } else { pos.0 },
                'L' => new.1 = if pos.1 > 0 { pos.1 - 1 } else { pos.1 },
                'R' => new.1 = if pos.1 < 4 { pos.1 + 1 } else { pos.1 },
                _   => {}, // shouldn't happen
            };
            // Ignore this `c' if it would take us off the diamond's edge
            if keypad[new.0][new.1] != 0 {
                pos = new;
            }
        }

        // Print as hexadecimal to follow puzzle description
        result.push_str(&format!("{:X}", keypad[pos.0][pos.1]));
    }

    result
}

fn main() {
    // Read directions from input text file
    let input = fs::read_to_string("input.txt").unwrap();
    let lines = input.lines().collect();

    // Part 1 gives 74921 for me
    println!("Part 1 solution: {}", solve_part1(&lines));

    // Part 2 gives A6B35 for me
    println!("Part 2 solution: {}", solve_part2(&lines));
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn part1_example1() {
        let lines = vec!["ULL", "RRDDD", "LURDL", "UUUUD"];
        assert_eq!(solve_part1(&lines), "1985");
    }

    #[test]
    fn part2_example1() {
        let lines = vec!["ULL", "RRDDD", "LURDL", "UUUUD"];
        assert_eq!(solve_part2(&lines), "5DB3");
    }
}