Boolean Table in 2D array C - c
I have some dificulties in creating the following array. My task is to fill using recursion a 2D array with all the possible combinations of 0 and 1 taken m times in lexical order. Mathematically speaking there are 2 ^ m combinations.My program just fills the first 3 rows of the array with the same order 0 1 0 1 and then just prints for the rest of the rows 0 0 0 0.
Example
m=4
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
1 0 0 0
1 0 0 1
1 0 1 0
1 0 1 1
1 1 0 0
1 1 0 1
1 1 1 0
1 1 1 1
This is my code so far and I appreciate if someone could correct it and explain me what I am doing wrong as I can't spot the mistake myself
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
void *safeMalloc(int n) {
void *p = malloc(n);
if (p == NULL) {
printf("Error: malloc(%d) failed. Out of memory?\n", n);
exit(EXIT_FAILURE);
}
return p;
}
void combine(int** arrTF,int m,int n,int row,int col){
if(m==0){
if(row<pow(2,m)){
row++;
combine(arrTF,n,n,row,0);
}else{
return;
}
}else{
arrTF[row][col]=0;
col++;
combine(arrTF,m-1,n,row,col);
arrTF[row][col]=1;
col++;
combine(arrTF,m-1,n,row,col);
}
}
int main(int argc, char *argv[]) {
int m
scanf("%d",&m);
int** arrTF;
arrTF = safeMalloc(pow(2,m)*sizeof(int *));
for (int r=0; r < pow(2,m); r++) {
arrTF[r] = safeMalloc(m*sizeof(int));
}
for(int i=0;i<pow(2,m);i++){
for(int j=0;j<m;j++){
arrTF[i][j]=0;
}
}
combine(arrTF,m,m,0,0);
for(int i=0;i<pow(2,m);i++){
for(int j=0;j<m;j++){
printf("%d ",arrTF[i][j]);
}
printf("\n");
}
return 0;
}
You want all the possible (2^m) combinations of 0's and 1's taken m times in lexical order and you are using a 2D array to store the result.
Things would be very easy if you just want to print all the possible combination of 0's and 1's instead of storing it in 2D array and printing array later.
Storing a combination of 0's and 1's to 2D array is a little bit tricky as every combination is one element of your 2D array.
You want to generate the combination of 0's and 1's in accordance with the recursive algorithm.
So, let's say, at some stage if your algorithm generates the combination 0010 which is stored in an element in 2D array.
And the next combination would be 0011 which the recursive algorithm will generate just by changing the last number from 0 to 1 in the last combination (0010).
So, that means everytime when a combination is generated, you need to copy that combination to its successive location in 2D array.
For e.g. if 0010 is stored at index 2 in 2D array before the algorithm starts computing the next combination, we need to do two things:
Copy the elements of index 2 to index 3
Increase the row number so that last combination will be intact
(Say, this is 2D array)
|0|0|0|0| index 0
|0|0|0|1| index 1
|0|0|1|0| index 2 ---> copy this to its successive location (i.e. at index 3)
|0|0|1|1| index 3 ---> Last combination (index 2) and the last digit is changed from 0 to 1
.....
.....
.....
This we need to do for after every combination generated.
Now, I hope you got where you are making the mistake.
Few practice good to follow:
If you want to allocate memory as well as initialized it with 0, use calloc instead of malloc.
Any math function you are calling again and again for the same input, it's better to call it once and store the result in a variable and use that result where ever required.
Do not include any header file which is not required in your program.
Once done, make sure to free the dynamically allocated memory in your program.
I have made the corrections in your program:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void *safeMalloc(size_t n, size_t size) {
void *p = calloc(n, size);
if (p == NULL) {
printf("Error: calloc(%zu) failed. Out of memory!\n", n);
exit(EXIT_FAILURE);
}
return p;
}
void deallocate(int ** ptr, int row) {
for(int i = 0; i<row; i++)
free(ptr[i]);
free(ptr);
}
void combine(int **arrTF, int m, int max_col, int max_row) {
static int row;
if(m==0){
int i;
if (row<(max_row - 1))
{
for(i=0; i<max_col; i++)
arrTF[row+1][i] = arrTF[row][i];
}
row++;
return;
} else {
arrTF[row][max_col-m] = 0;
combine(arrTF, m-1, max_col, max_row);
arrTF[row][max_col-m] = 1;
combine(arrTF, m-1, max_col, max_row);
}
}
int main(int argc, char *argv[]) {
int** arrTF;
int m, max_row;
printf ("Enter number: \n");
scanf("%d", &m);
max_row = pow(2, m);
arrTF = safeMalloc(max_row, sizeof(int *));
for (int r=0; r<max_row; r++) {
arrTF[r] = safeMalloc(m, sizeof(int));
}
combine(arrTF, m, m, max_row);
for(int i=0; i<max_row; i++) {
for(int j=0; j<m; j++) {
printf("%d ", arrTF[i][j]);
}
printf("\n");
}
deallocate(arrTF, max_row);
return 0;
}
Output:
$ ./a.out
Enter number:
2
0 0
0 1
1 0
1 1
$ ./a.out
4
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
1 0 0 0
1 0 0 1
1 0 1 0
1 0 1 1
1 1 0 0
1 1 0 1
1 1 1 0
1 1 1 1
Hope this helps.
Related
logical multiplication of matrices A and B by the operation "AND" and "OR" in C
This is the question: A logical matrix is a matrix in which all its elements are either 0 or 1. We define logical multiplication of matrices A and B by the operation defined below, where "·" is the logical AND operation, and "+" is the logical OR operation. In this assignment, you will create two 5x5 logical matrices and find the corresponding matrix which will be created from "multiply" these 2 matrices Define global SIZE equals to 5 (Already defined in the template) Write a function that gets a matrix reference and reads the input to the matrix from the user. If the input is non-zero replace it by 1. If the user did not enter enough values before the end of the line, the remaining cells in the matrix will be populated with zeros. Also make sure if the user inputs too many characters, you only take what's needed and discard the remaining input. (Eg: 1509 is a 2x2 matrix with values 1101, and ‘1 5 ‘ is also a 2x2 matrix with values 1111, the highlighted whitespace is taken as a 1 as discussed above.) Function signature: void read_mat(int mat[][SIZE]) Write a function that multiplies, as defined above, two matrices and enters the results into a third matrix with suitable dimensions. Function signature: void mult_mat(int mat1[][SIZE],int mat2[][SIZE], int result_mat[][SIZE]) Write a function that prints a matrix into the screen. Please use “%3d” for printing format to make it look nice as shown below. Function signature: void print_mat(int mat[][SIZE]) Write the main program which uses the functions above. The program reads the matrices values from the user, multiplies them and prints the result matrix on the screen. The function definitions given are intentional with the return statements as void. Do not change them. Arrays are transferred between functions as references rather as primitives like variables. So the function definitions are perfectly valid. Also, there is no limit on the input from the user. You can read only the required digits, and then stop reading, and discard the remaining input. Here is my code: #include <stdio.h> #define SIZE 5 void read_mat(int mat[][SIZE],int size) { int i = 0, j = 0, k = 0; char c; c=getchar(); while(c!='\n' && k<size*size){ if(c!='0'){ mat[i][j]=1; j++; } else{ mat[i][j]=0; j++; } if (j >= size){ j = 0; i++; } if (i >= size){ return; } c=getchar(); k++; } } void mult_mat(int mat1[][SIZE], int mat2[][SIZE], int result_mat[][SIZE]) { int i,j,k; for (i = 0; i <SIZE; ++i){ for (j = 0; j <SIZE; ++j) { result_mat[i][j] = 0; for (k = 0; k < SIZE; ++k) result_mat[i][j] += mat1[i][k] * mat2[k][j]; if(result_mat[i][j]!=0){ result_mat[i][j]=1; } } } } void print_mat(int mat[][SIZE],int size) { int i, j; for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) printf("%3d", mat[i][j]); printf("\n"); } //Please use the "%3d" format to print for uniformity. } int main() { int mat1[][SIZE]={ 0 }, mat2[][SIZE]={ 0 }, res_mat[][SIZE]={0}; printf("Please Enter Values For Matrix 1\n"); read_mat(mat1,SIZE); printf("Please Enter Values For Matrix 2\n"); read_mat(mat2,SIZE); mult_mat(mat1,mat2,res_mat); printf("The First Matrix Is :- \n"); print_mat(mat1,SIZE); printf("The Second Matrix Is :- \n"); print_mat(mat2,SIZE); printf("The Resultant Matrix Is :- \n"); print_mat(res_mat,SIZE); return 0; } The input and output should be like this: Please Enter Values For Matrix 1 111000654987010 Please Enter Values For Matrix 2 11 53 The First Matrix Is :- 1 1 1 0 0 0 1 1 1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 The Second Matrix Is :- 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 The Resultant Matrix Is :- 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 But when I run the program, this message appears: exception thrown: Run-Time Check Failure #2 - Stack around the variable 'mat2' was corrupted. and the output isn't right and I am getting some elements has a junk values: Please Enter Values For Matrix 1 111000654987010 Please Enter Values For Matrix 2 11 53 The First Matrix Is :- 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1-858993460-858993460-858993460 -858993460-858993460-858993460-858993460 1 The Second Matrix Is :- 1 1 1 1 1 -858993460-858993460-858993460-858993460-858993460 -858993460-858993460 1 1 1 1 1 1 1 1 1 1 1 1 1 The Resultant Matrix Is :- 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Another question: if I entered to the mat1 a big string it's calculated directly without letting me enter a string to mat2 how do I solve this problem ?
int mat1[][SIZE]={ 0 } will declare a 1x5 matrix. Change it to int mat1[SIZE][SIZE]={ 0 }
Generate combinations of k numbers in an array with ordering constraints
This is one of the questions from my midterm exam. Please trace the following program. Modify this program to write a recursive program int combinations(A, n, k) that you can print out all the combinations of k numbers out of n different numbers stored in an array A with additional rules of: (1) the order of A[0], A[1], ..., A[n-1] must remain and (2) the sequence of these k numbers must be in an increasing order. For example, assume there are four numbers 4, 1, 2, 3 stored in array int A[4]. Calling this recursive function combinations(A, 4, 2) will return a count 3 and print out (1, 2), (1, 3) and (2, 3), or calling combinations(A, 4, 3) will return a count 1 and print out (1, 2, 3). Your recursive program must consider to avoid the unnecessary recursive function calls. Teacher gave the following code as the hint: #include <stdio.h> #define N 4 int boolfunc(int *var, int m); int recursivebool(int *var, int n); int main(){ int varbool[20]; recursivebool(varbool, N); } int boolfunc(int *var, int m){ int result=var[0], i; for (i=1; i<m; i++) result = (result && var[i]); return result; } int recursivebool(int *var, int n){ int localvar[20], i, j; if (n == 0){ for(i=0; i<N; i++) printf("%d ", var[i]); printf("%d\n", boolfunc(var, N)); return; } for (j=0; j<=1; j++) { var[n-1] = j; recursivebool(var, n - 1); } } If we run this program we can get output like this: 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 1 0 0 0 0 0 1 0 0 1 0 1 0 0 0 1 1 0 0 1 1 1 0 0 0 0 0 1 0 1 0 0 1 0 0 1 0 1 0 1 1 0 1 0 0 0 1 1 0 1 0 1 1 0 0 1 1 1 0 1 1 1 1 1 I can understand the hint program. And I need to use this concept to write int combination(int *A, int n, int k) like the question asked. As what I know, if k is 2, I can use this concept to find the scenario that have two 1 with two 0 like this: 1 1 0 0 1 0 1 0 1 0 0 1 0 1 1 0 0 1 0 1 0 0 1 1 Then, we can find the numbers from corresponding index of 1 and exam the numbers to see if they are in the increasing order. I tried so hard to solve this question. But it's too difficult.
You can approach this as a simple constraint satisfaction problem and use recursive backtracking to solve the constraints. As you mention, we can naively generate all the possible combinations, then retroactively pick the ones we want, but then we've done a lot of useless work which the assignment correctly prohibits. A solution is to break off the recursive search as soon as a violation of a constraint is detected and try a different possibility. If we ever reach a point where we've satisfied all the constraints for the sequence, we print the result. Ideally, we'd return an array of results, but not having to do so makes it easier to focus on the algorithm. In terms of satisfying the constraints, we can do so by using a start index to fulfill the i < j requirement. If we add a number to an in-progress result, the result array must be empty or the existing element at the tail of the array is less than the element we're trying to add. Beyond that, we have our base case of k. #include <stdio.h> void print_arr(int len, int *a); int combinations_recurse(int *a, int n, int k, int *selected, int selected_len, int start) { if (selected_len == k) { print_arr(selected_len, selected); return 1; } int selected_count = 0; for (int i = start; i < n; i++) { if (!selected_len || selected[selected_len-1] < a[i]) { selected[selected_len] = a[i]; selected_count += combinations_recurse(a, n, k, selected, selected_len + 1, start + 1); } } return selected_count; } int combinations(int *a, int n, int k) { int selected[n]; return combinations_recurse(a, n, k, selected, 0, 0); } int main() { int a[] = {4, 1, 2, 3}; printf("count: %d\n\n", combinations(a, 4, 2)); printf("count: %d\n", combinations(a, 4, 3)); return 0; } void print_arr(int len, int *a) { printf("["); for (int i = 0; i < len - 1; printf("%d, ", a[i++])); if (len) printf("%d]\n", a[len-1]); else puts("]"); } Output: [1, 2] [1, 3] [2, 3] count: 3 [1, 2, 3] count: 1
Pass 2D array by reference
I want to be able to pass a 2D array to a function, and have it directly change the array in main, so pass by reference. When I try to compile, I get error: expected expression before { in the switch cases. (boardSize=10, but that is not known at compilation time) void fillBoard(int **, int); int main() { int **board = malloc(sizeof(int *) * boardSize); fillBoard(board, boardSize); } void fillBoard(int **board) { int i, *row = malloc(sizeof(int) * boardSize); for (i=0; i<boardSize; i++) { board[i] = malloc(sizeof(int) * boardSize); switch(i) { case 1: row = {1,0,1,0,1,1,0,0,1,0}; break; default: row = {0,0,0,0,0,0,0,0,0,0}; break; } board[i] = row; } }
There a many different ways to do this. The key is to keep track of what you are addressing where. You can use a single or double pointer to pass and fill board, it all depends on how you want to keep track of the elements. (while the 2-dimensional array, provides a convenience in referencing elements, all values are sequential in memory, and can be accessed with a 1-dimensional reference and offset). There is one important suggestion when allocating memory for numeric arrays. You must always initialize all elements of the array to protect against attempting to access or dereference an uninitialized value (Undefined behavior). The simple way to do this is to allocate with calloc instead of malloc. calloc allocates and initializes all values to zero (NULL). Also be aware of the need to track the memory you allocate over the life of your program and free the memory when you no longer need it. This will prevent memory leaks from developing. In a short bit of code like the following, the memory is freed when the program exits. If this were part of some larger code, you would need to free board and board2 when there data was no longer needed. An example using your original array would be: #include <stdio.h> #include <stdlib.h> #define boardSize 10 void fillBoard_p (int *a); void fillBoard_p2p (int **a); int main() { int i = 0; int j = 0; /* declaring board as an integer pointer */ int *board = calloc (boardSize * boardSize, sizeof (*board)); /* declaring board as a pointer to pointer */ int **board2 = calloc (boardSize, sizeof (*board2)); for (i = 0; i < boardSize; i++) { board2[i] = calloc (boardSize, sizeof (**board2)); } fillBoard_p (board); fillBoard_p2p (board2); printf ("\nboard as an integer pointer:\n"); for (i = 0; i < boardSize * boardSize; i++) { if (i % boardSize == 0) printf ("\n %d", board[i]); else printf (" %d", board[i]); } printf ("\n"); printf ("\nboard2 as an pointer to integer pointer:\n\n"); for (i = 0; i < boardSize; i++) { for (j = 0; j < boardSize; j++) { printf (" %d", board2[i][j]); } printf ("\n"); } printf ("\n"); return 0; } void fillBoard_p(int *a) { // 0=WHITE, 1=BLACK int i = 0; int j = 0; int b [][boardSize] = { {1,0,1,0,1,1,0,0,1,0}, {1,0,1,1,0,0,1,1,1,0}, {0,0,1,0,1,0,1,0,1,1}, {1,1,0,1,1,0,1,0,0,0}, {0,0,1,0,0,0,1,1,0,1}, {1,1,0,1,1,0,0,1,1,0}, {0,0,1,0,0,1,1,0,1,1}, {0,0,1,0,0,1,0,0,0,0}, {1,1,1,1,0,0,1,1,1,1}, {0,1,0,0,1,1,0,0,0,1} }; for (i = 0; i < boardSize; i++) for (j = 0; j < boardSize; j++) a[i*boardSize+j] = b[i][j]; } void fillBoard_p2p (int **a) { // 0=WHITE, 1=BLACK int i = 0; int j = 0; int b [][boardSize] = { {1,0,1,0,1,1,0,0,1,0}, {1,0,1,1,0,0,1,1,1,0}, {0,0,1,0,1,0,1,0,1,1}, {1,1,0,1,1,0,1,0,0,0}, {0,0,1,0,0,0,1,1,0,1}, {1,1,0,1,1,0,0,1,1,0}, {0,0,1,0,0,1,1,0,1,1}, {0,0,1,0,0,1,0,0,0,0}, {1,1,1,1,0,0,1,1,1,1}, {0,1,0,0,1,1,0,0,0,1} }; for (i = 0; i < boardSize; i++) for (j = 0; j < boardSize; j++) a[i][j] = b[i][j]; } output: $ ./bin/fillboard board as an integer pointer: 1 0 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 1 0 0 0 1 0 1 0 1 0 1 1 1 1 0 1 1 0 1 0 0 0 0 0 1 0 0 0 1 1 0 1 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 0 0 1 1 0 0 0 1 board2 as an pointer to integer pointer: 1 0 1 0 1 1 0 0 1 0 1 0 1 1 0 0 1 1 1 0 0 0 1 0 1 0 1 0 1 1 1 1 0 1 1 0 1 0 0 0 0 0 1 0 0 0 1 1 0 1 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1 1 0 1 1 0 0 1 0 0 1 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 1 0 0 1 1 0 0 0 1 Additionally, since a 2-D array is stored sequentially in memory, you can take advantage of that fact and make use of memcpy (in string.h) to fill the array passed to your function. This can reduce your function to: void fillBoard_mc (int *a) { // 0=WHITE, 1=BLACK int b [][boardSize] = { {1,0,1,0,1,1,0,0,1,0}, {1,0,1,1,0,0,1,1,1,0}, {0,0,1,0,1,0,1,0,1,1}, {1,1,0,1,1,0,1,0,0,0}, {0,0,1,0,0,0,1,1,0,1}, {1,1,0,1,1,0,0,1,1,0}, {0,0,1,0,0,1,1,0,1,1}, {0,0,1,0,0,1,0,0,0,0}, {1,1,1,1,0,0,1,1,1,1}, {0,1,0,0,1,1,0,0,0,1} }; memcpy (a, b, boardSize * boardSize * sizeof (int)); } Were it not for the particularity of the compiler and pointer decay, you could simply use a statically declared array, such as: int board[boardSize][boardSize] = {{0}}; passing the address of the array to your function (becoming a 3-star programmer): fillBoard (&board); with a function similar to: void fillBoard (int *a[][boardSize]) { // 0=WHITE, 1=BLACK int b [][boardSize] = { {1,0,1,0,1,1,0,0,1,0}, {1,0,1,1,0,0,1,1,1,0}, {0,0,1,0,1,0,1,0,1,1}, {1,1,0,1,1,0,1,0,0,0}, {0,0,1,0,0,0,1,1,0,1}, {1,1,0,1,1,0,0,1,1,0}, {0,0,1,0,0,1,1,0,1,1}, {0,0,1,0,0,1,0,0,0,0},A {1,1,1,1,0,0,1,1,1,1}, {0,1,0,0,1,1,0,0,0,1} }; memcpy (a, b, boardSize * boardSize * sizeof (int)); } Due to pointer decay (board[10][10] => board[*][10]), you will receive an incompatible pointer type warning, despite the function successfully copying the memory as intended. Code that does not compile without warning, should not be relied on in practice.
Storing subsets of a array
this program is "calculating" all subsets of the array source. I need to store the resulting values in another 2D filed named polje. If I just use the printf("%d %d %d ", source[i][0], source[i][1], source[i][2]); the code works fine but something fails when it is trying to copy everything into the resulting field. I suppose I am dogin something wrong in the indexing of the array polje. #include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { int f; int i,j; int source[2][3] = {{0,3,5},{3,4,2}}; int currentSubset = 3; int polje[8][3]; for(i=0;i<8;i++){ for(j=0;j<3;j++){ polje[i][j]=0; }} int tmp; while(currentSubset) { tmp = currentSubset; for( i = 0; i<3; i++) { if (tmp & 1) { printf("%d %d %d ", source[i][0], source[i][1], source[i][2]); //writes out everything I want polje[currentSubset][0]=source[i][0]; polje[currentSubset][1]=source[i][1]; polje[currentSubset][2]=source[i][2]; } tmp >>= 1; } printf("\n"); currentSubset--; } for(i=0;i<8;i++){ for(j=0;j<3;j++){ printf("%d ", polje[i][j]); }printf("\n");} return (EXIT_SUCCESS); } The output field should be: 0 3 5 3 4 2 3 4 2 0 0 0 0 3 5 0 0 0 0 0 0 0 0 0 But instead it is: 0 3 5 3 4 2 3 4 2 0 0 0 *0 0 0* 0 0 0 0 0 0 0 0 0
tmp is a bit mask with only two bits, so the inner loop should be for ( i = 0; i < 2; i++ ). Also the correct index into the polje array is polje[currentSubset * 2 + i][0] since each subset in polje takes two spaces and i is either 0 or 1.
I think you just have a logic error. Your loop's skeleton is: currentSubset = 3; while ( currentSubset ) { // ... polje[currentSubset][...] = ...; // ... currentSubset--; } So you never write to any rows except the first three.
Generate Binary Sequence
I want to generate permutations of string of 5 0s followed by the permutations of 4 0s and a single 1, followed by the permutations of 3 0s with 2 1s etc? My code is as follows: #include<stdio.h> int main(){ int i,j,k,l,s[5]; for(i=0;i<5;i++) s[i]=0; for(k=0;k<5;k++) printf("%d ",s[k]); printf("\n"); printf("---------------------------------------------\n"); for(i=0;i<5;i++){ for(j=0;j<5;j++) if(i==j) s[j]=1; else s[j]=0; for(k=0;k<5;k++) printf("%d ",s[k]); printf("\n"); } printf("---------------------------------------------\n"); for(i=0;i<5;i++){ for(k=0;k<5;k++) s[k]=0; s[i]=1; for(j=i+1;j<5;j++){ s[j]=1; for(k=0;k<5;k++) printf("%d ",s[k]); printf("\n"); for(k=j;k<5;k++) s[k]=0; } } printf("---------------------------------------------\n"); for(i=0;i<5;i++){ for(j=i+1;j<5;j++){ for(k=0;k<5;k++) s[k]=0; s[i]=1; s[j]=1; for(l=j+1;l<5;l++){ s[l]=1; for(k=0;k<5;k++) printf("%d ",s[k]); printf("\n"); for(k=l;k<5;k++) s[k]=0; } } } } So output is 0 0 0 0 0 --------------------------------------------- 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 --------------------------------------------- 1 1 0 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 0 1 0 1 1 0 0 0 1 0 1 0 0 1 0 0 1 0 0 1 1 0 0 0 1 0 1 0 0 0 1 1 --------------------------------------------- 1 1 1 0 0 1 1 0 1 0 1 1 0 0 1 1 0 1 1 0 1 0 1 0 1 1 0 0 1 1 0 1 1 1 0 0 1 1 0 1 0 1 0 1 1 0 0 1 1 1 Output is ok. However in my code I use different for loops for different cases. Is it possible to use better approach so that length of the code is reduced?
One approach follows. This solution needs O(n) space and each output string requires O(n) time. #include <stdio.h> #include <stdlib.h> char *buf; // Print combinations of m 1's in a field of n 0/1's starting at s. void print_combinations(char *s, int n, int m) { // If there is nothing left to append, we are done. Print the buffer. if (m == 0 && n == 0) { *s = '\0'; printf("%s\n", buf); return; } // Cut if there are more 1's than positions left or negative numbers. if (m > n || m < 0 || n < 0) return; // Append a 0 and recur to print the rest. *s = '0'; print_combinations(s + 1, n - 1, m); // Now do the same with 1. *s = '1'; print_combinations(s + 1, n - 1, m - 1); } int main(void) { int n = 5; buf = malloc(n + 1); for (int m = 0; m <= n; m++) { print_combinations(buf, n, m); printf("-----\n"); } return 0; }
You could use a recursive function like so - you don't have to print the result when finished, you could add it to a list etc. The function works by starting with an empty string. At each step you add one more character - in this case you add either a 0 or a 1. If a 1 is added we account for this by decrementing the ones value on the next call to the function. (In a more general case you could pass a list of all the elements to be permuted - then the process would be to pick from this list, add it to your permutation and remove it from the list. You repeat that until the list is empty and you have permuted all of the elements in the list.) When the string reaches the desired length we have finished and so we return. #include <stdio.h> void recurse(char *str, int length, int maxLength, int ones) { if (length == maxLength) { // we are finished printf("%s\n", str); return; } if (ones > 0) { // put a 1 into the new string str[length] = '1'; recurse(str, length + 1, maxLength, ones - 1); } if (ones < maxLength - length) { // there are still spaces for 0s // put a 0 into the string str[length] = '0'; recurse(str, length + 1, maxLength, ones); } } int main() { const int maxLength = 5; char buffer[maxLength + 1]; buffer[maxLength] = 0; int ones; for (ones = 0; ones <= maxLength; ones++) { printf("Ones: %i\n", ones); recurse(buffer, 0, maxLength, ones); printf("\n"); } return 0; } The output looks like this: Ones: 0 00000 Ones: 1 10000 01000 00100 00010 00001 Ones: 2 11000 10100 10010 10001 01100 01010 01001 00110 00101 00011 Ones: 3 11100 11010 11001 10110 10101 10011 01110 01101 01011 00111 Ones: 4 11110 11101 11011 10111 01111 Ones: 5 11111 Finally, unless you really want to/need to learn/use C, I would recommend using C++ because you get really nice features like std::vector and std::set and so many other things which will make your life so much easier. I would have written this completely different in C++.