It's tempting to flatten the input into a single list, then use one of rand
's built-in methods to keep choosing two elements at random until the list is empty or some variation on this. However, this can't guarantee that none of the output pairs are the same as the input pairs.
Instead, we use a two-step algorithm:
- Perform a Fisher-Yates shuffle (
O(n)
) of the list of input pairs, randomising their order - Iterate over chunks of the shuffled pairs, two pairs at a time.
- for each chunk, swap the pair members:
(a, b), (c, d)
->(a, d), (c, b)
This guarantees that no output pair is equal to an input pair.
- for each chunk, swap the pair members:
This is almost certainly not optimal, but it's good enough.