Reversing int array using recursion in C - c

I have learnt C language at school but I'm not good at it... And when I was trying to implement this algorithm using C language:
ReverseArray(int A[], int i, int j) {
Input: Array A, nonnegative integer indices i and j
Output: The reversal of the elements in A starting at index i and ending at j
if i < j then
swap A[i] and A[j]
ReverseArray(A, i+1, j-1)
}
I managed to code this:
int *reverseArray(int A[], int i, int j) {
int *R = NULL;
if(i < j) {
int temp = A[j];
A[j] = A[i];
A[i] = temp;
R = reverseArray(A, i+1, j-1);
return R;
} else {
return R;
}
}
But when I tried to print the original and reversed array in the main:
int main(void) {
int A[] = {1, 3, 5, 6, 8, 3, 4, 2};
int *r = reverseArray(A, 0, 7);
//This prints out the reversed array, when I intended to print the original
for (size_t i = 0; i < 8; i++) {
printf("%d ", A[i]);
}
printf("\n");
/* This was intended to print the reversed array but doesn't work
for (size_t i = 0; i < 8; i++) {
printf("%d ", r[i]);
}
*/
return 0;
}
Could anyone please explain why the commented out for loop doesn't work? And why the first for loop prints out the reversed array...
Is there any other way to get the result of reverseArray() without using *r?
I tried to malloc *r just in case that was the problem, but it still didn't work.
Thank you.

Just don't return anything. You make a reversion in place, so the resulting array is the same as the array to be reversed, and the caller knows it already.

You need to print the contents of A before you call reverseArray, not after. The reason is that you are reversing the bytes in place so the array A itself is changed by calling reverseArray.

A try from your code base and the problem description
If allowed to rewrite the Array in place, then it will work
#include<stdio.h>
void reverseArray(int A[], int i, int j) {
//int *R = NULL;
if(i < j) {
int temp = A[j];
A[j] = A[i];
A[i] = temp;
reverseArray(A, i+1, j-1);
}
}
int main(void) {
int A[] = {1, 3, 5, 6, 8, 3, 4, 2};
//This prints out original array
for (size_t i = 0; i < 8; i++) {
printf("%d ", A[i]);
}
printf("\n");
reverseArray(A, 0, 7);
// print the reversed array
for (size_t i = 0; i < 8; i++) {
printf("%d ", A[i]);
}
return 0;
}
It will Output:
1 3 5 6 8 3 4 2
2 4 3 8 6 5 3 1

R is always assigned to NULL, and A is not a pointer, then you are editing the real data of the array.
if you want to reverse and create a new array, you must do something like that :
int *reverseArray(int array[], int arraySize) {
int *reversedArray = malloc(sizeof(int) * arraySize);
for ( int i = 0 ; i < arraySize ; ++i ) {
reversedArray[i] = array[arraySize - i - 1];
}
return reversedArray;
}
You can also do it in recursive way :
int *reverseArray(int inputArray[], int arrayLength ) {
int *_reverseArray (int inputArray[], int arrayLength, int *outputArray, int actual) {
if (outputArray == NULL) {
outputArray = malloc(sizeof(int) * arrayLength);
}
if (actual < arrayLength) {
outputArray[actual] = inputArray[arrayLength - actual - 1];
return _reverseArray(inputArray, arrayLength, outputArray, ++actual);
}
return outputArray;
}
return _reverseArray(inputArray, arrayLength, NULL, 0);
}
If you want to edit the original array :
void reverseArray(int array[], int arraySize)
{
for ( int i = 0 ; i < arraySize / 2 ; ++i ) {
array[i] ^= array[arraySize - i - 1];
array[arraySize - i - 1] ^= array[i];
array[i] ^= array[arraySize - i - 1];
}
}

Related

dealing with dups in end of the array

