Created
February 6, 2010 00:12
-
-
Save rampion/296414 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <string.h> | |
int shuffle(size_t const * input, size_t const size, size_t ** p_output) | |
{ | |
int retval = 0; | |
size_t i; | |
char in_place = 0; | |
char cleanup_output = 0; | |
if (size == 0) | |
{ | |
return 0; // nothing to do | |
} | |
// make sure we can read our input and write our output | |
else if (input == NULL || p_output == NULL) | |
{ | |
return -2; // illegal input | |
} | |
// allocate memory for the output | |
else if (*p_output == NULL) | |
{ | |
*p_output = malloc(size * sizeof(size_t)); | |
if (*p_output == NULL) return -1; // memory allocation problem | |
cleanup_output = 1; // free this memory if we run into errors | |
} | |
// use a copy of our input, since the algorithm doesn't operate in place. | |
// and the input and output overlap | |
else if (*p_output - size < input && input < *p_output + size) | |
{ | |
size_t * const input_copy = malloc(size * sizeof(size_t)); | |
if (input_copy == NULL) return -1; // memory allocation problem | |
memcpy( input_copy, input, size * sizeof(size_t)); | |
input = input_copy; | |
in_place = 1; | |
} | |
// shuffle | |
for (i = 0; i < size; i++) | |
{ | |
if (input[i] >= size) | |
{ | |
retval = -2; // illegal input | |
break; | |
} | |
(*p_output)[i] = input[ input[i] ]; | |
} | |
// cleanup | |
if (in_place) | |
{ | |
free((size_t *) input); | |
} | |
if (retval != 0 && cleanup_output) | |
{ | |
free(*p_output); | |
*p_output = NULL; | |
} | |
return retval; | |
} | |
#ifndef MAIN | |
# define MAIN | |
#include <stdio.h> | |
void show_array(char const * const name, size_t const * const array, size_t const size) | |
{ | |
size_t i; | |
printf("size_t *(%s) = %p", name, array); | |
if (array != NULL) | |
{ | |
printf(" = {"); | |
for (i = 0; i < size; ++i) | |
printf(" %lu%c", (unsigned long) array[i], i != size - 1 ? ',' : ' '); | |
printf("}"); | |
} | |
printf("\n"); | |
} | |
size_t * show_steps( | |
char const * const input_name, size_t * input, | |
char const * const input_size_name, size_t input_size, | |
char const * const output_name, size_t * output | |
) { | |
show_array( input_name, input, input_size ); | |
show_array( output_name, output, input_size ); | |
printf("shuffle( %s, %s, %s ) = %d\n", | |
input_name, input_size_name, output_name, | |
shuffle( input, input_size, &output )); | |
show_array( input_name, input, input_size ); | |
show_array( output_name, output, input_size ); | |
printf("\n"); | |
return output; | |
} | |
# define SHOW_STEPS( input, size, output ) \ | |
show_steps( #input, (input), #size, (size), #output, output ) | |
int main(int argc, char ** argv) | |
{ | |
size_t my_array[] = { 1,2,3,4,5,6,7,8,9,0 }; | |
size_t my_larger_array[] = { 1,2,3,4,5,6,7,8,9,0, 10, 10, 10, 10, 10 }; | |
size_t const my_array_size = 10; | |
size_t *ret_ptr; | |
ret_ptr = NULL; | |
ret_ptr = SHOW_STEPS( my_array, my_array_size, ret_ptr ); | |
if (ret_ptr != NULL) free(ret_ptr); | |
ret_ptr = calloc( my_array_size, sizeof(size_t) ); | |
if (ret_ptr == NULL) return -1; | |
SHOW_STEPS( my_array, my_array_size, ret_ptr ); | |
free(ret_ptr); | |
SHOW_STEPS( my_array, my_array_size, my_array ); | |
SHOW_STEPS( my_larger_array, my_array_size, my_larger_array + 5); | |
SHOW_STEPS( my_larger_array + 5, my_array_size, my_larger_array); | |
return 0; | |
} | |
#endif | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment