Finding all possible combinations without duplicating selections? - c

How would you write something that selects all possible combinations of triples from an array {1, 2, 3, ..., N-1, N} without duplicates? This is from a recently-held programming competition. N is a multiple of 3.
Example using array {1,2,3,4,5,6}:
C_1 = { {1,2,3}, {4,5,6} }
C_2 = { {1,2,4}, {3,5,6} }
C_3 = { {1,2,5}, {3,4,6} }
are all valid, but
C_bad1 = { {1,2,3}, {3, 4, 5} }
C_bad2 = { {1,2,4}, {3, 5, 6}, {1, 2, 5} }
are not.

you have (N!) / ( ((3!)^(N/3)) * ((N/3)!)) position (prove) . you can just use recursive algorithm for provide all possible combinations of triples from an array {1, 2, 3, ..., N-1, N} without duplicates.
but for produce one of them you can use any idea such as user1952500 idea(though This algorithm also generates (N/3)! position duplicate) or every, for example you invariant last-(N-6)-member and put your solution for first-6-member in start of your result.(this algorithm do not generate duplicate position)
recursive solution:
void combtriples(int begin)
{
for(int i=1;i<=(n/3);i++)
for(int j=1;j<=(n/3);j++)
for(int k=1;k<=(n/3);k++)
{
if ((mark[i]<3) && (mark[j]<3) && (mark[k]<3))
{
count-position++;
c[count][3]=begin;
c[count][4]=begin+1;
c[count][5]=begin+2;
mark[i]++;
mark[j]++;
mark[k]++;
count-member-flase=count-member-flase+3;
if (count-member-flase > 0)
{
combtriples(begin+3);
}
}
}
}
int main()
{
int mark[];
int c[][];
count-position=0;
count-member-flase=0;
combtriples(1);
return 0;
}

Since N is a multiple of 3 we can solve it using a trick:
Generate all permutations of the numbers in ascending order
For each permutation,
partition the numbers into sets of 3 directly (0-2, 3-6,..., N-2..N)
That should give you your result without much fancy work.
EDIT: I was waiting for someone to spot the issue with the above and it was indeed spotted. The way to fix repetitions is to have an additional step:
Step 3: If any triple is lexicographically unsorted form discard the set. Else continue.

#include <stdio.h>
#define SEL_NUM 3
#define LIST_SIZE 6
void printset(int *list, int *map, int size);
void select(int *list, int *map, int n, int size, int start);
int main(int argc, const char **argv) {
int list[LIST_SIZE] = {1, 2, 3, 4, 5, 6};
int map[LIST_SIZE] = {0};
select(list, map, SEL_NUM, LIST_SIZE, 0);
return 0;
}
void select(int *list, int *map, int n, int size, int start) {
if (n == 0) {
printset(list, map, size);
return;
}
for (int i = start; i < size; i++) {
map[i] = 1;
select(list, map, n - 1, size, i + 1);
map[i] = 0;
}
}
void printset(int *list, int *map, int size) {
int list1[SEL_NUM], list2[SEL_NUM], list1cnt = 0, list2cnt = 0;
for (int i = 0; i < size; i++)
if (map[i])
list1[list1cnt++] = list[i];
else
list2[list2cnt++] = list[i];
for (int i = 0; i < list1cnt; i++)
printf(" %d ", list1[i]);
printf(" -- ");
for (int i = 0; i < list2cnt; i++)
printf(" %d ", list2[i]);
printf("\n");
}

Let's consider how many such distinct triplet-sets exist for N. First define T = floor(N/3) as the number of triplets in each set supported by N elements. Then note that since duplicate triplets are not desired, the triplets in each triplet set can be sorted ascending by first element without loss of generality. Then the total number of triplet-sets for N is:
product as t: 0 -> T-1 of ( (N - 3*t - 1) * (N - 3*t - 2) / 2 )
From this formula it is straightforward to see how to build the (brute-force) algorithm to generate the triplets.
Update: The above works only for N % 3 == 0. I am working on a generalization now. Forced; see comment by OP
Cases:
N<3 yields 0
N=3 yields 1
N=6 yields (5 * 4 / 2) * (2 * 1 / 2) = 10
N=9 yields (8 * 7 / 2) * (5 * 4 / 2) * (2 * 1 / 2) = 28 * 10 = 280
As you are in a programming competition, I assume you dont need any code.
Update #2:
Note that to automatically eliminate duplicates, the first element of each triplet must be forced to the lowest numbered unselected element .

Related

Speeding up the process to find elements which are divisible by elements of the same array

I came across a problem:
Given an array, find the max count of this array, where count for an element in the array is defined as the no. of elements from this array which can divide this element.
Example: max count from the array [2,2,2,5,6,8,9,9] is 4 as 6 or 8 can be divided by 2,2,2 and by themselves.
My approach is:
Sort the array.
Make a set from this array (in a way such that even this set is sorted in non-descending order).
Take another array in which the array indices are initialized to the no. of times an element appears in the original array. Example: in above example element '2' comes three times, hence index '2-1' in this new array will be initialized to 3, index '9-1' will be initialized to 2 as '9' comes 2 times in this array.
Using two loops I am checking the divisibility of largest (moving largest to smallest) element in the set with smallest (moving smallest to largest) element of the set.
Conditions
1 <= arr[i] <= 10000
1 <= i <= 10000
#include <stdio.h>
#include <stdlib.h>
#include<limits.h>
int cmp(const void *a, const void *b)
{
return (*(int*)a - *(int*)b);
}
void arr_2_set(int *arr, int arr_size,int *set, int *len)
{
int index = 0;
int set_len = 0;
int ele = INT_MIN;
qsort(arr,arr_size,sizeof(int),cmp);
while(index < arr_size)
{
if(ele != arr[index])
{
ele = arr[index];
set[set_len] = ele;
set_len++;
}
index++;
}
*len = set_len;
}
int main(void)
{
int arr[]={2,2,2,5,6,8,9,9}; //array is already sorted in this case
int size = sizeof(arr)/sizeof(arr[0]);
int set[size];
int index = 0;
int set_len = 0;
arr_2_set(arr, size, set, &set_len); //convert array to set - "set_len" is actual length of set
int rev = set_len-1; //this will point to the largest element of set and move towards smaller element
int a[100000] = {[0 ... 99999] = 0}; //new array for keeping the count
while(index<size)
{
a[arr[index] -1]++;
index++;
}
int half;
int max=INT_MIN;
printf("set len =%d\n\n",set_len);
for(;rev>=0;rev--)
{
index = 0;
half = set[rev]/2;
while(set[index] <= half)
{
if(set[rev]%set[index] == 0)
{
a[set[rev] -1] += a[set[index]-1]; //if there are 3 twos, then 3 should be added to count of 8
//printf("index =%d rev =%d set[index] =%d set[rev] =%d count = %d\n",index,rev,set[index],set[rev],a[set[rev] -1]);
}
if(max < a[set[rev]-1])
max = a[set[rev]-1];
index++;
}
}
printf("%d",max);
return 0;
}
Now my question is how can I speed up this program? I was able to pass 9/10 test cases - for the 10th test case (which was hidden), it was showing "Time Limit Exceeded".
For creating a set and finding the count - use a single while loop, when the size of array is big then using a single loop will matter a lot.
In the later half section where two nested loops are there - don't go from largest to smallest element. Go from smallest to largest element while checking which largest element with index lower than the current element can divide this element, add the count of that element to the current element's count (using set[i]/2 logic will still hold here). This way you'll avoid a lot of divisions. Example: if set is {2,3,4,8} in this case, lets say your current position is 8 then you go down till largest element smaller than or equal to 8 which can divide 8 and add it's count to current element's (8) count.
for the 10th test case (which was hidden), it was showing "Time Limit Exceeded".
That may suggest a more time efficient algorithm is expected.
The posted one, first sorts the array (using qsort) and then copies only the unique values into another array, set.
Given the constraints on the possible values, it may be cheaper to implement a counting sort algorithm.
The last part, which searches the maximum number of dividends, can then be implemented as a sieve, using an additional array.
#include <stdio.h>
enum constraints {
MAX_VALUE = 10000
};
int count_dividends(size_t n, int const *arr)
{
// The actual maximum value in the array will be used as a limit.
int maxv = 0;
int counts[MAX_VALUE + 1] = {0};
for (size_t i = 0; i < n; ++i)
{
if ( counts[arr[i]] == 0 && arr[i] > maxv )
{
maxv = arr[i];
}
++counts[arr[i]];
}
// Now, instead of searching for the dividends of an element, it
// adds the number of factors to each multiple.
// So, say there are two elements of value 3, it adds 2 to all
// the multiples of 3 in the total array.
int totals[MAX_VALUE + 1] = {0};
int count = 0;
// It starts from 2, it will add the numbers of 1's once, at the end.
for (int i = 2; i <= maxv; ++i)
{
// It always skips the values that weren't in the original array.
if ( counts[i] != 0 )
{
for ( int j = 2 * i; j <= maxv; j += i)
{
if ( counts[j] != 0 )
totals[j] += counts[i];
}
if ( counts[i] + totals[i] > count )
{
count = counts[i] + totals[i];
}
}
}
return count + counts[1];
}
int main(void)
{
{
int a[] = {2, 4, 5, 1, 1, 6, 14, 8, 2, 12, 1, 13, 10, 2, 8, 5, 9, 1};
size_t n = (sizeof a) / (sizeof *a);
// Expected: 10, because of 1 1 1 1 2 2 2 4 8 8
printf("%d\n", count_dividends(n, a));
}
{
int a[] = {2, 4, 5, 2, 7, 10, 9, 8, 2, 4, 4, 6, 5, 8, 4, 7, 6};
size_t n = (sizeof a) / (sizeof *a);
// Expected: 9, because of 2 2 2 4 4 4 4 8 8
printf("%d\n", count_dividends(n, a));
}
}

