|
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