Advent of code 2023/5
Ajax Direct

Answer

Part 1 :
Part 2 :
// ==================================================
// > PARSING
// ==================================================
$maps = $input->split("\n\n")->slice(1)->map(function ($map) {
    $map = $map->lines->slice(1)->map(function ($line) {
        [$ds, $ss, $rl] = $line->numbers();
        return [$ss, $ss + $rl - 1, $ds - $ss];
    })->sortBy(0)->values();

    if ($map[0][0] != 0) {
        $map = [[0, $map[0][0] - 1, 0], ...$map];
    }
    $map[] = [$map[count($map) - 1][1] + 1, INF, 0];

    return set($map);
});

// ==================================================
// > PART 1
// ==================================================
$seeds = $input->lines[0]->numbers();
foreach ($maps as $map) {
    $seeds = $seeds->map(function ($seed) use ($map) {
        $rule = $map->filter(fn ($range) => $range[0] <= $seed && $seed <= $range[1])->first();
        return $seed + ($rule[2] ?? 0);
    });
}
$solution_1 = $seeds->min();

// ==================================================
// > PART 2
// ==================================================
$ranges = $input->lines[0]->numbers()->chunk(2)->map(fn ($range) => [$range[0], $range[0] + $range[1] - 1]);

foreach ($maps as $map) {
    $nranges = set();
    foreach ($ranges as $r) foreach ($map as $m) {
        if ($r[1] < $m[0] || $r[0] > $m[1]) continue;
        $nranges[] = [
            max($r[0], $m[0]) + $m[2],
            min($r[1], $m[1]) + $m[2]
        ];
    }
    $ranges = $nranges;
}

$solution_2 = $ranges->merge()->min();