pathfinding 4.15.0

Pathfinding, flow, and graph algorithms
Documentation
use pathfinding::{directed::dijkstra::dijkstra, matrix::Matrix};

static TEST_INPUT: &str = "
2413432311323
3215453535623
3255245654254
3446585845452
4546657867536
1438598798454
4457876987766
3637877979653
4654967986887
4564679986453
1224686865563
2546548887735
4322674655533
";

static TEST_INPUT_2: &str = "
111111111111
999999999991
999999999991
999999999991
999999999991
";

fn part1(input: &str) -> u32 {
    part(input, 1, 3)
}

fn part2(input: &str) -> u32 {
    part(input, 4, 10)
}

fn part(input: &str, min_move: usize, max_move: usize) -> u32 {
    let grid = Matrix::from_rows(
        input
            .trim()
            .lines()
            .map(|l| l.chars().filter_map(|c| c.to_digit(10))),
    )
    .unwrap();
    dijkstra(
        &((0, 0), (0, 0), 0),
        |&(pos, (dr, dc), l)| {
            let mut next = Vec::with_capacity(3);
            let mut e = |dir, l| {
                next.extend(
                    &grid
                        .move_in_direction(pos, dir)
                        .map(|t| ((t, dir, l), grid[t])),
                );
            };
            if l < max_move {
                e((dr, dc), l + 1);
            }
            if l >= min_move {
                e((-dc, -dr), 1);
                e((dc, dr), 1);
            } else if l == 0 {
                e((1, 0), 1);
                e((0, 1), 1);
            }
            next
        },
        |&(pos, _, l)| pos == (grid.rows - 1, grid.columns - 1) && l >= min_move,
    )
    .unwrap()
    .1
}

#[test]
fn aoc_2023_17() {
    assert_eq!(102, part1(TEST_INPUT));
    assert_eq!(94, part2(TEST_INPUT));
    assert_eq!(71, part2(TEST_INPUT_2));
}