Advent of code 2022/5
Ajax Direct

Answer

Part 1 :
Part 2 :
function get_solution($crates, $moves, $reverse_order = false)
{
    // Create a more usable data structure
    $crates = grid($crates, 4, "\n")->columns()
        ->callEach()->reverse()
        ->callEach(2)->trim(" []")
        ->callEach()->filter();

    // Apply moves
    foreach ($moves->lines as $move) {
        preg_match_all("/([0-9]+)/", $move, $numbers);
        [$count, $from, $to] = $numbers[0];

        $chunk_to_move   = $crates[$from - 1]->splice(-$count);
        $crates[$to - 1] = $crates[$to - 1]->merge($reverse_order ? $chunk_to_move->reverse() : $chunk_to_move);
    }

    // Compile solution
    return $crates->callEach()->last()->join();
}

// ==================================================
// > SOLUTION
// ==================================================
[$crates, $moves] = $input->split("\n\n");
$solution_1 = get_solution($crates, $moves, true);
$solution_2 = get_solution($crates, $moves, false);