Skip to content

Commit d6bbc13

Browse files
committed
2nd day
1 parent 9b8ee4b commit d6bbc13

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed

data/examples/02.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
7 6 4 2 1
2+
1 2 7 8 9
3+
9 7 6 2 1
4+
1 3 2 4 5
5+
8 6 4 4 1
6+
1 3 6 7 9

src/bin/02.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
advent_of_code::solution!(2);
2+
3+
use advent_of_code::maneatingape::parse::*;
4+
5+
fn parse_data(input: &str) -> Vec<Vec<i32>> {
6+
input
7+
.lines()
8+
.map(|line| line.iter_signed().collect())
9+
.collect()
10+
}
11+
12+
fn is_valid_pair(x: i32, y: i32, inc: bool) -> bool {
13+
let diff = if inc { y - x } else { x - y };
14+
15+
(1..=3).contains(&diff)
16+
}
17+
18+
fn find_broken_position<'a, I>(mut iter: I) -> Option<usize>
19+
where
20+
I: Iterator<Item = &'a i32>,
21+
{
22+
let first = *iter.next().unwrap();
23+
let second = *iter.next().unwrap();
24+
let inc = second > first;
25+
26+
if !is_valid_pair(first, second, inc) {
27+
return Some(0);
28+
}
29+
30+
let mut x = second;
31+
let mut i = 1;
32+
for &next_x in iter {
33+
if !is_valid_pair(x, next_x, inc) {
34+
return Some(i);
35+
}
36+
37+
x = next_x;
38+
i += 1;
39+
}
40+
41+
None
42+
}
43+
44+
fn find_broken_position_with_problem_dampener(line: &[i32]) -> Option<usize> {
45+
match find_broken_position(line.iter()) {
46+
Some(pos) => {
47+
let left = &line[..pos];
48+
let right = &line[pos + 1..];
49+
find_broken_position(left.iter().chain(right.iter()))?;
50+
51+
if pos > 0 {
52+
let left = &line[..pos - 1];
53+
let right = &line[pos..];
54+
find_broken_position(left.iter().chain(right.iter()))?;
55+
}
56+
57+
if pos < line.len() {
58+
let left = &line[..pos + 1];
59+
let right = &line[pos + 2..];
60+
find_broken_position(left.iter().chain(right.iter()))?;
61+
}
62+
63+
Some(pos)
64+
}
65+
None => None,
66+
}
67+
}
68+
69+
pub fn part_one(input: &str) -> Option<usize> {
70+
let data = parse_data(input);
71+
72+
let result = data
73+
.into_iter()
74+
.map(|line| find_broken_position(line.iter()))
75+
.filter(|x| x.is_none())
76+
.count();
77+
78+
Some(result)
79+
}
80+
81+
pub fn part_two(input: &str) -> Option<usize> {
82+
let data = parse_data(input);
83+
84+
let result = data
85+
.into_iter()
86+
.map(|line| find_broken_position_with_problem_dampener(&line))
87+
.filter(|x| x.is_none())
88+
.count();
89+
90+
Some(result)
91+
}
92+
93+
#[cfg(test)]
94+
mod tests {
95+
use super::*;
96+
97+
#[test]
98+
fn test_part_one() {
99+
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
100+
assert_eq!(result, Some(2));
101+
}
102+
103+
#[test]
104+
fn test_part_two() {
105+
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
106+
assert_eq!(result, Some(4));
107+
}
108+
}

0 commit comments

Comments
 (0)