Generate combinations of k numbers in an array with ordering constraints - c

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

Related

This question is regarding A C program to replace the second the subsequent occurences of the digit with 0,-1,-2... so on so if 1,1,1 -> 1,0,-1

#include <stdio.h>
int main()
{
int a[]={1,2,1,2,1,2,1,2,1};
int count=1;
int size=sizeof(a)/sizeof(a[0]);
for(int k=0;k<=size;k++){
for(int i=0;i<=size;i++){
count = 1;
for(int j=i+1;j<=size;j++){
if(a[j]==a[i]){
count--;
a[j]=count
}
} }}
I tried like just two loops,and using a count variable to decrease the value to get the output like 1,2,0,0,-1,-1 for the array 1,2,1,2,1,2 as 1 and 2 repeating 3 three times but Im getting error with Second digit ie '2' im getting 2,0,0,0... like 1 2 0 0 -1 0 -2 0 -3.
You have too many loops, and invoke Undefined Behaviour by accessing the element one-past the end of the array.
If the array is being changed in place, you must account for the fact that values less than 1 will hold special meaning as marked duplicates. In this case all values in the array must be greater than zero beforehand.
Otherwise, elements already marked as duplicates will be used as candidates to check for more duplicates.
For example, with the data:
1, 2, 1, 2, 1, 2
| |
After the first two elements are checked the array will be
1, 2, 0, 0, -1, -1
|
When the third element is checked, the fourth element will be changed to a zero (although its already a zero).
When the fifth element is checked
1, 2, 0, 0, -1, -1
|
the sixth element will be changed to a zero, resulting in:
1, 2, 0, 0, -1, 0
So values less than 1 must be excluded from the duplicate sweep, or a copy of the array must be used.
#include <stdio.h>
void print_array(int *data, size_t length)
{
for (size_t i = 0; i < length; i++)
printf("%2d ", data[i]);
putchar('\n');
}
int main(void)
{
int list[] = { 1, 2, 1, 2, 1, 2, 1, 2, 1 };
size_t length = sizeof list / sizeof *list;
print_array(list, length);
for (size_t i = 0; i < length; i++) {
if (list[i] > 0) {
int rep = 0;
for (size_t j = i + 1; j < length; j++) {
if (list[j] == list[i]) {
list[j] = rep--;
}
}
}
}
print_array(list, length);
}
1 2 1 2 1 2 1 2 1
1 2 0 0 -1 -1 -2 -2 -3

Storing the right value in a two dimensional array in c. But when I tried to print the value it shows bigger value and even negative number

Problem:
In this question I tried to solve a bitwise operator problem. Giving two number as input
Input will be two number. Here is some input:
n = 3
k = 3
Then I need to construct "a" and "b" in some way(for instance when "a = 1" then b will be one past a to <= n. The results of the comparisons are below:
a b and or xor
1 2 0 3 3
1 3 1 3 2
2 3 2 3 1
Here is my code:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
//Complete the following function.
void calculate_the_maximum(int n, int k)
{
// Two dimentional array for storing the value of and or xor
int rowOfArray = 3;
int sets[rowOfArray][k];
//For loop for a
for (int i = 0; i < k; i++)
{
int a = i + 1;
//For loop for b
for (int j = a; j < n; j++)
{
int b = j;
b++;
printf("{%i, %i}\n", a, b);
//Storing and operation result to the array
sets[0][j - 1] = a&b;
printf("And: %i\n", sets[0][j - 1]);
//Storing or operation result to the array
sets[1][j] = a|b;
printf("Or: %i\n", sets[1][j]);
//Storing xor opertaion result to the array
sets[2][j + 1] = a^b;
printf("Xor: %i\n", sets[2][j + 1]);
}
}
//Find the biggest number in array
for (int i = 0; i < rowOfArray; i++)
{
int big;
for (int j = 0; j < k; j++)
{
big = 0;
printf("Big1: %i\n", big);
if (big < sets[i][j])
{
big = sets[i][j];
printf("Big2: %i\n", big);
}
}
printf("big3: %i\n", big);
if (big < k)
{
printf("%i\n", big);
}
else
{
printf("%i\n", 0);
}
}
}
int main() {
int n, k;
scanf("%d %d", &n, &k);
calculate_the_maximum(n, k);
return 0;
}
I used too many printf function to show that what have I done wrong. I stored the value as I expected but later in the for loop when I tried to print the specific position integer I didn't get the correct result even sometimes I got bigger and negative number too.
Here is the output:
3 3
{1, 2}
And: 0
Or: 3
Xor: 3
{1, 3}
And: 1
Or: 3
Xor: 2
{2, 3}
And: 2
Or: 3
Xor: 1
Big1: 0
Big1: 0
Big2: 2
Big1: 0
Big2: 120329728
big3: 120329728
0
Big1: 0
Big2: 1986993953
Big1: 0
Big2: 3
Big1: 0
Big2: 3
big3: 3
0
Big1: 0
Big1: 0
Big2: 32765
Big1: 0
Big2: 3
big3: 3
0
As is, for the input 3 3, j holds the values 1, 2, and 2, so clearly sets[2][j + 1] is Undefined Behaviour since it accesses the subarray at index 3, when valid indices are [0, 2].
Given the source problem, the issues are more clear.
k is simply a limit on output, and should not be used as a bound for iteration, or for calculating the storage required for the number of k-combinations.
It is unnecessary to store all the results at once. For each combination, each value of the operation a ? b (where ? is a bitwise operator) can be tested against the value k and the currently stored maximum value for the given operator.
Here is a quick solution. Compile with -DDEBUG to see additional output.
#include <stdio.h>
void setmax(int *dest, int value, int limit)
{
if (value < limit && value > *dest)
*dest = value;
}
void calc(int n, int k)
{
int and = 0;
int or = 0;
int xor = 0;
#ifdef DEBUG
printf("INFO: a b and or xor\n");
#endif
for (int a = 1; a < n; a++) {
for (int b = a + 1; b <= n; b++) {
setmax(&and, a & b, k);
setmax(&or, a | b, k);
setmax(&xor, a ^ b, k);
#ifdef DEBUG
printf("INFO: %-3d %-3d %-3d %-3d %-3d\n",
a, b, a & b, a | b, a ^ b);
#endif
}
}
printf("%d\n%d\n%d\n", and, or, xor);
}
int main(void)
{
int n, k;
if (2 != scanf("%d%d", &n, &k))
return 1;
calc(n, k);
}
Sample runs:
./a.out <<< "3 3"
2
0
2
./a.out <<< "5 4"
2
3
3
If you run the code, you'll get stack corruption error which is due to indexing the array beyond its allocated size. Accessing memory that's not for your program is undefined behavior. Anything might happen. The program may crash or it may not. For my specific compiler and the fact that I ran the code in debug mode and not release mode, the program crashed with the error I mentioned.
Now to fix the error, from what you explained, you have three columns for and, or and xor. So you need to reverse the dimensions of set (set[k][rowOfArray], better change the name to rowSize or n_columns or so). Also reverse the indexing, e.g. change set[0][j-1] to set[j-1][0] and so on. I'm not sure what you're trying to do in the second part, though.

Counting the number of elements of blocks with same consecutive elements

I'm having the following problem:
A park that have the form of a m x n board. There are k kinds of trees (1 <= k <= 100). The park is divided into m x n cells and each cell, they'll plant a tree. Now, on the map, each cell of the park have an integer i inside if the i-th kind of tree is planted in it, or a 0 if no tree is planted in it. A line of cells is considered "good" if it has at least t trees of same types, (and they must be on the same either line or column). Count the number of trees that is not in a "good" line.
Input: Integers m, n, t and an m x n array of integers represent the map.
Output: Number of trees that is not in a "good" line.
Example:
Input:
5 6 3
1 3 3 3 3 4
1 2 3 2 0 4
3 2 2 2 4 4
1 0 0 2 4 0
1 2 3 0 4 4
Output: 10
Explanation: The bold numbers are the trees that is not in a good line.
1 3 3 3 3 4
1 2 3 2 0 4
3 2 2 2 4 4
1 0 0 2 4 0
1 2 3 0 4 4
My idea is to check for each element in the array. If it is satisfied then I'll move to the nearest element outside the "good" line. Else, it will just move to the next element on the same line, or if the line is ended then the next element on the column.
Here is my code
#include <stdio.h>
#define maxn 120
int a[maxn][maxn], m, n, t;
int check(int *i, int *j){
int k, cnt_r, cnt_c;
cnt_r = 0;
//jump to the nearest cell that is not in good line
for(k = *i + 1; k < m; k++){
if(a[*i][*j] == a[k][*j]) cnt_r++;
if(cnt_r >= t){
*i = k;
return 1;
}
}
cnt_c = 0;
for(k = *j + 1; k < n; k++){
if(a[*i][*j] == a[*i][k]) cnt_c++;
if(cnt_c >= t){
*j = k;
return 1;
}
}
return 0;
}
//check if this is the last square or not
int lastSq(int r, int c){
return (r == n - 1 && c == n);
}
int main(){
int res = 0, i, j, pos_r = 0, pos_c = 0;
scanf("%d%d%d", &m, &n, &t);
for(i = 0; i < m; i++)
for(j = 0; j < n; j++)
scanf("%d", &a[i][j]);
while(!lastSq(pos_r, pos_c)){
if(a[pos_r][pos_c] == 0){
if(pos_c < n - 1) pos_c++;
else if(pos_r < n - 1){
pos_c = 0;
pos_r++;
}
}
if(!check(&pos_r, &pos_c)){
res++;
if(pos_c < n - 1) pos_c++;
else{
pos_c = 0;
pos_r++;
}
}
}
printf("%d", res);
}
But it doesn't print any output. The only thing I have is 0xC0000005. Can someone please check where did I make a mistake and provide me a direction? Thanks.

Boolean Table in 2D array 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.

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.

Resources