Unexpected result from Knapsack problem recursive function - c

I have to write a simple program to solve the Knapsack problem.
I wrote this code for now and I think this is all I need, but I keep having different results everytime I execute it. All I can think is that there is a problem of memory deallocation, but I don't know how to solve it. Any ideas?
P.S. Maybe it's a stupid question but I never worked in C.
#include <stdio.h>
int max(int a, int b){
if(a > b) {
return a;
} else {
return b;
}
}
int knapsack(int prices[], int weight[], int n, int max_weight){
if(n < 0)
return 0;
if (weight[n] > max_weight)
return knapsack(prices, weight, n-1, max_weight);
else
return max(knapsack(prices, weight, n-1, max_weight), (knapsack(prices, weight, n-1, max_weight - weight[n]) + prices[n]));
}
int main(int argc, char const *argv[]) {
int i, weight[] = {2,3,3,4}, prices[] = {1,5,2,9}, max_weight = 7, n, result;
for (i=0; i<argc; i++) {
printf("%d: \"%s\"\n", i, argv[i]);
}
n = (sizeof(weight))/(sizeof(weight[0]));
result = knapsack(prices, weight, n, max_weight);
printf("%d\n", result);
return 0;
}
RESULTS

It looks like you are indexing the arrays with an number that is too large.
You get the size of the array doing
n = (sizeof(weight))/(sizeof(weight[0]));
You cannot index weight at n because it only has indices 0 to n-1
Try calling
result = knapsack(prices, weight, n-1, max_weight);

Related

I want 2 for loop -> 1 for loop C

I am solving algorithm problem.
It is elements in array, pair -> one value;
I input array's size and add value.
i solve this problem but i meet time complexity problem at biggggg number - n
how can i solve this time complexity problem?
i try to solve one for loop but can't well
plz help me
#include <stdio.h>
int main(void){
int n,m,i,j;
int count=0;
scanf("%d %d",&n, &m);
int array[n];
for(i=0;i<n;i++){
scanf("%d",&array[i]);
}
for(i=0;i<n;i++){
for(j=i;j<n;j++){
if(m==array[i]+array[j]){
count++;
}}
}
printf("%d",count);
return 0;
}
Here is a simple two-pointer technique, after sorting.
It will work as it is because there is no duplicate.
In practice, two indices are used, one from the start of the array, one from the end of the array. We increase the first or decrease the second one, depending on the value of the sum.
Complexity: O(n logn) for sorting, and O(n) for the second step.
#include <stdio.h>
#include <stdlib.h>
int compare_ints(const void* a, const void* b)
{
int arg1 = *(const int*)a;
int arg2 = *(const int*)b;
if (arg1 < arg2) return -1;
if (arg1 > arg2) return 1;
return 0;
}
int count_sum (int* A, int n, int target) {
int count = 0;
qsort(A, n, sizeof(int), compare_ints);
int left = 0;
int right = n-1;
while (left < right) {
int sum = A[left] + A[right];
if (sum == target) {
count++;
left++;
right--;
} else if (sum < target) {
left++;
} else {
right--;
}
}
return count;
}
int main() {
int A[] = {8, 2, 7, 5, 3, 1};
int target = 10;
int n = sizeof(A)/sizeof(A[0]);
int ans = count_sum (A, n, target);
printf ("count = %d\n", ans);
return 0;
}

can't return the right variable in C [duplicate]

