Advent of code 2016/23
Ajax Direct

Answer

Part 1 :
Part 2 :
function solve($input, $r) {
    for ($i = 0; $i < $input->lines->count(); $i++) {
        $c = explode(" ", $input->lines[$i]->string);

        switch ($c[0]) {
            case "cpy":
                if (!is_string($c[2])) break;
                $r[$c[2]] = $r[$c[1]] ?? $c[1]; break;
            case "inc":
                $r[$c[1]]++; break;
            case "dec":
                $r[$c[1]]--; break;
            case "jnz":
                if ($r[$c[1]] ?? $c[1]) $i += ($r[$c[2]] ?? $c[2]) - 1; break;
            case "tgl":
                $v = $i + ($r[$c[1]] ?? $c[1]);
                if ($v == $i) break;
                if (empty($input->lines[$v])) break;
                $c = explode(" ", $input->lines[$v]->string);
                if (count($c) == 2) {
                    $c[0] = $c[0] == "inc" ? "dec" : "inc";
                } else {
                    $c[0] = $c[0] == "jnz" ? "cpy" : "jnz";
                }
                $input->lines[$v]->string = implode(" ", $c);
                break;
        }
    }

    return $r["a"];
}

// ==================================================
// > SOLUTIONS
// ==================================================
$r = array_fill_keys(["a", "b", "c", "d"], 0);
$r["a"] = 7;
$solution_1 = solve($input, $r);

// The solution loops until reaching {register a factorial} + a specific offset.
// Using solution_1 to find that offset allows to find solution_2 easly.
$solution_2 = (int) gmp_fact(12) + ($solution_1 - (int) gmp_fact(7));