function moves($cups, $count = 100) {
// Build circular linked list [item => next item]
$next = [];
foreach ($cups as $i=>$cup) {
$next[$cup] = $cups[$i + 1] ?? $cups[0];
}
// Move items by updating their relations
$current = $cups[0];
for ($i = 0; $i < $count; $i++) {
// Remove 3 items, relink current item
$removed = [];
$cr = $current;
for ($r = 0; $r < 3; $r++) {
$removed[] = $cr = $next[$cr];
}
$next[$current] = $next[$cr];
// Find placing
$pos = $current - 1;
while ($pos < 1 || in_array($pos, $removed)) {
$pos--; $pos = $pos < 1 ? count($cups) : $pos;
}
// Place items
$after = $next[$pos];
$next[$pos] = $removed[0];
$next[$removed[2]] = $after;
// Continue with next one
$current = $next[$current];
}
return $next;
}
// ==================================================
// > PART 1
// ==================================================
$list = moves($input->chars()->map("int"), 100);
$solution_1 = "";
$next = $list[1];
while (true) {
$solution_1 .= $next;
$next = $list[$next];
if ($next == 1) break;
}
// ==================================================
// > PART 2
// ==================================================
$list = moves($input->chars()->map("int")->merge(range(10, 1_000_000)), 10_000_000);
$solution_2 = $list[1] * $list[$list[1]];