summaryrefslogtreecommitdiff
path: root/d07/src/main.rs
blob: ef53b6e002b632652b2acdc48657e68619f1e989 (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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use std::fs;

fn solve_part1(lines: &Vec<&str>) -> usize {
    let mut total_tls = 0;

    for line in lines {
        let chars: Vec<char> = line.chars().collect();

        let mut has_tls = false;
        let mut in_brackets = false;
        for i in 0..chars.len() - 3 {
            // Are we entering/leaving a "hypernet sequence"?
            if chars[i] == '[' {
                in_brackets = true;
            } else if chars[i] == ']' {
                in_brackets = false;
            }

            // Check for ABBA pattern to know if address has TLS
            let ch0 = chars[i];
            let ch1 = chars[i + 1];
            if ch0 != ch1 && chars[i + 3] == ch0 && chars[i + 2] == ch1 {
                if !in_brackets {
                    has_tls = true;
                } else {
                    // Reject if an ABBA occurs in brackets
                    has_tls = false;
                    break;
                }
            }
        }

        if has_tls {
            total_tls += 1;
        }
    }

    total_tls
}

fn solve_part2(lines: &Vec<&str>) -> usize {
    let mut total_ssl = 0;

    for line in lines {
        let chars: Vec<char> = line.chars().collect();

        let mut has_ssl = false;
        let mut in_brack_aba = false;
        'outer: for i in 0..chars.len() - 2 {
            // Are we entering/leaving brackets on our ABA search?
            if chars[i] == '[' {
                in_brack_aba = true;
            } else if chars[i] == ']' {
                in_brack_aba = false;
            }

            // Check for ABA pattern
            let ch0 = chars[i];
            let ch1 = chars[i + 1];
            if !in_brack_aba && ch0 != ch1 && chars[i + 2] == ch0 {
                // If ABA was found, check entire address for BAB
                let mut in_brack_bab = false;
                for j in 0..chars.len() - 2 {
                    // Are we entering/leaving brackets on our BAB search?
                    if chars[j] == '[' {
                        in_brack_bab = true;
                    } else if chars[j] == ']' {
                        in_brack_bab = false;
                    }

                    if chars[j] == ch1 && chars[j + 1] == ch0 && chars[j + 2] == ch1 {
                        // BAB must be in square brackets
                        if in_brack_bab {
                            has_ssl = true;
                            break 'outer;
                        }
                    }
                }
            }
        }

        if has_ssl {
            total_ssl += 1;
        }
    }

    total_ssl
}

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

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

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

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

    #[test]
    fn part1_example1() {
        let lines = vec!["abba[mnop]qrst"];
        assert_eq!(solve_part1(&lines), 1);
    }

    #[test]
    fn part1_example2() {
        let lines = vec!["abcd[bddb]xyyx"];
        assert_eq!(solve_part1(&lines), 0);
    }

    #[test]
    fn part1_example3() {
        let lines = vec!["aaaa[qwer]tyui"];
        assert_eq!(solve_part1(&lines), 0);
    }

    #[test]
    fn part1_example4() {
        let lines = vec!["ioxxoj[asdfgh]zxcvbn"];
        assert_eq!(solve_part1(&lines), 1);
    }

    #[test]
    fn part2_example1() {
        let lines = vec!["aba[bab]xyz"];
        assert_eq!(solve_part2(&lines), 1);
    }

    #[test]
    fn part2_example2() {
        let lines = vec!["xyx[xyx]xyx"];
        assert_eq!(solve_part2(&lines), 0);
    }

    #[test]
    fn part2_example3() {
        let lines = vec!["aaa[kek]eke"];
        assert_eq!(solve_part2(&lines), 1);
    }

    #[test]
    fn part2_example4() {
        let lines = vec!["zazbz[bzb]cdb"];
        assert_eq!(solve_part2(&lines), 1);
    }
}