function reduce($num) {
// 1 - Explode
preg_match_all("/\[[^\]\[]+\]/", $num, $matches, PREG_OFFSET_CAPTURE);
foreach ($matches[0]??[] as [$match, $offset]) {
$deep = 0;
foreach (str_split(substr($num, 0, $offset)) as $c)
$deep += $c == "[" ? 1 : ($c == "]" ? -1 : 0);
if ($deep < 4) continue;
$num = substr_replace($num, "0", $offset, strlen($match));
[$a, $b] = explode(",", trim($match, "[]"));
if (preg_match_all("/(\d+)\D*$/", substr($num, 0, $offset), $before, PREG_OFFSET_CAPTURE)) {
$sum = int($before[1][0][0]) + $a;
$num = substr_replace($num, $sum, $before[1][0][1], strlen($before[1][0][0]));
$offset += strlen($sum) - 1;
}
if (preg_match_all("/^\D*(\d+)/", substr($num, $offset + 1), $after, PREG_OFFSET_CAPTURE)) {
$sum = int($after[1][0][0]) + $b;
$num = substr_replace($num, $sum, $offset + 1 + $after[1][0][1], strlen($after[1][0][0]));
}
return reduce($num);
}
// 2 - Split
preg_match("/[0-9]{2}/", $num, $matches, PREG_OFFSET_CAPTURE);
if ($matches) {
$rep = "[" . floor(int($matches[0][0]) / 2) . "," . ceil(int($matches[0][0]) / 2) . "]";
$num = substr_replace($num, $rep, $matches[0][1], 2);
return reduce($num);
}
return $num;
}
function magnitude($sum) {
while (preg_match("/\[(\d+),(\d+)\]/", $sum, $match)) {
$sum = str_replace($match[0], $match[1] * 3 + $match[2] * 2, $sum);
}
return int($sum);
}
// ==================================================
// > PART 1
// ==================================================
$sum = false;
foreach ($input->lines as $line) {
if (!$sum) $sum = $line;
else $sum = reduce("[$sum,$line]");
}
$solution_1 = magnitude($sum);
// ==================================================
// > PART 2
// ==================================================
$solution_2 = 0;
$lines = $input->lines;
// Only consider the 10 largest numbers
$m = $lines->mapAssoc(fn ($k, $v) => [(string) $v => magnitude($v)]);
$lines = $m->sort()->reverse()->keys()->slice(0, 10);
for ($a = 0; $a < count($lines); $a++) {
for ($b = 0; $b < count($lines); $b++) {
if ($a == $b) continue;
$la = $lines[$a]; $lb = $lines[$b];
$solution_2 = max($solution_2, magnitude(reduce("[$la,$lb]")));
$solution_2 = max($solution_2, magnitude(reduce("[$lb,$la]")));
}
}