Solution (source code)

= Solution

Let $a=n-k$ and $b=k$ be the lengths of the left and right blocks. Exchange the smaller block with the equally long block at the opposite end.
``
PROCEDURE rotate(i, n, k: INTEGER);
VAR a, b: INTEGER;
BEGIN
  IF (k = 0) OR (k = n) THEN RETURN END;
  a := n-k; b := k;
  IF a = b THEN
    blockswap(i, i+a, a)
  ELSIF a < b THEN
    blockswap(i, i+b, a);
    rotate(i, b, b-a)
  ELSE
    blockswap(i, i+a, b);
    rotate(i+b, a, b)
  END
END rotate;
``
If $a<b$, split $B=B_1B_2$ with $|B_2|=a$. The first <block swap> sends $AB_1B_2$ to $B_2B_1A$; $A$ is now in its final suffix. Rotate the remaining prefix of length $b$ right by $b-a$ to send $B_2B_1$ to $B_1B_2$. If $a>b$, split $A=A_1A_2$ with $|A_1|=b$. The swap sends $A_1A_2B$ to $BA_2A_1$; the fixed prefix is $B$, and rotating the remaining length-$a$ suffix right by $b$ restores $A_1A_2$. In both cases the exchanged segments are disjoint.

The remaining length strictly decreases, so <induction> on $n$ proves <algorithm termination> and correctness. \b[This implements the block-exchange rotation.] It uses only simple explicit variables, but its recursive call stack can have $\Theta(n)$ depth when one block has length $1$; the iterative version removes that extra storage.