Simulate Fisher-Yates Shuffling
Checking your account…
Sign in to save your code and progress across devices. The lesson and problem statement remain public.
Loading the interactive Practice workspace.If it does not appear, the problem and learning material remain readable, but browser execution is unavailable.Reload Practice workspace
Problem
Implement fisher_yates(values, choices). Return a shuffled copy. For i from n-1 down to 1, choices[n-1-i] is a valid j in [0,i]; swap indexes i and j.
Starter code
def fisher_yates(values, choices):
passTest cases
deterministic-swaps
{
"args": [
[
1,
2,
3,
4
],
[
1,
0,
1
]
]
}Expected: [3,4,1,2]
self-swaps
{
"args": [
[
1,
2,
3
],
[
2,
1
]
]
}Expected: [1,2,3]
Wizard outline
- Step 1: Protect the caller input
Create the output list without mutating the supplied sequence. The exercise contract returns a shuffled copy.
- Step 2: Place the final element
Use one supplied choice to swap the last position. Fisher-Yates fixes one tail position per iteration.
- Step 3: Place every remaining tail position
Walk backward and consume one choice per swap. After placing index i, later positions never need to move again.
Footguns and prerequisites
- Choosing j from the full array at every step biases the permutation.
- Mutating values violates the returned-copy contract.
- functions
- lists and tuples
- control flow
Reviewed references
Recommended approach and implementation
Copy the input and perform the supplied Fisher-Yates swap for every shrinking suffix boundary.
Why it works: At boundary i, the supplied choice selects one of exactly i+1 remaining candidates for position i. The swap fixes that position and never revisits it, yielding the specified permutation without mutating input.
def fisher_yates(values, choices):
shuffled = list(values)
for offset, index in enumerate(range(len(shuffled) - 1, 0, -1)):
choice = choices[offset]
shuffled[index], shuffled[choice] = shuffled[choice], shuffled[index]
return shuffled