function move($grid) {
return preg_replace_callback("/([^#\n^]+)/", fn ($m) =>
Cache::memoized(function ($string) {
$s = str_split($string);
sort($s);
return implode("", array_reverse($s));
}, [$m[0]])
, $grid);
}
function rotate($grid) {
$grid = array_map("array_reverse", array_map(null, ...array_map("str_split", explode("\n", $grid))));
$grid = implode("\n", array_map("implode", $grid));
return $grid;
}
function weight($grid) {
$width = strpos($grid, "\n") + 1;
preg_match_all("/O/", $grid, $m, PREG_OFFSET_CAPTURE);
return array_sum(
array_map(function ($m) use ($width) {
return $width - 1 - $m[1] % $width;
}, $m[0])
);
}
// ==================================================
// > PART 1
// ==================================================
$input = rotate(rotate(rotate($input)));
$solution_1 = weight(move($input));
// ==================================================
// > PART 2
// ==================================================
function pattern($grid) {
for ($l = 0;; $l++) {
for ($i = 0; $i < 4; $i++) $grid = rotate(move($grid));
$key = str_replace("\n", "", $grid);
if (isset($seen[$key])) break;
$seen[$key] = $l;
$cycles[$l] = weight($grid);
}
return [$seen[$key], $l - $seen[$key], $cycles];
}
[$start, $length, $cycles] = pattern($input);
$solution_2 = $cycles[$start + ((1000000000 - $start - 1) % $length)];