Card shuffles
There are many techniques that people use to shuffle cards for card games. Some are more effective than others.
The task here is to implement the (seemingly) more common techniques of the riffle shuffle and overhand shuffle for n iterations. Implementing playing cards is not necessary if it would be easier to implement these shuffling methods for generic collections. Where possible, compare this to a standard/built-in shuffling procedure.
Bonus: Implement other methods described here. Allow for "human errors" of imperfect cutting and interleaving.
Java
<lang java5>import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Random;
public class CardShuffles{
public static <T> LinkedList<T> riffleShuffle(List<T> list, int flips){ LinkedList<T> newList = new LinkedList<T>();
newList.addAll(list);
for(int n = 0; n < flips; n++){ //cut the deck at the middle +/- 10% int cutPoint = newList.size() / 2 + (Math.random() >= 0.5 ? -1 : 1 ) * (new Random()).nextInt((int)(newList.size() * 0.1));
//split the deck in half-ish List<T> left = new LinkedList<T>(); left.addAll(newList.subList(0, cutPoint)); List<T> right = new LinkedList<T>(); right.addAll(newList.subList(cutPoint, newList.size()));
newList.clear();
while(left.size() > 0 && right.size() > 0){ //allow for imperfect flipping so that more than one card can come form the same side in a row //biased towards the side with more cards if(Math.random() >= ((double)left.size() / right.size()) / 2){ newList.add(right.remove(0)); }else{ newList.add(left.remove(0)); } }
//if either hand is out of cards then flip all of the other hand to the shuffled deck if(left.size() > 0) newList.addAll(left); if(right.size() > 0) newList.addAll(right); } return newList; }
public static <T> LinkedList<T> overhandShuffle(List<T> list, int passes){ LinkedList<T> mainHand = new LinkedList<T>();
mainHand.addAll(list); for(int n = 0; n < passes; n++){ LinkedList<T> otherHand = new LinkedList<T>();
while(mainHand.size() > 0){ //cut at up to 20% of the way through the deck int cutSize = (new Random()).nextInt((int)(list.size() * 0.2)) + 1;
LinkedList<T> temp = new LinkedList<T>();
//grab the next cut up to the end of the cards left in the main hand for(int i = 0; i < cutSize && mainHand.size() > 0; i++){ temp.add(mainHand.remove()); }
//add them to the cards in the other hand, sometimes to the front sometimes to the back if(Math.random() >= 0.1){ //front most of the time otherHand.addAll(0, temp); }else{ //end sometimes otherHand.addAll(temp); } }
//move the cards back to the main hand mainHand = otherHand; } return mainHand; }
public static void main(String[] args){ List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20); System.out.println(list); list = riffleShuffle(list, 10); System.out.println(list + "\n");
list = Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20);
System.out.println(list); list = riffleShuffle(list, 1); System.out.println(list + "\n");
list = Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20); System.out.println(list); list = overhandShuffle(list, 10); System.out.println(list + "\n");
list = Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20);
System.out.println(list); list = overhandShuffle(list, 1); System.out.println(list + "\n");
list = Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20); System.out.println(list); Collections.shuffle(list); System.out.println(list + "\n"); } }</lang>
- Output:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] [20, 11, 1, 9, 15, 4, 19, 16, 8, 13, 7, 2, 14, 12, 10, 3, 17, 18, 6, 5] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] [1, 12, 2, 3, 4, 5, 13, 14, 15, 6, 16, 7, 8, 9, 17, 18, 10, 19, 20, 11] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] [20, 3, 10, 4, 2, 8, 1, 18, 13, 19, 14, 6, 9, 12, 16, 15, 5, 7, 11, 17] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] [18, 19, 20, 17, 13, 14, 15, 16, 9, 10, 11, 12, 8, 6, 7, 3, 4, 5, 1, 2] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] [18, 12, 13, 14, 2, 3, 15, 5, 9, 19, 7, 11, 1, 6, 4, 20, 16, 17, 10, 8]