patterncMinor
Shuffling array elements in C
Viewed 0 times
arrayelementsshuffling
Problem
This is an answer to this problem.
Basically, given an array, swap the given number of elements in the array.
The solution that came to my mind: since we always swap at least two elements, pick two random indices and swap array[first_random] with array[second_random]. Then, if there's more to swap, find index that was not swapped yet and swap it with one of previously swapped.
This might be confusing a little, but it works. I am curious whether there are some other, better approaches.
Basically, given an array, swap the given number of elements in the array.
The solution that came to my mind: since we always swap at least two elements, pick two random indices and swap array[first_random] with array[second_random]. Then, if there's more to swap, find index that was not swapped yet and swap it with one of previously swapped.
This might be confusing a little, but it works. I am curious whether there are some other, better approaches.
#include
#include
#include
void print_arr(int a[], int size) {
int i;
for (i = 0; i < size; i++) {
printf("%d ",a[i]);
}
printf("\n");
}
void swap(int a[], int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
int next_idx(int swapped[], int s_count, int size) {
int n, i;
char in_arr;
while (1) {
in_arr = 0;
n = rand() % size;
for (i = 0; i < s_count; i++) {
if (swapped[i] == n) {
in_arr = 1;
break;
}
}
if (!in_arr) {
break;
}
}
return n;
}
void swap2_or_more(int a[], int size,int count) {
srand(time(NULL));
int i, j, s_count = 0;
int swapped[size];
i = rand() % size;
swapped[s_count] = i;
s_count++;
do {
j = rand() % size;
} while (i == j); // make sure indexes are different
swapped[s_count] = j;
s_count++;
swap(a, i, j);
count -= 2;
while (count) {
i = next_idx(swapped, s_count, size);
j = rand() % s_count;
swap(a, i, swapped[j]);
swapped[s_count] = i;
s_count++;
count--;
}
printf("swapped indexes:\n");
print_arr(swapped, s_count);
}
int main(void)
{
int a[] = {1,2,3,4,5,6,7,8,9,10};
swap2_or_more(a, 10, 5);
printf("array after swap:\n");
print_arr(a, 10);
return 0;
}Solution
There is a huge amount of guessing in your program, code like:
Let's say the input data has 1000000 members, and we need to swap 10 of them...
One solution which will produce a suitably random distribution of the swapped items relies on a 'simple' algorithm which does just one rand() per item, and there's no guess-work. This is done using a fisher-yates shuffle. But, for this problem, we don't shuffle the items, we shuffle the indexes... so:
int next_idx(int swapped[], int s_count, int size) {
int n, i;
char in_arr;
while (1) {
in_arr = 0;
n = rand() % size;
for (i = 0; i < s_count; i++) {
if (swapped[i] == n) {
in_arr = 1;
break;
}
}
if (!in_arr) {
break;
}
}
return n;
}Let's say the input data has 1000000 members, and we need to swap 10 of them...
swapped[] array contains.... {1, 100, 500, 800, 1000, 10000} do we really just keep guessing until we hit a random value that is in the data? This is... a problem.One solution which will produce a suitably random distribution of the swapped items relies on a 'simple' algorithm which does just one rand() per item, and there's no guess-work. This is done using a fisher-yates shuffle. But, for this problem, we don't shuffle the items, we shuffle the indexes... so:
void swap2_or_more(int a[], int size,int count) {
int i, tmp;
int swapped[size];
// initialize the swapped array with all the data indices.
for (i = 0; i 0; i--) {
tmp = rand() % (i + 1);
swap(swapped, i, tmp);
}
// 'rotate' the values in the first count swapped/random indexes
tmp = a[swapped[--count]];
while(count > 0) {
a[swapped[count]] = a[swapped[count - 1]];
count--;
}
a[swapped[0]] = tmp;
}Code Snippets
int next_idx(int swapped[], int s_count, int size) {
int n, i;
char in_arr;
while (1) {
in_arr = 0;
n = rand() % size;
for (i = 0; i < s_count; i++) {
if (swapped[i] == n) {
in_arr = 1;
break;
}
}
if (!in_arr) {
break;
}
}
return n;
}void swap2_or_more(int a[], int size,int count) {
int i, tmp;
int swapped[size];
// initialize the swapped array with all the data indices.
for (i = 0; i < size; i++) {
swapped[i] = i;
}
// Fisher-Yates shuffle the indices.
// http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
for (int i = size-1; i > 0; i--) {
tmp = rand() % (i + 1);
swap(swapped, i, tmp);
}
// 'rotate' the values in the first count swapped/random indexes
tmp = a[swapped[--count]];
while(count > 0) {
a[swapped[count]] = a[swapped[count - 1]];
count--;
}
a[swapped[0]] = tmp;
}Context
StackExchange Code Review Q#58837, answer score: 4
Revisions (0)
No revisions yet.