Advent of code 2023/3
Ajax Direct

Answer 7ms

Part 1 : 531932 Part 2 : 73646890
// ==================================================
// > PARSE : Find the positions of all symbols, digits and numbers
// ==================================================
$symbols = $digits = $numbers = [];

foreach ($input->lines as $y=>$line) {

    foreach (str_split($input->lines[$y]) as $x=>$c) {

        if ($c == ".") continue;

        if (!is_numeric($c)) {
            $symbols[$y][$x] = $c;
            continue;
        }

        if ($x && is_numeric($line[$x - 1])) {
            $digits[count($digits) - 1] .= $c;
        } else {
            $digits[] = $c;
        }

        $numbers[$y][$x] = count($digits) - 1;
    }
}

// ==================================================
// > SOLVE
// ==================================================
$solution_1 = $solution_2 = 0;

foreach ($symbols as $y=>$row) {
    foreach ($row as $x=>$s) {

        $neighbors = set();
        foreach (neighbors([$x, $y], true) as [$nx, $ny]) {
            if (isset($numbers[$ny][$nx])) $neighbors[] = $numbers[$ny][$nx];
        }
        $neighbors = $neighbors->unique()->map(fn ($i) => $digits[$i]);

        $solution_1 += $neighbors->sum();
        if ($s == "*" && $neighbors->count() == 2) $solution_2 += $neighbors->multiply();
    }
}