C/C++ Bitwise operation university problem

Problem
Given a sequence of N integer values(possible values of N: 3, 5, 7, 9, 11 ...). Using at most one conditional operator(or conditional ternary operation), the program must determine whether it is true that every three elements the sequence increases and then decreases(sine sequence). Loops in a program can only be used to enumerate elements of a sequence.
Example
* *
* * * *
* * *
What I think
int compare_num(int num1, int num2)
{
return (int)(((num1 + num2) - sqrt((num1 - num2) * (num1 - num2))) / 2);
}
bool_t is_increasing2(int arr[], int size)
{
int tmin = arr[0];
int res = 0;
for (int i = 0; i < size - 1; i++)
{
tmin = compare_num(arr[i + 1], tmin);
res = tmin ^ arr[i + 1];
}
return res;
}
int main(void)
{
int arr[] = {10, 9, 8, 7, 6, 5};
int arr2[] = {1, 2, 3, 4, 5};
int res = is_increasing2(arr2, N);
if (res == 0)
{
printf("Decreasing\n");
}
else
{
printf("Increasing\n");
}
return 0;
}
I use this code to check, that sequence is increasing or not. But now I need to use it to check, that my sine sequence is sine and I can't use more ternary or if/else operators
There is what I have to real problem
bool_t is_increasingSine2(int arr[], int size){
int tmax = 0;
int res = 0;
for(int i = 0; i < size; i += 3){
for(int j = i; j < i + 2 && j < size - 1; j++){
tmax = compare_num(arr[j], arr[j + 1]);
res = tmax ^ arr[j + 1];
}
//There if res == 0 part of sine is increasing otherwise not, but what to do next???
}
return 0;
}
You do not need any conditional operators for this problem, but we will use one in the printf since it is suggested.
Rephrasing the problem as a requirement that each of the first two elements must be less than the one that follows it and each of the next two must be greater than the one that follows it makes it fairly simple to test:
#include <stdio.h>
#include <stdlib.h>
/* Given array Array with N elements, return true iff each of the first two
elements is less than the one following it, each of the next two is greater
than the one following it, and then repeating in a cycle until the end of
the array.
*/
static _Bool TestCriterion(int Array[], size_t N)
{
/* Iterate through each element of the array except the last (the one
with index N-1), since there is no element following the last element
to compare it to.
*/
for (size_t i = 0; i < N-1; ++i)
{
/* Set phase to 0 for the first two elements, 1 for the next two,
then 0, 1, 0, 1… Note that while "i & 2" has the value 0 or 2,
assigning it to a Boolean produces a value of 0 or 1.
*/
_Bool Phase = i & 2;
/* For phase 0, test whether the element with index i is less than
the element with index i+1, and return false (0) if it is not. For
phase 1, compare element i+1 with element i.
*/
if (! (Array[i+Phase] < Array[i+1-Phase]))
return 0;
}
// All elements passed the test, so return true (1).
return 1;
}
/* Compute the number of elements in an array by dividing the size of the
array by the size of an element.
*/
#define NumberOf(a) (sizeof (a) / sizeof *(a))
int main(void)
{
int Array[] = { 1, 2, 3, 2, 1, 2, 3, 2, 1 };
printf("%s.\n", TestCriterion(Array, NumberOf(Array)) ? "Passes" : "Fails");
}

