Skip to content

Commit 7c44ca0

Browse files
committed
feat(20/2024): solve first part
1 parent d5b9da2 commit 7c44ca0

File tree

2 files changed

+123
-6
lines changed

2 files changed

+123
-6
lines changed

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
| [Day 17: Chronospatial Computer](src/solutions/year2024/day17.rs) | - | - | - |
3131
| [Day 18: RAM Run](src/solutions/year2024/day18.rs) | ⭐⭐ | 2.487 | 204.885 |
3232
| [Day 19: Linen Layout](src/solutions/year2024/day19.rs) | ⭐⭐ | 2.923 | 22.751 |
33+
| [Day 20: Race Condition](src/solutions/year2024/day20.rs) || 7.355 | - |
3334

3435
# 2023
3536

src/solutions/year2024/day20.rs

Lines changed: 122 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,142 @@
11
use crate::solutions::Solution;
2+
use crate::utils::grid::Grid;
3+
use crate::utils::point::Point;
4+
use itertools::Itertools;
5+
use std::collections::HashMap;
6+
use std::ops::RangeBounds;
27

38
pub struct Day20;
49

510
impl Solution for Day20 {
6-
fn part_one(&self, _input: &str) -> String {
7-
String::from('0')
11+
fn part_one(&self, input: &str) -> String {
12+
self.cheats_in_range(input, 100..).to_string()
813
}
914

1015
fn part_two(&self, _input: &str) -> String {
1116
String::from('0')
1217
}
1318
}
1419

20+
impl Day20 {
21+
fn cheats_in_range<R>(&self, input: &str, range: R) -> usize
22+
where
23+
R: RangeBounds<usize>,
24+
{
25+
let grid: Grid<char> = Grid::from(input);
26+
let start = grid.get_first_position(&'S').unwrap();
27+
let end = grid.get_first_position(&'E').unwrap();
28+
29+
let path_without_cheats = self.get_path(start, end, &grid);
30+
31+
path_without_cheats
32+
.path()
33+
.iter()
34+
.flat_map(|(current_time, current)| {
35+
current
36+
.adjacent_vectors()
37+
.iter()
38+
.filter(|v| grid.is_for_point(&v.position(), '#'))
39+
.map(|p| p.forward())
40+
.filter(|v| {
41+
grid.get_for_point(&v.position())
42+
.is_some_and(|element| ['.', 'E'].contains(element))
43+
})
44+
.filter_map(|v| {
45+
if let Some(time_after_cheat) =
46+
path_without_cheats.picoseconds_from(v.position())
47+
{
48+
if time_after_cheat > *current_time {
49+
return Some(time_after_cheat - current_time - 2);
50+
// why -2
51+
}
52+
}
53+
54+
None
55+
})
56+
.collect_vec()
57+
})
58+
.filter(|time| range.contains(time))
59+
.count()
60+
}
61+
62+
fn get_path(&self, start: Point, end: Point, grid: &Grid<char>) -> PathWithoutCheats {
63+
let mut current = start;
64+
let mut index: usize = 0;
65+
let mut path: HashMap<Point, usize> = HashMap::new();
66+
67+
while current != end {
68+
let tmp = current.adjacent();
69+
let next = tmp
70+
.iter()
71+
.find(|p| {
72+
!path.contains_key(p)
73+
&& grid
74+
.get_for_point(p)
75+
.is_some_and(|element| ['.', 'E'].contains(element))
76+
})
77+
.unwrap();
78+
79+
index += 1;
80+
path.insert(current, index);
81+
current = *next;
82+
}
83+
84+
index += 1;
85+
path.insert(current, index);
86+
87+
PathWithoutCheats { path }
88+
}
89+
}
90+
91+
struct PathWithoutCheats {
92+
path: HashMap<Point, usize>,
93+
}
94+
95+
impl PathWithoutCheats {
96+
fn picoseconds_from(&self, point: Point) -> Option<usize> {
97+
self.path.get(&point).copied()
98+
}
99+
100+
fn path(&self) -> Vec<(usize, Point)> {
101+
self.path
102+
.iter()
103+
.map(|(point, time)| (*time, *point))
104+
.collect()
105+
}
106+
}
107+
15108
#[cfg(test)]
16109
mod tests {
17110
use crate::solutions::year2024::day20::Day20;
18-
use crate::solutions::Solution;
19111

20-
const EXAMPLE: &str = r#""#;
112+
const EXAMPLE: &str = r#"###############
113+
#...#...#.....#
114+
#.#.#.#.#.###.#
115+
#S#...#.#.#...#
116+
#######.#.#.###
117+
#######.#.#...#
118+
#######.#.###.#
119+
###..E#...#...#
120+
###.#######.###
121+
#...###...#...#
122+
#.#####.#.###.#
123+
#.#...#.#.#...#
124+
#.#.#.#.#.#.###
125+
#...#...#...###
126+
###############"#;
21127

22128
#[test]
23-
fn part_one_example_test() {
24-
assert_eq!("0", Day20.part_one(EXAMPLE));
129+
fn test_solve() {
130+
assert_eq!(14, Day20.cheats_in_range(EXAMPLE, 2..=2));
131+
assert_eq!(14, Day20.cheats_in_range(EXAMPLE, 4..=4));
132+
assert_eq!(2, Day20.cheats_in_range(EXAMPLE, 6..=6));
133+
assert_eq!(4, Day20.cheats_in_range(EXAMPLE, 8..=8));
134+
assert_eq!(2, Day20.cheats_in_range(EXAMPLE, 10..=10));
135+
assert_eq!(3, Day20.cheats_in_range(EXAMPLE, 12..=12));
136+
assert_eq!(1, Day20.cheats_in_range(EXAMPLE, 20..=20));
137+
assert_eq!(1, Day20.cheats_in_range(EXAMPLE, 36..=36));
138+
assert_eq!(1, Day20.cheats_in_range(EXAMPLE, 38..=38));
139+
assert_eq!(1, Day20.cheats_in_range(EXAMPLE, 40..=40));
140+
assert_eq!(1, Day20.cheats_in_range(EXAMPLE, 64..=64));
25141
}
26142
}

0 commit comments

Comments
 (0)