Okay, so I'm trying to solve the Knapsack problem.
On small input cases the program runs with no problem and provides the optimal solution, however when the input size is large, or rather the numbers in the input file become large, the program gives me a segmentation fault. I don't quite get why is this happening since the max value of INT exceeds any of these numbers too.
Here's my code.
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int W,n,i,j,k ;
scanf("%d %d",&W,&n); // capacity of knapsack and number of total items
int value[n+1],weight[n+1];
int** A;
A = (int **)malloc((n+1)*sizeof(int*));
for(i=0;i<W+1;i++)
A[i]=(int *)malloc(sizeof(int)*(W+1));
for(i=1;i<n+1;i++)
{
scanf("%d %d",&value[i],&weight[i]); //taking value and weight of each item
}
for(i=0;i<W+1;i++)
A[0][i]=0;
for(i=0;i<n+1;i++)
A[i][0]=0;
for(i=1;i<n+1;i++)
{
for(j=1;j<W+1;j++)
{
if(j-weight[i]<0)
{
A[1][j]=A[0][j];
}
else
{
if(A[0][j]>A[0][j-weight[i]]+value[i])
A[1][j]=A[0][j];
else
A[1][j]=A[0][j-weight[i]]+value[i];
}
}
for(k=0;k<W+1;k++)
A[0][k]=A[1][k];
}
int max=0;
i=1;
for(i=0;i<2;i++)
for(j=0;j<W+1;j++)
{
if(A[i][j]>max)
max=A[i][j];
}
printf("%d\n",max);
return(0);
}
It runs perfectly for this input http://spark-public.s3.amazonaws.com/algo2/datasets/knapsack1.txt
But when the input size is the one given in the link, it provides a seg fault http://spark-public.s3.amazonaws.com/algo2/datasets/knapsack2.txt
Thanks for the help!
When allocating the arrays for the 2nd dimension you do:
for(i=0;i<W+1;i++)
A[i]=(int *)malloc(sizeof(int)*(W+1));
It should be n+1 instead of W+1 in the loop. You should iterate over the "items" dimensions and allocate "weight" dimension.
The solution will work perfectly for n <= W, but for larger number of items (W < n) - you will get undefined behavior, because you are trying to access A[n][0] at some point, but you did not allocate the array for the nth item.
So basically - you need to change the initialization of the 2nd dimension to:
for(i=0;i<n+1;i++)
A[i]=(int *)malloc(sizeof(int)*(W+1));
Related
I have been teaching myself C for just a few weeks, and am attempting to write a code that enables the user to decide the size and elements in an array which is then separated into two arrays - one for odd numbers, and one for even numbers.
I am pretty sure that dynamic allocation has something to do with this, but I am unsure of how to implement it. Here is the code so far:
#include <stdio.h>
#include <stdlib.h>
int main()
{
//User decides the size of the array of numbers-------------------------------
int n;
printf("How many numbers? ");
scanf("%d",&n);
//User inputs values into array the size of array[n]--------------------------
int i;
int array[n];
printf("What are the numbers?\n");
for(i=0; i<n; i++)
{
scanf("%d",&array[i]);
}
//loop goes through array, separates even and odds into 2 new arrays----------
//use dynamic allocation??
for(i=0;i<n;i++)
{
int *evenarray = malloc(sizeof(evenarray)); //not sure if this is setup correctly
int *oddarray = malloc(sizeof(oddarray)); //not sure if this is setup correctly
if(array[i] % 2 == 0) //if value in array CAN be divided by 2
{
printf("Test statement.\n");
}
else //if this is not true, append to odd array
{
printf("Second test statement.\n");
}
}
}
/*this program accepts a user chosen number of numbers
then, the program separates the odd and even numbers into
two different arrays*/
There is no magical way to get this information at one shot. You can however, try either of the below:
Loop over the first array to figure out the count of odd (or even) numbers, then, you know the count of elements for which memory has to be allocated, and you can use either a VLA (as the first array itself) or use a pointer and allocator functions to allocate memory.
--> However, in this process, you have to perform the odd/even check twice - once to count the occurrence of odd/even numbers and next time, to actually decide and copy them to the new locations.
Allocate two chunks of memory similar to the first array size, and start filling the odd and even elements into the new memory, respectively. After all the elements are stored, take the counts, realloc() the allocated memories to the exact size.
--> In this case, the pre-allocation is to be done, but the odd/even check needs to be carried out only once.
You could copy into the odd/even arrays and keep seperate counters to track it. i.e:
//loop goes through array, separates even and odds into 2 new arrays----------
//use dynamic allocation??
int evencount =0;
int oddcount =0;
int *evenarray = malloc(sizeof(evenarray)); //not sure if this is setup correctly
int *oddarray = malloc(sizeof(oddarray)); //not sure if this is setup correctly
for(i=0;i<n;i++)
{
if(array[i] % 2 == 0) //if value in array CAN be divided by 2
{
printf("Printing to even array.\n");
evenarray[evencount] = array[i];
evencount++;
}
else //if this is not true, append to odd array
{
printf("Printing to odd array.\n");
oddarray[oddcount] = array[i];
oddcount++;
}
}
printf("evenarray = ");
for(i=0;i<evencount;i++){
printf("%d, ", evenarray[i]);
}
printf("\n");
printf("oddarray = ");
for(i=0;i<oddcount;i++){
printf("%d, ", oddarray[i]);
}
printf("\n");
I am currently doing a problem of addition of sparse matrices. I am making sparse matrix by using triplet form. The triplet form is made by using structure in c.
struct sparse
{
int row;
int col;
int val;
};
but while doing this sparse matrix problem I encountered a problem that my code only displays the correct sparse matrix when i am giving the indices of nonzero values in increasing order (eg. (0 1 3),(1 2 5),(2 2 7) etc)otherwise it is displaying incorrect matrix.for example if am giving input like (0 1 3),(2 2 7),(1 2 5) etc then it is displaying wrong matrix. How to solve this problem so that in any order of indices it will give correct output?
I have added my input and resulting output. I have done this for two sparse matrix.
#include<iostream>
#include<cstdio>
struct sparse
{
int row,col,val;
};
void readmat(sparse sp[])
{
printf("enter total number number of rows ,column of matrix and total
of nonzero values in this\n");
scanf("%d %d %d",&sp[0].row,&sp[0].col,&sp[0].val);
printf("now start entering the values by specifying index
position\n");
for(int i=1;i<=sp[0].val;i++)
scanf("%d %d %d",&sp[i].row,&sp[i].col,&sp[i].val);
}
void displaymat(sparse sp[])
{
int k=1;
for(int i=0;i<sp[0].row;i++)
{
for(int j=0;j<sp[0].col;j++)
{
if(k<=sp[0].val&&i==sp[k].row&&j==sp[k].col)
{
printf("%d\t",sp[k].val);
k++;
}
else
printf("0\t");
}
printf("\n");
}
}
int main()
{
struct sparse sp1[10],sp2[10],sp3[10];
printf("for first matrix\n");
readmat(sp1);
printf("for second matrix\n");
readmat(sp2);
displaymat(sp1);
printf("\n\n");
displaymat(sp2);
printf("\n\n");
displaymat(sp3);
return 0;
}`
Updating the original answer:
The reason out of order values are not getting printed is because when the value in triplet form points to an element further down the for loops go past all the other values that could have been printed. For example in your example the 3rd element is at row=1, col=3 however the 2nd element is at row=2,col=2. This will lead to the outer for-loop advancing down to 2nd row. At that point in time the loops will not go back and print 1st row.
One way will be to sort based on the row and col and then print the values.
I have written the following code to find the largest palindrome formed by the product of 3-digit numbers. There is a problem with the nested loops which is giving the segmentation fault. Can someone help me with the debugging?
The code works fine for smaller numbers but gives segmentation fault for larger numbers (which is the reason I took long int instead of int for k, l, max and a variables).
#include<stdio.h>
long reverse(long);
main()
{
long k, l, max, a[100];
int i, j, t=0;
printf("hello\n");
for(i=999; i>99; i--)
{
for(j=999; j>99;j--)
{
// printf("hello\n");
k=i*j;
l= reverse(k);
if(k==l) {a[t]=k; t++; }
}
}
printf("hello\n");
max=a[0];
for(t=1;t<100; t++)
{
if(max<a[t]) {max=a[t];}
}
printf("Largest palindrome is %ld\n", max);
}
long reverse(long n)
{
long rev=0;
while(n!=0)
{
rev= rev*10;
rev= rev+n%10;
n=n/10;
}
return rev;
}
For large numbers, t increases beyond the size of the array a.
This will cause the program to write on the program stack where it shouldn't which can cause a crash with a core dump.
If you only want to find the largest palindrome, you don't to save them all. You can just save the largest one.
Since your a is only 100 elements long, you need to ensure t is always less than 100 or you will overflow the bounds of your array. You might want to use realloc to dynamically allocate a using a pointer.
This is a problem from spoj named prime1. The code seems to be correct to me. This even runs and produces desirable results on ideone.com but spoj gives me a runtime error, saying this is a segmentation fault. I can't find any memory leaks, no buffer overflow, etc. Please help me find the segmentation fault.
#include <stdio.h>
unsigned int arr[32200];
int prime()
{
unsigned int i,j,k=2;
int flag;
arr[0]=2;
arr[1]=3;
for (i=5;i<32200;i+=2)
{
flag=0;
for(j=3;j<i;j+=2)
{
if(i%j==0)
{
flag=1;
break;
}
}
if (flag==0)
{
arr[k++]=i;
}
}
return 0;
}
int main()
{
int t;
unsigned int a,b,i,m;
scanf("%d",&t);
prime();
while(t--)
{
scanf("%u%u",&a,&b);
for(i=0;;i++)
{
if (arr[i]>=a)
{
m=i;
break;
}
}
while(arr[m]<=b)
{
printf("%u\n",arr[m]);
m++;
}
printf("\n");
}
return 0;
}
If an a is given that is greater than all elements in arr, the first for() loop in main() overruns the array, yielding undefined behavior. The fact that the global variable arr will be zero initialized helps to trigger this condition: start with any a other than zero, and you immediately have undefined behavior.
The array you are keeping your primes is too small.
The maximum number you can have as b is 10^9 and the smallest for a is 1. Therefore, you need to store all primes between 1 and one billion.
If you type "how many primes between 1 and 1000000000" in wolfram alpha, for instance, you will get that there are 50847534 primes between those two. So your array is too small.
Also, after you fix that, you're getting a TLE. Your code is too inefficient for this problem. You need to develop a faster method to generate the prime numbers.
I want to add numbers to an array using scanf
What did i do wrong? it says expected an expression on the first bracket { in front of i inside the scanf...
void addScores(int a[],int *counter){
int i=0;
printf("please enter your score..");
scanf_s("%i", a[*c] = {i});
}//end add scores
I suggest:
void addScores(int *a, int count){
int i;
for(i = 0; i < count; i++) {
printf("please enter your score..");
scanf("%d", a+i);
}
}
Usage:
int main() {
int scores[6];
addScores(scores, 6);
}
a+i is not friendly to newcomer.
I suggest
scanf("%d", &a[i]);
Your code suggests that you expect that your array will be dynamically resized; but that's not what happens in C. You have to create an array of the right size upfront. Assuming that you allocated enough memory in your array for all the scores you might want to collect, the following would work:
#include <stdio.h>
int addScores(int *a, int *count) {
return scanf("%d", &a[(*count)++]);
}
int main(void) {
int scores[100];
int sCount = 0;
int sumScore = 0;
printf("enter scores followed by <return>. To finish, type Q\n");
while(addScores(scores, &sCount)>0 && sCount < 100);
printf("total number of scores entered: %d\n", --sCount);
while(sCount >= 0) sumScore += scores[sCount--];
printf("The total score is %d\n", sumScore);
}
A few things to note:
The function addScores doesn't keep track of the total count: that variable is kept in the main program
A simple mechanism for end-of-input: if a letter is entered, scanf will not find a number and return a value of 0
Simple prompts to tell the user what to do are always an essential part of any program - even a simple five-liner.
There are more compact ways of writing certain expressions in the above - but in my experience, clarity ALWAYS trumps cleverness - and the compiler will typically optimize out any apparent redundancy. Thus - don't be afraid of extra parentheses to make sure you will get what you intended.
If you do need to dynamically increase the size of your array, look at realloc. It can be used in conjunction with malloc to create arrays of variable size. But it won't work if your initial array is declared as in the above code snippet.
Testing for a return value (of addScores, and thus effectively of scanf) >0 rather than !=0 catches the case where someone types ctrl-D ("EOF") to terminate input. Thanks #chux for the suggestion!