summaryrefslogtreecommitdiff
path: root/src/bin/day13.rs
blob: 6f6ac97ae3beefe78d99ac7be7a29d1c84a3152b (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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
static DAY: u8 = 13;

fn main() {
    let input = advent::read_lines(DAY);
    println!("{DAY}a: {}", summarize_patterns(&input));
    println!("{DAY}b: {}", 0);
}

#[derive(Clone,Copy)]
enum Reflection {
    Vertical(usize),
    Horizontal(usize),
}

impl Reflection {
    fn summary(&self) -> usize {
        match *self {
            Reflection::Vertical(column) => column,
            Reflection::Horizontal(row) => row * 100,
        }
    }
}

struct Map {
    pattern: Vec<Vec<bool>>,
}

impl Map {
    fn new(input: &[String]) -> Map {
        let mut pattern = Vec::new();
        for line in input {
            let row = line.chars()
                          .map(|c| c == '#')
                          .collect();
            pattern.push(row);
        }

        Map { pattern }
    }

    fn is_horizontal_reflection(&self, y: usize) -> bool {
        for pair in (y+1 .. self.pattern.len()).zip((0 ..= y).rev()) {
            if self.pattern[pair.0] != self.pattern[pair.1] {
                return false;
            }
        }
        true
    }

    fn is_vertical_reflection(&self, x: usize) -> bool {
        for pair in (x+1 .. self.pattern[0].len()).zip((0 ..= x).rev()) {
            for y in 0 .. self.pattern.len() {
                if self.pattern[y][pair.0] != self.pattern[y][pair.1] {
                    return false;
                }
            }
        }
        true
    }

    fn find_reflection(&self) -> Reflection {
        for y in 0 .. self.pattern.len() - 1 {
            if self.is_horizontal_reflection(y) {
                return Reflection::Horizontal(y+1)
            }
        }
        for x in 0 .. self.pattern[0].len() - 1 {
            if self.is_vertical_reflection(x) {
                return Reflection::Vertical(x+1)
            }
        }
        panic!("no reflection found");
    }
}

fn summarize_patterns(input: &[String]) -> usize {
    input.split(|line| line.is_empty())
         .map(Map::new)
         .map(|m| m.find_reflection().summary())
         .sum()
}

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

    #[test]
    fn test() {
        let input = [
            "#.##..##.",
            "..#.##.#.",
            "##......#",
            "##......#",
            "..#.##.#.",
            "..##..##.",
            "#.#.##.#.",
            "",
            "#...##..#",
            "#....#..#",
            "..##..###",
            "#####.##.",
            "#####.##.",
            "..##..###",
            "#....#..#",
        ].iter().map(|&x| String::from(x)).collect::<Vec<_>>();
        assert_eq!(summarize_patterns(&input), 405);
    }
}