function solve($grid, $time) {
$width = count($grid[0]);
$height = count($grid);
$track = [];
for ($t = 1; $t <= $time; $t++) {
$next = [];
foreach ($grid as $y=>$row) foreach ($row as $x=>$c) {
$nc = ["|" => 0, "." => 0, "#" => 0];
foreach (neighbors([$x, $y], true, 0, $width - 1, 0, $height - 1) as $n) {
$nc[$grid[$n[1]][$n[0]]]++;
}
$next[$y][$x] = match($grid[$y][$x]) {
"." => $nc["|"] >= 3 ? "|" : ".",
"|" => $nc["#"] >= 3 ? "#" : "|",
"#" => $nc["#"] >= 1 && $nc["|"] >= 1 ? "#" : ".",
};
}
$grid = $next;
$cells = set($grid)->merge();
$track[$t] = $cells->keep("#")->count() * $cells->keep("|")->count();
}
return $track;
}
// ==================================================
// > PART 1
// ==================================================
$grid = array_map("str_split", explode("\n", $input->string));
$solution_1 = solve($grid, 10)[10];
// ==================================================
// > PART 2
// ==================================================
$t = $tx = 500;
$track = solve($grid, $t); // Track 500 minutes
while ($track[--$tx] != $track[$t]); // Find repeated pattern starting from the end
$s = array_search($track[$t], $track); // Find start of pattern
$l = $t - $tx; // Length of pattern
$p = (1_000_000_000 - $s) % $l; // Place in pattern
$solution_2 = $track[$s + $p]; // Value at that moment