Struggling with PairInverse problem in c using recursion [duplicate] - c

I encountered a hard question I don't know the answer to: "Rearrange the digits from an integer in blocks of two with a recursive function" here's an example:
Input: 123456
unsigned long pairinvPrint(unsigned long number) {
printf("%d", number % 100);
if ((number / 100) <= 99) {
printf("%d", number / 100);
}
else {
pairinv(number / 100);
}
}
Output: 563412
More I/O Examples: 42 -> 42; 1234 -> 3412
However, the set circumstances to do this are hard (no loops, arrays, pointers, global- or static variables, no libraries) and it should not print the solution directly, rather return it upon a call like this:
printf("Rearrange int (%lu) = %lu", input, pairinvert(input));
Luckily there's one circumstance to make it easier, the number of the input digits is always even.
Now I experimented for a while, but cant come up with a working solution, except the invalid one using printf.
Does anyone have some inspiration for me or idea how to tackle this?

I'll bite :-)
unsigned long p(unsigned long p1, unsigned long p2) {
// no loops, no arrays, no pointers, no global, no static, no variables, no libraries
if (p1 < 100) return p2*100 + p1;
return p(p1/100, p2*100 + p1%100);
}
unsigned long pairinvert(unsigned long n) {
// no loops, no arrays, no pointers, no global, no static, no variables, no libraries
if (n < 100) return n;
return p(n/100, n%100);
}
// need <stdio.h> for printf()
#include <stdio.h>
int main(void) {
unsigned long input;
input = 123456;
printf("Rearrange int (%lu) = %lu\n", input, pairinvert(input));
input = 42;
printf("Rearrange int (%lu) = %lu\n", input, pairinvert(input));
input = 1234;
printf("Rearrange int (%lu) = %lu\n", input, pairinvert(input));
}

Following program should work.
#include <stdio.h>
void rearrange(int n, int *output) {
int lsd = 0, slsd = 0;
if(n == 0)
return;
if(n > 0) {
lsd = n%10;
}
if (n > 9) {
slsd = (n%100)/10;
}
*output = 100*(*output) + 10*slsd + lsd;
n = n/100;
rearrange(n, output);
}
int main() {
int n;
int output = 0;
scanf("%d", &n);
rearrange(n, &output);
printf("%d\n", output);
return 0;
}
It is simple to understand, so I am not writing any comments.
Note that it is tail recursive so with O2 optimization it can recurse infinitely.

Try this :
unsigned long pairinv(unsigned long number, unsigned long result) {
unsigned long n = number % 100; // Gets the two digit number
if (n == 0) return result; // If it's zero returns the result
result = result * 100 + n; // Else multiplies the result by 100, adds n
return pairinv(number / 100, result); // and continues by recursion
}
int main() {
unsigned long r= 0;
printf("%lu\n", pairinv(123456, r)); //==> 563412
return 0;
}

Related

I made a function which covert decimal to binary. but it does not work

