I'm trying to implement segmented sieve of Eratosthenes in C (im beginner programmer) and it just prints proper output but I'm getting SIGSEGV when I'm submitting in on SPOJ. Can you help me spot the leak?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void segmented_sieve(int *m, int *n, int t) {
int count, i, j, l, sqrt_imax, hlp_imin;
count = i = j = l = sqrt_imax = hlp_imin = 0;
int *imin, *imax;
imin = m;
imax = n;
sqrt_imax = (int)sqrt((double)imax[t]);
int *sieve;
sieve = malloc((imax[t] + 1) * sizeof(*sieve));
memset(sieve, 1, (imax[t] + 1) * sizeof(*sieve));
for (i = 2; i <= sqrt_imax; ++i) {
for (j = i * i; j <= imax[t]; j += i)
sieve[j] = 0;
}
int *next;
next = malloc((int)sqrt(1000000000) * sizeof(*next));
for (i = 2; i <= sqrt_imax; ++i) {
if (sieve[i] > 0) {
++count;
next[count] = i;
}
}
for (i = 1; i <= count; ++i) {
if (imin[t] <= 2) {
imin[t] = 2;
for (j = next[i]; j <= sqrt_imax; j = next[i]) {
for (l = j * j; l <= n[t]; l += j)
sieve[l] = 0;
break;
}
}
else {
hlp_imin = (int)(m[t] / next[i]);
hlp_imin *= next[i];
for (j = next[i]; j <= sqrt_imax; j = next[i]) {
for (l = hlp_imin; l <= imax[t]; l += j)
sieve[l] = 0;
break;
}
}
}
for (i = imin[t]; i < imax[t]; ++i)
sieve[i] > 0 ? printf("%d\n", i) : 0;
free(sieve);
free(next);
}
int main()
{
int t, tmp, i;
t = tmp = i = 0;
scanf("%d", &t);
int *m;
m = malloc(t * sizeof(*m));
int *n;
n = malloc(t * sizeof(*n));
for (i = 0; i < t; ++i) {
scanf("%d", &tmp);
m[i] = tmp;
scanf("%d", &tmp);
n[i] = tmp;
}
for (i = 0; i < t; ++i) {
segmented_sieve(m, n, i);
printf("\n");
}
free(m);
free(n);
return 0;
}
I fixed it by changing int to char. now just getting TLE...
Think about what happens if you get two values imin = 2,000,000,000 and imax = 2,000,000,010. You should create a tiny sieve for just 11 numbers. But you allocate storage for 2 billion ints which is probably more than your computer can handle.
Related
I'm making the sieve of erasthostenes in c. I have programmed it in other languages before but I never encountered this problem. Here's my algorithm:
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <time.h>
#include <limits.h>
int main(){
clock_t t;
t = clock();
int n = 1299710;
bool pPrimes[n];
for(int i = 0; i<n; i++){
pPrimes[i] = true;
}
pPrimes[0] = false;
pPrimes[1] = false;
for(int i = 2; i<sqrt(n); i++){
if(pPrimes[i]){
for(int x = i*i; x<n; x+=i){
pPrimes[x] = false;
}
}
}
for(int i = 2; i<n; i++){
if (pPrimes[i]){
printf("%d\n", i);
}
}
t = clock() - t;
double time_taken = ((double)t)/CLOCKS_PER_SEC;
printf("%f", time_taken);
return 0;
}
It's when I declare pPrimes that n can't be large enough. A million or so works but not more. Is there anyway of fixing this?
I tried debugging but I only get this error message:
line 1: 4320 Segmentation fault: 11
Some issues:
Out of local space
OP reports with large n, there is trouble. Better to allocate with malloc().
bool is not certainly the narrowest type - use unsigned char. Better to allocate with an unsigned size such as unsigned or size_t.
//int n = 1299710;
//bool pPrimes[n];
unsigned n = 1299710;
if (n < 2) { // Avoid edge cases
fprintf(stderr, "Use larger value, not %u\n", n);
return EXIT_FAILURE;
}
unsigned char *pPrimes = malloc(sizeof *nPrimes * n);
if (pPrimes == NULL) {
fprintf(stderr, "Out-of-memory %u\n", n);
return EXIT_FAILURE;
}
Off by one
I would expect int n = 1299710; to imply finding all the primes up to and including n.
unsigned char *pPrimes = malloc(sizeof *nPrimes * (n+1));
// for(int i = 2; i<n; i++){
for(unsigned i = 2; i <= n; i++){ // <=
Referencing this pseudocode, edge tests are off by one.
Do not trust a raw sqrt() for an integer problem. When the expected result is x.00000..., that function may return x_minus_1.99999....
unsigned qsrt_n = lround(sqrt(n));
// for(int i = 2; i<sqrt(n); i++){
for(unsigned i = 2; i <= sqrt_n; i++){ // <=
if(pPrimes[i]){
// for(int x = i*i; x<n; x+=i){
for(unsigned x = i*i; x <= n; x+=i){ // <=
pPrimes[x] = false;
}
}
}
You are allocating too much memory in the stack. This is known as a stack overflow.
Either (as #Gerhardh said in a comment):
Use a static array
Use a global array
Use malloc()
1. With a static array:
int main(void)
{
#define n 1299710
static bool primes[n] = {false, false};
for (size_t i = 2; i < n; ++i) {
primes[i] = true;
}
long srn = sqrt(n) + 1;
for (size_t i = 0; i < srn; ++i) {
if (!primes[i]) continue;
for (size_t ii = i*i; ii < n; ii += i)
primes[ii] = false;
}
// print...
}
2. With a global array:
#define n 1299710
/*static?*/ bool primes[n] = {false, false};
int main(void)
{
for (size_t i = 2; i < n; ++i) {
primes[i] = true;
}
long srn = sqrt(n) + 1;
for (size_t i = 0; i < srn; ++i) {
if (!primes[i]) continue;
for (size_t ii = i*i; ii < n; ii += i)
primes[ii] = false;
}
// print...
}
3. With a dynamic array:
int main(void)
{
const size_t n = 1299710;
bool *primes = malloc(n * sizeof bool);
if (!primes) {
printf("Memory issues. Goodbye!\n");
return EXIT_FAILURE;
}
for (size_t i = 2; i < n; ++i) {
primes[i] = true;
}
primes[0] = false;
primes[1] = false;
long srn = n == 1 ? 1 : sqrt(n) + 1;
for (size_t i = 0; i < srn; ++i) {
if (!primes[i]) continue;
for (size_t ii = i*i; ii < n; ii += i)
primes[ii] = false;
}
// print...
}
How do I get to write to 2D pointers where I have pnumber[2%4][2%4] and how can I get pnumber with more than 3 ciphers to be displayed?
I'm making a program to write pascals triangle in C.
When the pointer pnumbers[i][j] have both i and j = 2 mod 4, except for when i and j = 2, then my program won't write to the address and give the error message:
pascals triangle: malloc.c:2406: sysmalloc: Assertion '{old_top == initial_top (av) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.
Aborted.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int factorial(int p) {
if (p>=1) {
return p*factorial(p-1);
}
else {
return 1;
}
}
int NchooseM(int n, int m) {
return factorial(n)/(factorial(n-m)*factorial(m));
}
int main() {
int n =7;
int x = n-2;
int i, j, k;
/*
printf("How many rows of Pascals triangle do you want to write?\n");
scanf("%d", &n);
*/
int **pnumbers;
pnumbers = (int **) malloc(n *sizeof(int *));
/* Allocate memory for storing the individual elements in a row */
for (i = 0; i < n; i++) {
pnumbers[i] = (int *) malloc(i * sizeof(int));
}
pnumbers[0][1] = 1;
/* Calculating the value of pnumbers[k][l] */
for (i = 0; i < n; i++) {
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
/*
if (!(i % 4 == 2 && i != 2))
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
} else if (i > 2) {
for (j = 0; j <= i-1; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
}
*/
}
/* Writing out the triangle */
for (i = 0; i < n; i++) {
for (k = 0; k <= x; k++){
printf(" ");
}
for (j = 0; j <= i; j++) {
printf("%d ", pnumbers[i][j]);
}
x = x-1;
printf("\n");
}
for (i = 0; i < n; i++) {
free(pnumbers[i]);
}
free(pnumbers);
return 0;
}
When I avoid writing to these addresses and just print them out I get some seemingly random integer at these memory addresses.
Also when avoid these addresses and just print out so many rows that I get some spots with a higher integer with more than 3 siphers, it seems to overflow - and I don't see the logic behind it.
The result of running the second code
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int factorial(int p) {
if (p>=1) {
return p*factorial(p-1);
}
else {
return 1;
}
}
int NchooseM(int n, int m) {
return factorial(n)/(factorial(n-m)*factorial(m));
}
int main() {
int n =20;
int x = n-2;
int i, j, k;
/*
printf("How many rows of Pascals triangle do you want to write?\n");
scanf("%d", &n);
*/
int **pnumbers;
pnumbers = (int **) malloc(n *sizeof(int *));
/* Allocate memory for storing the individual elements in a row */
for (i = 0; i < n; i++) {
pnumbers[i] = (int *) malloc(i * sizeof(int));
}
pnumbers[0][1] = 1;
/* Calculating the value of pnumbers[k][l] */
for (i = 0; i < n; i++) {
/*
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
*/
if (!(i % 4 == 2 && i != 2))
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
} else if (i > 2) {
for (j = 0; j <= i-1; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
}
}
/* Writing out the triangle */
for (i = 0; i < n; i++) {
for (k = 0; k <= x; k++){
printf(" ");
}
for (j = 0; j <= i; j++) {
printf("%d ", pnumbers[i][j]);
}
x = x-1;
printf("\n");
}
for (i = 0; i < n; i++) {
free(pnumbers[i]);
}
free(pnumbers);
return 0;
}
But row number 13 is still quite messed up.
Code is experiencing int overflow and thus undefined behavior (UB).
With 32-bit int and int factorial(int p), p > 12 oveflows the int range.
Code could use a wider integer type (long long works up to p==20), but improvements can be made at NchooseM() to avoid overflow for higher values.
Something like the below. Works up to int n = 30;
int NchooseM(int n, int m) {
// return factorial(n)/(factorial(n-m)*factorial(m));
int nm = 1;
int den = 1;
for (int i = m+1; i <= n; i++) {
assert(INT_MAX/i >= nm);
nm *= i;
assert(nm % den == 0);
nm /= den++;
}
return nm;
}
Tried unsigned long long and works up to int n = 62;
Edit: Another bug:
I "fixed" by initializing all to 1, yet I suspect something remains amiss in /* Calculating the value of pnumbers[k][l] */ for (i = 0; i < n; i++) { code.
pnumbers[i] = malloc((i + 1) * sizeof pnumbers[i][0]);
for (int j = 0; j < i + 1; j++) {
pnumbers[i][j] = 1;
}
Aside: rather than pnumbers[i] = (int *) malloc((i+1) * sizeof(int));, consider below with no unneeded cast nor trying to match the right type.
pnumbers[i] = malloc(sizeof pnumbers[i][0] * (i+1));
Im trying to submit a solution for the problem FCTRL2(https://www.codechef.com/problems/FCTRL2) on codechef. On executing the code it sometimes gets executed successfully while sometimes it gives a SIGSEGV error. But when I submit it, it always shows wrong answer. Though the code gives correct answer when i run it on any other IDE.
#include <iostream>
#include <stdio.h>
using namespace std;
int main(void)
{
int testCases, i, j, k, n, num, digits, carry = 0, temp;
scanf("%d", &testCases);
int testArr[160];
for (i = 0; i < testCases; i++)
{
scanf("%d", &n);
num = n;
if (n == 0 || n == 1)
{
testArr[0] = 1;
digits = 1;
}
else
{
k = 0;
for (j = 10; n != 0; j = j * 10)
{
testArr[k] = n % j;
n = n / j;
k++;
}
digits = k;
for (j = 1; j < num; j++)
{
for (k = 0; k < digits; k++)
{
temp = testArr[k] * j + carry;
if (temp > 10)
{
testArr[k] = temp % 10;
carry = temp / 10;
}
else
{
testArr[k] = temp;
carry = 0;
}
}
if (carry > 10)
{
testArr[k] = carry % 10;
k++;
testArr[k] = carry / 10;
digits = k + 1;
carry = 0;
}
else if (carry > 0)
{
testArr[k] = carry;
digits = k + 1;
carry = 0;
}
}
}
for (k = (digits - 1); k >= 0; k--)
{
printf("%d", testArr[k]);
}
printf("\n");
}
return 0;
}
#include<stdio.h>
void multiplyTwoMatrices(int (*)[2], int[][2], int[][2]);
void copyMatrix(int[][2], int[][2]);
void powerAMatrix(int[][2], int[][2], int);
int main()
{
int num;
scanf("%d", &num);
int i;
for(i = -1; i <= num; i++)
{
printf("\n%d", fib(i));
}
}
int fib(int num)
{
if(num <= 0)
{
return 0;
}
else
{
int matrix[2][2] = {{1, 1}, {1, 0}};
//int fibMatrix[2][2] = powerAMatrix(matrix[2][2], num);
int fibMatrix[2][2];
powerAMatrix(fibMatrix, matrix, num);
return getFibNum(fibMatrix);
}
}
void powerAMatrix(int fibMatrix[2][2], int matrix[2][2], int num)
{
//fibMatrix = matrix;
copyMatrix(fibMatrix, matrix);
int i = 0;
for(i = 1; i < num; i++)
{
//fibMatrix = fibMatrix * matrix;
multiplyTwoMatrices(fibMatrix, fibMatrix, matrix);
}
}
void copyMatrix(int destinationMatrix[2][2], int sourceMatrix[2][2])
{
int i = 0; int j = 0;
for(i = 0; i < 2; i++)
for(j = 0; j < 2; j++)
destinationMatrix[i][j] = sourceMatrix[i][j];
}
void multiplyTwoMatrices(int multipliedMatrix[2][2], int matrixA[2][2], int matrixB[2][2])
{
int i = 0; int j = 0; int k = 0;
for(i = 0; i < 2; i++)
{
for(j = 0; j < 2; j++)
{
multipliedMatrix[i][j] = 0; //or just initialize it as a zero matrix.
for(k = 0; k < 2; k++)
{
multipliedMatrix[i][j] += (matrixA[i][k] * matrixB[k][j]);
}
}
}
//working alternative
/*
int x = matrixA[0][0]*matrixB[0][0] + matrixA[0][1]*matrixB[1][0];
int y = matrixA[0][0]*matrixB[0][1] + matrixA[0][1]*matrixB[1][1];
int z = matrixA[1][0]*matrixB[0][0] + matrixA[1][1]*matrixB[1][0];
int w = matrixA[1][0]*matrixB[0][1] + matrixA[1][1]*matrixB[1][1];
multipliedMatrix[0][0] = x;
multipliedMatrix[0][1] = y;
multipliedMatrix[1][0] = z;
multipliedMatrix[1][1] = w;
*/
}
int getFibNum(int fibMatrix[2][2])
{
return fibMatrix[0][1];
}
The function multiplyTwoMatrices() seems to work only if "working alternative" (code closed in comments inside this function) is used instead of the one used currently. I'm unable to understand what is going wrong with this code. A little help is appreciated.
Output expected: 0 0 1 1 2 3 5 8 ...
Output coming: 0 0 1 1 1 1 1 1 ...
while your multiplication function is correct, it doesn't work correctly when the destination is one of the operands; if it is, the operand is changed there while the calculation is underway.
Either require that multipliedMatrix is distinct from both matrixA and matrixB (that'd be preferred), or have a temporary matrix there and copy it into the result!
P.S. it would be much easier wrapping the matrix class into a struct:
struct intmatrix2x2 {
int values[2][2];
};
this would make implicit copies when calling functions; and instead of copyMatrix you can say:
struct intmatrix2x2 b = a;
and your multiplication could read as
struct intmatrix2x2 multiply(struct intmatrix2x2 a, struct intmatrix2x2 b)
{
struct intmatrix2x2 result;
int i = 0; int j = 0; int k = 0;
for(i = 0; i < 2; i++)
{
for(j = 0; j < 2; j++)
{
result.values[i][j] = 0; //or just initialize it as a zero matrix.
for(k = 0; k < 2; k++)
{
result.values[i][j] += a.values[i][k] * b.values[k][j]);
}
}
}
return result;
}
and you could use it as
struct intmatrix2x2 result = multiply(a, b);
Description of the problem :
Compute the number of all the sequences which go up down from some input n.
So the user input n; with that n then I create an array of numbers 1..n and then number the sequences with that property
Example: n = 4
1 3 2 4
1 4 2 3
2 3 1 4
2 4 1 3
3 4 1 2
Answer: 5
My program works but for some reason I sometimes get 0 instead of the answer.
#include <stdio.h>
#include <stdlib.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 swap(int *fir, int *sec) {
int temp = *fir;
*fir = *sec;
*sec = temp;
}
void permute(int *array, int i, int length, int *count) {
if (length == 2) {
*count = 1;
return;
}
if (length == i) {
int v = 0, flag = 1;
while (v < length) {
if (v % 2 == 0) {
if (array[v] < array[v + 1]) {
v++;
} else {
flag = 0;
return;
}
}
if (v % 2 != 0) {
if (array[v] > array[v + 1]) {
v++;
} else {
flag = 0;
return;
}
}
}
if (flag == 1) {
/*
int a;
for (a = 0; a < length; a++)
printf("%d", array[a]);
printf("\n");
*/
*count = *count + 1;
}
}
int j = i;
for (j = i; j < length; j++) {
swap(array + i, array + j);
permute(array, i + 1, length, count);
swap(array + i, array + j);
}
return;
}
int main(int argc, char **argv) {
int n;
scanf("%d", &n);
int *arr = safeMalloc(n * sizeof(int));
int i;
for (i = 0; i < n; i++) {
arr[i] = i + 1;
}
int count = 0;
permute(arr, 0, n, &count);
printf("%d\n", count);
return 0;
}
You basically generate all permutations of the array elements and count the valid ones.
Your code has a minor flaw:
the loop while (v < length) { goes one step too far: you access tab[v + 1] so the loop should stop at v < length - 1. As currently coded, it has undefined behavior.
You can further simply the code:
there should be no need to special case length == 2.
flag useless as you always return when you clear it.
if (v % 2 != 0) is redundant: else would suffice.
Here is a fixed and simplified version:
#include <stdio.h>
#include <stdlib.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 swap(int *fir, int *sec) {
int temp = *fir;
*fir = *sec;
*sec = temp;
}
void permutate(int *array, int i, int length, int *count) {
if (i == length) {
for (int v = 0; v < length - 1; v++) {
if (v % 2 == 0) {
if (array[v] >= array[v + 1]) {
return;
}
} else {
if (array[v] <= array[v + 1]) {
return;
}
}
}
*count = *count + 1;
} else {
for (int j = i; j < length; j++) {
swap(array + i, array + j);
permutate(array, i + 1, length, count);
swap(array + i, array + j);
}
}
}
int main(int argc, char **argv) {
int n;
if (scanf("%d", &n) == 1 && n > 0) {
int *arr = safeMalloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
arr[i] = i + 1;
}
int count = 0;
permutate(arr, 0, n, &count);
printf("%d\n", count);
}
return 0;
}
if you call tab(n,k) the number of updown sequence of length n with k being the last number in your sequence, you can write a recursive formula and implement it like that:
int N = 5+1;
int** tab = new int*[N];
for (int n = 0; n < N; n++) {
tab[n] = new int[N];
for (int k = 0; k < N; k++) {
tab[n][k] = 0;
}
}
tab[1][1] = 1;
for (int n = 2; n < N; n++) {
for (int k = 1; k <= n; k++) {
if (n % 2 == 0) {
for (int j = 0; j < k; j++) {
tab[n][k] += tab[n-1][j];
}
}
else {
for (int j = k; j < n; j++) {
tab[n][k] += tab[n-1][j];
}
}
}
}
int res = 0;
for (int j = 0; j < N; j++) {
res += tab[N - 1][j];
}
You can solve this without iterating through the permutations. Say you're trying to calculate f(n). Where can the new, high number go? It has to go in an 'up' position, which is an even position. You can have any valid sequence of odd length preceding it, and any valid sequence following it.
Let's say we're calculating f(n,k) where the highest val is in position k, zero indexed. This is zero for k even. For odd k we get:
f(n,k) = choose(n-1, k) * f(k) * f(n - k - 1)
To get f(n), sum f(n,k) over odd k < n.
We have to calculate the first few by hand.
f(0) = 1
f(1) = 1
f(2) = 1
f(3) = f(3,1) = choose(2,1) * f(1) * f(1) = 2 * 1 *1 = 2
f(4) = f(4,1) + f(4,3) = choose(3,1) * f(1) * f(2) + choose(3,3) * f(3) * f(0) = 3*1*1 + 1*2*1 = 5
f(5) = f(5,1) + f(5,3) = choose(4,1) * f(1) * f(3) + choose(4,3) * f(3) * f(1) = 4*1*2 + 4*2*1 = 16