Advent of code 2019/12
Ajax Direct

Answer

Part 1 :
Part 2 :
$p = $input->numbers()->chunk(3);
$v = set([0])->repeat(12)->chunk(3);
$log = [];

for ($t = 1; $t <= 250_000; $t++) {
    // Calculate velocities
    for ($i = 0; $i < 4; $i++) {
        for ($j = 0; $j < 4; $j++) {
            if ($i == $j) continue;
            for ($k = 0; $k <= 2; $k++) {
                $v[$i][$k] += -($p[$i][$k] <=> $p[$j][$k]);
            }
        }
    }

    // Move moons
    for ($i = 0; $i < 4; $i++) {
        for ($k = 0; $k <= 2; $k++) {
            $p[$i][$k] += $v[$i][$k];
        }
    }

    // ==================================================
    // > PART 1
    // ==================================================
    if ($t === 1000) {
        $ps = $p->callEach()->map(fn ($i) => abs($i))->callEach()->sum();
        $vs = $v->callEach()->map(fn ($i) => abs($i))->callEach()->sum();
        $solution_1 = 0;
        for ($i = 0; $i < 4; $i++) {
            $solution_1 += $ps[$i] * $vs[$i];
        }
    }

    // ==================================================
    // > PART 2
    // ==================================================
    $log[] = (array) $p[0];
}

$rec = [];
for ($l = 0; $l < 3; $l++) {
    $s = join(";", array_column($log, $l));
    $pos = strpos(substr($s, 250), substr($s, 0, 250));
    $rec[] = count(explode(";", substr($s, 0, $pos + 250))) - 1;
}

$solution_2 = Math::lcm(Math::lcm($rec[0], $rec[1]), $rec[2]);