Answer ⏱  605ms
                        
                                                        Part 1 : 
                            5819
                            Part 2 : 
                            18516
                        
                     
                    [$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)));
    }
}