Skip to content

Commit 9733d8f

Browse files
committed
20th day
1 parent 9761aae commit 9733d8f

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

data/examples/20.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
###############
2+
#...#...#.....#
3+
#.#.#.#.#.###.#
4+
#S#...#.#.#...#
5+
#######.#.#.###
6+
#######.#.#...#
7+
#######.#.###.#
8+
###..E#...#...#
9+
###.#######.###
10+
#...###...#...#
11+
#.#####.#.###.#
12+
#.#...#.#.#...#
13+
#.#.#.#.#.#.###
14+
#...#...#...###
15+
###############
16+
17+
EXAMPLE: LIMIT=50

src/bin/20.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
advent_of_code::solution!(20);
2+
3+
use advent_of_code::maneatingape::grid::*;
4+
use advent_of_code::maneatingape::parse::ParseOps;
5+
use advent_of_code::maneatingape::point::*;
6+
7+
fn parse_data(input: &str) -> (Grid<u8>, usize) {
8+
const DEFAULT_LIMIT: usize = 100;
9+
10+
let default_right = format!("{DEFAULT_LIMIT}",);
11+
let (left, right) = input.split_once("\n\n").unwrap_or((input, &default_right));
12+
13+
let grid = Grid::parse(left);
14+
let limit = right.unsigned();
15+
16+
(grid, limit)
17+
}
18+
19+
fn find_path(grid: Grid<u8>, start_position: Point) -> Vec<Point> {
20+
let mut result = vec![];
21+
let mut next_position = Some(start_position);
22+
23+
while let Some(position) = next_position {
24+
result.push(position);
25+
26+
next_position = ORTHOGONAL.into_iter().map(|d| position + d).find(|&p| {
27+
(result.len() < 2 || result[result.len() - 2] != p)
28+
&& grid.contains(p)
29+
&& grid[p] != b'#'
30+
});
31+
}
32+
33+
result
34+
}
35+
36+
fn part_x<const N: usize>(grid: Grid<u8>, limit: usize) -> u32 {
37+
let start_location = grid.find(b'S').unwrap();
38+
39+
let path = find_path(grid, start_location);
40+
let normal_cost = path.len();
41+
42+
let mut result = 0;
43+
44+
for (i1, &p1) in path.iter().enumerate() {
45+
for (i2, &p2) in path.iter().skip(i1 + limit).rev().enumerate() {
46+
let point_distance = p1.manhattan(p2) as usize;
47+
if point_distance <= N {
48+
let cheated_cost = i1 + point_distance + i2;
49+
if normal_cost - cheated_cost >= limit {
50+
result += 1;
51+
}
52+
}
53+
}
54+
}
55+
56+
result
57+
}
58+
59+
pub fn part_one(input: &str) -> Option<u32> {
60+
let (grid, limit) = parse_data(input);
61+
62+
let result = part_x::<2>(grid, limit);
63+
64+
Some(result)
65+
}
66+
67+
pub fn part_two(input: &str) -> Option<u32> {
68+
let (grid, limit) = parse_data(input);
69+
70+
let result = part_x::<20>(grid, limit);
71+
72+
Some(result)
73+
}
74+
75+
#[cfg(test)]
76+
mod tests {
77+
use super::*;
78+
79+
#[test]
80+
fn test_part_one() {
81+
let input = advent_of_code::template::read_file("examples", DAY);
82+
let result = part_one(&input);
83+
assert_eq!(result, Some(1));
84+
}
85+
86+
#[test]
87+
fn test_part_two() {
88+
let input = advent_of_code::template::read_file("examples", DAY);
89+
let result = part_two(&input);
90+
assert_eq!(result, Some(285));
91+
}
92+
}

0 commit comments

Comments
 (0)