This question already has answers here:
How do I return multiple values from a function in C?
(8 answers)
Closed 3 years ago.
I want to try write Kadane algorithms using C. Instead of just return maximum subarray value, I also want to return the start and end index.
And here's the code :
#include <limits.h>
#include <stdio.h>
int kadane(int A[], int size){
int current_max = INT_MIN;
int global_max = INT_MIN;
int start, last;
for (int i = 0; i <= size; i++){
if (A[i] > A[i] + current_max){
current_max = A[i];
start = i;
} else {
current_max += A[i];
};
if (current_max >= global_max){
global_max = current_max;
last = i;
};
};
return (start, last ,global_max);
}
int main(){
int sum, size, start, last;
int A[] = {3,-4,5,1,9,-10,11,2,5,-1,2};
size = sizeof(A)/sizeof(A[0]);
start, last, sum = kadane(A, size-1);
printf("start at %d ; end at %d; sum : %d\n", start, last, sum);
return 0;
}
Although the answer of maximum sum is right, the value of start and last are really weird. I use printf to check the value of start and last in the for loop of kadane function, and it seems work fine there. So I thought the problem might have something to do with the way I return variable.
so I modify some part of code like this :
int kadane(int A[], int size){
......
......
return (&start, &last ,global_max);
}
and then using pointer to store them :
int main(){
.......
.......
int *start;
int *last;
*start, *last, sum = kadane(A, size-1);
printf("start at %d ; end at %d; sum : %d\n", *start, *last, sum);
return 0;
}
then I got "Segmentation Fault 11" error.
I try to understand and search what I'm doing wrong here but I just can't find it.The only solution that work is to store variable start and last in global so that I can just call then anywhere without return.But I feel like that is not a suitable solution. Can anyone help me here?
You have two solutions:
1: Return a struct which contains all the types you need.
struct data {
int start;
int last;
int global_max;
};
struct data kadane(int A[], int size){
stuct data test = { 1, 1, 1 };
......
......
return test;
}
void main() {
......
struct data t = kadane(A, ize);
}
2: Use pointers to pass out values.
void kadane(int A[], int size, int *start, int *last, int *global_max) {
......
......
*start = 1;
*last= 1;
*global_max= 1;
}
void main() {
......
int a, b, c;
kadane(A, size, &a, &b, &c);
}
From
How do I return multiple values from a function in C?

Function to sum all permutations

