$w = strlen($input->lines[0]);
$h = $input->lines->count();
// Group coordonates
$groups = set($input->replace("\n", "")->matchAll("/[a-zA-Z0-9]/", true)[0])
->map(fn ($p) => [$p[0], [$p[1] % $w, intdiv($p[1], $w)]])
->groupBy(0, fn ($p) => $p[1]);
// ==================================================
// > SOLVE
// ==================================================
function solve($groups, $w, $h, $part_2 = false) {
$map = [];
foreach ($groups as $l=>$g) {
for ($i = 0; $i < count($g) - 1; $i++) {
for ($j = $i+1; $j < count($g); $j++) {
[$ix, $iy] = $g[$i];
[$jx, $jy] = $g[$j];
// Find vectors from $i and $j
[$nx, $ny] = [abs($ix - $jx), abs($iy - $jy)];
$di = [$ix < $jx ? -$nx : $nx, -$ny];
$dj = [$ix < $jx ? $nx : -$nx, $ny];
// Multiply vector (0, ...) until OOB for $i and $j; or only once for part 1
foreach ([[$di, $g[$i]], [$dj, $g[$j]]] as [[$dx, $dy], [$px, $py]]) {
for ($mult = $part_2 ? 0 : 1;; $mult++) {
[$x, $y] = [$px + ($dx * $mult), $py + ($dy * $mult)];
if (0 <= $x && $x < $w && 0 <= $y && $y < $h) {
$map["$x;$y"] = true;
} else {
break;
}
if (!$part_2) break;
}
}
}
}
}
return count($map);
}
$solution_1 = solve($groups, $w, $h, false);
$solution_2 = solve($groups, $w, $h, true);