function find_mirror($pattern, $diff_allowed, $exclude, $mult) {
for ($i = 1; $i < count($pattern); $i++) {
$diff_found = 0;
for ($j = 1; $j <= min($i, count($pattern) - $i); $j++) {
if (!$diff_allowed && $pattern[$i - $j] != $pattern[$i + $j - 1]) continue 2;
if ($diff_allowed) {
$diff_found += strlen(
str_replace("0", "", decbin(bindec($pattern[$i - $j]) ^ bindec($pattern[$i + $j - 1])))
);
if ($diff_found > $diff_allowed) continue 2;
}
}
if ($i * $mult != $exclude) return $i * $mult;
}
return null;
}
function solve($pattern, $diff_allowed, $exclude) {
// Try horizontal
$h = explode("\n", $pattern);
if (($m = find_mirror($h, $diff_allowed, $exclude, 100)) != null) return $m;
// Try vertical
$v = array_map("join", array_map(null, ...$pattern->lines->map("str_split")));
return find_mirror($v, $diff_allowed, $exclude, 1);
}
// ==================================================
// > SOLUTION
// ==================================================
[$solution_1, $solution_2] = $input->split("\n\n")->reduce(function ($carry, $p) {
$p = $p->replace([".", "#"], ["0", "1"]);
$p1 = solve($p, 0, false);
$p2 = solve($p, 1, $p1);
return [$carry[0] + $p1, $carry[1] + $p2];
}, [0, 0]);