This is the task I have got:
I need to write a function (not recursive) which has two parameters.
An array of integers.
An integer representing the size of the array.
The function will move the duplicates to an end of the array.
And will give the size of the different digits.
Example:
5 , 2 , 4 , 5 , 6 , 7 , 2, n = 7
we will get back 5 , 2 , 4 , 6 , 7 , 5 , 2 and 5
We must keep the original sort as it is (which means like in example 5 must)
It does not matter how we sort the duplicates ones but just keep the sort for the original array as it is)
The function has to print the number of different digits (like in example 5)
The the input range of numbers in array [-n,n]
I can only use 1 additional array for help.
It has to be O(n)
I tried it so many times and feel like am missing something. Would appreciate any advice/suggestions.
int moveDup(int* arr, int n)
{
int* C = (int*)calloc(n * 2 + 1, sizeof(int));
assert(C);
/*int* count = C + n;*/
int *D = arr[0];
int value = 0, count = 0;
for (int i = 0; i < n; i++)
{
value = arr[i];
if (C[value + n] == 0)
{
*D = arr[i];
D++;
count++;
}
C[value + n] = C[value + n] + 1;
}
while (1 < C[value + n])
{
*D = i;
D++;
C[value + n]--;
}
free(C);
return count;
}
This algorithm will produce the required results in O(n) arithmetic complexity:
Input is an array A with n elements indexed from A0 to An−1 inclusive. For each Ai, −n ≤ Ai ≤ n.
Create an array C that can be indexed from C−n to C+n, inclusive. Initialize C to all zeros.
Define a pointer D. Initialize D to point to A0.
For 0 ≤ i < n:
If CAi=0, copy Ai to where D points and advance D one element.
Increment CAi.
Set r to the number of elements D has been advanced from A0.
For −n ≤ i ≤ +n:
While 1 < CAi:
Copy i to where D points and advance D one element.
Decrement CAi.
Release C.
Return r. A contains the required values.
A sample implementation is:
#include <stdio.h>
#include <stdlib.h>
#define NumberOf(a) (sizeof (a) / sizeof *(a))
int moveDuplicates(int Array[], int n)
{
int *memory = calloc(2*n+1, sizeof *Array);
if (!memory)
{
fprintf(stderr, "Error, unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
int *count = memory + n;
int *destination = Array;
for (int i = 0; i < n; ++i)
// Count each element. If it is unique, move it to the front.
if (!count[Array[i]]++)
*destination++ = Array[i];
// Record how many unique elements were found.
int result = destination - Array;
// Append duplicates to back.
for (int i = -n; i <= n; ++i)
while (0 < --count[i])
*destination++ = i;
free(memory);
return result;
}
int main(void)
{
int Array[] = { 5, 2, 4, 5, 6, 7, 2 };
printf("There are %d different numbers.\n",
moveDuplicates(Array, NumberOf(Array)));
for (int i = 0; i < NumberOf(Array); ++i)
printf(" %d", Array[i]);
printf("\n");
}
here is the right answer, figured it out by myself.
int moveDup(int* arr, int n)
{
int* seen_before = (int*)calloc(n * 2 + 1, sizeof(int));
assert(seen_before);
int val = 0, count = 0, flag = 1;
int j = 0;
for (int i = 0; i < n; i++)
{
val = arr[i];
if (seen_before[arr[i] + n] == 0)
{
seen_before[arr[i] + n]++;
count++;
continue;
}
else if (flag)
{
j = i + 1;
flag = 0;
}
while (j < n)
{
if (seen_before[arr[j] + n] == 0)
{
count++;
seen_before[arr[j] + n]++;
swap(&arr[i], &arr[j]);
j++;
if (j == n)
{
free(seen_before);
return count;
}
break;
}
/*break;*/
j++;
if (j == n)
{
free(seen_before);
return count;
}
}
}
}
second right answer
int* mem = (int*)calloc(2 * n + 1, sizeof * arr);
assert(mem);
int* count = mem + n;
int* dest = arr;
for (i = 0; i < n; ++i)
{
if (count[arr[i]]++ == 0)
{
*dest = arr[i];
*dest++;
}
}
res = dest - arr;
for (i = -n; i <= n; ++i)
{
while (0 < --count[i])
{
*dest++ = i;
}
}
free(mem);
return res;

Find the smallest number in an array that is not in another array

Currently I am trying to solve this task: Two arrays of five integers each are given. Find the lowest number in the first array that is not in the second array.
It seems to me that if the user enters such integers in the first array:
0 1 2 3 4
And the integers of the second array:
0 2 3 4 5
The lowest integer, according to the condition of the task, will be 1, because it is not in the second array.
So here is my code:
#include <stdio.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, "Rus");
int arr1[5]; //initialize arrays
int arr2[5];
printf("Enter integers\n");
for (int i = 0; i < 5; i++) {
int element;
scanf_s("%d", &element);
arr1[i] = element;
}
printf("Enter integers\n");
for (int i = 0; i < 5; i++) {
int element;
scanf_s("%d", &element);
arr2[i] = element;
}
int min1 = arr1[0];
int min2 = arr2[0];
for (int i = 0; i < 5; i++) { // algorithm for finding the minimum number of an array 1
if (min1 > arr1[i]) {
min1 = arr1[i];
}
if (min2 > arr2[i]) {
min2 = arr2[i];
}
}
}
Well, the code is very clear, but here's how to make this check, if the first array input 0 1 2 3 4 and the second 0 2 3 4 5 then how to remove this zero.
There are some issues ...
We don't care about the min value for arr2--only for arr1
We must scan all arr2 values for a match to the current/candidate value of arr1
There are some special cases we must handle
Normally, if we're just looking for the min value in arr1 (e.g. arr2 is not a factor), we can do [as you've done]:
int min1 = arr1[0];
And, we could start indexing into arr1 from 1 in the for loop.
But, this fails if:
arr1[0] is the min value in arr1 and that value is in arr2
arr1 and arr2 have identical values [even if they are in a different order].
So, we need an extra [boolean] value to denote whether the min1 value is valid. And, we must start indexing in the for loop from 0.
Here is the refactored code. It is annotated:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <locale.h>
#define A1MAX 5
#define A2MAX 5
int
main(void)
{
setlocale(LC_ALL, "Rus");
// define arrays
int arr1[A1MAX];
int arr2[A2MAX];
printf("Enter integers\n");
for (int i = 0; i < A1MAX; i++) {
if (scanf("%d", &arr1[i]) != 1) {
printf("missing arr1[%d] -- %s\n",i,strerror(errno));
return 2;
}
}
printf("Enter integers\n");
for (int i = 0; i < A2MAX; i++) {
if (scanf("%d", &arr2[i]) != 1) {
printf("missing arr2[%d] -- %s\n",i,strerror(errno));
return 3;
}
}
int nomin = 1;
int min1 = arr1[0];
// check all values in arr1
for (int i = 0; i < A1MAX; i++) {
// current value we're going to test
int val = arr1[i];
// check value if it's a _new_ minimum or we do _not_ yet have a minimum
if ((val < min1) || nomin) {
// scan all elements of arr2, looking for a match to the current
// arr1 value
int match = 0;
for (int j = 0; j < A2MAX; j++) {
match = (val == arr2[j]);
if (match)
break;
}
// if the current value is _not_ in arr2, we have a new minimum
if (! match) {
min1 = val;
nomin = 0;
}
}
}
if (nomin)
printf("there are no elements in arr1 that are not in arr2\n");
else
printf("the minimum element in arr1 not in arr2 is: %d\n",min1);
return nomin;
}
Things get complicated with code tries to maintain multiple indexes into multiple arrays... Things are simplified if you re-use code and break out functions (that can test user input, too)...
#include <stdio.h>
void fill( int arr[], size_t sz ) { // Get user input (with checking)
printf("Enter integers\n");
for( size_t i = 0; i < sz; i++ )
if( scanf( "%d", &arr[i] ) != 1 ) {
fprintf( stderr, "scanf failure\n" );
exit(1);
}
}
// Search for a value in an array. Return index if found, or size if not found
size_t hunt( int val, int arr[], size_t sz ) {
for( size_t i = 0; i < sz; i++ )
if( val == arr[i] )
return i;
return sz;
}
int main() {
#if 0 // Normal with user entry
int arr1[5], arr2[5];
size_t a1sz = sizeof arr1/sizeof arr1[0];
size_t a2sz = sizeof arr2/sizeof arr2[0];
fill( arr1, a1sz );
fill( arr2, a2sz );
#else // less tedious with compile time init of data
int arr1[] = { 0, 1, 2, 3, 4 };
int arr2[] = { 0, 2, 3, 4, 5 };
size_t a1sz = sizeof arr1/sizeof arr1[0];
size_t a2sz = sizeof arr2/sizeof arr2[0];
#endif
size_t gotOne = 0;
for( size_t i = 0; i < a1sz; i++ ) {
// don't bother testing values if got a candidate and value is larger
if( gotOne && arr1[i] >= arr1[ gotOne ] ) continue;
// following is TRUE when not found...
if( hunt( arr1[i], arr2, a2sz ) == a2sz )
gotOne = i + 1;
}
if( gotOne )
printf( "Smallest in arr1 not in arr2 = %u\n", arr1[ gotOne - 1 ] );
else
puts( "No such value matching criteria" );
return 0;
}
Smallest in arr1 not in arr2 = 1
Algorithm
The naive approach to this, and one that works very well for small datasets, is to nest a couple of loops. This approach grows in time complexity very fast. O(m*n) where m is the length of the first array and n is the length of the second array.
Fortunately, we can approach this in a way that does not involve nested loops. This assumes both arrays contain only unique values. If they have duplicates, removing those duplicates would be a necessary step before the below can be performed.
Let's start with a couple of simple arrays:
int foo[] = {1, 4, 7, 9, 2};
int bar[] = {4, 1, 6, 7, 3};
Let's combine them into another array. This is a linear operation.
{1, 4, 7, 9, 2, 4, 1, 6, 7, 3}
Let's then use qsort to sort them. This operation is typically O(n*log n).
{1, 1, 2, 3, 4, 4, 6, 7, 7, 9}
Now, we can do a linear loop over these and find the unique elements. These are the ones present in one but not both of the arrays.
{2, 3, 6, 9}
But this doesn't tell us which is in the first array. That sounds like a nested loop issue. Instead, though, let's combine that with the first array.
{1, 4, 7, 9, 2, 2, 3, 6, 9}
And we'll sort this.
{1, 2, 2, 3, 4, 6, 7, 9, 9}
Now we'll scan for the first repeated number.
2
An implementation
Note: Does not check for malloc errors.
#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a, const void *b) {
int c = *(const int *)a;
int d = *(const int *)b;
if (c == d) return 0;
else if (c < d) return -1;
else return 1;
}
int min_not_in_2nd_array(int *result, int *arr1, size_t m, int *arr2, size_t n) {
int *temp = malloc(sizeof(int) * (m + n));
//if (!temp) return 0;
for (size_t i = 0; i < m; ++i) temp[i] = arr1[i];
for (size_t i = 0; i < n; ++i) temp[m+i] = arr2[i];
qsort(temp, m+n, sizeof(int), cmp);
int *uniques = malloc(sizeof(int) * (m + n));
//if (!uniques) return 0;
size_t n_uniques = 0;
int cur = temp[0] - 1;
size_t cur_count = 0;
for (size_t i = 0; i < m+n; ++i) {
if (i == m+n-1 && temp[i] != temp[i-1]) {
uniques[n_uniques++] = temp[i];
}
else if (temp[i] != cur) {
if (cur_count == 1) uniques[n_uniques++] = cur;
cur = temp[i];
cur_count = 1;
}
else {
cur_count++;
}
}
//for (size_t i = 0; i < n_uniques; ++i) printf("%d ", uniques[i]);
//printf("\n");
int *temp2 = malloc(sizeof(int) * (m + n_uniques));
// if (!temp2) return 0;
for (size_t i = 0; i < m; ++i) temp2[i] = arr1[i];
for (size_t i = 0; i < n_uniques; ++i) temp2[m+i] = uniques[i];
qsort(temp2, m+n_uniques, sizeof(int), cmp);
int found = 0;
for (size_t i = 0; i < m+n_uniques-1; ++i) {
if (temp2[i] == temp2[i+1]) {
*result = temp2[i];
found = 1;
break;
}
}
free(temp);
free(uniques);
free(temp2);
return found;
}
int main(void) {
int foo[] = {1, 4, 7, 9, 2};
int bar[] = {4, 1, 6, 7, 3};
int baz;
if (min_not_in_2nd_array(&baz, foo, sizeof(foo)/sizeof(*foo),
bar, sizeof(bar)/sizeof(*bar))) {
printf("Min not in 2nd array is %d\n", baz);
}
else {
printf("All elements shared.\n");
}
return 0;
}

