|
1 |
| -use mygrid::{direction::ORTHOGONAL, grid::Grid, point::Point}; |
| 1 | +use mygrid::{ |
| 2 | + direction::{Direction, ORTHOGONAL}, |
| 3 | + grid::Grid, |
| 4 | + point::Point, |
| 5 | +}; |
2 | 6 | use rayon::iter::ParallelIterator;
|
3 | 7 |
|
4 | 8 | advent_of_code::solution!(20);
|
@@ -44,38 +48,32 @@ fn dijkstra(grid: &Grid<char>, start: Point, end: Point) -> Grid<i64> {
|
44 | 48 | cost
|
45 | 49 | }
|
46 | 50 |
|
47 |
| -#[inline] |
48 |
| -fn diamond_iter<const DIAMOND_RADIUS: isize>( |
49 |
| - start_pos: Point, |
50 |
| -) -> impl Iterator<Item = (Point, i64)> { |
51 |
| - // this could be more efficient tbh |
52 |
| - (0..(DIAMOND_RADIUS * 2 + 1)) |
53 |
| - .into_iter() |
54 |
| - .flat_map(move |i| { |
55 |
| - let line = start_pos.line - DIAMOND_RADIUS + i; |
56 |
| - (0..(DIAMOND_RADIUS * 2 + 1)) |
57 |
| - .into_iter() |
58 |
| - .map(move |j: isize| { |
59 |
| - let col = start_pos.column - DIAMOND_RADIUS + j; |
60 |
| - let pos = Point::new(line, col); |
61 |
| - let moves = |
62 |
| - (start_pos.line - pos.line).abs() + (start_pos.column - pos.column).abs(); |
63 |
| - (pos, moves as i64) |
64 |
| - }) |
65 |
| - }) |
66 |
| - .filter(|&(_, moves)| moves <= DIAMOND_RADIUS as i64) |
67 |
| -} |
68 |
| - |
69 | 51 | fn solve<const CHEAT_MOVES: isize>(input: &str, min_gain: i64) -> Option<i64> {
|
70 | 52 | let (grid, start, end) = parse_input(input);
|
71 | 53 | let cost = dijkstra(&grid, start, end);
|
72 | 54 |
|
| 55 | + let diamond_diff = (0..(CHEAT_MOVES * 2 + 1)) |
| 56 | + .into_iter() |
| 57 | + .flat_map(move |i| { |
| 58 | + let line = -CHEAT_MOVES + i; |
| 59 | + (0..(CHEAT_MOVES * 2 + 1)).into_iter().map(move |j: isize| { |
| 60 | + let col = -CHEAT_MOVES + j; |
| 61 | + let diff = Direction::new(line, col); |
| 62 | + let moves = (diff.vertical).abs() + (diff.horizontal).abs(); |
| 63 | + (diff, moves as i64) |
| 64 | + }) |
| 65 | + }) |
| 66 | + .filter(|&(_, moves)| moves <= CHEAT_MOVES as i64) |
| 67 | + .collect::<Vec<_>>(); |
| 68 | + |
73 | 69 | let count = cost
|
74 | 70 | // makes p1 slightly slower, but p2 much faster
|
75 | 71 | .par_iter_item_and_position()
|
76 | 72 | .filter(|&(_, c)| *c != i64::MAX)
|
77 | 73 | .map(|(start_pos, &start_cost)| {
|
78 |
| - let count = diamond_iter::<CHEAT_MOVES>(start_pos) |
| 74 | + let count = diamond_diff |
| 75 | + .iter() |
| 76 | + .map(|&(diff, moves)| (start_pos + diff, moves)) |
79 | 77 | .filter(|&(pos, _)| cost.is_in_bounds(pos))
|
80 | 78 | .filter(|&(pos, _)| cost[pos] != i64::MAX)
|
81 | 79 | .filter(|&(pos, moves)| cost[pos] > start_cost + moves as i64)
|
|
0 commit comments