I am trying to figure out a way to "shuffle" an array without using inbuilt shuffle functions of random or numpy.
I have the following code, but it will select a cell more than once, and I would like to use only the values in Deck1. However, if Deck1 has two instances of 3 (for instance) then it should result in two instances of 3 in Deck2
I suspect this should be searching Deck2 as it is built for the value in Deck1, but I am not completely sure how to go about it, especially if Deck1 has multiple instances of a value.
def shuffler():
n = int(input(" Please enter the number of cards in the deck: "))
s = input("Should the deck be shuffled? (Y/N): ").lower()
# Create the decks
# First deck is filled with either random or ordered numbers
if s == "y":
Deck1 = np.random.randint(low = 0, high = n, size = n)
print("Original deck:")
print(Deck1)
Deck2 = np.empty(n, np.int)
else:
Deck1 = np.arange(n)
print("Original deck:")
print(Deck1)
Deck2 = np.empty(n, np.int)
for i in Deck1:
j = np.random.randint(0, n)
Deck2[i] = Deck1[j]
print("Shuffled deck:")
print(Deck2)
CodePudding user response:
A few comments:
Deck1 = np.random.randint(low = 0, high = n, size = n)
isn't a very good way of initializing a deck since it's supposed to contain n
unique cards. You should use Deck1 = np.arange(n)
.
A way of shuffling a deck is to create a random array of positions, then swap the items in these positions. For example:
np.random.seed(42)
np.random.randint(low = 0, high = 10, size = 10)
yields array([6, 3, 7, 4, 6, 9, 2, 6, 7, 4])
. Consider this a way of moving the card at position 0
to position 6
. The card at position 6
could either be shifted to the right, or move to position 0
. Similarly, the card at position 1
goes to 3
, and the card at 3
goes to 1
.
This is how I implemented your code:
import numpy as np
np.random.seed(42) # Reproducible outputs
def shuffler(n = 10, s = "Y"): # Don't want to type 10 and 'Y' every time
print("Original deck:")
Deck = np.arange(n)
print(Deck)
if s.lower() == "y":
positions = np.random.randint(low = 0, high = n, size = n)
for i, position in enumerate(positions):
Deck[i], Deck[position] = Deck[position], Deck[i] # Swaps
print("Shuffled deck:")
print(Deck)
shuffler()
Yielded
Original deck:
[0 1 2 3 4 5 6 7 8 9]
Shuffled deck:
[6 3 1 4 5 9 2 8 7 0]
CodePudding user response:
You can write your own shuffle function, but be careful to have a homogeneous distribution. Here is an implementation of the Durstenfeld shuffle algorithm:
def shuffle(arr):
for i in range(len(arr) - 1, 0, -1):
j = np.random.randint(0, i 1)
arr[[i, j]] = arr[[j, i]] # Swap
Then in your code:
Deck2 = np.copy(Deck1)
shuffle(Deck2)