Split array into two arrays by index even or odd in c

How to separate the even position number of an array from the odd position number in C.
Example
int arr[]= {2,3,4,5,6,7,8,9,1};
int odd[]= {2,4,6,8,1};
int even[] = {3,5,7,9};
Use % to get the remainder. If the remainder is nonzero, then the index is odd, otherwise even. But index starts from 0 and not 1, thus the first element's index is 0 and is even. if you want to sort according to that (seems to be you do), add 1 to index.
#include <stdio.h>
int main() {
int arr[] = {2, 3, 4, 5, 6, 7, 8, 9, 1}; // our array
const size_t max_size = sizeof(arr) / sizeof(arr[0]);
int odd[max_size];
size_t odd_cnt = 0;
int even[max_size];
size_t even_cnt = 0;
for (size_t i = 0; i != max_size; ++i) {
if ((i + 1) % 2) { // if (i + 1) % 2 is nonzero, i + 1 is odd
odd[odd_cnt++] = arr[i];
} else {
even[even_cnt++] = arr[i];
}
}
for (size_t i = 0; i != odd_cnt; ++i) {
printf("%d ", odd[i]);
}
printf("\n");
for (size_t i = 0; i != even_cnt; ++i) {
printf("%d ", even[i]);
}
printf("\n");
return 0;
}

