Optimizing the following recursive function - c

trying to solve an assignment question...
info I have is:
foo(0)=0
foo(1)=1
foo(2)=2
the below code works upto approximately 30 numbers...but it needs to work fluently until 100, so I need to optimize it. I tried to create an equation which links every successive number but it did not work. Any ideas how to optimize it?
#include <stdio.h>
#include<stdlib.h>
long foo(int n) {
long a;
if (n==0)
{
return 0;
}
else if(n==1)
{
return 1;
}
else if(n==2)
{
return 2;
}
else
{
return foo(n-1)-2*foo(n-2)+foo(n-3)-2;
}
}
int main(void) {
long b=foo(7);
printf("%ld",b);
}

For such a simple problem, you can make the function iterative.
#include <stdint.h>
uint64_t foo (int n)
{
if (n == 0)
return 0;
else if (n == 1)
return 1;
else if (n == 2)
return 2;
else
{
uint64_t a = 0, b = 1, c = 2;
uint64_t ret;
for (int i = 2; i<n; i++)
{
ret = a + 2*b + c - 2;
a = b;
b = c;
c = ret;
}
return (ret);
}
}
If you have to use recursion, you can significantly improve runtime with memoisation. In this case, you need an extra array to store the results of already calculated values.
uint64_t memo[101]; // size this array to the maximum value of n needed to be calculated.
uint64_t foo(int n) {
uint64_t a;
if (n==0)
{
return 0;
}
else if(n==1)
{
return 1;
}
else if(n==2)
{
return 2;
}
else
{
if (memo[n] == 0)
{
a = foo(n-1)-2*foo(n-2)+foo(n-3)-2;
memo[n] = a;
}
else
{
a = memo[n];
}
return a;
}
}

Related

Way to represent an object in C or dealing with multiple value return

I was wondering if you might be able to help, I'm trying to "convert" some code that was written in javascript to 'C' code, but I'm not sure how to deal with the object :
function updateObj(o, k) {
return {
n: o.n + 1,
way: k + "-" + o.way
}
}
function steps(k) {
if (k == 1) {
return {
n: 2,
way: "1-0<BR>"
};
}
let case1 = updateObj(steps(k - 1),k);
for (i = 2; k % i > 0; i++);
if (k == i) {
return case1;
}
let case2 = updateObj(steps(k / i),k);
if (case1.n < case2.n) return case1
else return case2;
}
document.write(steps(291).way);
How would you transfer it to 'C' ?
Here is my try :
#include <stdio.h>
#include <conio.h>
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
int steps(int num);
int main() {
int res;
res = steps(150);
_getch();
return 0;
}
int steps(k)
{
int i = 0;
if (k == 1) return 1;
for (int i = 2; k%i > 0; i++);
if (k == i) {
return steps(k - 1);
}
return 1 + MIN(steps(k - 1), steps(k / i));
}
Example of a close mapping of javascript to 'C' code.
// Include needed headers.
#include <stdio.h>
#include <stdlib.h>
// Form a struct
typedef struct {
int n;
char *way; // Code will need to manage the strings - oh the joy of C!
} function;
function updateObj(function o, int k) {
// Body left for OP to implement
// Determine concatenation memory needs
// Allocate
// Concatenate
// Free `o` resources
// Form `function`
}
function steps(int k) {
if (k == 1) {
// v---Compound Literal -----------------------v Since C99
return (function) {.n = 2, .way = strdup("1-0<BR>")};
}
function case1 = updateObj(steps(k - 1), k);
int i;
for (i = 2; k % i > 0; i++) {
;
}
if (k == i) {
return case1;
}
function case2 = updateObj(steps(k / i), k);
if (case1.n < case2.n) {
function_free(case2); // need to free resources in case2
return case1;
} else {
function_free(case1); // need to free resources in case1
return case2;
}
}
int main() {
function f = steps(291);
puts(f.way);
function_free(f);
}
structs might be what you are looking for.
They can be used to group some kind of data. In order to declare a structure that contains an integer and a char pointer, use:
struct S {
int i;
char *c;
};
Then you can do something like:
struct S function() {
struct S s;
s.i = 1;
// more code
return s;
}
If your structure is memory intensive you might want to put it on the heap and return a pointer.

Recursive Caching Based Fibonacci

