function solve($expand_4d = false) {
global $input;
$cube = [[array_map("str_split", explode("\n", (string) $input))]];
// Range of each dimension
[$fw, $tw] = [0, 0];
[$fz, $tz] = [0, 0];
[$fy, $ty] = [0, count($cube[0][0]) - 1];
[$fx, $tx] = [0, count($cube[0][0][0]) - 1];
$ncube = $cube;
for ($i = 0; $i < 6; $i++) {
// Expand the cube
if ($expand_4d) { $fw--; $tw++; }
$fz--; $tz++; $fy--; $ty++; $fx--; $tx++;
// Consider each cell
for ($w = $fw; $w <= $tw; $w++)
for ($z = $fz; $z <= $tz; $z++)
for ($y = $fy; $y <= $ty; $y++)
for ($x = $fx; $x <= $tx; $x++) {
// Count neighbors from -1 to +1 in each dimension
$active_neighbors = 0;
for ($nw = $w - 1; $nw <= $w + 1; $nw++)
for ($nz = $z - 1; $nz <= $z + 1; $nz++)
for ($ny = $y - 1; $ny <= $y + 1; $ny++)
for ($nx = $x - 1; $nx <= $x + 1; $nx++) {
if (($nw == $w && $nz == $z && $ny == $y && $nx == $x)) continue;
if (($cube[$nw][$nz][$ny][$nx] ?? false) == "#") $active_neighbors++;
}
// Update cell acording to number of active neighbors
if (($cube[$w][$z][$y][$x] ?? ".") == "#") {
$ncube[$w][$z][$y][$x] = $active_neighbors == 2 || $active_neighbors == 3 ? "#" : ".";
} else {
$ncube[$w][$z][$y][$x] = $active_neighbors == 3 ? "#" : ".";
}
}
$cube = $ncube;
}
// Merge everything, count active cells
return set(array_merge(...array_merge(...array_merge(...$cube))))->remove(".")->count();
}
$solution_1 = solve();
$solution_2 = solve(true);