Reversing arrays in C

I am attempting to make a program that takes an array and reverts it backwards however the program must do this to the array in groups of three. So if the user enters the numbers 1, 2, 3, 4, 5, 6 into the array the program will then output: 3, 2, 1, 6, 5, 4.
When I run the current program I get: 3 2 1 4 5 6. If anyone could help me figure out why that would be great as I am a little confused.
Here is my code:
int * numbersProcessFour(int *x, int size)
{
int i = 0, three = 3, six = 6, nine = 9;
if (size < 4)
{
for (i; i < three; i++)
{
reverse_array(x, three);
printf("%d ", x[i]);
}
}else if (size > 3 && size < 7)
{
for (i; i < three; i++)
{
reverse_array(x, three);
printf("%d ", x[i]);
}
for (i; i < 6; i++)
{
reverse_array(x, three);
printf("%d ", x[i]);
}
}
else if (size > 6 && size < 10)
{
for (i; i < three; i++)
{
reverse_array(x, three);
printf("%d ", x[i]);
}
for (i; i < 6; i++)
{
reverse_array(x, three);
printf("%d ", x[i]);
}
for (i; i < 9; i++)
{
reverse_array(x, three);
printf("%d ", x[i]);
}
}
}
void reverse_array(int *x, int length)
{
int i, temp;
for (i = 0; i<length / 2; i++)
{
temp = x[i];
x[i] = x[length - i - 1];
x[length - i - 1] = temp;
}
}
Continuing from your comment to fluter's answer, you may be over thinking it a bit. In order to swap the 1st and 3rd element in each 3-element partition of an array, you simply need to step though the array 3-elements at a time. You need to decide how you will handle any final partial partition, but since your goal is to swap the 1st and 3rd, there is no 3rd in anything less than a full partition, so the logical choice is to ignore any final partial partition.
A variant of what you and fluter have done incorporating a swap would be:
/* reverse 1st and 3rd element in each group of 3 */
void rev3 (int *a, size_t sz)
{
if (sz < 3) return;
size_t i;
for (i = 0; i < sz; i += 3) {
if (sz - i < 3) break;
swap (&a[i], &a[i+2]);
}
}
You can put it together with:
#include <stdio.h>
void rev3 (int *a, size_t sz);
void swap (int *a, int *b);
int main (void) {
int a[] = {1,2,3,4,5,6,7,8,9};
size_t i;
rev3 (a, sizeof a/sizeof *a);
for (i = 0; i < sizeof a/sizeof *a; i++) printf (" %2d", a[i]);
putchar ('\n');
return 0;
}
void swap (int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
Example Use
When compiled and run it will give you the swap (reversal) of the 1st and 3rd elements throughout the array that you specify in your problem.
$ ./bin/revarr3
3 2 1 6 5 4 9 8 7
There is no difference whether you use a separate swap or whether you include that operation in your reversal function. There is also no need to incur the additional overheard of calling a recursive function when a procedural approach will work. Look over all the answers and compare/contrast the differing ways to accomplish your goal.
You have branches for each multiple of 3, that is inefficient. One way to solve it is you can take the array as a split by 3 smaller arrays, and reverse on them. Also, reversing an array of 3 elements is the same as swap the 1st and the 3rd element.
int i;
int temp;
for (i = 0; i < count; i += 3) {
if (i+2 >= count)
break;
temp = arr[i];
arr[i] = arr[i+2];
arr[i+2] = temp;
}
A generalized version of numberProcessFour might look like this.
int reverse_array_mod(int *input, size_t size, int mod)
{
int i, smod;
/* Error: return modulus if size cannot be divided by mod */
if(size%mod)
return size%mod;
smod = size/mod;
for(i=0; i<smod; i++)
reverse_array(input+i*mod, mod);
/* return 0 on success */
return 0;
}
Test
int main(int argc, char **argv)
{
int a[] = {0, 1, 2, 3, 4, 5};
int i, err, mod;
for(mod=1; mod<5; mod++) {
err = reverse_array_mod(a, 6, mod);
if(err) {
fprintf(stderr, "Error %d, modulus %d invalid\n", err, mod);
return err;
}
for(i=0; i<6; i++)
printf("%d\n", a[i]);
printf("\n");
}
return 0;
}
Result:
0
1
2
3
4
5
1
0
3
2
5
4
3
0
1
4
5
2
Error 2, modulus 4 invalid
try this
int *numbersProcessFour(int *x, int size) {
int i;
for(i = 0; i + 3 < size; i += 3){
reverse_array(x + i, 3);
}
if(size - i > 1)
reverse_array(x + i, size - i);
return x;
}

Enumerating Permutations of a set of subsets

I have sets S1 = {s11,s12,s13), S2 = {s21,s22,s23) and so on till SN.I need to generate all the permutations consisting elements of S1,S2..SN.. such that there is only 1 element from each of the sets.
For eg:
S1 = {a,b,c}
S2 = {d,e,f}
S3 = {g,h,i}
My permuations would be:
{a,d,g}, {a,d,h}, {a,d,i}, {a,e,g}, {a,e,h}....
How would I go about doing it? (I could randomly go about picking up 1 from each and merging them, but that is even in my knowledge a bad idea).
For the sake of generality assume that there are 'n' elements in each set. I am looking at implementing it in C. Please note that 'N' and 'n' is not fixed.
It's just a matter of recursion. Let's assume these definitions.
const int MAXE = 1000, MAXN = 1000;
int N; // number of sets.
int num[MAXN]; // number of elements of each set.
int set[MAXN][MAXE]; // elements of each set. i-th set has elements from
// set[i][0] until set[i][num[i]-1].
int result[MAXN]; // temporary array to hold each permutation.
The function is
void permute(int i)
{
if (i == N)
{
for (int j = 0; j < N; j++)
printf("%d%c", result[j], j==N-1 ? '\n' : ' ');
}
else
{
for (int j = 0; j < num[i]; j++)
{
result[i] = set[i][j];
permute(i+1);
}
}
}
To generate the permutations, simply call permute(0);
If you know exactly how many sets there are and it's a small number one might normally do this with nested loops. If the number of sets is greater than 2 or 3, or it is variable, then a recursive algorithm starts to make sense.
And if this is homework, it's likely that implementing a recursive algorithm is the object of the entire assignment. Think about it, for each set, you can call the enumeration function recursively and have it start enumerating the next set...
If they are in a container, just iterate through each:
#include <stdio.h>
int main(void)
{
int set1[] = {1, 2, 3};
int set2[] = {4, 5, 6};
int set3[] = {7, 8, 9};
for (unsigned i = 0; i < 3; ++i)
{
for (unsigned j = 0; j < 3; ++j)
{
for (unsigned k = 0; k < 3; ++k)
{
printf("(%d, %d, %d)", set1[i], set2[j], set3[k]);
}
}
}
return 0;
}
Generic solution:
typedef struct sett
{
int* nums;
int size;
} t_set;
inline void swap(t_set *set, int a, int b)
{
int tmp = set->nums[a];
set->nums[a] = set->nums[b];
set->nums[b] = tmp;
}
void permute_set(t_set *set, int from, void func(t_set *))
{
int i;
if (from == set->size - 1) {
func(set);
return;
}
for (i = from; i < set->size; i++) {
swap(set, from, i);
permute_set(set, from + 1, func);
swap(set, i, from);
}
}
t_set* create_set(int size)
{
t_set *set = (t_set*) calloc(1, sizeof(t_set));
int i;
set->size = size;
set->nums = (int*) calloc(set->size, sizeof(int));
for(i = 0; i < set->size; i++)
set->nums[i] = i + 1;
return set;
}
void print_set(t_set *set) {
int i;
if (set) {
for (i = 0; i < set->size; i++)
printf("%d ", set->nums[i]);
printf("\n");
}
}
int main(int argc, char **argv)
{
t_set *set = create_set(4);
permute_set(set, 0, print_set);
}
This is a fairly simple iterative implementation which you should be able to adapt as necessary:
#define SETSIZE 3
#define NSETS 4
void permute(void)
{
char setofsets[NSETS][SETSIZE] = {
{ 'a', 'b', 'c'},
{ 'd', 'e', 'f'},
{ 'g', 'h', 'i'},
{ 'j', 'k', 'l'}};
char result[NSETS + 1];
int i[NSETS]; /* loop indexes, one for each set */
int j;
/* intialise loop indexes */
for (j = 0; j < NSETS; j++)
i[j] = 0;
do {
/* Construct permutation as string */
for (j = 0; j < NSETS; j++)
result[j] = setofsets[j][i[j]];
result[NSETS] = '\0';
printf("%s\n", result);
/* Increment indexes, starting from last set */
j = NSETS;
do {
j--;
i[j] = (i[j] + 1) % SETSIZE;
} while (i[j] == 0 && j > 0);
} while (j > 0 || i[j] != 0);
}
You may think about the elements of a set as values of a cycle counter. 3 sets means 3 for cycles (as in GMan answare), N sets means N (emulated) cycles:
#include <stdlib.h>
#include <stdio.h>
int set[3][2] = { {1,2}, {3,4}, {5,6} };
void print_set( int *ndx, int num_rows ){
for( int i=0; i<num_rows; i++ ) printf("%i ", set[i][ndx[i]] );
puts("");
}
int main(){
int num_cols = sizeof(set[0])/sizeof(set[0][0]);
int num_rows = sizeof(set)/sizeof(set[0]);
int *ndx = malloc( num_rows * sizeof(*ndx) );
int i=0; ndx[i] = -1;
do{
ndx[i]++; while( ++i<num_rows ) ndx[i]=0;
print_set( ndx, num_rows );
while( --i>=0 && ndx[i]>=num_cols-1 );
}while( i>=0 );
}
The most efficient method I could come up with (in C#):
string[] sets = new string[] { "abc", "def", "gh" };
int count = 1;
foreach (string set in sets)
{
count *= set.Length;
}
for (int i = 0; i < count; ++i)
{
var prev = count;
foreach (string set in sets)
{
prev = prev / set.Length;
Console.Write(set[(i / prev) % set.Length]);
Console.Write(" ");
}
Console.WriteLine();
}

Resources