Segmentation fault for numbers too big for Ackermann's function - c

Why is this failing? I have written Ackermann's function in C and used longs to make sure that no number will be too small. Yet, when I go above (including) 4 for m and n, it gives me a segmentation fault: 11. Does anyone know why?
#include <stdio.h>
int ackermann(long m, long n) {
if (m == 0)
return n + 1;
else if (m > 0 && n == 0)
return ackermann(m - 1, 1);
else if (m > 0 && n > 0)
return ackermann(m - 1, ackermann(m, n - 1));
}
int main() {
long result = ackermann(4, 4);
printf("%lu", result);
}

I have written Ackermann's function in C and used longs to make sure
that no number will be too small.
The size of an unsigned long long is 2^6 (64) bits. The size of the result for ackermann(4, 2) is greater than 2^16 (65536) bits. You can compute ackermann(4, 1) and ackermann(5, 0) but not much with larger values of m and n.
Code-wise, you use a signed long when an unsigned long might serve you better and you declare the ackermann() function itself to return a signed int which is inconsistent. (Your ackermann() function also has a fourth exit point that isn't properly defined, compiler-wise.) Here's a rework of your code using unsigned long long which still won't get you very far:
#include <stdio.h>
unsigned long long ackermann(unsigned long long m, unsigned long long n) {
if (m == 0) {
return n + 1;
}
if (m > 0 && n == 0) {
return ackermann(m - 1, 1);
}
return ackermann(m - 1, ackermann(m, n - 1));
}
int main() {
unsigned long long result = ackermann(5, 0);
printf("%llu\n", result);
return 0;
}

Related

How to print values in reverse without the use of arrays nor pointers in C

I've been working on a code that converts a given number (decimal base) to any other base from 2 to 16.
Clearly, I've come across the issue that the function base_conversion_it (it stands for iterative) prints the values in reverse.
I cannot use arrays nor pointers, and everyone on the internet seems to solve this issue like that. My assignment requires making both an iterative and a recursive function (which I did and works).
void base_conversion_it(unsigned int n, unsigned int b) {
if (n > 0) {
//bases between 2 and 16
if (b >= 2 && b <= 16) {
int r; //r = remainder
int q = 1; //quotient
int num; //saves the remainder
while (q != 0) {
r = n % b;
printf("%X", r);
q = n / b;
n = q;
}
}
}
}
You start converting from the units digit.
Maybe start with the most significant digit instead?
// It's Undefined Behaviour if `b` is outside the range [2...16]
void base_conversion_it(unsigned int n, unsigned int b) {
unsigned highestbase = 1;
while (highestbase * b <= n) highestbase *= b; //possible wrap around and infinite loop
while (highestbase) {
printf("%X", n / highestbase);
n %= highestbase;
highestbase /= b;
}
printf("\n");
}
Sorry missed iterative.
char digits[] = "0123456789ABCDEFGHIJKLMNOP";
void print(unsigned long long val, unsigned base)
{
unsigned long long mask = base;
while(val / mask >= base) mask *= base;
do
{
printf("%c", digits[val / mask]);
val %= mask;
mask /= base;
}while(val);
}
int main(void)
{
print(45654756453, 10); printf("\n");
print(45654756453, 16); printf("\n");
print(45654756453, 24); printf("\n");
print(45654756453, 2); printf("\n");
}
https://godbolt.org/z/W3fGnnhYs
Recursion:
char digits[] = "0123456789ABCDEF";
void print(unsigned long long val, unsigned base)
{
if(base <= 16 && base > 1)
{
if(val >= base) print(val / base, base);
printf("%c", digits[val % base]);
}
}
https://godbolt.org/z/84hYocnjv
If you cannot use either arrays (including strings) or recursion, then I think you need to compute the output digits in most-significant-first order. This is a bit less natural than computing them in the opposite order and reversing the result, but it can be done:
use a loop to find the place value of the most significant non-zero base-b digit of n. For example, check the result of dividing n by successive powers of b until the result is 0, then back off one step.
In a separate loop, read off the base-b digits of n one by one, starting with the one at the discovered most-significant position. For each digit,
Divide the current value of n by the place value pv of the current digit to get a digit value.
Replace n with n % pv.
Be careful to continue all the way down to place value 1, as opposed, say, to stopping when n becomes zero.

How do I reverse the order of the digits of an integer using recursion in C programming?

Problem statement :
Given a 32-bit signed integer, reverse digits of an integer.
Note: Assume we are dealing with an environment that could only store
integers within the 32-bit signed integer range: [ −2^31, 2^31 − 1]. For
the purpose of this problem, assume that your function returns 0 when
the reversed integer overflows.
I'm trying to implement the recursive function reverseRec(), It's working for smaller values but it's a mess for the edge cases.
int reverseRec(int x)
{
if(abs(x)<=9)
{
return x;
}
else
{
return reverseRec(x/10) + ((x%10)*(pow(10, (floor(log10(abs(x)))))));
}
}
I've implemented non recursive function which is working just fine :
int reverse(int x)
{
long long val = 0;
do{
val = val*10 + (x%10);
x /= 10;
}while(x);
return (val < INT_MIN || val > INT_MAX) ? 0 : val;
}
Here I use variable val of long long type to check the result with MAX and MIN of signed int type but the description of the problem specifically mentioned that we need to deal within the range of 32-bit integer, although somehow it got accepted but I'm just curious If there is a way to implement a recursive function using only int datatype ?
One more thing even if I consider using long long I'm failing to implement it in the recursive function reverseRec().
If there is a way to implement a recursive function using only int datatype ?
(and) returns 0 when the reversed integer overflows
Yes.
For such +/- problems, I like to fold the int values to one side and negate as needed. The folding to one side (- or +) simplifies overflow detection as only a single side needs testing
I prefer folding to the negative side as there are more negatives, than positives. (With 32-bit int, really didn't make any difference for this problem.)
As code forms the reversed value, test if the following r * 10 + least_digit may overflow before doing it.
An int only recursive solution to reverse an int. Overflow returns 0.
#include <limits.h>
#include <stdio.h>
static int reverse_recurse(int i, int r) {
if (i) {
int least_digit = i % 10;
if (r <= INT_MIN / 10 && (r < INT_MIN / 10 || least_digit < INT_MIN % 10)) {
return 1; /// Overflow indication
}
r = reverse_recurse(i / 10, r * 10 + least_digit);
}
return r;
}
// Reverse an int, overflow returns 0
int reverse_int(int i) {
// Proceed with negative values, they have more range than + side
int r = reverse_recurse(i > 0 ? -i : i, 0);
if (r > 0) {
return 0;
}
if (i > 0) {
if (r < -INT_MAX) {
return 0;
}
r = -r;
}
return r;
}
Test
int main(void) {
int t[] = {0, 1, 42, 1234567890, 1234567892, INT_MAX, INT_MIN};
for (unsigned i = 0; i < sizeof t / sizeof t[0]; i++) {
printf("%11d %11d\n", t[i], reverse_int(t[i]));
if (t[i] != INT_MIN) {
printf("%11d %11d\n", -t[i], reverse_int(-t[i]));
}
}
}
Output
0 0
0 0
1 1
-1 -1
42 24
-42 -24
1234567890 987654321
-1234567890 -987654321
1234567892 0
-1234567892 0
2147483647 0
-2147483647 0
-2147483648 0
You could add a second parameter:
int reverseRec(int x, int reversed)
{
if(x == 0)
{
return reversed;
}
else
{
return reverseRec(x/10, reversed * 10 + x%10);
}
}
And call the function passing the 0 for the second parameter. If you want negative numbers you can check the sign before and pass the absolute value to this function.
In trying to learn C programming I programed this question and get some correct results and some incorrect. I don't see the reason for the difference.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h> // requires adding link to math -lm as in: gcc b.c -lm -o q11
int ReverseInt(int startValue, int decimalPlace)
{
if(decimalPlace == 0) // if done returns value
{
return startValue;
}
int temp = startValue % 10; // gets units digit
int newStart = (startValue -temp)/10; // computes new starting value after removing one digit
int newDecimal = decimalPlace -1;
int value = temp*pow(10,decimalPlace);
return value + ReverseInt(newStart,newDecimal); // calls itself recursively until done
}
int main()
{
int x, decimalP, startValue;
printf("Input number to be reversed \n Please note number must be less than 214748364 :");
scanf("%d", &x);
if (x > 214748364)
{
printf("Input number to be reversed \n Please note number must be less than 214748364 :");
scanf("%d", &x);
}
decimalP = round(log10(x)); // computes the number of powers of 10 - 0 being units etc.
startValue = ReverseInt(x, decimalP); // calls function with number to be reversed and powers of 10
printf("\n reverse of %d is %d \n", x, startValue);
}
Output is: reverse of 1234 is 4321 but then reverse of 4321 is 12340
It's late and nothing better does not come into my mind. No float calculations. Of course, integer has to be big enough to accommodate the result. Otherwise it is an UB.
int rev(int x, int partial, int *max)
{
int result;
if(x / partial < 10 && (int)(x / partial) > -10)
{
*max = partial;
return abs(x % 10) * partial;
}
result = rev(x, partial * 10, max) + abs(((x / (int)(*max / partial)) % 10) * partial);
return result;
}
int reverse(int x)
{
int max;
return rev(x, 1, &max) * ((x < 0) ? -1 : 1);
}
int main(void){
printf("%d", reverse(-456789));
}
https://godbolt.org/z/M1eezf
unsigned rev(unsigned x, unsigned partial, unsigned *max)
{
unsigned result;
if(x / partial < 10)
{
*max = partial;
return (x % 10) * partial;
}
result = rev(x, partial * 10, max) + (x / (*max / partial) % 10) * partial;
return result;
}
unsigned reverse(unsigned x)
{
unsigned max;
return rev(x, 1, &max);
}
int main(void){
printf("%u", reverse(123456));
}
when using long long to store the result all possible integers can be reversed
long long rev(int x, long long partial, long long *max)
{
long long result;
if(x / partial < 10 && (int)(x / partial) > -10)
{
*max = partial;
return abs(x % 10) * partial;
}
result = rev(x, partial * 10, max) + abs(((x / (int)(*max / partial)) % 10) * partial);
return result;
}
long long reverse(int x)
{
long long max;
return rev(x, 1, &max) * ((x < 0) ? -1 : 1);
}
int main(void){
printf("%d reversed %lld\n", INT_MIN, reverse(INT_MIN));
printf("%d reversed %lld\n", INT_MAX, reverse(INT_MAX));
}
https://godbolt.org/z/KMfbxz
I am assuming by reversing an integer you mean turning 129 to 921 or 120 to 21.
You need an initial method to initialize your recursive function.
Your recursive function must figure out how many decimal places your integer uses. This can be found by using log base 10 with the value and then converting the result to a integer.
log10 (103) approx. 2.04 => 2
Modulus the initial value by 10 to get the ones place and store it in a variable called temp
Subtract the ones place from the initial value and store that in a variable called newStart.
divide this value by 10
Subtract one from the decimal place and store in another variable called newDecimal.
Return the ones place times 10 to the power of the decimal place and add it to the function where the initial value is newStart and the decimalPlace is newDecimal.
#include <stdio.h>
#include <math.h>
int ReverseInt(int startValue, int decimalPlace);
int main()
{
int i = -54;
int positive = i < 0? i*-1 : i;
double d = log10(positive);
int output = ReverseInt(positive,(int)d);
int correctedOutput = i < 0? output*-1 : output;
printf("%d \n",correctedOutput);
return 0;
}
int ReverseInt(int startValue, int decimalPlace)
{
if(decimalPlace == 0)
{
return startValue;
}
int temp = startValue % 10;
int newStart = (startValue -temp)/10;
int newDecimal = decimalPlace -1;
int value = temp*pow(10,decimalPlace);
return value + ReverseInt(newStart,newDecimal);
}

Reverse integer in c gives overflow

I am solving reverse integer problem in leetcode in c language.But it gives runtime error on line sum=sum+rem*10;.
runtime error: signed integer overflow: 964632435 * 10 cannot be represented in type 'int'
Here is the code.
#define INT_MAX 2147483647
#define INT_MIN -2147483648
int reverse(int x){
int sum=0,rem=0;
int p;
if(x > INT_MAX || x < INT_MIN){return 0;}
if(x==0){return 0;}
if(x<0){p=x;x=abs(x);}
while(x%10==0){x=x/10;}
while(x>0){
rem=x%10;
if(sum > INT_MAX || sum*(-1) < INT_MIN){return 0;}
sum=sum*10+rem;
x/=10;
}
if(p<0){sum=sum*(-1);return sum;}
else{return sum;}
}
One way - which isn't performance optimal but simple - is to convert the integer to a string and then revert the string and then convert back to integer.
The below solution is for positive integers - I'll leave it to OP to extend it to handle negative integers.
Could look like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
int reverse(const int n)
{
if (n < 0)
{
printf("Handling of negative integers must be added\n");
exit(1);
}
char tmp1[100];
char tmp2[100] = { 0 };
sprintf(tmp1, "%d", n);
printf("Input : %s\n", tmp1);
size_t sz = strlen(tmp1);
for (size_t i = 0; i < sz; ++i)
{
tmp2[i] = tmp1[sz-i-1];
}
int result = tmp2[0] - '0';
char* p = tmp2+1;
while(*p)
{
if ((INT_MAX / 10) < result)
{
printf("oh dear: %d can't be reversed to int\n", n);
exit(1);
}
result = result * 10;
if ((INT_MAX - (*p - '0')) < result)
{
printf("oh dear: %d can't be reversed to int\n", n);
exit(1);
}
result += *p - '0';
p++;
}
return result;
}
int main()
{
printf("Output: %d\n", reverse(123));
printf("Output: %d\n", reverse(123456789));
printf("Output: %d\n", reverse(1234567899));
return 0;
}
Output:
Input : 123
Output: 321
Input : 123456789
Output: 987654321
Input : 1234567899
oh dear: 1234567899 can't be reversed to int
But it gives runtime error on line sum=sum+rem*10;.
To test for potential int overflow of positive sum, rem, compare against INT_MAX/10 and INT_MAX%10 beforehand.
if (sum >= INT_MAX / 10 && (sum > INT_MAX / 10 || rem > INT_MAX % 10)) {
// overflow
} else {
sum = sum * 10 + rem;
}
Handling negatives
Watch out for x = INT_MIN ... x = -x;. That is int overflow and undefined behavior.
Sometimes it is fun to solve such int problems of positive and negative numbers by converting the positive numbers to negative ones embrace the dark side - its your only hope. (maniacal laughter)
There are more int values less than zero than there are int values more than zero - by one. So x = -x is always well defined when x > 0.
// C99 or later code
#include <limits.h>
int reverse(int x) {
int x0 = x;
if (x0 > 0) {
x = -x; // make positive values negative, embrace the dark side
}
int reversed = 0;
while (x < 0) {
int rem = x % 10;
x /= 10;
if (reversed <= INT_MIN / 10
&& (reversed < INT_MIN / 10 || rem < INT_MIN % 10)) {
// overflow
return 0;
}
reversed = reversed * 10 + rem;
}
if (x0 > 0) {
if (reversed < -INT_MAX) {
// overflow
return 0;
}
reversed = -reversed;
}
return reversed;
}
Test code
#include <stdio.h>
int main() {
int x[] = {0, 1, -1, 42, 123456789, INT_MAX/10*10+1, INT_MIN/10*10-1,INT_MAX, INT_MIN};
size_t n = sizeof x / sizeof x[0];
for (size_t i = 0; i < n; i++) {
printf("Attempting to reverse %11d ", x[i]);
printf("Result %11d\n", reverse(x[i]));
}
}
Sample output
Attempting to reverse 0 Result 0
Attempting to reverse 1 Result 1
Attempting to reverse -1 Result -1
Attempting to reverse 42 Result 24
Attempting to reverse 123456789 Result 987654321
Attempting to reverse 2147483641 Result 1463847412
Attempting to reverse -2147483641 Result -1463847412
Attempting to reverse 2147483647 Result 0
Attempting to reverse -2147483648 Result 0
First, you should not be defining your own values for INT_MAX and INT_MIN. You should instead #include <limits.h> which defines these value.
Second, this:
sum > INT_MAX
Will never be true because sum can never hold a value larger than INT_MAX. So you can't perform an operation and then check afterward if it overflowed. What you can do instead is check the operation first and do some algebra that prevents overflow.
if ( INT_MAX / 10 < sum) return 0;
sum *= 10;
if ( INT_MAX - rem < sum) return 0;
sum += rem;

Exponentiaion program

Question is this
Nancy hates any and every string that contains the number "13". Clouseau wants to gift her a string and is looking over his options, ofcourse he would never pick a string that has "13" as a substring.
Tell Clouseau the total number of such strings s that are made of exactly N characters. The strings may contain any integer from 0-9, repeated any number of times.
Input :
The first line of input file contains a number T indicating number of test cases. The following T lines, each contain an integer N.
Output :
The output file should contain answer to each query in a new line modulo 1000000009.
Constraints :
1 T 100000 ,
0 N 1000000009
I am not getting the logic correct.
# include <stdio.h>
# define MOD 1000000009
unsigned long long mod_pow(unsigned long long num, unsigned long long pow, unsigned long long mod)
{
unsigned long long test;
unsigned long long n = num;
for(test = 1; pow; pow >>= 1) {
if (pow & 1)
test = ((test % mod) * (n % mod)) % mod;
n = ((n % mod) * (n % mod)) % mod;
}
return test;
}
int main(int argc, char* argv[])
{
long t;
unsigned long long total_no, bad_no, n;
scanf ("%ld", &t);
while (t--) {
scanf ("%lld", &n);
if (n != 1) {
total_no = (10 * (mod_pow (10, n-1, MOD))) % MOD;
bad_no = ((n - 1) * (mod_pow(10, n-2, MOD))) % MOD;
printf ("%lld\n", (((total_no - bad_no) % MOD)));
}
else
printf ("10\n");
}
return 0;
}
You can use this function:
long long int bigmod ( long long a, long long p, long long m )
{
if ( p == 0 )return 1; // If power is 0, then a ^ 0 = 1 for any value of a, And 1 Mod m=1 for any value of m, So return 1
if ( p % 2 ) // If power is odd, Split it : a ^ 5 =( a )* (a ^ 4) --> left and right child respectively.
{
return ( ( a % m ) * ( bigmod ( a, p - 1, m ) ) ) % m;
}
else //If power is even then split it equally and return the result...
{
long long c = bigmod ( a, p / 2, m );
return ( (c%m) * (c%m) ) % m;
}
}
and call this function like this:
int main(){
// take input....
//Calling...
printf("result is %lld\n",bigmod(a,p,MOD)); //
return 0;
}

Calculating n! mod m when m is not prime

I have read a lot of good algos to calculate n! mod m but they were usually valid when m was prime . I wanted to know whether some good algo exists when m is not prime .I would be helpful if someone could write the basic function of the algo too.I have been using
long long factMOD(long long n,long long mod)
{
long long res = 1;
while (n > 0)
{
for (long long i=2, m=n%mod; i<=m; i++)
res = (res * i) % mod;
if ((n/=mod)%2 > 0)
res = mod - res;
}
return res;
}
but getting wrong answer when I try to print factMOD(4,3) even. source of this algo is :
http://comeoncodeon.wordpress.com/category/algorithm/
The basic algorithm is valid for any value of m:
product := 1
for i := 2 to n
product := (product * i) mod m
return product
and an easy optimization is that you can bail out early and return 0 whenever product becomes 0. You can also return 0 at the beginning if n > m, since that guarantees that n! is a multiple of m.
This is what I've come up with:
#include <stdio.h>
#include <stdlib.h>
unsigned long long nfactmod(unsigned long long n, unsigned long long m)
{
unsigned long long i, f;
for (i = 1, f = 1; i <= n; i++) {
f *= i;
if (f > m) {
f %= m;
}
}
return f;
}
int main(int argc, char *argv[])
{
unsigned long long n = strtoull(argv[1], NULL, 10);
unsigned long long m = strtoull(argv[2], NULL, 10);
printf("%llu\n", nfactmod(n, m));
return 0;
}
and this:
h2co3-macbook:~ h2co3$ ./mod 1000000 1001001779
744950559
h2co3-macbook:~ h2co3$
runs in a fraction of a second.

Resources