Advent of code 2017/16
Ajax Direct

Answer

Part 1 :
Part 2 :
function dance($items, $instructions) {
    foreach ($instructions as $inst) {
        switch ($inst[0]) {
            case "s":
                $items = array_merge(
                    array_slice($items, -$inst[1][0]),
                    array_slice($items, 0, -$inst[1][0])
                );
                break;
            case "x":
                [$a, $b] = $inst[1];
                [$items[$a], $items[$b]] = [$items[$b], $items[$a]];
                break;
            case "p":
                $index = array_flip($items);
                [$a, $b] = $inst[1];
                [$a, $b] = [$index[$a], $index[$b]];
                [$items[$a], $items[$b]] = [$items[$b], $items[$a]];
                break;
        }
    }

    return $items;
}

// Pre-parse instructions
$instructions = $input->split(",")->map(function ($inst) {
    return [$inst[0], explode("/", trim(substr($inst, 1)))];
});

$items = range("a", "p");

// ==================================================
// > PART 1
// ==================================================
$solution_1 = implode("", dance($items, $instructions));

// ==================================================
// > PART 2
// ==================================================
$loop = [implode("", $items)];
while (true) {
    $items  = dance($items, $instructions);
    $string = implode("", $items);
    if ($string == $loop[0]) break; // Stop as soon as we loop back to the start
    $loop[] = $string;
}
$solution_2 = $loop[1_000_000_000 % count($loop)];