some time ago I wrote a program that prints all possible permutations of of a given array, even printing all partial arrays:
#define MAXARRAY 32
#include <stdio.h>
void combinations(int array[], int temp[], int start, int end, int index, int r);
void print_combinations(int array[], int n, int r){
int temp[r];
combinations(array, temp, 0, n-1, 0, r);
}
void combinations(int array[], int temp[], int start, int end, int index, int r){
if (index == r){
for (int j=0; j<r; j++)
printf("%d ", temp[j]);
printf("\n");
return;
}
for (int i=start; i<=end && end-i+1 >= r-index; i++){
temp[index] = array[i];
combinations(array, temp, i+1, end, index+1, r);
}
}
int main(){
int array[MAXARRAY];
int r;
int n = sizeof(array)/sizeof(array[0]);
int i=MAXarray, j;
for(j=0;j<MAXARRAY;j++){
array[j]=j+1;
}
for(r=0;r<=i;r++)
print_combinations(array, n, r);
}
Now I'm trying to convert this program to do the following:
Instead of printing the permutations, I want to sum up ALL permutations and compare the sum with a fixed value, and if the sum of numbers in the permutation truly is equal to that fixed value, it increases the counter so in the end I could check how many sums of permutation equals that value. This is what I came up with for now:
#define MAXARRAY 32
#include <stdio.h>
int combinations (int array[], int temp[], int start, int end, int index, int r);
void print_combinations (int array[], int n, int r){
int temp[r];
combinations(array, temp, 0, n-1, 0, r);
}
int combinations (int array[], int temp[], int start, int end, int index, int r){
int sum=0, counter=0;
if (index == r) {
for (int j=0; j<r; j++){
sum=sum+temp[j];
}
if(sum==264){
counter++;
}
}
for (int i=start; i<=end && end-i+1 >= r-index; i++){
temp[index] = array[i];
combinations(array, temp, i+1, end, index+1, r);
}
return counter;
}
int main()
{
int array[MAXARRAY];
int r;
int n = sizeof(array)/sizeof(array[0]);
int i=MAXARRAY, j;
for(j=0;j<MAXARRAY;j++){
array[j]=j+1;
}
for(r=0;r<=i;r++)
print_combinations(array, n, r);
I don't know how to alter this correctly to get what I want, precisely I am a bit lost with how to switch up the void function to print a counter that does not appear in the function, and I am unsure if I can just easily "alter" this code to get what I want, or I just need to write completely new functions.
You want to know in how many ways you can pick numbers from a given set so that they sum up to a given target value. You seem to approach this the wrong way, because you have mixed up permutations and combinations.
Permutations are different arrangements of a set of items with a fixed size n and number of possible arrangements is n! if all of the items are different. That's of no use here, because summation is commutative; the order of operands doesn't matter.
Combinations tell you which items of a set are included and which are not. This is what you want here. Luckily for you, there are only 2ⁿ possilbe ways to pick items from a set of n, including all items or none.
You can also solve this recursively. Each level of recursion treats one item and you can either chose to include it or not. For thee items, you get the following decision tree:
0
/ \
0 1
/ \ / \
0 2 0 2
/ \ / \ / \ / \
0 3 0 3 0 3 0 3
sum 0 3 2 5 1 4 3 6
Take the left branch to omit an item and take the right branch to include it. This will give you the sum of 3 twice and all other sums from 0 to 6 inclusively once. There are 8 possible paths.
The program below does that:
#include <stdlib.h>
#include <stdio.h>
#define N 32
#define TARGET 264
/*
* Print the summands
*/
void print(const int a[], int n)
{
int i;
for (i = 0; i < n; i++) {
if (i) printf(" + ");
printf("%d", a[i]);
}
puts("");
}
/*
* Actual recursive combination function
*/
size_t combine_r(const int pool[], // summand pool
int res[], // currently included items
int max, // length of pool
int n, // length of res
int i, // current item's index in pool
int sum, // running sum
int target) // desired target
{
int count = 0;
if (i == max) {
if (sum == target) {
//print(res, n);
count++;
}
} else {
count += combine_r(pool, res, max, n, i + 1, sum, target);
res[n++] = pool[i];
count += combine_r(pool, res, max, n, i + 1,
sum + pool[i], target);
}
return count;
}
/*
* Interface function for the recursive function.
*/
size_t combine(const int pool[], int n, int target)
{
int res[n];
return combine_r(pool, res, n, 0, 0, 0, target);
}
int main()
{
int pool[N];
size_t n;
int i;
for (i = 0; i < N; i++) pool[i] = i + 1;
n = combine(pool, N, TARGET);
printf("%zu combinations.\n", n);
return 0;
}
The function goes down each path and records a hit if the sum equals the target. The number of hits in each subtree is returned as you return from the recursion and go up the tree, so that the root level you've got the total number of hits.
The function combine is just a front-end to the actual recursive function, so that you don't have to pass so many zeros from main. The arguments for the recursive function could probably be reduced and organised more elegantly. (Tow of them exist only because in C you have to pass i the length of an array. If you just want to count the possibilities, you can get rid of res and n, which just serve to print the array.)

How to sum up the matching elements of arrays and count number of them in C

I need to get the program to find the matching values from the two arrays, sum of matching elements and their count. I seem to have done the first one but the second is giving me the wrong total. It should be 25 but I get 14. Finally I could not figure out how to get the count of the matching elements. All help is appreciated. My code is below.
int main(int argc, char *argv[]) {
int a[] = {1,2,3,4,5,7,8};
int b[] = {1,2,3,4,6,7,8};
int i,j,sum,count;
for (i=0;i<7;i++)
{
enter code here
for (j=0;j<7;j++)
{
if (a[i] == b[j])
printf("Numbers match: %d\n",a[i]);
}
}
printf("--------------------------------\n");
if ( i == j )
sum= (i+j);
printf("Sum: %d\n",sum);
return 0;
}
Try this. Assumes both arrays are the same size. You need to set all counters (sum, count) to a known value (0), otherwise, will have garbage in them.
#include <stdio.h>
int main(int argc, char *argv[]) {
int a[] = {1,2,3,4,5,7,8};
int b[] = {1,2,3,4,6,7,8};
int i,j,sum=0,count=0;
int numElements = sizeof(a)/sizeof(int);
for (i=0;i<numElements;i++)
{
for (j=0;j<numElements;j++)
{
if (a[i] == b[j]) {
printf("Numbers match: %d\n",a[i]);
count++;
sum += a[i];
}
}
}
printf("--------------------------------\n");
printf("Sum: %d\n",sum);
return 0;
}

largest sum contiguous sub array using recursion to directly output result

Is is possible to find the largest sum contiguous sub array using recursion such that the function would directly return the output.
Below is my solution where I store the max subarray ending at each index and then find the largest among those in the print() function. However, I want the following
Use recursion
Use the recursive function to directly output the final result.
My code which uses a recursive function and a helper print() function to find the largest among those numbers
#include <stdio.h>
//int a[] = {-6,60,-10,20};
int a[] = {-2, -3, 4, -1, -2, 1, 5, -3};
int len = sizeof(a)/sizeof(*a);
int maxherearray[10];
int main(void)
{
fun(len-1);
printf("max sub array == %d\n",print(maxherearray));
printf("\n");
return 0;
}
int fun(int n)
{
if(n==0)
return a[n];
maxherearray[n] = max(a[n], a[n]+fun(n-1));
return maxherearray[n];
}
int max(int a, int b)
{
return (a > b)? a : b;
}
EDIT : Posting the print() function which I somehow missed out
//Please make sure that #include <limits.h> is added
int print(int a[])
{
int i = 0;
int largest = INT_MIN;
printf("largest == %d\n",largest);
for(i=0;i<len;i++)
{
if(a[i] > largest)
largest = a[i];
}
return largest;
}
Generally, your algorithm logic is OK. It's like,
f(0) = a(i);
f(i) = max(f(i-1) + a(i), a(i));, get the middle result array
max(0, f(1), f(2), ... , f(n-1)), get the final max_sub result
And you designed a function namedfun for #2, and a helper print() for #3.
Now, (I guess ) what you'd like is to combine #2 and #3 together, i.e., to utilise the middle results of #2 to avoid extra computing/memory space. In terms of your original algorithm logic, here are some possible ways, such as
Add a parameter in your fun to keep max_sub result
int fun(int n, int *result)// add int *result to return max_sub
{
int max_here = 0;
if(n==0){
return a[n];
}
max_here = max(a[n],a[n]+fun(n-1, result));
*result = max(*result, max_here);
return max_here;
}
//...
int main(void)
{
int result = 0;
fun(len-1, &result);
printf("max sub : %d\n", result);
}
Use a global variable (Oh!) to get max_sub in time
int g_maxhere = 0;
int fun2(int n)
{
if(n==0){
return a[n];
}
g_maxhere = max(g_maxhere, max(a[n],a[n]+fun2(n-1)));
return max(a[n], a[n]+fun2(n-1));
}
//...
int main(void)
{
fun2(len-1);
printf("max sub:%d\n",g_maxhere)
}
In fact, your original solution of using a helper function can make your algorithm more clear.
Introduce two global variables, start_idx and end_idx to track the start and end indices of the largest contiguous subarray. Update these variables accordingly in the recursive function.
#include <stdio.h>
/* int a[] = {-6,60,-10,20}; */
int a[] = {-2, -3, 4, -1, -2, 1, 5, -3};
int len = sizeof(a)/sizeof(*a);
int maxherearray[10];
int fun(int n);
int max(int a, int b);
int find_max(int a[], int len);
void print_array(int a[], int start_idx, int end_idx);
int start_idx = 0; // Start of contiguous subarray giving max sum
int end_idx = 0; // End of contiguous subarray giving max sum
#define NEG_INF (-100000)
int max_sum = NEG_INF; // The max cont sum seen so far.
int main(void)
{
start_idx = 0;
end_idx = len - 1;
maxherearray[0] = a[0];
printf("Array a[]: ");
print_array(a, 0, len-1);
printf("\n");
// Compute the necessary information to get max contiguous subarray
fun(len - 1);
printf("Max subarray value == %d\n", find_max(maxherearray, len));
printf("\n");
printf("Contiguous sums: ");
print_array(maxherearray, 0, len - 1);
printf("\n");
printf("Contiguous subarray giving max sum: ");
print_array(a, start_idx, end_idx);
printf("\n\n");
return 0;
}
int fun(int n)
{
if(n==0)
return a[0];
int max_till_j = fun(n - 1);
// Start of new contiguous sum
if (a[n] > a[n] + max_till_j)
{
maxherearray[n] = a[n];
if (maxherearray[n] > max_sum)
{
start_idx = end_idx = n;
max_sum = maxherearray[n];
}
}
// Add to current contiguous sum
else
{
maxherearray[n] = a[n] + max_till_j;
if (maxherearray[n] > max_sum)
{
end_idx = n;
max_sum = maxherearray[n];
}
}
return maxherearray[n];
}
int max(int a, int b)
{
return (a > b)? a : b;
}
// Print subarray a[i] to a[j], inclusive of end points.
void print_array(int a[], int i, int j)
{
for (; i <= j; ++i) {
printf("%d ", a[i]);
}
}
int find_max(int a[], int len)
{
int i;
int max_val = NEG_INF;
for (i = 0; i < len; ++i)
{
if (a[i] > max_val)
{
max_val = a[i];
}
}
return max_val;
}

Resources