function solve($pass, $instructions, $reverse = false) {
$pass = set(str_split($pass));
foreach ($instructions as $line) {
if (preg_match("/rotate (right|left) (\d)/", $line, $matches)) {
$direction = ($matches[1] == "left" && !$reverse) || ($matches[1] == "right" && $reverse) ? -1 : 1;
$pass = $pass->rotate(($matches[2] % count($pass)) * $direction);
}
if (preg_match("/swap position (\d) with position (\d)/", $line, $matches)) {
[$pass[$matches[1]], $pass[$matches[2]]] = [$pass[$matches[2]], $pass[$matches[1]]];
}
if (preg_match("/swap letter (\w) with letter (\w)/", $line, $matches)) {
[$a, $b] = [$pass->search($matches[1]), $pass->search($matches[2])];
[$pass[$a], $pass[$b]] = [$pass[$b], $pass[$a]];
}
if (preg_match("/reverse positions? (\d) through (\d)/", $line, $matches)) {
$pass->splice(
$matches[1], $matches[2] - $matches[1] + 1,
$pass->slice($matches[1], $matches[2] - $matches[1] + 1)->reverse()
);
}
if (preg_match("/move position (\d) to position (\d)/", $line, $matches)) {
[$a, $b] = $reverse ? [$matches[2], $matches[1]] : [$matches[1], $matches[2]];
$letter = $pass[$a];
unset($pass[$a]);
$pass->splice($b, 0, [$letter]);
}
if (preg_match("/rotate based on position of letter (\w)/", $line, $matches)) {
$rots = $rots ?? set(range(0, $pass->count() - 1))->map(fn ($i) => ($i + 1 + ($i > 3 ? 1 : 0)) % $pass->count());
if (!$reverse) {
$pass = $pass->rotate($rots[$pass->search($matches[1])]);
} else {
$rrots = $rrots ?? $rots->map(fn ($v, $k) => ($v + $k) % $rots->count(), true)->flip();
$pos = $rrots[$pass->search($matches[1])];
$pass = $pass->rotate($pos - $pass->search($matches[1]));
}
}
}
return $pass->join("");
}
// ==================================================
// > SOLUTIONS
// ==================================================
$solution_1 = solve("abcdefgh", $input->lines, false);
$solution_2 = solve("fbgdceah", $input->lines->reverse(), true);