I ran multiple simulations of the following function, and it seems to be fair shuffling, given that all permutations were roughly equal, but I don't understand why it works. It's just inserting at random positions within the current shuffled deck isn't it? I know about Fisher-Yates shuffling, for reference.
def shuffle_deck(deck):
shuffled_deck = []
for card in deck:
r = random.randint(0, len(shuffled_deck))
shuffled_deck.insert(r, card)
return shuffled_deck
I was expecting that it would be uneven probability permutation.
One way of showing this is to consider the set of possible paths through the code. Note that at step $i$, a random number between $0$ and $i$ is chosen to determine where to insert the next card. This gives us $1\cdot2\cdot3\cdots\cdot n=n!$ different paths through the code, and each path clearly corresponds to a different permutation. Contrariwise, it's possible to run the algorithm 'in reverse'; for each $i$ from $n$ downward, look at the position of $i$ within the subpermutation of the shuffled permutation consisting of only the elements $1..i$ .