Related
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);
can you help me with code which returns partial sum of 'X' numbers in array in c?
Complete :
int arr_sum( int arr[], int n )//Recursive sum of array
{
if (n < 0) //base case:
{
return arr[0];
}
else
{
return arr[n] + arr_sum(arr, n-1);
}
}
void sum_till_last (int *ar,int si )
{
**int sum,i;// the problem some where here
ar=(int*) malloc(si*sizeof(int));
for (i=0; i<si;i++)
{
sum=arr_sum(ar,i);
ar [i]=sum;
}
free (ar);**
}
void main ()
{
int i;
int a [5];
for (i = 0; i < 5; i++)
scanf_s("%d", &a[i]);
sum_till_last(a,5);
printf("%d\n",a[5]);
}
\i want to create new array with this this legality:
My input :
4
13
23
21
11
The output should be (without brackets or commas):
4
17
40
61
72
Now when we can see the full code, it's quite obvious that the problem is in the sum_till_last function where you overwrite the pointer you pass to the function with some new and uninitialized memory you allocate.
Drop the allocation (and the call to free of course). And fix the logical bug in arr_sum that causes you to get arr[0] + arr[0] when i is zero.
Here you go:
#include <stdio.h>
int main () {
int in_arr[5] = {4,13,23,21,11};
int out_arr[5];
int p_sum =0;
int i;
for ( i=0;i<5;i++){
out_arr[i] = in_arr[i]+p_sum;
p_sum=p_sum+in_arr[i];
}
for (i=0;i<5;i++){
printf("%d", out_arr[i] );
}
}
Fix according to your policy
#include <stdio.h>
#include <stdlib.h>
int arr_sum(int arr[], int n){
if (n == 0){//Change to this
return arr[0];
} else {
return arr[n] + arr_sum(arr, n-1);
}
}
void sum_till_last(int *ar, int si){
int sum,i;
int *temp = malloc(si * sizeof(int));//variable name ar is shadowing parameter name ar.
for(i = 0; i < si; i++){
temp[i] = arr_sum(ar, i);
if(i)
putchar(' ');
printf("%d", temp[i]);//need print out :D
}
free(temp);
}
int main(void){
int i, a[5];
for (i = 0; i < 5; i++)
scanf_s("%d", &a[i]);
sum_till_last(a, 5);
//printf("%d\n",a[5]);<-- this print only one element. and It's out of bounds element XD
}
I just made it simple so it´s easy to understand :)
I´m assuming "n" is always equal or less then array element number. Then you just print the SUM.
#include <stdio.h>
int arr_sum( int arr[], int n ){
int i=0,SUM=0;
for(; i < n;i++){
SUM= SUM+ arr[i];
printf("%d ",SUM);
}
}
int main(void) {
int array[] = {4, 13, 23, 21, 11};
arr_sum(array,5);
return 0;
}
I have got a piece of code that prints the combination of M number From N (nCm);
As it is a recursion, it works very slow when N is large.
#include <stdio.h>
#include <stdlib.h>
#define N 80
#define M 4
int result[M]= {0}; // THE ARRAY THAT SAVE THE RESULT OF ONE COMBINATION
int queue[N] = {0};
int top = 0;
void comb(int* input,int s, int n, int m)
{
if (s > n)
return ;
if (top == m)
{
for (int i = 0; i < m; i++)
{
result[i] = queue[i];
printf("%d\n", queue[i]);
}
}
queue[top++] = input[s];
comb(input,s+1, n, M);
top--;
comb(input,s+1, n, M);
}
int main()
{
int array[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,
27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,
73,74,75,76,77,78,79,80};
printf("\ncombination():\n");
comb(array,0, N, M);
printf("\n");
}
I would like to know if there is any space for improvement in the algorithm above?
if possible, can I use openMP ?
Thanks
To me your code was even giving the desired output. see
I have changed
printing format each combination was not good enough.
repeated combinations. (note: else part of if statement added).
reduced 2 recursive call with a loop and a recursive call. (Less space.)
The required code is:
#include <stdio.h>
#include <stdlib.h>
#define N 20
#define M 6
int result[M]= {0}; // THE ARRAY THAT SAVE THE RESULT OF ONE COMBINATION
int queue[N] = {0};
int top = 0;
void comb(int* input,int s, int n, int m)
{
if (s > n)
return ;
if (top == m)
{
printf("\n");
for (int i = 0; i < m; i++)
{
result[i] = queue[i];
printf("%d ", queue[i]);
}
}else{
for(int ss=s;ss<n;ss++){
queue[top++] = input[ss];
comb(input,ss+1, n, m);
top--;
}
//comb(input,s+1, n, m);
}
}
int main()
{
int array[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,
27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,
73,74,75,76,77,78,79,80};
printf("\ncombinations():\n");
comb(array,0, N, M);
printf("\n");
}
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;
}
Here is my program it is compiling and running without syntax errors.How ever it does not sort the array.The problem lies in where I am passing the array in function
#include<stdio.h>
#include<string.h>
int partition (int *,int,int);
void quicksort (int *,int,int);
static int call=0;
int main()
{
int i,j,choice;
int length;
int a[]={81, 12, 90, 3, 49, 108, 47};
i=0;
length=sizeof(a)/sizeof(a[0]);
quicksort(a,0,length-1);
printf("the sorted array is\n");
for(i=0;i<length;i++)
printf (" %d ",a[i]);
}
int partition(int *num,int p,int r)
{
int x,j,i,temp,bak;
x=num[r];
i=p-1;
for(j=0;j<=r-1;j++)
{
if(num[j]<=x)
{
i=i+1;
temp=num[i];
num[i]=num[j];
num[j]=temp;
{
printf(" %d",num[bak]);
}
}
}
num[i+1]=num[r];
return i+1;
}
void quicksort (int *num,int p,int r)
{
int q;
if (p<r)
{
call++;
q=partition(num,p,r);
quicksort(num,p,q-1);
quicksort(num,q+1,r);
}
}
The above way of passing array in functions is that right that is what I want to know because that is giving problem in function partition.
Inside the function partition when swapping happens then I tried printing the array there itself (it is not sorted array but just to see upto what point things reached) then I saw that only 2 or 3 elements of array which I had passed are being printed and rest of the array is lost some where.So my doubt is array is not being passed properly.
To be able to see as what is the problem with array passing in a function I wrote a smaller program ka1.c
#include<stdio.h>
void pass(int *);
int main ()
{
int a[]={3,5,61,32,12};
pass(a);
}
void pass (int *num)
{
int i,j;
j=sizeof(num)/sizeof(num[0]);
for (i=0;i<j;i++)
printf(" %d",num[i]);
}
Now when I run the above code I get output just
3 5
I was expecting the complete array to be printed in output of ka1.c.
Where as if you notice rest of the array is not getting printed.Where did that go?
I have used the same logic in quicksort also hence I feel the error is same in both cases.
UPDATE1
After the comment below I checked the length of array recieved in quicsort.c paritition function via
sizeof(num)/sizeof(num[0]);
and found of original array
int a[]={81, 12, 90, 3, 49, 108, 47};
which is having length 7 here when I passed it in the function partition
the length is only 2.
The same is case with program ka1.c So why only length is 2 in both cases?
UPDATE2
As the suggestions given below now I have passed on the length also
#include<stdio.h>
#include<string.h>
int partition (int *,int,int,int);
void quicksort (int *,int,int,int);
static int call=0;
int main()
{
int i,j,choice;
int length;
int a[]={81, 12, 90, 3, 49, 108, 47};
i=0;
printf("the sorted array is\n");
length=sizeof(a)/sizeof(a[0]);
printf("length of array %d\n",length);
printf("quick sort called in main\n");
quicksort(a,0,length-1,length);
for(i=0;i<length;i++)
printf (" %d ",a[i]);
}
int partition(int *num,int p,int r,int june)
{
int x,j,i,temp,bak,length;
x=num[r];
i=p-1;
bak=0;
printf("inside the partition\n");
printf("length of june recieved =%d \n",june);
for(j=0;j<=r-1;j++)
{
if(num[j]<=x)
{
i=i+1;
temp=num[i];
num[i]=num[j];
num[j]=temp;
printf("printing array after swap\n");
for(;bak<7;bak++)
{
printf(" %d ",num[bak]);
}
}
}
num[i+1]=num[r];
return i+1;
}
void quicksort (int *num,int p,int r,int june)
{
int q,bbc,ccd;
if (p<r)
{
call++;
printf("partition called %d times p=%d r=%d\n",call,p,r);
printf("before sending to function length of june=%d \n",june);
q=partition(num,p,r,june);
bbc=q-1-p+1;
quicksort(num,p,q-1,bbc);
ccd=r-q-1+1;
quicksort(num,q+1,r,ccd);
}
}
But the program is still failing to print the sorted array.
You can compile and run the above code.
SOLVED
Finally with help of replies below I have been able to solve the above problem.
The mistake lied in function partition in statement
for (j = 0; j <= r - 1; j++)
instead it should have been
for (j = p; j <= r - 1; j++)
note j=p and j=0
here
j=0
is wrong since when recursively second partition is tried to be sorted it started disturbing the first partition and hence the result was also wrong.
In this program I faced a problem in using gdb to debug a recursive function.
Please check this thread also
Debugging recurssion was quite tricky.
SO the correct code is
#include<stdio.h>
#include<string.h>
int partition (int *, int, int, int);
void quicksort (int *, int, int, int);
static int call = 0;
int
main ()
{
int i, j, choice;
int length;
int a[] = { 81, 12, 90, 3, 49, 108, 47 };
i = 0;
printf ("the sorted array is\n");
length = sizeof (a) / sizeof (a[0]);
printf ("length of array %d\n", length);
printf ("quick sort called in main\n");
quicksort (a, 0, length - 1, length);
for (i = 0; i < length; i++)
printf (" %d ", a[i]);
}
int
partition (int *num, int p, int r, int june)
{
int x, j, i, temp, bak, length;
x = num[r];
i = p - 1;
bak = 0;
for (j = p; j <= r - 1; j++)
{
if (num[j] <= x)
{
i = i + 1;
temp = num[i];
num[i] = num[j];
num[j] = temp;
}
}
temp=num[i+1];
num[i + 1] = num[r];
num[r]=temp;
return i + 1;
}
void
quicksort (int *num, int p, int r, int june)
{
int q, bbc, ccd;
if (p < r)
{
call++;
q = partition (num, p, r, june);
bbc = q - 1 - p + 1;
quicksort (num, p, q - 1, bbc);
ccd=r-q+1;
quicksort (num, q + 1, r, ccd);
}
}
The problem is in the way you are calculating the length of teh array.......try simply giving the number of elements in the array as the parameter for the quicksort method....i guess u will have the right answer...
and also i agree to the point made....try and passing the length of the array with the array.....try both and tell me which works...:)
NEW CODE:
#include<stdio.h>
#include<string.h>
//int partition (int *,int,int);
void q_sort(int*,int,int);
void quicksort (int *,int);
static int call=0;
int main()
{
int i,j,choice;
int length;
int a[]={81, 12, 90, 3, 49, 108, 47};
i=0;
printf("the sorted array is\n");
length=sizeof(a)/sizeof(a[0]);
printf("length of array %d\n",length);
printf("quick sort called in main\n");
quicksort(a,length);
for(i=0;i<length;i++)
printf (" %d ",a[i]);
}
/*int partition(int *num,int p,int r)
{
int x,j,i,temp,bak,length;
x=num[r];
i=-1;
bak=0;
printf("inside the partition\n");
for(j=0;j<=r-1;j++)
{
if(num[j]<=x)
{
i=i+1;
temp=num[i];
num[i]=num[j];
num[j]=temp;
printf("printing array after swap\n");
for(;bak<7;bak++)
{
printf(" %d ",num[bak]);
}
}
}
num[i+1]=num[r];
return i+1;
}
*/
/*void quicksort (int *num,int p,int r)
{
int q,bbc,ccd;
if (p<r)
{
call++;
printf("partition called %d times p=%d r=%d\n",call,p,r);
q=partition(num,p,r);
bbc=q-1-p+1;
quicksort(num,p,q-1);
ccd=r-q-1+1;
quicksort(num,q+1,r);
}
}*/
void quicksort(int numbers[], int array_size)
{
q_sort(numbers, 0, array_size - 1);
}
void q_sort(int numbers[], int left, int right)
{
int pivot, l_hold, r_hold;
l_hold = left;
r_hold = right;
pivot = numbers[left];
while (left < right)
{
while ((numbers[right] >= pivot) && (left < right))
right--;
if (left != right)
{
numbers[left] = numbers[right];
left++;
}
while ((numbers[left] <= pivot) && (left < right))
left++;
if (left != right)
{
numbers[right] = numbers[left];
right--;
}
}
numbers[left] = pivot;
pivot = left;
left = l_hold;
right = r_hold;
if (left < pivot)
q_sort(numbers, left, pivot-1);
if (right > pivot)
q_sort(numbers, pivot+1, right);
}
You need to put a ; at the end of the function declaration before main:
void pass(int *) ;
^
You have to pass the size of the array along with the array itself. The function receiving the array cannot determine its size. The receiving function only sees num as a pointer, so when you use sizeof(num) it returns the size of the pointer num, not the size of the memory allocated for the array in the main function. So, you have to do something like this:
#include<stdio.h>
void pass(int *, int);
int main ()
{
int a[]={3,5,61,32,12};
int length;
length = sizeof(a)/sizeof(a[0]);
pass(a, length);
}
void pass (int *num, int size)
{
int i;
for (i=0;i<size;i++)
printf(" %d",num[i]);
}
This post explains a similar issue in more detail:
Passing an array as an argument in C++