3
$\begingroup$

enter image description here

I currently have a deck of cards (in fact this deck is an array of sorted elements in descending order as indicated by the picture above), that I want to shuffle. However, the caveat is that I want the card near the top of the deck to be shuffled to a new position relatively close to the top, while a card near the bottom to be shuffled anywhere including the middle and bottom, but have a very unlikely chance of ending up near the top of the deck.

Therefore I would break down the problem as following:

A card in the top 33% of the deck has about:

  • 90% chance of ending up in the top 33%
  • 8% chance of ending up in the middle 33%
  • 2 % chance of ending up in the bottom 33%

A card in the middle 33% of the deck has about:

  • 5% chance of ending up in the top 33%
  • 90% chance of ending up in the middle 33%
  • 5 % chance of ending up in the bottom 33%

A card in the bottom 33% of the deck has about:

  • 2% chance of ending up in the top 33%
  • 8% chance of ending up in the middle 33%
  • 90 % chance of ending up in the bottom 33%

The percentages of the shuffle do not need to be constant. I wouldn't mind if they were continuous probabilities across the entire deck. Would this boil down to a randomized selection problem? I have no clue as to how to approach this problem as of now.

$\endgroup$
1
$\begingroup$

I needed this same thing, a biased shuffling for local/proximity shuffling, but couldn't find any answers, so this is my attempt to create one.

Pseudocode:

For X passes through the array from 0 to len(array)-1:
    Roll for a 50% chance to swap index and index+1
    Swap direction of array traversal

Python:

import numpy as np
import matplotlib.pyplot as plt

swap_passes = 50

player_count = 100

positions = {}

player = np.arange(1,player_count+1)
for p in player:
    positions[p] = []

for i in range(10000):
    player = np.arange(1,player_count+1)

    for j in range(swap_passes):
        pre_rand = np.random.randint(0,2,player_count)
        if j%2 == 0:
            for i in range(len(player)-1):
                if pre_rand[i] == 0:
                    player[i], player[i+1] = player[i+1], player[i]
        else:
            for i in range(len(player)-1,0,-1):
                if pre_rand[i] == 0:
                    player[i], player[i-1] = player[i-1], player[i]

    for idx, p in enumerate(player):
        positions[p].append(idx)

fcs = [(1,0,0,0.3),(0,1,0,0.3),(0,0,1,0.3),(0.5,0.5,0,0.3),(0,0.5,0.5,0.3)]
plt.figure()
for idx, i in enumerate([1,30,50,70,100]):
    bins = np.arange(0,player_count+1)
    plt.hist(positions[i], bins=bins, fc=fcs[idx])
plt.title('Histogram of indices: 1, 30, 50, 70, 100. 10000 trials, 50 swap passes.')

Results:

histogram results

Looks roughly gaussian. Increasing the number of passes will increase the spread of the distribution.

| cite | improve this answer | |
$\endgroup$
  • $\begingroup$ Nearly 2 years later nice $\endgroup$ – Sharan Duggirala Aug 26 at 2:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.