Why does my recursive function seg fault in C? - c

My program is as follows:
#include <stdio.h>
int collatz(int seed, int count) {
int next = 0;
if (seed % 2 == 0) {
next = seed / 2;
} else {
next = 3 * seed + 1;
}
count++;
if (next == 1) {
return count;
} else {
return collatz(next, count);
}
}
int main() {
int max = 0;
int index = 0;
int i;
for (i=1; i<1000000; i++) {
int current = collatz(i, 1);
if (current > max) {
max = current;
index = i;
}
}
printf("%i\n", index);
return 0;
}
I understand that recursion normally only goes to a certain depth. However as far as I can tell I have implemented tail recursion which should stop the seg fault. If I set i to 100,000 the program runs which leads me to believe the underlying algorithm is correct. However at one million I get:
Segmentation fault: 11
What am I doing wrong?

If you use a debugger you may find that indeed your function is not tail-recursive. But why not? Probably because you simply forgot to enable optimization during compilation. On my system (GCC on Mac OS), a default build will crash, but building with the -O3 option will let it run (at least for a lot longer than otherwise; I didn't want to kill my battery testing).

If you are running it with 1 million i would say you are probably just running out of stack space causing a segfault
What compiler/os are you using in VS stacksize is 1MB by default but it can be increased.
I am not sure about other compiler/os combinations

collatz function is causing the overflow in the middle of a calculation. (it's stack overflow for that).
note:compiler optimization for tail recursion may or may not be done.
use long long (Int64).
int collatz(long long seed, int count) {
long long next = 0;
if (seed % 2 == 0) {
next = seed / 2;
} else {
next = 3 * seed + 1;
}
count++;
if (next == 1) {
return count;
} else {
return collatz(next, count);
}
}

Related

Recursion not getting me the output I need

I'm new to programing and I'm doing recursion exercises, and one of them was to count how many odd numbers I have inside a number:
this is my code:
int countOdd(int num, int count)
{
int temp;
printf("num\n%d", num);
if (num<ZERO)return count;
temp = num % 10;
if ((temp % 2) != 0) countOdd(num / 10, count + ONE);
printf("test");
countOdd(num / 10, count);
}
its suppose to get the number and count how many odd number there is and return it as a value, could someone explain to me why it isn't working, tips and ideas will be highly appreciated.
whatever non-negative value divided by 10 will be again non-negative.
But your recursion termination condition is if (num<ZERO)return count;, that will never happen.
A fixed variant of your code may look like this (still using recursion for your educational reasons, otherwise non recursive code would be better):
int countOdd(int num) {
if (num <= 0) return 0;
return (num&1) + countOdd(num/10);
}
Also don't use printf for debugging your code, use proper debugger.
As you said, you're supposed to return something. So make sure you return something, i.e., add the missing return statements. Also terminate the recursion when you reach zero, or you'll have an infinite loop.
int countOdd(int num, int count)
{
int temp;
printf("num\n%d", num);
if (num<=ZERO) return count;
temp = num % 10;
if ((temp % 2) != 0) return countOdd(num / 10, count + ONE);
printf("test");
return countOdd(num / 10, count);
}

Trying to turn the factorial part into another function

I have to begin my thanking you guys for the help. I am trying to turn the factorial part of the code into another function and was wondering if I needed to add everything within the
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num;
int indx;
int arrayIndx;
int accumulator;
int fact;
int individualDigit[50];
int length;
for(indx = 99999; indx > 0; indx--)
{
num = indx;
for (length = 0; num > 0; length++)
{
individualDigit[length] = num % 10;
num /= 10;
}
accumulator = 0;
for (arrayIndx = 0; arrayIndx < length; arrayIndx++)
{
fact = 1;
while(individualDigit[arrayIndx] > 0)
{
fact*= individualDigit[arrayIndx];
individualDigit[arrayIndx]--;
}
accumulator += fact;
}
if(accumulator == indx)
{
printf("%d ", accumulator);
}
}
return 0;
}
You program is badly designed. It is not indented, you are using variable names index, indx and idex which is confusing for the reader and would lead to nightmares for long term maintenance. Also the factorial computation would deserve to be in a function for better modularity.
But apart from that, your program does what you ask, correctly computes factorials and adds them in the accumulator variable. The only problem is that you never print that accumulator except for the last 2 cases (2 and 1) where n = n!.
Simply replace :
if (accumulator == indx)
{
printf("\n%d\n", indx);
}
with
printf("\n%d\n", accumulator);
and you will see your results.
If you want to store the sum of factorials in an array, you just have to declare int sumOfFact[26] = {0}; just before int individualDigit[50]; to define the array and initialize sumOfFact[0] to 1, and then add sumOfFact[indx] = accumulator; just before printing the accumulator.
To put the factorial part in a function, it is quite simple. First declare it above your main:
int ffact(int n);
the define it anywhere in your code (eventually in another compilation unit - a .c file - if you want)
inf ffact(int n) {
fact = 1;
while (n > 1) {
fact *= n--;
/* if (fact < 0) { fprintf(stderr, "Overflow in ffact(%d)\n", n); return 0; } */
}
return fact
}
I commented out the test for overflow, because I assume you use at least 32 bits int and fact(9) will not overflow (but fact(13) would ...)
The loop computing the sum of factorials becomes:
accumulator = 0;
for (arrayIndx = 0; arrayIndx < length; arrayIndx++)
{
accumulator += ffact(individualDigit[arrayIndx]);
}
printf("\n%d\n", accumulator);
Advantages for that modularity: it is simpler to separately test the code for ffact. So when things go wrong, you have not to crawl among one simple piece of code of more than 40 lines (not counting the absent but necessaries comments). And the code no longers clutters the individualDigit array.

Segmentation Fault 11 with recursive function in C

I keep receiving a Segmentation Fault 11 for the following code. I believe it has something to do with recursion but I'm not entirely sure how. The method should take in an array, skip the odd values, and keep repeating until it has an array with only value left and returns that value.
Thanks!
#include <stdio.h>
int callTable(int table[], int size)
{
int i = 0;
int j = 0;
int cHeight = size / 2;
int cTable[cHeight];
while (i < size)
{
if (table[i] % 2 == 0)
{
cTable[j] = table[i];
j++;
}
i++;
}
if (size > 1)
return callTable(cTable, cHeight);
else
return cTable[0];
}
int main()
{
int tPass[100];
int i, answer;
for (i = 0; i < 100; i++)
tPass[i] = i + 1;
answer = callTable(tPass, sizeof(tPass) / sizeof(tPass[0]));
printf("%d\n", answer);
}
Do you want to skip the odd values or the odd indexes? You are currently skipping the odd values, so after you call callTable once, there are only even values left. Then, on the second call, you try to use an array of half the size to store the even values (which are all of them), so you try to store the entire array on another with half the size.
If you intended to skip the odd indexes, then change this line:
if (table[i]%2==0)
for this one:
if (i%2==0)
That runs fine and returns 1 (which is the number with index 0).

C program - weird Seg fault in dynamic programming algorithm

I'm writing a program in C to do a simple dynamic programming algorithm where you return the minimum number of coins needed to add up to a certain amount. Here's my code:
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
/*
This function returns the minimum number of stamps required for a given value.
It assumes that the given array contains the available stamp sizes, and that it
always contains 1, so a solution is always possible
*/
int min_number_of_stamps(const int* array, size_t array_size, int request) {
/* Construct a table with dimensions (array_size+1)*(request+1) */
int numRows = array_size + 1;
int numCols = request + 1;
int **DPtable;
DPtable = malloc(numRows*sizeof(int));
int i;
for (i = 0; i < numRows; i++) {
DPtable[i] = malloc(numCols*sizeof(int));
}
printf("%d",DPtable[4][0]);
int r, c, useIt, loseIt;
for (r = 0; r < numRows; r++) {
for (c = 0; c < numCols; c++) {
printf("%d,%d\n", r, c);
if (c==0) {
printf("1\n");
//if the amount of change is 0, 0 coins are needed
DPtable[r][c] = 0;
}
else if ((r==0) || c < array[r-1]) {
printf("2\n");
//if there are no coins or if the change needed is less than
//the smallest coin available, then 'infinity' coins are needed
DPtable[r][c] = INT_MAX;
}
else {
printf("3\n");
useIt = DPtable[r][c-array[r-1]] + 1;
loseIt = DPtable[r-1][c];
if (useIt <= loseIt) {
//if 'use it' requires fewer coins than 'lose it,' then
//'use it' coins are needed.
DPtable[r][c] = useIt;
}
else {
//if 'lose it' requires fewer coins, 'lose it' coins are needed
DPtable[r][c] = loseIt;
}
}
}
}
return DPtable[numRows][numCols];
}
int main() {
const int array[] = {1,5,10,25};
const int* stamps = &array[0];
printf("%d", min_number_of_stamps(stamps, 4, 44));
}
I'm getting a segfault when my inner for loop gets to the case where r=4 and c=0. I left my debugging print statements in because I'm lazy, but you can see where I got stuck. If I access the same place in the array outside of my for loops, there's no problem. But in the for loop, I get a `Segmentation fault: 11' message after it outputs "4,0" for the array element and "1" for the if case it's in. Can anyone see what I'm missing?
Learn to enable warnings & debugging for your compiler, i.e. gcc -g -Wall on Linux.
Learn to use a debugger, i.e. gdb -tui on Linux.
Consider using valgrind
EDIT
Many tutorials (in several languages, e.g. English, French, ....) for GCC, GDB, and ValGrind are easily found on the Web.
You're allocating dpTable incorrectly. It should be
DPtable = malloc(numRows*sizeof(int*));
See if that fixes the problem.
return DPtable[numRows][numCols];
thats out of bounds isn't it?

UVa 3n+1 Case Recursive Stack Overflow

im trying to solve this very first challange but i get stuck,
i like fast program, so i decided to use recursive method not iteration
unfortunately, when the input is a big integer (100000 > input > 1000000), its often crash
so i debug it, and it shows stack overflow error
please help me, i dont know what to do, ive tried to change data type to unsigned long, unsigned int, etc, but none of it works
here is my code,
im using ANSI C
#include "stdio.h"
int cek(int n) {
return n % 2;
}
int fung(int n,int c) {
if (n == 1) {
return c;
}
if (!cek(n)) {
return fung(n/2,++c);
}
else {
return fung((n*3)+1,++c);
}
}
int comp(int i,int j,int tmp) {
int temp;
if (i == j)
return tmp;
temp = fung(i,1);
if (temp > tmp)
return comp(++i,j,temp);
else
return comp(++i,j,tmp);
}
int main() {
int i,j,tmp;
while (scanf("%d %d",&i,&j)) {
if (i > j) {
tmp = i;
i = j;
j = tmp;
}
printf("%d %d %d\n",i,j,comp(i,j,0));
}
return 0;
}
PS: sorry for my stupidness, im really a newbie #_#
Recursion is not likely to be faster than iteration, and in fact it's likely to be slower.
The call stack has a limited size, and if your recursion goes deeper than that, there's nothing you can do about it. Especially in the Collatz problem, there's no way to tell up front how many steps you'll need. Rewrite this using an iterative method instead.
(If your compiler does tail call optimization, recursion might still work. But TCO is not required by the standard, so it will lead to unportable code. And apparently, your compiler does not optimize this particular tail call anyway.)
Not a C expert, but usually there is a call stack depth limit enforced by the compiler. Probably you can change this with a compiler flag, but this will not solve your problem. Making the algorithm iterative instead of recursive will fix it.
Recursive algorithms won't go faster than iterative ones, usually. But they are typically nicer to understand. (= more elegant)
Okay guys,
i found it!!!
so this is my code, i still use recursion but only for the inner loop fung(),
im not really impressed of it, because its need 0,5 sec to count input 1 and 1000000, someone's code outhere can do it in 0 sec, LOL
i change the outer loop comp() with iterative method,
look here
#include "stdio.h"
/*#include "windows.h"*/
int cek(int n) {
return n % 2;
}
unsigned int fung(unsigned int n,unsigned int c) {
if (n == 1) return c;
if (!cek(n)) return fung(n/2,++c);
else return fung((n*3)+1,++c);
}
/*
Above recursion will looked like this in iterative method
int func(int n) {
int c=1;
while (n != 1) {
c++;
if (n % 2 == 0)
n=n/2;
else
n=(n*3)+1;
}
return c;
}
*/
/*Outer Loop*/
int iter(int i,int j) {
int tmp1=0,tmp2;
while (i <= j) {
tmp2 = fung(i,1);
if (tmp1 < tmp2)
tmp1 = tmp2;
i++;
}
return tmp1;
}
int main() {
unsigned int i,j,s,f;
while (scanf("%d %d",&i,&j)) { /*UVa Standard, infinite loop*/
/*s = GetTickCount();*/
printf("%d %d %d",i,j,iter(i,j));
/*f = GetTickCount();
printf("%lu\n",f-s);*/
}
return 0;
}

Resources