Advent of code 2021/20
Ajax Direct

Answer

Part 1 :
Part 2 :
[$algo, $grid] = $input->split("\n\n");
$algo = (string) $algo->replace(["#", "."], [1, 0]);
$grid = (array) $grid->replace(["#", "."], [1, 0])->split("\n")->map(fn ($r) => (array) $r->chars());
[$w, $h] = [count($grid[0]), count($grid)];

for ($i = 1; $i <= 50; $i++) {
    $oob = $i % 2 || !$algo[0] ? "0" : "1";

    // Extend grid
    $row = array_map(fn () => $oob, $grid[0]);
    $grid[-$i]  = $row;
    $grid[$h++] = $row;
    $grid = array_map(function ($row) use ($i, $w, $oob) {
        $row[-$i] = $oob;
        $row[$w] = $oob;
        return $row;
    }, $grid);
    $w++;

    // Update pixels
    $ngrid = [];
    foreach ($grid as $y=>$row) foreach ($row as $x=>$px) {
        $loc = "";
        foreach (range(-1, 1) as $dy) foreach (range(-1, 1) as $dx) {
            $loc .= $grid[$y + $dy][$x + $dx] ?? $oob;
        }
        $ngrid[$y][$x] = $algo[bindec($loc)];
    }
    $grid = $ngrid;

    if ($i == 2) {
        $solution_1 = count(array_filter(array_merge(...$grid)));
    }
    if ($i == 50) {
        $solution_2 = count(array_filter(array_merge(...$grid)));
    }
}