Repeating an Array in C

I was wondering how to repeat an array in C any number of times.
Let's say I have an array like: int Array[4] = [1, 2, 3, 4]
Is there a simple way to get an array: int Array2[8] = [1, 2, 3, 4, 1, 2, 3, 4]
by doing some operation on Array[4]?
I'm pretty sure this is a bad idea, which will hit you in the foot later, but maybe try
#define VALUES 1, 2, 3, 4
int a[] = { VALUES, VALUES, VALUES, VALUES };
You can try this...to get an idea on how you can do it.
for(int i=0;i<8;i++) {
array2[i]=array[i%4];
}
This should be a good way to repeat an array in C any number of times because your explanation is not a good one. The modulo operation returns integers from [0,REPEAT) so doing +1 you have integers in [1,REPEAT].
Here is the code:
#define N 5
#define REPEAT 2
int main(){
int arr[N];
for(int i = 0;i<N;i++){
arr[i] = (i % REPEAT) + 1;
printf("%d\n",arr[i]);
}
return 0;
}
Output:
1
2
1
2
1
The simplest way to do this might be to use a VLA, sized to whatever you require, and filled by using the modulus operator. Disadvantages include the inability to return such an array from a function, and silent failure when the VLA can't be allocated for some reason. Of course, VLA's were introduced in C99, and then made optional in C11. Though they are commonly available, you may opt for the next method.
Perhaps a more reliable approach uses a function that allocates space for the new array. If malloc() fails, a null pointer is returned, so it is the responsibility of the caller to check this. It is also the callers responsibility to free the allocation when through with it.
#include <stdio.h>
#include <stdlib.h>
void print_arr(size_t, int *);
int * expand_array(size_t, int *, size_t);
int main(void)
{
int input_arr[] = {1, 2, 3, 4};
size_t input_arr_sz = sizeof input_arr / sizeof *input_arr;
size_t new_arr_sz = 17;
/* Method 1: VLA */
int new_arr_1[new_arr_sz];
for (size_t i = 0; i < new_arr_sz; i++) {
new_arr_1[i] = input_arr[i % input_arr_sz];
}
print_arr(new_arr_sz, new_arr_1);
/* Method 2: function with malloc() */
int *new_arr_2 = expand_array(input_arr_sz, input_arr, new_arr_sz);
if (new_arr_2) {
print_arr(new_arr_sz, new_arr_2);
}
free(new_arr_2);
return 0;
}
void print_arr(size_t sz, int *arr)
{
for (size_t i = 0; i < sz; i++) {
printf("%3d", arr[i]);
}
putchar('\n');
}
int * expand_array(size_t input_sz, int *arr, size_t output_sz)
{
int *new_arr = malloc(sizeof *new_arr * output_sz);
if (new_arr) {
for (size_t i = 0; i < output_sz; i++) {
new_arr[i] = arr[i % input_sz];
}
}
return new_arr;
}
Program output:
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1
I figured it out!
So if I have an array: int Array[4] = [1, 2, 3, 4];
To repeat it I used two for loops as such:
int Array2[8];
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++)
{
Array2[i*4 + j] = Array[j];
}
}
The i*4 + j made it so I could count past four in the assignment of Array2

