How to resolve the algorithm Knuth shuffle step by step in the C programming language

Published on 7 June 2024 03:52 AM
#C

How to resolve the algorithm Knuth shuffle step by step in the C programming language

Table of Contents

Problem Statement

The   Knuth shuffle   (a.k.a. the Fisher-Yates shuffle)   is an algorithm for randomly shuffling the elements of an array.

Implement the Knuth shuffle for an integer array (or, if possible, an array of any type).

Given an array items with indices ranging from 0 to last, the algorithm can be defined as follows (pseudo-code):

(These are listed here just for your convenience; no need to demonstrate them on the page.)

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Knuth shuffle step by step in the C programming language

The provided C code defines two shuffle functions: a generic one (shuffle) that can be used with any data type and a specialized one (shuffle_int) that is optimized for integers.

  1. Generic Shuffle Function (shuffle):

    • The shuffle function takes three arguments: obj (a pointer to an array of elements), nmemb (number of elements in the array), and size (size of each element in bytes).
    • It uses the Fisher-Yates shuffle algorithm to randomly rearrange the elements in the array.
    • The algorithm maintains a pointer n to the unsorted portion of the array and repeatedly selects a random element from the unsorted portion to swap with the element at position n.
    • It uses the rrand function to generate random numbers.
    • The function allocates a temporary buffer temp to facilitate the swapping.
  2. Specialized Shuffle Function (shuffle_int):

    • The shuffle_int function is a specialized version of the generic shuffle function that is optimized for integer data.
    • It uses the irand function to generate random indices and does not need to allocate a temporary buffer since it can directly swap integers using the tmp variable.
    • This optimization can lead to improved performance compared to the generic shuffle function for integer arrays.
  3. Random Number Generation Functions:

    • The rrand function generates a random integer between 0 and m-1 using the rand function and a floating-point conversion.
    • The irand function generates a random integer between 0 and n-1 by filtering out values that fall outside the desired range and using integer division to map the generated random number to the desired range.
  4. Main Function (main):

    • The main function demonstrates the usage of the shuffle_int function.
    • It initializes an array x with integers from 0 to 19, prints the initial order of elements, shuffles the array using shuffle_int, and then prints the shuffled order.

Source code in the c programming language

#include <stdlib.h>
#include <string.h>

int rrand(int m)
{
  return (int)((double)m * ( rand() / (RAND_MAX+1.0) ));
}

#define BYTE(X) ((unsigned char *)(X)) 
void shuffle(void *obj, size_t nmemb, size_t size)
{
  void *temp = malloc(size);
  size_t n = nmemb;
  while ( n > 1 ) {
    size_t k = rrand(n--);
    memcpy(temp, BYTE(obj) + n*size, size);
    memcpy(BYTE(obj) + n*size, BYTE(obj) + k*size, size);
    memcpy(BYTE(obj) + k*size, temp, size);
  }
  free(temp);
}


#include <stdio.h>
#include <stdlib.h>

/* define a shuffle function. e.g. decl_shuffle(double).
 * advantage: compiler is free to optimize the swap operation without
 *            indirection with pointers, which could be much faster.
 * disadvantage: each datatype needs a separate instance of the function.
 *            for a small funciton like this, it's not very big a deal.
 */
#define decl_shuffle(type)				\
void shuffle_##type(type *list, size_t len) {		\
	int j;						\
	type tmp;					\
	while(len) {					\
		j = irand(len);				\
		if (j != len - 1) {			\
			tmp = list[j];			\
			list[j] = list[len - 1];	\
			list[len - 1] = tmp;		\
		}					\
		len--;					\
	}						\
}							\

/* random integer from 0 to n-1 */
int irand(int n)
{
	int r, rand_max = RAND_MAX - (RAND_MAX % n);
	/* reroll until r falls in a range that can be evenly
	 * distributed in n bins.  Unless n is comparable to
	 * to RAND_MAX, it's not *that* important really. */
	while ((r = rand()) >= rand_max);
	return r / (rand_max / n);
}

/* declare and define int type shuffle function from macro */
decl_shuffle(int);

int main()
{
	int i, x[20];

	for (i = 0; i < 20; i++) x[i] = i;
	for (printf("before:"), i = 0; i < 20 || !printf("\n"); i++)
		printf(" %d", x[i]);

	shuffle_int(x, 20);

	for (printf("after: "), i = 0; i < 20 || !printf("\n"); i++)
		printf(" %d", x[i]);
	return 0;
}


  

You may also check:How to resolve the algorithm Optional parameters step by step in the OCaml programming language
You may also check:How to resolve the algorithm Count in factors step by step in the Forth programming language
You may also check:How to resolve the algorithm Least common multiple step by step in the PARI/GP programming language
You may also check:How to resolve the algorithm Validate International Securities Identification Number step by step in the Visual Basic .NET programming language
You may also check:How to resolve the algorithm Arithmetic evaluation step by step in the Oz programming language