Advent of code 2018/12
Ajax Direct

Answer

Part 1 :
Part 2 :
preg_match("/initial state: ([^\n]+)/", $input, $state);
$state = str_repeat(".", 150) . $state[1] . str_repeat(".", 150);

preg_match_all("/([\.#]{5}) => #/", $input, $comb);
$comb = array_fill_keys($comb[1], "#");

function grow($state, $comb) {
    $next = "";
    for ($i = 0; $i < strlen($state); $i++) {
        $next[$i] = $comb[implode("", [
            $state[$i - 2] ?? ".",
            $state[$i - 1] ?? ".",
            $state[$i]     ?? ".",
            $state[$i + 1] ?? ".",
            $state[$i + 2] ?? "."
        ])] ?? ".";
    }
    return $next;
}

$p = [];
$d = [];
for ($i = 0; $i < 150; $i++) {
    $state = grow($state, $comb);
    $plants = set(str_split($state))->keep("#");
    $p[$i] = $plants->keys()->sum() - $plants->count() * 150;
    $d[$i] = $p[$i] - ($p[$i - 1]??0);
}

// ==================================================
// > PART 1
// ==================================================
$solution_1 = $p[19];

// ==================================================
// > PART 2
// ==================================================
$incr = $d[149]; // Last diff is the repeated increment
$start = array_search($incr, $d); // Start of the repeated increment in the loop
$solution_2 = $p[$start] + (50_000_000_000 - $start - 1) * $incr; // Calc increments left after we enter the loop until 5B iterations