Splitting a 2D array to an array of smaller 2D arrays in C

Given:
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
I want to split the 2d array (struct MATRIX) into the an array of struct MATRIX
given a chunksize CS:
assume cs to be 2,
the answer would be
Seg[0]:
1 2
1 2
1 2
Seg[1]:
3 4
3 4
3 4
....
Seg[3]:
7 8
7 8
7 8
Here is my Matrix Struct:
typedef struct MATRIX {
int nrow;
int ncol;
int **element;
} MATRIX;
and here is the function the seperates them:
void SegmentMatrix(MATRIX input,MATRIX* segs,int Chunksize, int p) {
int i,j,r;
//Allocate segs
for (i = 0; i<p;i++)
{
CreateMatrix(&(segs[i]),input.nrow ,Chunksize,0);
}
//Now Copy the elements from input to the segs
//where seg0 takes from 0 to cs cols of a, and all their rows, and seg1 takes from cs to 2cs ...
printf("Stats:\n\t P: %d\t CS: %d\n",p,Chunksize);
for (r = 0; r<p; r++) {
for (i = 0; i<input.nrow;i++) {
for (j = r*Chunksize; j<r*Chunksize+Chunksize-1; j++) {
//I tried (&(segs[r]))->element... Doesn't work, produces wrong data
segs[r].element[i][j] = input.element[i][j];
}
}
PRINTM(segs[r]);
}
}
Note that PRINTM basically prints the matrix, it knows the limits by checking segs[r].nrow and ncol
and CreateMatrix takes the following inputs (&matrix, number of rows, number of colums, filltype) and mallocs from within.
filltype:
0- generates zeroth matrix
1- generates identity
else A[i][j] = j; for simplicity
The problem is that the if i print the matrices Segs[i], they all come down with their default value given by CreateMatrix, and not the newly added values.
CLARIFICATION:
Okay, so if you guys check that last PRINTM in SegmentMatrix function, it outputs the matrices as if the for loops didn't happen, aka, i can delete the for loops and would get the same output..
did i do something wrong in this line (taken from the SegmentMatrix)
Segs[r].element[i][j] = input.element[i][j];
I don't see why and what you are manipulating with multiplication by ChunkSize and r (which is uninitialized anyway), I'd suggest simplifying the code (rule of thumb: if it seems messy, it's too complex). All you need is a 3-dimensional array to store the array of chunks, and modulo arithmetic plus integer division to insert into the appropriate column of the appropriate chunk:
/* the variable-sized dimension of the `chunks' argument is w / chsz elements big
* (it's the number of chunks)
*/
void split(int h, int w, int mat[h][w], int chsz, int chunks[][h][chsz])
{
/* go through each row */
for (int i = 0; i < h; i++) {
/* and in each row, go through each column */
for (int j = 0; j < w; j++) {
/* and for each column, find which chunk it goes in
* (that's j / chsz), and put it into the proper row
* (which is j % chsz)
*/
chunks[j / chsz][i][j % chsz] = mat[i][j];
}
}
}
Demonstration, a. k. a. how to call it:
int main(int agrc, char *argv[])
{
const size_t w = 8;
const size_t h = 3;
const size_t c = 2;
int mat[h][w] = {
{ 1, 2, 3, 4, 5, 6, 7, 8 },
{ 1, 2, 3, 4, 5, 6, 7, 8 },
{ 1, 2, 3, 4, 5, 6, 7, 8 }
};
int chunks[w / c][h][c];
split(h, w, mat, c, chunks);
for (int i = 0; i < w / c; i++) {
for (int j = 0; j < h; j++) {
for (int k = 0; k < c; k++) {
printf("%3d ", chunks[i][j][k]);
}
printf("\n");
}
printf("\n\n");
}
return 0;
}
Question was unclear . so i thought he wanted just to know how to achieve this.
So i wrote this simple Pseudo code . Otherwise accept my apologize :
matrix[i] matrix
//matrixes total column size should be bigger big 2d array column size
first condition check: sum(matrix[i].colsize)>=big2d.colsize
//in this simple code raw sizes must be equal
second condition: for all i matrix[i].rawsize=big2d.rawsize
//if columns sizes will be equal the algorithm could be simplified , does not mean optimized
//splitting big2d into matrixes
for (int br=0;br<big2d.rawsize;br++){
i=0;//store matrix index
int previndex=0;//store offset for next matrix
for(int bc=0;bc<big2d.colsize;bc++){
matrix[i].val[bc-previndex][br]=big2d.val[bc][br]; //assign (bc,br)
if(bc-previndex==matrix[i].colsize-1){
i++; //move to next matrix;//if we not have next matrix then break;
previndex=bc+1;
}
/*if it be for equal chunks matrixes offset can be calculated this way too
matrix[bc/chunk].val[bc%chunk][br]=big2d.val[bc][br];
*/
}//loop columns
}//loop raws

Permutation of char array In C

I have been working on an algorithm to find all permutations of the elements of a char array for a few days now and well it just doesn't seem to work.
The char array is an **array, which I iterate through based on the number entered by the user and I then malloc space for each word(40 chars each). The number entered by the user is the length of the array, and it is the number they expect to enter. This part works as expected.
What I am having trouble with is iterating through the char array and calculating the permutation of the entire set(**array). I then want to have another char array consisting of all permutations of the set. Now just permutations of the unit indices's of **array, not each indices's individual characters.
Does anybody have any tips on how to successfully do this, regardless of the size of the initial set? I assume it would be much easier if the set size where static.
My starting array looks like this as an example
char *array[] = {
"Hello",
"Calculator",
"Pencil",
"School Bus"
};
Which would be held in **array, with "Hello" in array[0] and "School Bus" in array[3], with '\0' at the end of each.
I want the permutation to be on the indices, not the characters.
So
"Hello"
.
.
.
"School BusSchool BusSchool BusSchool Bus"
Here's a dumb permutation generator (up to N=32... or 64).
#include <stdio.h>
const int N = 5;
int x[N];
int main( void ) {
int i,j;
x[0]=-1;
unsigned mask = -1; // unused numbers
for( i=0;; ) {
for( j=x[i]+1; j<N; j++ ) { // check remaining numbers
if( (mask>>j)&1 ) { // bit j is 1 -> not used yet
x[i] = j; // store the number
mask ^= (1<<x[i]); // mask used
// try going further, or print the permutation
if( ++i>=N ) { for( j=0; j<N; j++ ) printf( "%3i", x[j] ); printf( "\n" ); }
else x[i]=-1; // start next cell from 0
break;
}
}
// go back if there's no more numbers or cells
if( (j>=N) || (i>=N) ) {
if( --i<0 ) break;
mask ^= (1<<x[i]);
}
}
}
By your edit, I am taking that you have an array of four elements. Your desired output is a combination of these elements and is the concatenation of between one and four elements. The output may contain an input element more than once. Is this a correct summary?
If so, think of your output in four cases: for output generated from one, two, three, or four elements. For output generated from n elements, you have n^n possibilities. For all four of these cases combined, this gives you 1^1 + 2^2 + 3^3 + 4^4 = 288 possible outputs.
Your 1-element output permutations are simply: 0, 1, 2, 3
Your 2-element output permutations can be generated by the pseudo-code:
for i = 0 to 3 {
for j = 0 to 3 {
next_permutation = {i, j}
}
}
For 3- and 4-element output, permutations can be generated using three and four nested loops, respectively. For some arbitrary number of input elements x, you can generate permutations using the same technique with x number of nested loops. Be warned that the number of loops requires grows exponentially with the number of input elements, so this can get ugly fairly fast.
You can use the numbers from these permutations as indices into your initial array in order to generate the output as strings (as in your sample).
Update: Here's a recursive pseudo-code function that can generate these pseudo-permutations:
int output_array[dimension] = {0};
generate_combinations (unsigned dimension, int index) {
for i = 0 to (dimension-1) {
output_array[index] = i;
if index == 0
next_permutation = output_array
else
generate_combinations(dimension, index-1)
endif
}
}
You would use this with dimension set to the number of elements in your input array and index = dimension - 1. Hopefully, your input dimensionality won't be so large that this will recurse too deeply for your CPU to handle.
Here's one solution. Remember that the time complexity is factorial, and that if you're storing all the permutations then the space required is also factorial. You're not going to be able to do very many strings.
void CalculatePermutations(unsigned long permSize, const char** candidates, const char** currentPerm, unsigned long currentPermIdx, const char** ouputBuffer, unsigned long* nextOutputIdx)
{
//base case (found a single permutation)
if(currentPermIdx >= permSize){
unsigned long i = 0;
for(i = 0; i < permSize; ++i){
ouputBuffer[*nextOutputIdx] = currentPerm[i];
(*nextOutputIdx)++;
}
return;
}
//recursive case
unsigned long i = 0;
for(i = 0; i < permSize; ++i){
if(candidates[i]){
currentPerm[currentPermIdx] = candidates[i]; //choose this candidate
candidates[i] = NULL; //mark as no longer a candidate
CalculatePermutations(permSize, candidates, currentPerm, currentPermIdx + 1, ouputBuffer, nextOutputIdx);
candidates[i] = currentPerm[currentPermIdx]; //restore this as a possible candidate
}
}
}
int main(int argc, char** argv)
{
const char* allStrings[8] = {"0", "1", "2", "3", "4", "5", "6", "7"};
static const char* allPermutations[322560]; // = fact(8) * 8
const char* permBuffer[8];
unsigned long nextOutputIdx = 0;
CalculatePermutations(8, allStrings, permBuffer, 0, allPermutations, &nextOutputIdx);
for(unsigned long i = 0; i < 322560; ++i){
printf("%s", allPermutations[i]);
if(i % 8 == 7){
printf("\n");
} else {
printf(", ");
}
}
return 0;
}
here my code that give us the r-permutation of a n! possible permutations. Code works with all kind of size (I only check with 3!, 4!, 5! and 8! and always works correct, so I suppouse that works right):
#include <stdio.h>
#include <stdint.h>
enum { NPER = 4, };
static const char *DukeQuote[NPER] = {
"Shake it, baby!",
"You wanna dance?",
"Suck it down!",
"Let's rock!",
};
void fill(const uint32_t, uint32_t * const);
void fact(const uint32_t, uint32_t * const);
void perm(uint32_t, const uint32_t, const uint32_t * const, uint32_t * const);
int main(void)
{
uint32_t f[NPER+1];
uint32_t p[NPER];
uint32_t r, s;
/* Generate look-up table for NPER! factorial */
fact(NPER, f);
/* Show all string permutations */
for(r = 0; r < f[NPER]; r++)
{
perm(r, NPER, f, p);
for(s = 0; s < NPER; s++)
printf("%s, ", DukeQuote[p[s]]);
printf("\n");
}
return 0;
}
/* Generate look-up table for n! factorial.
That's a trick to improve execution */
void fact(const uint32_t n, uint32_t * const f)
{
uint32_t k;
for(f[0] = 1, k = 1; k <= n; k++)
f[k] = f[k-1] * k;
}
/* Fill the vector starting to 0 up to n-1 */
void fill(const uint32_t n, uint32_t * const p)
{
uint32_t i;
for(i = 0; i < n; i++)
p[i] = i;
}
/* Give us the r-permutation of n! possible permutations.
r-permutation will be inside p vector */
void perm(uint32_t r, const uint32_t n, const uint32_t * const f, uint32_t * const p)
{
uint32_t i, j;
fill(n, p);
for(i = n-1; i > 0; i--)
{
uint32_t s;
j = r / f[i];
r %= f[i];
s = p[j];
for(; j < i; j++)
p[j] = p[j+1];
p[i] = s;
}
}
For instance, if you want the first permutation of 4! possibles then:
perm(0, 4, f, p)
where p will have:
p = [3, 2, 1, 0]
Take care, 0 is 1th, 1 is 2th, and so on.
You can use p[i] like indices in your string array, how I've used in DukeQuote array.
PD1: This code implements the correct definition of a permutation (A r-permutation is a bijection. The cardinal of the set of all bijections N_n to N_n is exactly n!)
PD2: I hope that my mistakes in my poor English doesn't influence in the goal of my explanation.

Resources