I am trying to implement caching based Fibonacci sequence. But it gave me the wrong output for example (fibcache(8) gave me an answer of 13 instead of 21. However in some cases it gave me the correct output. For example fibcache(6) gave me 8. Cant figure out whats wrong
#include <stdio.h>
#include <stdlib.h>
#define DCACHE_SIZE 5
int fibcache(int number);
long cacheodd[DCACHE_SIZE] = {0};
long cacheeven[DCACHE_SIZE] = {0};
int i_odd, i_even;
int main(int argc, char *argv[])
{
int fibNum = fibcache(6);
printf("The Fibonacci number is %d\n", fibcache(fibNum));
}
int fibcache(int n)
{
int result;
if (n == 0)
return 0;
if (n == 1)
return 1;
if(n%2==0)
{
if (cacheodd[i_odd] != 0)
result = cacheodd[i_odd];
else
{
cacheodd[i_odd] = fibcache(n-1) + fibcache(n-2);
result = cacheodd[i_odd];
}
}
else
if(n%2==1)
{
if (cacheeven[i_even] != 0)
result = cacheeven[i_even];
else
{
cacheeven[i_even] = fibcache(n-1) + fibcache(n-2);
result = cacheeven[i_even];
}
}
return result;
}
You have some problems:
You actually print fib(fib(6)), a much larger number than fib(6).
Your caching function is too complicated: why handle even and odd numbers differently? You should make a special case of numbers larger than the cache size and verify if the cached value has been computed.
Here is a simpler version:
#include <stdio.h>
#define DCACHE_SIZE 5
long fibcache(int number);
long fibcache_values[DCACHE_SIZE] = { 0 };
int main(void) {
printf("List of Fibonacci numbers:\n");
for (int i = 0; i < 47; i++) {
printf(" fib(%d) = %ld\n", fibcache(i));
}
return 0;
}
long fibcache(int n) {
if (n <= 0)
return 0;
if (n == 1)
return 1;
if (n < DCACHE_SIZE) {
if (fibcache_values[n] != 0)
return fibcache_values[n];
else
return fibcache_values[n] = fibcache(n - 1) + fibcache(n - 2);
} else {
return fibcache(n - 1) + fibcache(n - 2);
}
}

C program recursive function

I have a small problem I want to build a function that returns with recursive function the nn expression with one parameter in the calling function. Can someone help me? My thought so far :
int powerThroughRecursion(int n) {
if (n == 0) {
return 1;
}
if (n <= 1) {
return n;
}
return n * powerThroughRecursion(n - 1);
}
Yes, you are actually computing n! there. One way to do it is the following:
#include <iostream>
#include <string>
int powerThroughRecusion(int n, int step) {
if (step < 1)
return 1;
return n * powerThroughRecusion(n, step - 1);
}
int main()
{
std::cout << powerThroughRecusion(4, 4);
}
You multiply by n, but a step will tell you how much multiplications to be done.
[edit] using a single parameter function
#include <iostream>
#include <string>
int powerThroughRecusionInternal(int n, int step) {
if (step < 1)
return 1;
return n * powerThroughRecusionInternal(n, step - 1);
}
int powerThroughRecusion(int n)
{
return powerThroughRecusionInternal(n, n);
}
int main()
{
std::cout << powerThroughRecusion(2) << "\n";
std::cout << powerThroughRecusion(4);
}
If you want a one parameter function. just hide and wrap the two parameter implementation version with another function call.
static int powerThroughRecusionImpl(int n, int power) {
if (power == 0) {
return 1;
}
if (power == 1) {
return n;
}
return n * powerThroughRecusionImpl(n ,power - 1);
}
int powerThroughRecusion(int n) {
return powerThroughRecusionImpl(n ,n);
}
Or if you want to be non thread-safe.
int powerThroughRecusion(int n) {
static int base = 0;
if (!base) {
base = n;
n = powerThroughRecusion(n);
base = 0;
return n;
} else {
if (n == 0) {
return 1;
} else if (n == 1) {
return base;
}
return base * powerThroughRecusion(n - 1);
}
}

How do you properly implement turning an int into a string?

I am writing a bit of an operating system, and I require the ability to print the addition of a variable. I have a working atoi function and so I reversed it to give me an itoa function. There is no way to access free memory, so I need to figure out the the number of digits in order to create the proper sized char array. I figured I would need to divide by 10 to get that, and then modulus the values into the correct spot. This is my c code so far:
char* itoa(int res) {
int size = 0;
int t = res;
while(t / 10 != 0) {
t = t/10;
size ++;
}
char ret[size+1];
ret[size] = '\0';
t = res;
int i = size - 1;
while(i > 0) {
ret[i] = t % 10;
t = t/10;
i--;
}
return ret;
}
As of right now, it prints nothing. What is wrong with it?
It has a few bugs. Here's a working version for positive numbers at least:
char* itoa(int res) {
int size = 0;
int t = res;
while(t / 10 != 0) {
t = t/10;
size++;
}
static char ret[64];
size++;
ret[size] = '\0';
t = res;
int i = size - 1;
while(i >= 0) {
ret[i] = (t % 10) + '0';
t = t/10;
i--;
}
return ret;
}
There are a lot of things wrong here. Most obviously:
You're returning the value of a temporary. ret is on the stack and doesn't exist after popping.
You're trying to dynamically allocate something on the stack. This might actually work, but you shouldn't unless you know what you're doing.
Put together, these basically kill your implementation. So, to be helpful, here's some untested code:
void putc(char c) {
/*Output "c" via BIOS interrupt or VGA write. Or whatever.*/
}
void print(int num) {
if (num!=0) {
/*Largest num is `2,147,483,64(7|8)`*/
char temp[10];
int i = 0;
if (num<0) { putc('-'); num=-num; }
if (num>0); else { temp[i++]='8'; num=-(num/10); } //signed wraparound
while (num>0) {
temp[i++] = num%10 + '0';
num /= 10;
}
while (--i>=0) putc(temp[i]);
} else putc('0');
}
If you can put up with the caller providing a buffer large enough for all expected outputs, then you can:
#include <stdio.h>
char * rIntToAscii(int num, char * result){
if( num == 0 ) return result;
else{
result=rIntToAscii( num/10, result );
*result = '0'+num%10;
return result+1;
}
};
void intToAscii(int num,char *output){
if (num==0){
*output++='0';
*output='\0';
}
else
{
if(num<0){
*output++='-';
num=-num;
};
*rIntToAscii(num, output) = '\0';
};
};
int main(void)
{
int test = -10;
char testOutput[ 32 ];
intToAscii(test,testOutput);
printf( "%s", testOutput );
return 0;
}

String calculation

I got an excersice to make a string calculator which only has an add function. When digits are not seperated, the digits have te make one whole number. When the input is 11 the program may not do 1 + 1 but has to make it eleven.
When I execute the following program it is printing "Sum = 111" on my screen, does anyone know why it is not printing 11 and maybe has a solution?
int main(void)
{
int sum = Add("11");
if(sum == -1)
{
printf("Can not return a sum");
}
else
{
printf("Sum = %d\n", sum);
}
}
extern int Add(char* numbers)
{
size_t string_length = strlen(numbers);
int Sum = 0;
int index = 0;
char number_string[255];
int number = 0;
if(string_length == 0)
{
Sum = 0;
return Sum;
}
else if(string_length == 1)
{
if(isdigit(numbers[0]))
{
Sum = numbers[0] - '0';
}
else
{
return -1;
}
return Sum;
}
else if(string_length >= 2)
{
for(index; index <= string_length; index++)
{
if(isdigit(numbers[index]))
{
strcat(number_string, &numbers[index]);
}
else if(!isdigit(numbers[index]))
{
Sum += atoi(number_string);
memset(number_string, 0, 255);
}
else
{
return -1;
}
}
return Sum;
}
else
{
return -1;
}
}
you function uses strcat, you can debug and see how it works:
1st iteration - append string "11" (&numbers[0] points to begin of the string) to number_string
2nd iteration - append string "1" (&numbers[1] points to 2nd symbol) to number_string
this is how you get "111"
what you need to do is to convert your string to number without concatenation, like this:
int Add(char* numbers) {
int n = 0;
for (; *numbers; numbers++)
if (isdigit(*numbers))
n = n*10 + (*numbers - '0');
return n;
}
Your strcat cats 11 and then cats 1 to number string, so you the 111. Here is a simple way to do this without any built in functions other than printf.
#include <stdio.h>
int main(int argc, char *argv[])
{
int sum = -1;
printf("%d\n", argc);
if (argc == 2) {
sum = Add(argv[1]);
}
if(sum == -1)
{
printf("Can not return a sum\n");
}
else
{
printf("Sum = %d\n", sum);
}
}
int Add(char* numbers)
{
char *ptr = numbers;
char *end = numbers;
int sum = 0;
while (*end >= '0' && *end <= '9') {
end++;
}
for( ; ptr < end; ptr++) {
sum *= 10;
/* *ptr is always positive */
sum += *ptr - '0';
}
return sum;
}

Resources