How to calculate how effective a Riffle is

deck of cards
Image by Hebi B. from Pixabay

In my previous post I mentioned about writing a program to determine how effective a riffle shuffle was. So here’s the code.

How it works

I’m using an array of 52 chars to hold the deck. I’m only interested in the card’s position in the deck so each card is initialised with a value in the range 0-51. I’m using three other similar sized arrays.

  • tempCards are used purely for doing the riffle.
  • distances are used to calculate the maximum distance the card moved
  • startPos tracks the cards starting position 0-51 before doing lots of rounds of riffles.

The program starts by picking up ( as a parameter) how many rounds you want it to run. It defaults to 10 if no value is input.

It then clears distances and inits cards. In each round, it starts by storing card positions in startPos. It then does seven riffles and works out how far a card has moved. If it has moved more than before (in distances) it stores it in distances.

DoRiffle works by indexing through the two 1/2 deck piles taking a card from each and a 50:50 random chance determines which of the two cards goes into the shuffled deck first and then second.

Here’s the listing.

// riffle.c by D. Bolton (C) 2020 Learncgames.com - TYou are free to redistribute but please keep this line in

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// #defines
#define MAXROUNDS 10
#define NUMRIFFLES 7
#define NUMCARDS 52

// variables
int NumRounds;
char cards[NUMCARDS],tempCards[NUMCARDS],startPos[NUMCARDS];
int distances[NUMCARDS];
time_t t;

// functions

// Convert string to int calling strtol
int GetIntArg(char* str) {
	char* ptr;
	return strtol(str, &ptr, 10);
}

// Merges two cards a and b. 50:50 chance that a above b or other way
void DoRiffle() {
	// Copy cards into tempCards
	memcpy(tempCards, cards, sizeof(cards));
	// Merge each pair of cards tempCards[i] and TempCards[i+26]
	int cardIndex = 0;
	for (int i = 0; i < NUMCARDS / 2; i++) {
		if (rand() % 2) {
			cards[cardIndex++] = tempCards[i];
			cards[cardIndex++] = tempCards[i + 26];

		}
		else {
			cards[cardIndex++] = tempCards[i + 26];
			cards[cardIndex++] = tempCards[i];
		}
	}
}

// Works out how far cards have moved, added to distances
void CalculateDistances() {
	for (int i = 0; i < NUMCARDS; i++) {
		int moved = abs(cards[i] - startPos[i]);
		if (moved > distances[i])
			distances[i] = moved;
	}
}

void DoShuffles() {
	// Clear distances and init cards
	for (char i = 0; i < NUMCARDS; i++) {
		distances[i] = 0;		
		cards[i] = i;
	}
    // do Numrounds  rounds
	for (int round =0;round<NumRounds;round++){
		// Mark where the card starts
		for (char i = 0; i < NUMCARDS; i++) {
			startPos[i] = cards[i];
		}
		// Do seven riffles
		for (int i = 0; i < NUMRIFFLES; i++) {
			DoRiffle();
		}		
		CalculateDistances();
	}
	int furthest = 0;
	for (int i = 0; i < NUMCARDS; i++) {
		printf("Distance[%d]=%d\n", i, distances[i]);
		if (distances[i]> furthest) {
			furthest = distances[i];
		}
	}
	printf("furthest moved is %d\n", furthest);
}


int main(int argc, char* argv[]) {
	srand((unsigned)time(&t));
	if (argc ==1 || argc== 2) {
		NumRounds = MAXROUNDS;
		if (argc == 2) {
			NumRounds = GetIntArg(argv[1]);
			printf("Numrounds = %d\n", NumRounds);
		}
		DoShuffles();
	}
	else {
		printf("Please supply 0 or 1 arguments e.g. riffle 60\n");
	}
}

Even with ten rounds I’ve seen cards move 51 positions. With 5,000 rounds all cards but one moved by 51 and one by 50.

Leave a Reply

Your email address will not be published. Required fields are marked *