I have been cracking my head at achieving something very simple in C in order to make my one of the programs (not written by me) in our computational physics project more dynamic:
comparing two different arrays element by element in an if conditional.
#include <math.h>
#include <stdio.h>
#include "header.h"
const int nParam = 10;
double a[nParam], a_tmp[nParam];
double values[10000];
double FitParam(double x){
int xindex;
double value;
xindex=(int) x;
if (a_tmp[1]==a[1] && a_tmp[2]==a[2] && a_tmp[3]==a[3] && a_tmp[4]==a[4]){
value=values[xindex];
return(value);
}
// code continues... (very long subroutine and there is recursion for
// the subroutine so this if statement above is very important).
The array a[ ] has a varying number of significant elements every time we run our program; for example, right now, we are using this subroutine for only elements [1] through [4]. However, in other cases, we will want to have fewer or more elements, say, up to 3 elements or up to 5 elements, respectively.
So essentially, I want to be able to rewrite the if statement above so that it is dynamic... in other words, if there are N elements considered, then it will do:
if (a_tmp[1]==a[1] && ... && a_tmp[N]==a[N]){}
So this if conditional should vary whenever our number N of elements of interest is changed (N is defined as a #define in the header of this file, which I just named header.h).
I would greatly appreciate your support on this task. Thank you.
Your best bet is to rewrite it as a function that returns true or false (1 or 0):
int compareArrays(double a[], double b[], int n) {
int ii;
for(ii = 1; ii <= n; ii++) {
if (a[ii] != b[ii]) return 0;
// better:
// if(fabs(a[ii]-b[ii]) < 1e-10 * (fabs(a[ii]) + fabs(b[ii]))) {
// with the appropriate tolerance
}
return 1;
}
Note that it is usually bad practice to compare doubles for equality - you are better off comparing their difference, and making sure the absolute value is less than some tolerance.
Also note you are comparing elements 1 through n - C arrays start at 0 though.
You would use the above with
if (compareArrays(a, a_tmp, N)) {
where the value N is #define'd per your question.
If you want to be "clever" and avoid a loop, you can write the following - it will stop ("short-circuiting") as soon as you reach the right number of comparisons. It is still a Bad Idea to compare doubles for equality but I will leave that for another time (see comment in code above for a solution).
if(a[1]==a_temp[1] && (2 > N || (a[2]==a_temp[2] && (3 > N || (a[3]==a_temp[3]))))) {
This makes the "and the rest" true as soon as you have compared the right number of terms - so it will stop evaluating terms (as you need). I am not convinced this is either faster, or better code - but it is "dynamic"... You can obviously make this expression as long as you would like; I just wrote the first three terms so you get the idea. I DO NOT RECOMMEND IT.
As for the comparison of doubles, you might consider replacing
if(a == b)
with
if(closeEnough(a, b))
where you define the macro
#define closeEnough(a, b) (fabs((a)-(b)) < 1e-10 * (fabs(a) + fabs(b)))? 1 : 0
This will make sure that your doubles don't have to be "exactly equal" - depending on how you arrived at them, they will almost never be, and the relative tolerance of 1 part in 10^10 is usually plenty for most practical comparisons.
If it must be at compile time, there is nothing in the standard that provides for a repeating macro like that. As in another (question), for bounded N, you can prepare N macros that expand to your desired comparison.
While yet another alternative is memcmp
memcmp( data, data2, array_len_in_bytes );
reference
An implementation might be to loop over all the elements and set a flag when a difference is detected
int i, N;
int is_equal = 1;
for (i=1; i<N; ++i) {
if (a[i] != a_tmp[i]) {
is_equal = 0;
break;
}
}
if (is_equal)
printf("Arrays are equal");
A simple implementation is a linear comparison between both arrays, it just iterate over the array length and check if (a[i] != b[i]), if so return false & break out of the iteration.
See the example below:
#include <stdio.h>
int compareArrays(int a[], int b[], int n)
{
for (int i=0; i<n; ++i)
{
if (a[i] != b[i])
{
return -1;
}
}
return 0;
}
int main()
{
int arr1[4] = {3, 4, 5, 7};
int arr2[4] = {3, 4, 5, 7};
int arr3[4] = {1, 5, 3, 7};
int arr4[4] = {3, 4, 5, 19};
printf("Should be True %d\n", compareArrays(arr1, arr2, 4));
printf("Should be False %d\n", compareArrays(arr3, arr4, 4));
return 0;
}
You should get:
Should be True 0
Should be False -1
Run it online this example: https://repl.it/#abranhe/compare-arrays-in-c
This one, lets you compare two arrays of any type and will return the index of the first unequal elements found. If the arrays are identical the returned value will be the number of elements in the array.
int compareArrays(void* arrayA, void* arrayB, uint numElements, uint elementSizeBytes) {
//returns -1 on error, numElememts if the arrays are equal or the index
//of the first unequal elements
uint i;
uint8_t* byteArrayA;
uint8_t* byteArrayB;
if(elementSizeBytes < 1) {
return -1;
}
if(numElements < 1) {
return -1;
}
byteArrayA = (uint8_t*) arrayA;
byteArrayB = (uint8_t*) arrayB;
for(i = 0; i < (numElements*elementSizeBytes); i++) {
if(byteArrayA[i] != byteArrayB[i]) {
break;
}
}
return i / elementSizeBytes;
}
An example call:
uint16_t test1[6] = {12, 15, 24, 86, 92, 15};
uint16_t test2[6] = {12, 15, 24, 86, 93, 15};
int retVal = compareArrays(test1, test2, 6, 2);
Today i came across same kind of problem statement,i googled for solution for an hour and end up with no solution,the above all approaches are not correct solutions for the stated problem
The Better way to resolve above Problem is
Sort the two arrays either in ascending or descending order, Then compare both the arrays.
#include<stdio.h>
void sort_it(int a[], int size)
{
int i,j,temp=0;
for(i=0;i<size;++i)
{
for(j=i+1;j<size;++j)
{
if(a[i]>a[j])
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
};
int compare(int size,int a[],int b[])
{
int i,j,is_equal;
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)`enter code here`
{
if(a[i]!=b[j])
{
is_equal=0;
}
else
is_equal=1;
}
}
return is_equal;
};
int main()
{
int size=4,i,is_equal;
int a[]={1,2,5,4};
int b[]={1,7,4,2};
sort_it(a,size);
sort_it(b,size);
is_equal=compare(4,a,b);
if(is_equal)
printf("arrays are equal\n");
else
printf("arrays are not equal\n");
return (0);
}
Related
I need to write a function which fills array rez with the conjugate-complex pairs from the array bounded by p1 and p2. The function returns the number of conjugate-complex pairs placed in the array. Duplicates must not be placed in the sequence. Conjugate-complex pairs are pairs of forms a + bi and a - bi.
This task should be solved using structures and pointer arithmetic. Auxiliary arrays are not allowed.
#include <stdio.h>
typedef struct {
int im, re;
} complex;
void remove_duplicates(complex *rez, int *number){
int i,j,k;
for (i = 0; i < *number; i++) {
for (j = i + 1; j < *number; j++) {
if (rez[i].im == rez[j].im && rez[i].re == rez[j].re) {
for (k = j; k < *number - 1; k++) {
rez[k].im = rez[k + 1].im;
rez[k].re = rez[k + 1].re;
}
(*number)--;
j--;
}
}
}
}
int conjugate_complex(complex *p1, complex *p2, complex *rez) {
int number_of_pairs = 0;
while (p1 < p2) {
if (p1->im == p1->re||p1->im == -1*p1->re) {
number_of_pairs++;
rez->re = p1->re;
rez->im = -1*p1->im;
}
rez++;
p1++;
}
remove_duplicates(rez,&number_of_pairs);
return number_of_pairs;
}
int main() {
int i;
complex arr1[5] = {{5, 5}, {3, 3}, {-5, -5}, {5, 5}, {-3, 3}};
complex arr2[5];
int vel = conjugate_complex(arr1, arr1 + 5, arr2);
printf("%d\n", vel);
for (i=0; i<vel; i++)
printf("(%d,%d) ",arr2[i].im,arr2[i].re);
return 0;
}
OUTPUT should be:
4
(-5,5) (-3,3) (5,-5) (3,3)
My output is:
5
(-5,5) (-3,3) (5,-5) (-5,5) (3,3)
The problem with my code is that it prints duplicates.
Could you help me fix my remove_duplicates function?
If I call it in main function it would work. However, I need to call it in the function conjugate_complex.
To see why it would be nice to have some O(n) space, consider what you would do in real life with graph paper. Take each complex number and place a spot in the graph (re, abs(im)). In that way, any duplicates get merged into one. This solution is O(n). (Expected, the hash is O(n) size, so you have to throw out some information, which will lead to collisions.)
It would be better to not duplicate elements in the first place. Whether you are using a Bloom filter to get around the restriction of not having an array, O(n) hash, O(n log n) sort, or an O(n^2) approach (arguably the simplest,) it would be good to have this function, (in pseudo-code, <stdbool.h> is C99, use int, adornments aside):
boolean pair_is_equal(pair a, pair b)
Be aware that a pair is not semantically equivalent to a complex. You can use the same representation (which you've been using, and, considering the output format, the simplest,) but be aware that they represent different things. If you let a complex stand in for a pair:
boolean pair_is_equal(complex a, complex b)
then you have to also also check one of a or b's complex conjugate, (except Im[a] == 0 || Im[b] == 0.) It might also be useful care about 2's-compliment INT_MIN, which is out of the domain of abs and will not have a complement (how to test.)
I'm trying to write some code in C-language. The main idea is that I have an input linear array that consists the readius for each pixel (`````` - something like that, moreover, the length of pix_r, for instance, for picture with size (128,512) will be 128 * 512). And I need for each radius random selected fixed numbers of pixels and other set to -1. What I mean:
r = 2 in pix_r = [1, 8, 2, 2, 4, 6, 7, 7, 8, 2, 8] is in the following positions currentR = [2, 3, 9], and let's NumberOfRandomS = 2, so one of the possible result can be pix_r = [*, *, 2, -1, *, *, *, *, *, 2, *]. and the same should be doe for each r. If number of items == r is less than NumberOfRandomS, we should pick up all elements without any modification.
I try to write this in C-code. But I am a newbie and don't know all features and tips for optimization. My first aprroach of writing this function is
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdint.h>
#include <stddef.h>
#include <limits.h>
#include <string.h>
#include <ctype.h>
const int NumberOfRandomS = 5;
void RandomSelected(size_t numEl, int maxRad, int *pix_r){
srand(time(NULL));
int lenRandomIndex = NumberOfRandomS*sizeof(int);
int* RandomIndex = (int*) malloc(lenRandomIndex);
memset(RandomIndex, 0, lenRandomIndex);
int lenNumPerShell1 = (maxRad) * sizeof(int);
int* numPerShell1 = (int*) malloc(lenNumPerShell1);
memset(numPerShell1, 0, lenNumPerShell1);
//Calculate the number of each pix_r per shell
for (int i=0; i<numEl; ++i){
numPerShell1[pix_r[i]]++;
}
//Main part for random selection of NumberOfRandomS items
//for each pix_r
for(int r=0; r<maxRad; ++r){
int lenShellR = numPerShell1[r];
//if number of items for this r is less than should be
//selected, skip it. It means that we selected all items
//for this r
if(lenShellR <= NumberOfRandomS){
continue;
}
int lenCurrentR = lenShellR*sizeof(int);
int* currentR = (int *) malloc(lenCurrentR); // array of indexes for this r
memset(currentR, 0, lenCurrentR);
//filling currentR array with all indexes for this r
int cInd = 0;
for(register int j=0; j<numEl; ++j){
if(pix_r[j] == r){
currentR[cInd] = j;
cInd++;
}
}
//generate random indexes without repetiotion that should be selected from currentR
//this indexes help us to save r value in these positions and others indexes for this r
//set to -1
int value[NumberOfRandomS];
for (int i=0;i<NumberOfRandomS;++i)
{
int check; //variable to check or index is already used for this r
size_t pick_index; //variable to store the random index in
do
{
pick_index = rand() % lenShellR;
//check or index is already used for this r:
check=1;
for (int j=0;j<i;++j)
if (pick_index == value[j]) //if index is already used
{
check=0; //set check to false
break; //no need to check the other elements of value[]
}
} while (check == 0); //loop until new, unique index is found
value[i]=pick_index; //store the generated index in the array
RandomIndex[i] = currentR[pick_index];
}
//set all positions for each r that are not on random selected to -1
for(register int k=0; k < lenShellR; ++k)
{
int flag = 0; // flag will be 1 if this index for this r in RandomIndex
for (register int q = 0; q < NumberOfRandomS; ++q)
{
if(RandomIndex[q] == currentR[k])
{
flag = 1; //this index is found
}
}
if(flag != 1)
{
//index for this r not in RandomIndex, so set this index for this r to -1
pix_r[currentR[k]] = -1;
}
}
}
return;
}
I tried to optimize a little bit, but different resources contradict each other and after testing it didn't show any speeding up:
void ModRandomSelected(size_t numEl, int maxRad, int *pix_r){
srand(time(NULL));
int lenRandomIndex = NumberOfRandomS*sizeof(int);
int* RandomIndex = (int*) malloc(lenRandomIndex);
memset(RandomIndex, 0, lenRandomIndex);
int lenNumPerShell1 = (maxRad) * sizeof(int);
int* numPerShell1 = (int*) malloc(lenNumPerShell1);
memset(numPerShell1, 0, lenNumPerShell1);
//Calculate the number of each pix_r per shell
for (int i=numEl-1; i>=0; --i){
numPerShell1[pix_r[i]]++;
}
//Main part for random selection of NumberOfRandomS items
//for each pix_r
for(int r=maxRad-1; r>=0; --r)
{
int lenShellR = numPerShell1[r];
//if number of items for this r is less than should be
//selected, skip it. It means that we selected all items
//for this r
if(lenShellR <= NumberOfRandomS){
continue;
}
int lenCurrentR = lenShellR*sizeof(int);
int* currentR = (int *) malloc(lenCurrentR); // array of indexes for this r
memset(currentR, 0, lenCurrentR);
//filling currentR array with all indexes for this r
int cInd = 0;
for(register int i = numEl-1; i>=0; --i)
{
if(pix_r[i] == r){
currentR[cInd] = i;
cInd++;
}
}
//generate random indexes without repetiotion that should be selected from currentR
//this indexes help us to save r value in these positions and others indexes for this r
//set to -1
int value[NumberOfRandomS];
for (int i=NumberOfRandomS-1; i>=0; --i)
{
int check; //variable to check or index is already used for this r
size_t pick_index; //variable to store the random index in
do
{
pick_index = rand() % lenShellR;
//check or index is already used for this r:
check=1;
for (int j=0;j<i;++j)
if (pick_index == value[j]) //if index is already used
{
check=0; //set check to false
break; //no need to check the other elements of value[]
}
} while (check == 0); //loop until new, unique index is found
value[i]=pick_index; //store the generated index in the array
RandomIndex[i] = currentR[pick_index];
}
//set all positions for each r that are not on random selected to -1
for(register int k=lenShellR-1; k >= 0; --k)
{
int flag = 0; // flag will be 1 if this index for this r in RandomIndex
for (register int q = NumberOfRandomS-1; q >= 0; --q)
{
if(RandomIndex[q]== currentR[k]){
flag = 1; //this index is found
}
}
if(flag != 1)
{
//index for this r not in RandomIndex, so set this index for this r to -1
pix_r[currentR[k]] = -1;
}
}
}
return;
}
I will be very thankful if you help and explain what and how I can improve this function.
The code is rather messy and hard to follow, so I can't be bothered to figure out what it actually does. The algorithm overall might be the true bottleneck. Anyway, here's some misc comments & advise of potential problems that I spotted:
Ensure to only call srand once in the whole program.
The register keyword is obsolete, from a time when compilers were bad at determining when to place variables in registers. Nowadays, compilers are more competent at this than programmers, don't use register, it is bloat.
Similarly, replacing up-counting loops with down-counting ones for the sake of performance is an obsolete technique nowadays sorting under "pre-mature optimization". The compiler can do that optimization for you - so write the code as readable as possible instead.
Avoid iterating over the same range/array multiple times.
Keep loop conditions as trivial as possible. This helps readability and data cache optimization both. The ideal for loop should look like for(int i=0; i<n; i++).
malloc is much slower than static or local storage. In this case you have a few items and only need to access them locally, so all malloc calls should be swapped with local arrays. You may use VLA here, to get stack allocation instead. That is, drop this code:
int lenRandomIndex = NumberOfRandomS;
int* RandomIndex = (int*) malloc(lenRandomIndex);
memset(RandomIndex, 0, lenRandomIndex);
and replace with this code:
int RandomIndex [NumberOfRandomS];
You have similar situations all over the code. And you probably don't need to set it to zero, because:
Don't zero-initialize or memset arrays that you indeed to fill with data the first thing you do anyway. This is a rather big performance problem in the posted code.
Empty return ; at the end of a function returning void is just clutter.
Investigate if some of these searches could be replaced with binary search. It means sorting the data in advance but might lead to much faster code overall.
Minimize the amount of checks, particularly inside loops.
Split up your big monster functions into several. Local static functions are very certain to get inlined and they improve readability a lot. Splitting functions into several smaller also allows much easier benchmarking.
Please benchmark your code when optimizations are enabled.
The following is an implementation of the problem from spoj:- http://www.spoj.com/problems/COINS/
#include <stdio.h>
#define ll long long
ll arr[100000];
ll max(ll n)
{
if(n < 49999)// Doubt
{
if(!arr[n])
return arr[n] = max(n/2) + max(n/3) + max(n/4);
else
return arr[n];
}
else
return max(n/2) + max(n/4) + max(n/3);
}
int main()
{
ll n, c = 0, i;
for(i = 0; i < 12; i++) // Also why 12 when the input can be <12
{
arr[i] = i;
}
while(scanf("%lld", &n) != EOF)
{
printf("%lld\n", max(n));
}
return 0;
}
Why does the if condition contain n<49999?
without having examined each possibility, other than the first 20+ values and the max and min values:
MY expectation is
the first 12 entries in the arr[] are pre-calculated to help reduce the depth of a recursion however the dollar value is not the same as the calculated value for those first 12 entries.
for coin values <= 49999, check to see if value already calculated, if not then break the coin into the /2 /3 /4 values and recurse each of those resulting values.
This limit value (49999) could be extended to 100000 as that is the available size of the arr[] array.
the presetting and the saving into the arr[] array are to help reduce execution time taken and the depth of the recursion.
the use of the array is so any previously calculated values (in the posted code, up to 49999) can be immediately returned by the max() function, without further recursion.
I would modify the code slightly for better documentation and robustness and faster execution as follows:
#include <stdio.h>
#include <stdint.h>
#define MAX_ARRAY_LEN (100000)
uint32_t arr[ MAX_ARRAY_LEN ] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
uint32_t max(uint32_t n)
{
if(n < MAX_ARRAY_LEN)
{ // value of 'n' within the range of the learning array arr[]
if(!arr[n] && n)
{ // then learning array arr[] not yet set
return arr[n] = max(n/2) + max(n/3) + max(n/4);
}
else
{ // else learning array arr[] already set for 'this' value of 'n'
return arr[n];
}
}
else
{ // value of 'n' is greater than the learning array arr[]
return max(n/2) + max(n/4) + max(n/3);
}
} // end function: max
int main( void )
{
uint32_t n;
int status;
while( (status = scanf("%u", &n)) == 1 && EOF != status)
{
if( 1000000000 >= n)
{
printf("%u\n", max(n) );
}
else
{
printf(" invalid value entered, must be in the range 0...1 000 000 000\n");
} // end if
} // end while
return 0;
} // end function: main
As far I understand that,
The person who write the code, somehow he found out that (manually) if
the coin less than 12 then result will be itself. so that he use 12.
(check the explanation of the input coin = 2)
And about the recursion function
as we know we can't declare array with 1,000,000,000 size so he try to
use some other value (49999 here) in which size he can create array
and later take the result for the coin in array like arr[12] = 13
(where 12 is coin and 13 is the result) so that he can get the result
without generate for the value by using that array with arr[12] (only)
for coin 12.
Hope you understand.
`/* finding the minimum number of a array */
#include<stdio.h>
int minimum(int n, int a[n], int x);
int main(void)
{
int a[5] = { 5, 4, 3, 4, 5 };
printf("%d \n", minimum(4, a, 0));
return 0;
}
int minimum(int n, int a[n], int x)
{
int minima;
if (x >= n)
return a[x];
else
minima = minimum(n, a, x + 1);
if (a[x] > minima)
return minima;
}
`
Hey I read few recursion sources in stackoverflaw. Also found same kind problem using JAVA. Can you please explain me how this code works.Or is this a good coding. I make it my self to learn recursion and it is working.Please explain.
There are two problems in your code:
The termination happens too late: you return a[x] when x==n - that's one element past the end.
There is a missing return when a[x] > minima is false: your function ends without returning a[x].
To fix these two problems, change the check of the termination condition, and add the missing return:
if(x >= n-1) return a[n-1];
// You do not need an else after a return
minima = minimum(n,a,x+1);
if (a[x] > minima) return minima;
return a[x];
Note that you can save one parameter by starting the search at the end of the array and going backward until you reach index zero.
This question already has answers here:
nth fibonacci number in sublinear time
(16 answers)
Closed 6 years ago.
I am a CSE student and preparing myself for programming contest.Now I am working on Fibonacci series. I have a input file of size about some Kilo bytes containing positive integers. Input formate looks like
3 5 6 7 8 0
A zero means the end of file. Output should like
2
5
8
13
21
my code is
#include<stdio.h>
int fibonacci(int n) {
if (n==1 || n==2)
return 1;
else
return fibonacci(n-1) +fibonacci(n-2);
}
int main() {
int z;
FILE * fp;
fp = fopen ("input.txt","r");
while(fscanf(fp,"%d", &z) && z)
printf("%d \n",fibonacci(z));
return 0;
}
The code works fine for sample input and provide accurate result but problem is for my real input set it is taking more time than my time limit. Can anyone help me out.
You could simply use a tail recursion version of a function that returns the two last fibonacci numbers if you have a limit on the memory.
int fib(int n)
{
int a = 0;
int b = 1;
while (n-- > 1) {
int t = a;
a = b;
b += t;
}
return b;
}
This is O(n) and needs a constant space.
You should probably look into memoization.
http://en.wikipedia.org/wiki/Memoization
It has an explanation and a fib example right there
You can do this by matrix multiplictation, raising the matrix to power n and then multiply it by an vector. You can raise it to power in logaritmic time.
I think you can find the problem here. It's in romanian but you can translate it with google translate. It's exactly what you want, and the solution it's listed there.
Your algorithm is recursive, and approximately has O(2^N) complexity.
This issue has been discussed on stackoverflow before:
Computational complexity of Fibonacci Sequence
There is also a faster implementation posted in that particular discussion.
Look in Wikipedia, there is a formula that gives the number in the Fibonacci sequence with no recursion at all
Use memoization. That is, you cache the answers to avoid unnecessary recursive calls.
Here's a code example:
#include <stdio.h>
int memo[10000]; // adjust to however big you need, but the result must fit in an int
// and keep in mind that fibonacci values grow rapidly :)
int fibonacci(int n) {
if (memo[n] != -1)
return memo[n];
if (n==1 || n==2)
return 1;
else
return memo[n] = fibonacci(n-1) +fibonacci(n-2);
}
int main() {
for(int i = 0; i < 10000; ++i)
memo[i] = -1;
fibonacci(50);
}
Nobody mentioned the 2 value stack array version, so I'll just do it for completeness.
// do not call with i == 0
uint64_t Fibonacci(uint64_t i)
{
// we'll only use two values on stack,
// initialized with F(1) and F(2)
uint64_t a[2] = {1, 1};
// We do not enter loop if initial i was 1 or 2
while (i-- > 2)
// A bitwise AND allows switching the storing of the new value
// from index 0 to index 1.
a[i & 1] = a[0] + a[1];
// since the last value of i was 0 (decrementing i),
// the return value is always in a[0 & 1] => a[0].
return a[0];
}
This is a O(n) constant stack space solution that will perform slightly the same than memoization when compiled with optimization.
// Calc of fibonacci f(99), gcc -O2
Benchmark Time(ns) CPU(ns) Iterations
BM_2stack/99 2 2 416666667
BM_memoization/99 2 2 318181818
The BM_memoization used here will initialize the array only once and reuse it for every other call.
The 2 value stack array version performs identically as a version with a temporary variable when optimized.
You can also use the fast doubling method of generating Fibonacci series
Link: fastest-way-to-compute-fibonacci-number
It is actually derived from the results of the matrix exponentiation method.
Use the golden-ratio
Build an array Answer[100] in which you cache the results of fibonacci(n).
Check in your fibonacci code to see if you have precomputed the answer, and
use that result. The results will astonish you.
Are you guaranteed that, as in your example, the input will be given to you in ascending order? If so, you don't even need memoization; just keep track of the last two results, start generating the sequence but only display the Nth number in the sequence if N is the next index in your input. Stop when you hit index 0.
Something like this:
int i = 0;
while ( true ) {
i++; //increment index
fib_at_i = generate_next_fib()
while ( next_input_index() == i ) {
println fib_at_i
}
I leave exit conditions and actually generating the sequence to you.
In C#:
static int fib(int n)
{
if (n < 2) return n;
if (n == 2) return 1;
int k = n / 2;
int a = fib(k + 1);
int b = fib(k);
if (n % 2 == 1)
return a * a + b * b;
else
return b * (2 * a - b);
}
Matrix multiplication, no float arithmetic, O(log N) time complexity assuming integer multiplication/addition is done in constant time.
Here goes python code
def fib(n):
x,y = 1,1
mat = [1,1,1,0]
n -= 1
while n>0:
if n&1==1:
x,y = x*mat[0]+y*mat[1], x*mat[2]+y*mat[3]
n >>= 1
mat[0], mat[1], mat[2], mat[3] = mat[0]*mat[0]+mat[1]*mat[2], mat[0]*mat[1]+mat[1]*mat[3], mat[0]*mat[2]+mat[2]*mat[3], mat[1]*mat[2]+mat[3]*mat[3]
return x
You can reduce the overhead of the if statement: Calculating Fibonacci Numbers Recursively in C
First of all, you can use memoization or an iterative implementation of the same algorithm.
Consider the number of recursive calls your algorithm makes:
fibonacci(n) calls fibonacci(n-1) and fibonacci(n-2)
fibonacci(n-1) calls fibonacci(n-2) and fibonacci(n-3)
fibonacci(n-2) calls fibonacci(n-3) and fibonacci(n-4)
Notice a pattern? You are computing the same function a lot more times than needed.
An iterative implementation would use an array:
int fibonacci(int n) {
int arr[maxSize + 1];
arr[1] = arr[2] = 1; // ideally you would use 0-indexing, but I'm just trying to get a point across
for ( int i = 3; i <= n; ++i )
arr[i] = arr[i - 1] + arr[i - 2];
return arr[n];
}
This is already much faster than your approach. You can do it faster on the same principle by only building the array once up until the maximum value of n, then just print the correct number in a single operation by printing an element of your array. This way you don't call the function for every query.
If you can't afford the initial precomputation time (but this usually only happens if you're asked for the result modulo something, otherwise they probably don't expect you to implement big number arithmetic and precomputation is the best solution), read the fibonacci wiki page for other methods. Focus on the matrix approach, that one is very good to know in a contest.
#include<stdio.h>
int g(int n,int x,int y)
{
return n==0 ? x : g(n-1,y,x+y);}
int f(int n)
{
return g(n,0,1);}
int main (void)
{
int i;
for(i=1; i<=10 ; i++)
printf("%d\n",f(i)
return 0;
}
In the functional programming there is a special algorithm for counting fibonacci. The algorithm uses accumulative recursion. Accumulative recursion are used to minimize the stack size used by algorithms. I think it will help you to minimize the time. You can try it if you want.
int ackFib (int n, int m, int count){
if (count == 0)
return m;
else
return ackFib(n+m, n, count-1);
}
int fib(int n)
{
return ackFib (0, 1, n+1);
}
use any of these: Two Examples of recursion, One with for Loop O(n) time and one with golden ratio O(1) time:
private static long fibonacciWithLoop(int input) {
long prev = 0, curr = 1, next = 0;
for(int i = 1; i < input; i++){
next = curr + prev;
prev = curr;
curr = next;
}
return curr;
}
public static long fibonacciGoldenRatio(int input) {
double termA = Math.pow(((1 + Math.sqrt(5))/2), input);
double termB = Math.pow(((1 - Math.sqrt(5))/2), input);
double factor = 1/Math.sqrt(5);
return Math.round(factor * (termA - termB));
}
public static long fibonacciRecursive(int input) {
if (input <= 1) return input;
return fibonacciRecursive(input - 1) + fibonacciRecursive(input - 2);
}
public static long fibonacciRecursiveImproved(int input) {
if (input == 0) return 0;
if (input == 1) return 1;
if (input == 2) return 1;
if (input >= 93) throw new RuntimeException("Input out of bounds");
// n is odd
if (input % 2 != 0) {
long a = fibonacciRecursiveImproved((input+1)/2);
long b = fibonacciRecursiveImproved((input-1)/2);
return a*a + b*b;
}
// n is even
long a = fibonacciRecursiveImproved(input/2 + 1);
long b = fibonacciRecursiveImproved(input/2 - 1);
return a*a - b*b;
}
using namespace std;
void mult(LL A[ 3 ][ 3 ], LL B[ 3 ][ 3 ]) {
int i,
j,
z;
LL C[ 3 ][ 3 ];
memset(C, 0, sizeof( C ));
for(i = 1; i <= N; i++)
for(j = 1; j <= N; j++) {
for(z = 1; z <= N; z++)
C[ i ][ j ] = (C[ i ][ j ] + A[ i ][ z ] * B[ z ][ j ] % mod ) % mod;
}
memcpy(A, C, sizeof(C));
};
void readAndsolve() {
int i;
LL k;
ifstream I(FIN);
ofstream O(FOUT);
I>>k;
LL A[3][3];
LL B[3][3];
A[1][1] = 1; A[1][2] = 0;
A[2][1] = 0; A[2][2] = 1;
B[1][1] = 0; B[1][2] = 1;
B[2][1] = 1; B[2][2] = 1;
for(i = 0; ((1<<i) <= k); i++) {
if( k & (1<<i) ) mult(A, B);
mult(B, B);
}
O<<A[2][1];
}
//1,1,2,3,5,8,13,21,33,...
int main() {
readAndsolve();
return(0);
}
public static int GetNthFibonacci(int n)
{
var previous = -1;
var current = 1;
int element = 0;
while (1 <= n--)
{
element = previous + current;
previous = current;
current = element;
}
return element;
}
This is similar to answers given before, but with some modifications. Memorization, as stated in other answers, is another way to do this, but I dislike code that doesn't scale as technology changes (size of an unsigned int varies depending on the platform) so the highest value in the sequence that can be reached may also vary, and memorization is ugly in my opinion.
#include <iostream>
using namespace std;
void fibonacci(unsigned int count) {
unsigned int x=0,y=1,z=0;
while(count--!=0) {
cout << x << endl; // you can put x in an array or whatever
z = x;
x = y;
y += z;
}
}
int main() {
fibonacci(48);// 48 values in the sequence is the maximum for a 32-bit unsigend int
return 0;
}
Additionally, if you use <limits> its possible to write a compile-time constant expression that would give you the largest index within the sequence that can be reached for any integral data type.
#include<stdio.h>
main()
{
int a,b=2,c=5,d;
printf("%d %d ");
do
{
d=b+c;
b=c;
c=d;
rintf("%d ");
}