Explain Fibonacci code - c

#include<stdio.h>
#define max 2000
int arr1[max], arr2[max], arr3[max];
void fib();
int main()
{
int num, i, j, flag = 0;
for(i = 0; i<max; i++)
arr1[i] = arr2[i] = arr3[i] = 0;
arr2[max - 1] = 1;
printf("Enter the term : ");
scanf("%d", &num);
for(i = 0; i<num; i++)
{
fib();
if(i == num - 3)
break;
for(j = 0; j<max; j++)
arr1[j] = arr2[j];
for(j = 0; j<max; j++)
arr2[j] = arr3[j];
}
for(i = 0; i<max; i++)
{
if(flag || arr3[i])
{
flag = 1;
printf("%d", arr3[i]);
}
}
getch();
return 1;
}
void fib()
{
int i, temp;
for(i = 0; i<max; i++)
arr3[i] = arr1[i] + arr2[i];
for(i = max - 1; i>0; i--)
{
if(arr3[i]>9)
{
temp = arr3[i];
arr3[i] %= 10;
arr3[i - 1] += (temp / 10);
}
}
}
The above code generates the nth Fibonacci number. I am not able to understand how this works. Basically the Fibonacci number get stored in a very large array arr3[].
Please explain the logic involved in this code.
How does the fib() function work as well?

Here is a simple Fibonacci loop.
#include <stdio.h>
int main()
{
int term = 20, last2=0, last1=1, fib, i;
for (i=0; i<term; i++) {
fib = last2 + last1;
last2 = last1;
last1 = fib;
}
printf ("Term %d = %d\n", i, fib);
return 0;
}
Program output:
Term 20 = 10946
Although there is more than one idea as to where the sequence starts.

The example code in the original post is dealing with large numbers by storing 1 decimal digit per element in each of the arrays. It initializes arr[3] = arr2[] = arr1[] = 0, then arr2[] = 1. In the loop, fib() performs one instance of arr3[] = arr1[] + arr2[], handling the carries, then the loop does arr[1] = arr2[], arr2[] = arr3[]. If num < 3, the for loop exits on the loop condition i < num, if n >= 3, the loop exit when i == (num-3). (This could be avoided). The print loop skips leading zeroes in arr3[], setting flag once a non-zero value is found. The code needs some minor fixes. Here is a fixed example. Note that getch() may be _getch() in some environments (from conio.h). The second example below only uses two arrays. Fibonacci numbers starting from 0 are 0 1 1 2 3 5 8 ...
#include <conio.h>
#include <stdio.h>
#define max 2000
int arr1[max], arr2[max], arr3[max];
void fib();
int main()
{
int num, i, j;
for(i = 0; i<max; i++)
arr1[i] = arr2[i] = arr3[i] = 0;
arr1[max - 1] = 1;
printf("Enter the term : ");
scanf("%d", &num);
for(i = 0; i<num; i++)
{
fib();
for(j = 0; j<max; j++)
arr1[j] = arr2[j];
for(j = 0; j<max; j++)
arr2[j] = arr3[j];
}
for(i = 0; i < max-1; i++)
if(arr3[i])
break;
for( ; i < max; i++)
printf("%d", arr3[i]);
getch();
return 0;
}
void fib()
{
int i, temp;
for(i = 0; i<max; i++)
arr3[i] = arr1[i] + arr2[i];
for(i = max - 1; i>0; i--)
{
if(arr3[i]>9)
{
temp = arr3[i];
arr3[i] %= 10;
arr3[i - 1] += (temp / 10);
}
}
}
This example only uses two arrays, by alternating which array contains the sum (a1 += a0, a0 += a1). It uses Duff's device to enter the loop. Since the largest sum from digit + digit + carry is < 20, the carry loop in fib() was simplified.
#include <conio.h>
#include <stdio.h>
#define max 2000
void fib(unsigned char *a0, unsigned char *a1);
int main()
{
unsigned char a0[max], a1[max];
size_t i;
int n;
printf("Enter the term : ");
scanf("%d", &n);
for(i = 0; i < max; i++)
a0[i] = a1[i] = 0;
a0[max-1] = n & 1; /* if n even, a0=0=fib(0), a1=1=fib(-1) */
a1[max-1] = 1 - a0[max-1]; /* if n odd, a1=0=fib(0), a0=1=fib(-1) */
switch(n&1){
do{
fib(a0, a1);
case 1:
fib(a1, a0);
case 0:
continue;
}while(0 <= (n -= 2));
}
for(i = 0; i < max-1; i++)
if(a0[i])break;
for( ; i < max; i++)
printf("%d", a0[i]);
getch();
return 0;
}
void fib(unsigned char *a0, unsigned char *a1)
{
size_t i;
for(i = 0; i < max; i++)
a1[i] += a0[i];
for(i = max - 1; i > 0; i--){
if(a1[i] >= 10){
a1[i] -= 10;
a1[i-1] += 1;
}
}
}