#include <stdio.h>
void DectoBin(int *n);
int *p;
int position;
int main()
{
int num;
printf("Input number : ");
scanf("%d", &num);
DectoBin(&num);
for (int i = position - 1; i >= 0; i--)
{
printf("%d", p[i]);
}
}
when launch this code, this code compile well...
but I have a error message 'zsh : segmentation fault'
void DectoBin(int *n)
{
int binary[20] = { 0, };
p = binary;
while (1)
{
binary[position++] = *n % 2;
*n = *n / 2;
if (n == 0)
break;
}
return;
}
so, What parts should be corrected to solve the problem??
I think the minimum change to make it seem to work is this:
// you use *n as an integer, but test "n"
// (which is its address, and will never be zero).
// So the while loop goes on indefinitely, eventually overflowing the buffer.
if (*n == 0)
break;
A more serious problem is that the buffer is allocated backwards: you have the pointer outside the function and the buffer is allocated on the stack inside the function. So, as soon as the function exits, the buffer is no longer "legal". The data is probably still there (on my system, it is) and you might even be able to use it as if nothing was amiss. On a short program, and depending on your system, you might not notice that the code has become a time bomb.
You ought to estimate how much of a buffer you need (how many binary digits), then allocate memory on the heap, using malloc(), check it worked, and pass that memory to the function - which will allocate nothing - together with the allocated size, so it can ensure it doesn't overflow the buffer.
The function would then return how many digits to actually print.
#include <stdio.h>
#include <malloc.h>
size_t DectoBin(size_t maxdigits, int *digits, int number);
int main() {
int num;
int *buffer;
size_t maxdigits, position;
printf("Input number : ");
scanf("%d", &num);
// Always check your inputs.
if (num < 0) {
printf("Negative numbers are not supported yet\n");
return 1;
}
maxdigits = 1;
{
// Calculate how many digits are required. Could use ceiling of base-2 logarithm of num.
int tmp = num;
while (tmp > 0) {
maxdigits ++;
tmp /= 2;
}
}
buffer = malloc(maxdigits * sizeof(int));
if (NULL == buffer) {
fprintf(stderr, "Out of memory\n");
return 2;
}
position = DectoBin(maxdigits, buffer, num);
for (size_t i = position; i > 0; i--) {
printf("%d", buffer[i-1]);
}
printf("\n");
return 0;
}
size_t DectoBin(size_t maxdigits, int *digits, int number) {
size_t pos = 0;
do {
digits[pos++] = number % 2;
number /= 2;
} while (number && pos < maxdigits);
return pos;
}
For starters there is a typo
if (n == 0)
It seems you mean
if (*n == 0)
Though there is no any sense to accept a number indirectly through a pointer to it.
You are using the local array binary with automatic storage duration within the function DectoBin
void DectoBin(int *n)
{
int binary[20] = {
0,
};
//...
that will not be alive after exiting the function. So the pointer p will have an invalid value.
Also it is unclear why you are using the magic number 20 in the array declaration. At least you should use the value of the expression sizeof( int ) * CHAR_BIT.
Also it is a bad idea to use global variables.
At Least you could declare the array within the function with the storage-class specifier static and return a pointer to the array from the function.
Pay attention to that for negative numbers you can get an incorrect result.
For example the function can be implemented the following way as shown in the demonstration program below.
#include <stdio.h>
#include <limits.h>
#include <string.h>
const char * DecToBin( int n )
{
static char binary[CHAR_BIT * sizeof( int ) + 1 ];
memset( binary, 0, sizeof( binary ) );
unsigned int un = n;
char *p = binary + sizeof( binary ) - 1;
do
{
*--p = '0' + ( un & 1 );
} while ( un >>= 1 );
return p;
}
int main( void )
{
printf( "%d -> %s\n", 123, DecToBin( 123 ) );
printf( "%d -> %s\n", -123, DecToBin( -123 ) );
}
The program output is
123 -> 1111011
-123 -> 11111111111111111111111110000101

How do I process the return value inf

I working through a book on C on my own. This isn't homework to be turned in. I am writing a C program to determine the largest Fibonacci number my machine can produce. And instructed to use a nonrecursive method.
My Code:
#include<stdio.h>
double fibo(int n);
int main(void)
{
int n = 0; // The number input by the user
double value; // Value of the series for the number input
while (n >= 0)
{
// Call fibo function
value = fibo(n);
// Output the value
printf("For %d the value of the fibonacci series = %.0f\n", n,
value);
n++;
}
return 0;
}
double fibo(int n)
{
int i; // For loop control variable
double one = 0; // First term
double two = 1; // Second term
double sum = 0; // placeholder
if (n == 0)
return 0;
else if (n == 1)
return 1;
else
{
for (i = 2; i <= n; i++)
{
sum = one + two;
one = two;
two = sum;
}
}
return sum;
Code works fine but I want to to break when the output gives me the fist instance of :
For 17127 the value of the fibonacci series = inf
Is there way to us an if statement like:
if (value == inf)
break;
The simplest is to use INFINITY or isinf().
Just did a little search and found this nice trick:
...
double value, temp; // Value of the series for the number input
while (n >= 0)
{
// Call fibo function
temp = fibo(n);
if (temp - temp != 0)
break;
else
value=temp;
...
well it turns out that whats happening is when temp hits Inf the if condition temp - temp produces Nan which equals nothing and the rest is just executing break; to exit the process.
I want to to break when the output gives me the first instance of : inf
Simply test against INFINITY from <math.h>. The output will not be an exact Fibonacci number.
#include <math.h>
#include <stdio.h>
int main(void) {
double a;
double b = 0;
double c = 1;
do {
a = b;
b = c;
c = a + b;
} while (c < INFINITY);
printf("%e\n", b);
return 0;
}
Output
1.306989e+308
long double
Use the widest floating point type and look for an inexact addition.
#include <fenv.h>
#include <stdio.h>
int main(void) {
long double a;
long double b = 0;
long double c = 1;
do {
a = b;
b = c;
c = a + b;
} while (fetestexcept(FE_INEXACT) == 0);
printf("%.0Lf\n", b);
return 0;
}
Output
12200160415121876738
Integers
Use the widest type available. This is akin to #Syed.Waris unsigned long long approach. Although common that unsigned long long and uintmax_t have the same range, using uintmax_t insures the widest.
uintmax_t: The following type designates an unsigned integer type capable of representing any value of any unsigned integer type:
#include <stdint.h>
#include <stdio.h>
uintmax_t a;
uintmax_t b = 0;
uintmax_t c = 1;
do {
a = b;
b = c;
c = a + b;
} while(c >= b);
printf("%ju\n", b);
Output
12200160415121876738
String
An alternative to double or some int type, is to create a simple string add function str_add(), then quite easy to form large Fibonacci numbers.
int main(void) {
char fib[3][4000];
strcpy(fib[0], "0");
strcpy(fib[1], "1");
int i;
for (i = 2; i <= 17127 && strlen(fib[1]) < sizeof fib[1] - 1; i++) {
printf("Fib(%3d) %s.\n", i, str_add(fib[2], fib[1], fib[0]));
strcpy(fib[0], fib[1]);
strcpy(fib[1], fib[2]);
}
printf("%zu\n", strlen(fib[2]));
return 0;
}
Output
Fib(1476) 13069...(299 digits)....71632. // Exact max `double`
Fib(17127) 95902...(3569 digits)...90818.
largest Fibonacci number my machine can produce
This question is not concerned with any data type but it is concerned with machine.
The basic rule of fibonacci is this:
n = (n-1) + (n-2)
You can take a big sized unsigned long long variable and you can keep on adding. But what if that datatype is overflowed? You are not concerned with data type. Your machine may produce a number even bigger than the long long. What would that number be ? Entire bits on RAM? Hard Disk ?
Since you are required to use an iterative method and not recursive method, your teacher/book/instructor might be testing you on loops (and not any standard API). Below is sample code using unsigned long long:
#include <stdio.h>
int main ()
{
unsigned long long a = 0;
unsigned long long b = 1;
unsigned long long c = a + b;
while(c >= b)
{
a = c;
c = b + c;
b = a;
}
printf("\n%llu\n", b);
return 0;
}
Output:
12200160415121876738

Recursive function for reversing a number

The statement of my problem is this:
Write a recursive function that takes a natural number as argument and returns the value of the number read backwards (with the decimal digits in opposite order):
E.g : f(3120) = 213
I have solved the problem but I used static to store my reversed number as in the code below:
unsigned long f(unsigned long n){
static long rev;
if(n==0)
return 0;
else
{
rev=rev*10+n%10;
f(n/10);
}
return rev;
}
but I would like to know if there is a way to solve this problem without using the static data type and still keeping only one parameter in the function.
Of course. Just remove the word static from your code and do calulations in loop:
unsigned long f(unsigned long n){
long rev = 0;
while(n != 0) {
rev = rev*10 + n%10;
n /= 10;
}
return rev;
}
You could put current result as an argument of your function:
int f(int x, int r = 0)
{
if (x == 0) return r;
return f(x / 10, r * 10 + x % 10);
}

Printing float values using only syscalls in C

I am trying to write a C program to print the filesizes in human readable format (i.e, in KB, MB, GB, etc). The input is the filesize in bytes. The catch is that this is to be done using only system calls and NO library calls.
I have already written a function that converts a positive integer into a string and then prints it using write() system call. I am clueless as to how to print decimal values using write() as the filesize after conversion(in KB or MB or GB) could be decimals.(For Ex: 4.0K, 5.6G etc).
Also, is it possible to limit precision to some fixed length (say 2 decimal places) ??
For a lot of cases, you can convert your floats the same way you do with integers. First convert the integer part by casting your float to int and converting that to string. Then append the decimal point, subtract the integer from your original float, multiply by your required precision and do the same (with leading zeros if required).
Conceptually you could do something like that:
int integerPart = myFloat;
int decimalPart = (myFloat - integerPart) * 1000; // for three decimal places
char* stringRep = intToStringNoLeadingZeros(integerPart);
appendChar(stringRep, '.');
appendIntToStringWithLeadingZeros(stringRep, decimalPart);
This does not work with floats that are larger than the largest possible integer and it will lose precision if you need lots of decimal places. But for the common case this is a quick way to do it. You would have to write code that interpretes the floating point format directly if you want it to work for alle cases, but I imagine that to be a lot more work.
I think that this is your solution:
#include <unistd.h>
void printInt(int n) {
char c;
if (!n)
return ;
printInt(n/10);
c = n % 10 + '0';
write(1, &c, 1);
}
void _printInt(int n) {
if (!n)
write(1, "0", 1);
else
printInt(n);
}
void _printD(double n, int K) {
_printInt((int)n);
n -= (int)n;
if (!n && !K)
return ;
write(1, ".", 1);
while ((!n && K) || K) {
_printInt((int)(n*10));
n=n*10-((int)(n*10));
K--;
}
}
int main() {
_printD(10.543, 2);
return 0;
}
if you need some advice just say!
void printNum(unsigned n){
char nums[4];
int i;
if(n == 0)
write(1, "0", 1);
for(i=4; n ;){
nums[--i] = '0' + n % 10;
n /= 10;
}
write(1, &nums[i], 4 - i);
}
void printStr(const char *s){
while(*s)
write(1, s++, 1);
}
void printSizeWithUnit(unsigned long long n){
static char *unit[] = { "B", "KB", "MB", "GB", "TB", "PB", "EB" };
unsigned long long v = n;
int u_no = 0;
while(n >= 1024){
v = (n * 10+512) / 1024;
n /= 1024;
++u_no;
}
if(v>=1000){
v = (n * 10+512) / 1024;
++u_no;
}
if(u_no==0){
printNum((unsigned)v);
printStr(unit[u_no]);
printStr("\n");
} else {
printNum((unsigned)v/10);
printStr(".");
printNum((unsigned)v%10);
printStr(unit[u_no]);
printStr("\n");
}
}
int main(void){
printSizeWithUnit(777ULL);
printSizeWithUnit((unsigned long long)(5.56*1024*1024));
printSizeWithUnit(1024*777ULL);
printSizeWithUnit(1024*1024*777ULL);
return 0;
}

<math.h> pow() giving wrong result

This is from google's code jam, practice problem "All your base".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long long pow_longlong(int digit, int raiseto)
{
if (raiseto == 0) return 1;
else return digit * pow_longlong(digit, raiseto - 1);
}
long long base10_with_map(int base, char* instr, char* digits)
{
if (base < 2) base = 2;
long long result = 0;
int len = strlen(instr);
int i = 0;
while (len--)
result += digits[instr[len]] * pow_longlong(base, i++);
return result;
}
long long test(char* in)
{
char appear[256];
int i;
int len = strlen(in);
int hold = 0;
for (i = 0; i < 256; i++) appear[i] = '\xFF';
for (i = 0; i < len; i++)
if (appear[in[i]] == '\xFF')
{
if (hold == 0) { appear[in[i]] = 1; hold++; }
else if (hold == 1) { appear[in[i]] = 0; hold++; }
else appear[in[i]] = hold++;
}
return base10_with_map(hold, in, appear);
}
int main(int argc, char* argv[])
{
if (argc < 2)
{
printf("Usage: %s <input-file> \n", argv[0]); return 1;
}
char buf[100];
int a, i;
FILE* f = fopen(argv[1], "r");
fscanf(f, "%d", &a);
long long result;
for (i = 1; i <= a; i++)
{
fscanf(f, "%s", buf);
result = test(buf);
printf("Case #%d: %lld\n", i, result);
}
return 0;
}
This works as intended and produces correct result to the problem. But if I replace my own pow_longlong() with pow() from math.h some calculations differ.
What is the reason to this? Just curious.
Edits:
- No overflow, plain long is enough to store the values, long long is just overkill
- Of course I include math.h
- In example: test("wontyouplaywithme") with pow_longlong returns 674293938766347782 (right) and with math.h 674293938766347904 (wrong)
Sorry that I won't go through your example and your intermediary function; the issue you're having occurs due to double being insufficient, not the long long. It is just that the number grows too large, causing it to require more and more precision towards the end, more than double can safely represent.
Here, try this really simple programme out, or just trust in the output I append to it to see what I mean:
#include <stdio.h>
int main( ){
double a;
long long b;
a = 674293938766347782.0;
b = a;
printf( "%f\n", a );
printf( "%lld", b );
getchar( );
return 0;
}
/*
Output:
674293938766347780.000000
674293938766347776
*/
You see, the double may have 8 bytes, just as much as the long long has, but it is designed so that it would also be able to hold non-integral values, which makes it less precise than long long can get in some cases like this one.
I don't know the exact specifics, but here, in MSDN it is said that its representation range is from -1.7e308 to +1.7e308 with (probably just on average) 15 digit precision.
So, if you are going to work with positive integers only, stick with your function. If you want to have an optimized version, check this one out: https://stackoverflow.com/a/101613/2736228
It makes use of the fact that, for example, while calculating x to the power 8, you can get away with 3 operations:
...
result = x * x; // x^2
result = result * result; // (x^2)^2 = x^4
result = result * result; // (x^4)^2 = x^8
...
Instead of dealing with 7 operations, multiplying them one by one.
pow (see reference) is not defined for integers, but only for floating point numbers. If you call pow with int as an argument the result will be a double.
You can in general not assume that the result of pow will be exactly the same as if you would use pure integer math as in the function pow_longlong.
Citation from wikipedia about double precision floating point numbers:
Between 2^52=4,503,599,627,370,496 and 2^53=9,007,199,254,740,992 the
representable numbers are exactly the integers. For the next range,
from 2^53 to 2^54, everything is multiplied by 2, so the representable
numbers are the even ones, etc.
So you get inaccurate results with pow if the result would be bigger than 2^53.

Resources