Advent of code 2022/12
Ajax Direct

Answer 223ms

Part 1 : 534 Part 2 : 525
$grid = grid($input);

// Save positions of start and end
[$start, $end] = [$grid->search("S"), $grid->search("E")];

// Convert letters to height value
$grid = $grid->map(fn ($cell) => $cell == "S" ? 1 : ($cell == "E" ? 26 : ord($cell) - 96));

// Generate the list of nodes
$nodes = $grid->reduce(function ($nodes, $cell, $xy) use ($grid) {
    $xy = xy($xy);
    $nodes[(string) $xy] = $xy->getNeighbors()->filter(
        // Keep only neighbors with a height difference of 1 or less
        fn ($neighbor) => ($grid->get($neighbor) ?: INF) - $cell <= 1
    )->mapAssoc(fn ($dir, $xy) => [(string) xy($xy) => 1]);
    return $nodes;
}, set());



// ==================================================
// > PART 1
// ==================================================
$solution_1 = (new Graph($nodes))->explore((string) xy($start), (string) xy($end))[1];

// ==================================================
// > PART 2
// ==================================================
$starts = $grid->cells()->keep(1)->keys();
$nodes["S"] = $starts->mapAssoc(fn ($i, $xy) => [$xy => 0]);
$solution_2 = (new Graph($nodes))->setQueue("LIFO")->explore("S", (string) xy($end))[1];