Here's a much better implementation of the Fibonacci series
#include<iostream>
using namespace std;
main()
{
int n, c, first = 0, second = 1, next;
cout << "Enter the number of terms of Fibonacci series you want" << endl;
cin >> n;
cout << "First " << n << " terms of Fibonacci series are :- " << endl;
for ( c = 0 ; c < n ; c++ )
{
if ( c <= 1 )
next = c;
else
{
next = first + second;
first = second;
second = next;
}
cout << next << endl;
}
return 0;
}

Related

What is this sorting algorithm? And is there a more efficient way?

I wrote this algorithm while learning about O(N) algorithms, and after the last question I posted moments ago, I was wondering if theres a similar algorithm that already exists as well.
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
/*algorithm designed by hoholee12*/
typedef struct{
int val;
int dup;
} duplicates;
int ScoopSort(int* arr, int size, int buf){
//subarr buffer size
buf += size;
int* bigarr = malloc(size * sizeof(int));
duplicates* subarr = malloc(buf * sizeof(duplicates));
//subarr init: O(N)
for (int i = 0; i < buf; i++) {
subarr[i].val = INT_MIN;
subarr[i].dup = 0;
}
//will always have biggest number of section
int lastsize = INT_MIN;
//big loop(until all elements are scooped: O(count of 'diff bigger than size'))
int j = 0;
int loopcount = 0;
while (1){
//min check per iteration: O(N)
int min = INT_MAX;
for (int i = 0; i < size; i++){
if (min > arr[i] && arr[i] > lastsize) min = arr[i];
}
//initval per iteration
int initval = min - 1;
//follow index: incr dup
for (int i = 0; i < size; i++){
int val = arr[i] - min;
if (val < buf && val >= 0){
subarr[val].val = arr[i];
subarr[val].dup++;
}
}
//scoop subarr to bigarr: O(N)
for (int i = 0; i < buf; i++){
if (subarr[i].val > initval){
for (int x = 0; x < subarr[i].dup; x++) bigarr[j++] = subarr[i].val;
subarr[i].dup = 0;
if (lastsize < subarr[i].val) lastsize = subarr[i].val;
}
}
loopcount++;
//break on all scooped
if (j >= size) break;
}
//copy back: O(N)
for (int i = 0; i < size; i++) arr[i] = bigarr[i];
free(subarr);
free(bigarr);
return loopcount;
}
int test2(){
#define ARRSIZE 1000000
int* arr = malloc(ARRSIZE * sizeof(int));
srand(time(NULL));
for (int i = 0; i < ARRSIZE; i++){
arr[i] = rand() *(RAND_MAX + 1) + rand();
}
//printf("before: ");
//for (int i = 0; i < ARRSIZE; i++) printf("%d ", arr[i]);
//printf("\n");
time_t start = time(NULL);
int result = ScoopSort(arr, ARRSIZE, 0);
time_t end = time(NULL);
//printf("after: ");
for (int i = 0; i < ARRSIZE; i++) printf("%d ", arr[i]);
printf("\nlooped %d time(s).\ntook %d second(s).", result, end - start);
free(arr);
return 0;
}
int test1(){
//3 0 3 2 6 3 1 4 1 7
int arr[10] = { 8, 3, 4, 9, 4, 3, 9, 5, 4, 0 };
srand(time(NULL));
printf("before: ");
for (int i = 0; i < 10; i++) printf("%d ", arr[i]);
printf("\n");
time_t start = time(NULL);
int result = ScoopSort(arr, 10, 0);
time_t end = time(NULL);
printf("after: ");
for (int i = 0; i < 10; i++) printf("%d ", arr[i]);
printf("\nlooped %d time(s).\ntook %d second(s).", result, end - start);
return 0;
}
int main(){
test2();
return 0;
}
in short, it is somewhat of a count sort mixed with bucket sort for limited memory. so still O(N^2) but probably faster than the last one..
I went from the last question -> count sort + insertion sort -> to this. I am also wondering if theres still a more efficient way (except for hashing).
test results:
size = 10000000, rand() short int range:
quicksort: took 12 seconds
above: 1 loop, took 0 seconds
size = 10000000, rand() int range:
quicksort: took 8 seconds
above: 108 loops, took 21 seconds
its good enough for small values since its basically a counting sort, but for big values not so much.

The pointer variables overflows when they store integers larger than 1024 and some adresses seem to be locked.in C

How do I get to write to 2D pointers where I have pnumber[2%4][2%4] and how can I get pnumber with more than 3 ciphers to be displayed?
I'm making a program to write pascals triangle in C.
When the pointer pnumbers[i][j] have both i and j = 2 mod 4, except for when i and j = 2, then my program won't write to the address and give the error message:
pascals triangle: malloc.c:2406: sysmalloc: Assertion '{old_top == initial_top (av) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.
Aborted.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int factorial(int p) {
if (p>=1) {
return p*factorial(p-1);
}
else {
return 1;
}
}
int NchooseM(int n, int m) {
return factorial(n)/(factorial(n-m)*factorial(m));
}
int main() {
int n =7;
int x = n-2;
int i, j, k;
/*
printf("How many rows of Pascals triangle do you want to write?\n");
scanf("%d", &n);
*/
int **pnumbers;
pnumbers = (int **) malloc(n *sizeof(int *));
/* Allocate memory for storing the individual elements in a row */
for (i = 0; i < n; i++) {
pnumbers[i] = (int *) malloc(i * sizeof(int));
}
pnumbers[0][1] = 1;
/* Calculating the value of pnumbers[k][l] */
for (i = 0; i < n; i++) {
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
/*
if (!(i % 4 == 2 && i != 2))
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
} else if (i > 2) {
for (j = 0; j <= i-1; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
}
*/
}
/* Writing out the triangle */
for (i = 0; i < n; i++) {
for (k = 0; k <= x; k++){
printf(" ");
}
for (j = 0; j <= i; j++) {
printf("%d ", pnumbers[i][j]);
}
x = x-1;
printf("\n");
}
for (i = 0; i < n; i++) {
free(pnumbers[i]);
}
free(pnumbers);
return 0;
}
When I avoid writing to these addresses and just print them out I get some seemingly random integer at these memory addresses.
Also when avoid these addresses and just print out so many rows that I get some spots with a higher integer with more than 3 siphers, it seems to overflow - and I don't see the logic behind it.
The result of running the second code
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int factorial(int p) {
if (p>=1) {
return p*factorial(p-1);
}
else {
return 1;
}
}
int NchooseM(int n, int m) {
return factorial(n)/(factorial(n-m)*factorial(m));
}
int main() {
int n =20;
int x = n-2;
int i, j, k;
/*
printf("How many rows of Pascals triangle do you want to write?\n");
scanf("%d", &n);
*/
int **pnumbers;
pnumbers = (int **) malloc(n *sizeof(int *));
/* Allocate memory for storing the individual elements in a row */
for (i = 0; i < n; i++) {
pnumbers[i] = (int *) malloc(i * sizeof(int));
}
pnumbers[0][1] = 1;
/* Calculating the value of pnumbers[k][l] */
for (i = 0; i < n; i++) {
/*
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
*/
if (!(i % 4 == 2 && i != 2))
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
} else if (i > 2) {
for (j = 0; j <= i-1; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
}
}
/* Writing out the triangle */
for (i = 0; i < n; i++) {
for (k = 0; k <= x; k++){
printf(" ");
}
for (j = 0; j <= i; j++) {
printf("%d ", pnumbers[i][j]);
}
x = x-1;
printf("\n");
}
for (i = 0; i < n; i++) {
free(pnumbers[i]);
}
free(pnumbers);
return 0;
}
But row number 13 is still quite messed up.
Code is experiencing int overflow and thus undefined behavior (UB).
With 32-bit int and int factorial(int p), p > 12 oveflows the int range.
Code could use a wider integer type (long long works up to p==20), but improvements can be made at NchooseM() to avoid overflow for higher values.
Something like the below. Works up to int n = 30;
int NchooseM(int n, int m) {
// return factorial(n)/(factorial(n-m)*factorial(m));
int nm = 1;
int den = 1;
for (int i = m+1; i <= n; i++) {
assert(INT_MAX/i >= nm);
nm *= i;
assert(nm % den == 0);
nm /= den++;
}
return nm;
}
Tried unsigned long long and works up to int n = 62;
Edit: Another bug:
I "fixed" by initializing all to 1, yet I suspect something remains amiss in /* Calculating the value of pnumbers[k][l] */ for (i = 0; i < n; i++) { code.
pnumbers[i] = malloc((i + 1) * sizeof pnumbers[i][0]);
for (int j = 0; j < i + 1; j++) {
pnumbers[i][j] = 1;
}
Aside: rather than pnumbers[i] = (int *) malloc((i+1) * sizeof(int));, consider below with no unneeded cast nor trying to match the right type.
pnumbers[i] = malloc(sizeof pnumbers[i][0] * (i+1));

C programming with functions

I have got some more problems with the code. This program ask the user to specify the nr of throws then it throws 3 dices and add these 3 dices to sum.
Then another function sorts the sum form the smallest to the largest with a bubble sorting algorithm.
the first two functions seems to work but the program does not print out the result of the 3rd sorting function.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 100
//This function ask the user for the amout of throws
int numberofthrows() {
int throws
printf("Type in the number of throws");
scanf("%d", &throws);
return throws;
}
//This function makes the random throws of 3 dices with regard to the number of throws
int filler(int thrownr, int dice1[MAX], int dice2[MAX], int dice3[MAX], int sum[MAX]) {
int i, nr;
srand(time(NULL));
for(i = 0; i <= thrownr; i++) {
nr = rand()%6;
dice1[i] = nr + 1;
nr = rand()%6;
dice2[i] = nr + 1;
nr = rand()%6;
dice3[i] = nr + 1;
sum[i] = dice1[i] + dice2[i] + dice3[i];
}
int j;
for(j = 0; j <= thrownr; j++) {
printf("%d ", dice1[j]);
printf("%d ", dice2[j]);
printf("%d ", dice3[j]);
printf("%d\n", sum[j]);
}
}
//This function sorts the result in form the sum array
int sorter(int thrownr, int sum[MAX], int sortsum[MAX]) {
int tmp, i, j, k, m;
for(i = 0; i <= thrownr; i++) {
sortsum[i] = sum[i];
}
for(m = 0; m <= 10; m++) {
for(j = 0; j <= thrownr; i++) {
if (sortsum[j] > sortsum[j+1]) {
tmp = sortsum[j];
sortsum[j] = sortsum[j+1];
sortsum[j+1] = tmp;
}
}
}
for(k = 0; k <= thrownr; k++) {
printf("%d\n", sortsum[k]);
printf("%d\n", sum[k]);
}
}
int main(void) {
srand(time(NULL));
int dice1[MAX];
int dice2[MAX];
int dice3[MAX];
int sum[MAX];
int sortsum[MAX];
int numberofthrows2;
numberofthrows2 = numberofthrows();
filler(numberofthrows2, dice1, dice2, dice3, sum);
sorter(numberofthrows2, sum, sortsum);
return 0;
}
The code for sorting is a bit wrong. Change
for(m = 0; m <= 10; m++)
To
for(m = 0; m <= thrownr-1; m++)
And
for(j = 0; j <= thrownr; i++)
To
for(j = 0; j < thrownr-m-1; i++)
To fix it. Also, call srand once at the start of main. Don't call it more than once in a program or you might get the same "random" numbers everytime you run your program.

HP Code Wars Check digit algorithm error

QUESTION:
http://www.hpcodewars.org/past/cw17/problems/Prob02--CheckDigit.pdf
Here's my code:
int checkdigit(){
int n,i,j,sum1,sum2,k;
char ch;
printf("Enter the number of lines.Then enter ther the codes!");
scanf("%d",&n);
char *codes[n];
int msum[n];
int fsum[n];
for(i=0;i<n;++i){
scanf("%s",codes[i]);
}
for(i=0;i<n;++i){
for(j=0,k=3;j<21;j+=3,k+=3){
char *num;
num=codes[i];
ch=num[j];
sum1+=atoi(ch);
if(k<21)
ch=num[k];
sum2+=atoi(ch);
}
msum[i]=sum1*3;
fsum[i]=((msum[i]+sum2)%10);
if(fsum[i]!=0)
fsum[i]-=10;
}
for(k=0;k<sizeof(fsum);k++){
printf("%s %d",codes[k],fsum[k]);
}
return 0;
}
The Code now crashes after taking the first UPC code as input.
Change
fsum[i]=((msum+sum2)%10);
to
fsum[i]=((msum[i]+sum2)%10);
That is because msum is an array of integers, and msum[i] is an integer. As msum is an array, it is of type int* and is not compatible with int for the binary operator %
Here
char *codes[n];
is array of n pointers and you don't allocate memory for these pointers and try to scan values to this location so you see a crash
#include <stdio.h>
int checkdigit(int data[12]){
int i, even, odd, result;
even = odd = 0;
for(i = 0; i < 11; ++i){
if(i & 1)
even += data[i];
else
odd += data[i];
}
result = (odd * 3 + even) % 10;
if(result)
result = 10 - result;
return data[11] = result;
}
int main(){
int n;
scanf("%d", &n);
int codes[n][12];
int i, j;
for(i = 0; i < n; ++i){
for(j = 0; j < 11; ++j){
scanf("%d", &codes[i][j]);
}
checkdigit(codes[i]);
}
for(i = 0; i < n; ++i){
for(j = 0; j < 12; ++j){
if(j) putchar(' ');
printf("%d", codes[i][j]);
}
putchar('\n');
}
return 0;
}

Check recurring characters in simple array [C]

The part that is commented 'recurring characters code' is a bit flawed as later on when I try to print the letter and number of occurrences, the letter is correct, but the number of occurrences is some random number. Can somebody explain where my logic is faulty?
#include <stdio.h>
#include <stdlib.h>
#define MAX 20
int main()
{
//declare variables
char arr[MAX], ch;
int counter1 = 0, counter2 = 0, i, j, temp, mostcommon[128], x = 0, y = 0;
//ask for user input until array reaches MAX or is interrupted by the 'X' character and append arr[i]
for(i = 0; i < MAX; i++)
{
printf("Input %d. character into array: ", i + 1);
ch = getchar();
if (ch == 'X'){
break;
}
getchar();
arr[i] = ch;
counter1++;
}
//recurring characters code
for (i = 0; i < 128; i++){
mostcommon[i] = 0;
}
x = mostcommon[0];
y = 0;
for (i = 0; i < counter1; i++)
{
mostcommon[(int) arr[i]] += i;
}
for (i = 0; i < 128; i++){
if (x < mostcommon[i]){
x = mostcommon[i];
y = i;
}
}
//print array as it was appended
printf ("\nArray:");
for (i = 0; i < counter1; i++)
{
printf("\narray[%d] = %c", i, arr[i]);
}
//sort array by descending ASCII value
for(i = 0; i < counter1 - 1; i++)
{
for(j = i + 1; j < counter1; j++)
{
if (arr[i] < arr[j])
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
//print sorted array
printf ("\n\nSorted array:");
for (i = 0; i < counter1; i++)
{
printf("\narray[%d] = %c", i, arr[i]);
}
//print array without reoccuring characters
printf ("\n\nFinal array:");
for (i = 0; i < counter1; i++)
{
if (arr[i] != arr[i-1]){
printf("\narray[%d] = %c", counter2, arr[i]);
counter2++;
}
}
printf("\n\nThe most common character is %c and it recurred %d times", y, x);
return 0;
}
One note before:
*Shouldn't you raise counter1 at the start of the loop ? Because if you don't - when X is entered it won't raise counter1 and I supposed you want number of characters entered.
Now to the code - first in the loop:
for (i = 0; i < counter1; i++)
{
mostcommon[(int) arr[i]] += i;
}
What was your purpose? If you want the number of occurrences of the character then the loop should look like this:
for(i = 0 ; i < counter1 ; i++)
{
mostcommon[(int)arr[i]]++;
}
as "+= i" has no purpose according to my understanding - so it would be kind of random as you describe. Hope it helped.

Resources