I have broken my head trying to solve this question on an exam. I'm stil shocked by it.
Can anybody help me write a function:
void get2(int a[], int n, *i1, *i2)
that receives the massive a[] of integers and his length n and saves to pointers i1 and i2 the indexes of the two biggest numbers in the massive (i1 - the biggest, i2 - the second biggest).
The solution must be recursive and can not contain loops. It has be done by the complextiy of O(n). The numbers in the massive are all diffrent. We cant use any helper functions.
There aren't any additional conditions. I tried some solutions, but they werent good enough.
I dont know how to save the indexes without losing there values when I recurse.
There was additional hint, that I should pay attention to how I use the *i1, *i2 to pass information between recursive steps, but i tried to use it some how and it didn't work for me anything I tried. Help somebody ?
There is only one trick to play on this exercise: Recognize when we are in the outermost recursive call and when we are not, or simpler terms when the current call of get2 is the first one and when it is not.
Using the pointers and the n parameter to do some basic Divide et Impera strategy is straightforward and require no further explanation.
We need to tell the first and subsequent calls because in the first, and only there, call we need to initialize the pointers.
We cannot rely on i1 or i2 values as they are uninitialized.
Only n has enough structure to carry some information: When we are called from the extern, i.e. not by recurring, then n >= 0.
We can then perform the one-time initialization and then negate n. This way if n<=0 we know that we are in the recursive calls.
However we still have a problem: if n >= 0 then it's opposite is n <= 0. The two condition overlaps for n == 0.
This will make the initialization happen two time and further worst the second one at the end of the recursion stack thereby voiding the state calculated.
In order to avoid them, the n is not simply negated but negated and decremented by 1, so the 5 becomes -6.
We can then recover the usable value of n by again negating and decrementing by 1. In the code below this is done and stored in m.
The else part is straightforward as pointed above. We only additionally check that the second maximal element is not equal to the maximal element in the second if.
If one index is -1 it means that it is not pointing to any element and can be assigned unconditionally.
When the function return, i1 cannot point to -1 unless the array is empty.
i2 can point to -1 if all elements are the same.
#include <stdio.h>
void get2(int a[], int n, int* i1, int* i2)
{
/* Transform from encoded n to actual length */
int m = -n-1;
/* Is this the first call? */
if (n >= 0)
{
/* Initialize the pointer to -1, i.e. no elements */
*i1 = *i2 = -1;
/* Start the recursion, encode the length */
get2(a, -n-1, i1, i2);
}
/* Here we are in the subsequent calls, we use m and not n */
else if (m-- > 0)
{
/* Assign i1 */
if (*i1 == -1 || a[m] > a[*i1])
{
*i2 = *i1; /* Don't forget to update i2 too! */
*i1 = m;
}
/* Opportunity to assign i2, check that the second max != max */
else if ((*i2 == -1 || a[m] > a[*i2]) && a[m] != a[*i1])
{
*i2 = m;
}
/* Tail recursion, do proper encoding of the n parameter */
get2(a, -m-1, i1, i2);
}
}
This function can be tested with this code
void test(int a[], int n)
{
int max, smax, i;
get2(a, n, &max, &smax);
printf("------------------------------\n");
for (i = 0; i < n; i++)
printf("%d ", a[i]);
printf("\nMax is ");
if (max >= 0)
printf("%d", a[max]);
else
printf("NOT FOUND");
printf("\nSecond Max is ");
if (smax >= 0)
printf("%d\n", a[smax]);
else
printf("NOT FOUND\n");
}
int main()
{
int v1[] = {};
int v2[] = {1};
int v3[] = {1,2};
int v4[] = {2, 1};
int v5[] = {2, 2};
int v6[] = {1,2,3,4};
int v7[] = {4,3,2,1};
int v8[] = {2,1,4,3};
int v9[] = {2,2,2,2};
int v10[] = {1,2,3,4,3,2,1};
int v11[] = {1,1,2,3,4,4};
test(v1, 0);
test(v2, 1);
test(v3, 2);
test(v4, 2);
test(v5, 2);
test(v6, 4);
test(v7, 4);
test(v8, 4);
test(v9, 4);
test(v10, 7);
test(v11, 6);
return 0;
}
With the below output
------------------------------
Max is NOT FOUND
Second Max is NOT FOUND
------------------------------
1
Max is 1
Second Max is NOT FOUND
------------------------------
1 2
Max is 2
Second Max is 1
------------------------------
2 1
Max is 2
Second Max is 1
------------------------------
2 2
Max is 2
Second Max is NOT FOUND
------------------------------
1 2 3 4
Max is 4
Second Max is 3
------------------------------
4 3 2 1
Max is 4
Second Max is 3
------------------------------
2 1 4 3
Max is 4
Second Max is 3
------------------------------
2 2 2 2
Max is 2
Second Max is NOT FOUND
------------------------------
1 2 3 4 3 2 1
Max is 4
Second Max is 3
------------------------------
1 1 2 3 4 4
Max is 4
Second Max is 3
I will give you another hint instead of writing the actual code for you:
You have 4 arguments, use all of them to pass the relevant data to the recursive calls. What I mean by that is - the first 2 arguments can describe the part of the array that is interesting for us, the pointers store the largest integers we have found, you modify them each time you find a bigger one.
And here lies the trap that most likely caught you - those are int *, that is a pointer to an integer. What the function receives is simply an address in memory. If you set that pointer to point to anything, the caller will not receive that data. You can simply write directly to that address instead of setting the pointer, like so:
int myInteger;
int *ptr = &myInteger;
*ptr = 123;
Here is a non-threadsafe way to do it: by keeping track of the original start of the array using a static variable. The addresses of the largest elements are stored in the pointers, which are used as pointers to pointers, and right at the end they are replaced by the indexes of the elements by using some pointer arithmetic aided by the static variable.
void get2(int a[], int n, int *one, int *two) {
static int *arr_start = 0;
if (n > 0) {
if (arr_start == 0) {
arr_start = a;
}
if (a[0] > **((int **)one)) {
*one = a;
} else if (a[0] > **((int **)two)) {
*two = a;
}
get2(a + 1, n - 1, one, two);
} else {
*one = *((int **)one) - arr_start;
*two = *((int **)two) - arr_start;
}
}
EDIT
Without using static variables: Use the second pointer as an indicator of whether or not we have already allocated space to keep track of the the start of the array and the indexes. Use the allocated space to keep track of the initial array size and the two largest indexes, then assign them to the correct pointers at the end:
#include <stdlib.h>
void get2(int a[], int n, int *one, int *two) {
int **pp_one = (int **)one;
if (*two != NULL) {
*pp_one = malloc(sizeof(int) * 3);
(*pp_one)[0] = n;
(*pp_one)[1] = 0;
(*pp_one)[2] = 0;
}
if (n > 0) {
if (a[0] > (*pp_one)[1]) {
(*pp_one)[1] = a;
} else if (a[0] > (*pp_one)[2]) {
(*pp_one)[2] = a;
}
get2(a + 1, n - 1, one, two);
} else {
int *t = *one;
*two = (*pp_one)[1] - (*pp_one)[0];
*one = (*pp_one)[2] - (*pp_one)[0];
free(t);
}
}
Thanks for the brain teaser. It sounded like an interesting problem. Even though it's homework, I decided to solve it.
This gets a bit annoying to do without having the indices pre-initialized somehow, but it's doable. Sounds like an artificial restriction to create artificial pain.
void
get2(int a[], int n, int *i1, int *i2) {
if (n == 0) {
*i1 = *i2 = -1;
return;
}
get2(&a[1], n - 1, i1, i2);
if (*i1 != -1)
(*i1)++;
if (*i2 != -1)
(*i2)++;
if (*i1 == -1) {
*i1 = 0;
} else if (*i2 == -1 || a[*i2] < a[0]) {
*i2 = 0;
if (a[*i1] < a[0]) {
*i2 = *i1;
*i1 = 0;
}
}
}
Here we just recurse until we have no array left to look at, then initialize the indices and on the way back we figure out the indices we're interested in. On the way back through all the recursions we update the indices i1 and i2 if they are initialized to properly point into the array we have in this iteration, then if i1 isn't initialized yet, then we know that n == 0 and must be the biggest element. On iterations after that we know that is the only interesting element of the array is element 0, if that's not bigger than a[*i2], then it's not bigger than a[*i1] either. If it is (or we're just initializing i2), we compare to see if we need to swap i1 and i2.
"But wait!", you might yell. "You're not doing tail recursion, if the array is massive you will run out of stack.". Glad you mentioned it, in fact, C doesn't say anything about the compiler having to do optimizations for tail recursion so I'd like to argue that any solution has to account for this problem. Here's a solution that works on the same principles (run out of array before we initialize the indices) that solves this in O(log n) stack space:
void
get2(int a[], int n, int *i1, int *i2) {
/*
* Reset the indices at the end of the recursion.
*/
switch (n) {
case 0:
*i1 = -1;
*i2 = -1;
return;
case 1:
*i1 = 0;
*i2 = -1;
return;
}
/*
* Number of elements in the lower and upper halves of the array.
* Notice the '+ (n & 1)' which is there to add one element to the
* upper half of the array if n is odd.
*
* The asserts document the invariants.
*/
int lower_half = n / 2, upper_half = (n / 2) + (n & 1);
int li1, li2, ui1, ui2;
assert(lower_half >= 1);
assert(upper_half >= 1);
assert(lower_half + upper_half == n);
get2(&a[0], n - upper_half, &li1, &li2);
get2(&a[lower_half], n - lower_half, &ui1, &ui2);
ui1 += lower_half;
if (ui2 != -1)
ui2 += lower_half;
assert(li1 != -1);
assert(ui1 != -1);
assert(li2 == -1 || a[li2] < a[li1]);
assert(ui2 == -1 || a[ui2] < a[ui1]);
if (a[li1] < a[ui1]) {
*i1 = ui1;
if (ui2 == -1 || a[li1] > a[ui2])
*i2 = li1;
else
*i2 = ui2;
} else if (a[li1] > a[ui1]) {
*i1 = li1;
if (li2 == -1 || a[ui1] > a[li2])
*i2 = ui1;
else
*i2 = li2;
} else {
*i1 = li1;
if (li2 == -1 || a[ui2] > a[li2])
*i2 = ui2;
else
*i2 = li2;
}
}
I'm not going to explain it, the comments and asserts should be enough to show what's going on. I'm pretty sure that the big block of ifs at the end can be written much more efficiently, but I didn't bother.
It might not be perfectly correct, it worked on the first try with a few test cases taken from the previous answers and I didn't do more testing. There might be some edge cases I haven't considered, but the general idea works.
Here is a nice answer I got. The next few strokes are just to get enough characters to publish my answer with this image. this it requieres 30 characters, so i wiil write anything.
It's brilliant as simple as it is. Isnt it ))?
* This code need a little correction, with one more condition, if one of the pointers is NULL, not to loop.
Here's my take on it. This implementation is pretty concise.
void get2(int a[], int n, int *i1, int *i2)
{
if (n == 0) return;
if (*i1 == -1 || a[n-1] > a[*i1]) {
*i2 = *i1;
*i1 = n-1;
} else if (*i2 == -1 || a[n-1] > a[*i2]) {
*i2 = n-1;
}
get2(a, n-1, i1, i2);
}
To test:
#define NUM 10
int main()
{
int a[NUM];
int i, i1, i2;
srand(time(NULL));
for (i=0;i<NUM;i++) {
a[i] = rand() & 0xFFFF;
fprintf(stderr,"%d ",a[i]);
}
fprintf(stderr,"\n");
i1 = i2 = -1;
get2(a,NUM,&i1,&i2);
fprintf(stderr,"i1=%d, i2=%d\n", i1, i2);
fprintf(stderr,"a[i1]=%d, a[i2]=%d\n", a[i1], a[i2]);
}
Just another try on your function prototype,
void get2(int a[], int n, int *i1, int *i2)
{
if(n <= 0)
return;
if(*i1 == -1 && n < 2){//initial a[] is null or with only one element
*i1 = n-1;
return;
}
if(*i1 == -1 && n >=2){
if(a[n-1] > a[n-2]){
*i1 = n-1;
*i2 = n-2;
}else{
*i1 = n-2;
*i2 = n-1;
}
return get2(a, n-2, i1, i2);
}
int max= a[*i1], less = a[*i2];
if(a[n-1] > max){
*i2 = *i1;
*i1 = n-1;
}else if (a[n-1] > less){
*i2 = n-1;
}
get2(a, n-1, i1, i2);
}
Test as follows,
int main()
{
int a[] = { 1, 2, 3, 4, 7, 8, 6, 5, 0};
int maxIndex = -1, lessIndex= -1;
get2(a,sizeof(a)/sizeof(int),&maxIndex,&lessIndex);
printf("maxIndex=%d(value:%d), lessIndex=%d(value:%d)\n",
maxIndex,a[maxIndex],lessIndex, a[lessIndex]);
}
Output,
maxIndex=5(value:8), lessIndex=4(value:7)
Related
I have a recursive function that I wrote in C that looks like this:
void findSolutions(int** B, int n, int i) {
if (i > n) {
printBoard(B, n);
} else {
for (int x = 1; x <= n; x++) {
if (B[i][x] == 0) {
placeQueen(B, n, i, x);
findSolutions(B, n, i + 1);
removeQueen(B, n, i, x);
}
}
}
}
The initial call is (size is an integer given by user and B is a 2D array):
findSolutions(B, size, 1);
I tried to convert it into a iteration function but there is another function called removeQueen after findSolutions. I got stuck on where to put this function call. How to solve this problem? Stack is also fine but I'm also having trouble doing that.
I'm going to assume that placeQueen(B, n, i, x) makes a change to B and that removeQueen(B, n, i, x) undoes that change.
This answer shows how to approach the problem generically. It doesn't modify the algorithm like Aconcagua has.
Let's start by defining a state structure.
typedef struct {
int **B;
int n;
int i;
} State;
The original code is equivalent to the following:
void _findSolutions(State *state) {
if (state->i >= state->n) {
printBoard(state->B, state->n);
} else {
for (int x = 1; x <= state->n; ++x) {
if (state->B[state->i][x] == 0) {
State *state2 = State_clone(state); // Deep clone.
placeQueen(state2);
++state2->i;
findSolutions(state2);
}
}
}
State_free(state); // Frees the board too.
}
void findSolutions(int** B, int n, int i) {
State *state = State_new(B, n, i); // Deep clones B.
_findSolutions(state);
}
Now, we're in position to eliminate the recursion.
void _findSolutions(State *state) {
StateStack *S = StateStack_new();
do {
if (state->i >= state->n) {
printBoard(state->B, state->n);
} else {
for (int x = state->n; x>=1; --x) { // Reversed the loop to maintain order.
if (state->B[state->i][x] == 0) {
State *state2 = State_clone(state); // Deep clone.
placeQueen(state2);
++state2->i;
StateStack_push(S, state2);
}
}
}
State_free(state); // Frees the board too.
} while (StateStack_pop(&state));
StateStack_free(S);
}
void findSolutions(int** B, int n, int i) {
State *state = State_new(B, n, i); // Deep clones B.
_findSolutions(state);
}
We can eliminate the helper we no longer need.
void findSolutions(int** B, int n, int i) {
StateStack *S = StateStack_new();
State *state = State_new(B, n, i); // Deep clones B.
do {
if (state->i >= state->n) {
printBoard(state->B, state->n);
} else {
for (int x = state->n; x>=1; --x) { // Reversed the loop to maintain order.
if (state->B[state->i][x] == 0) {
State *state2 = State_clone(state); // Deep clone.
placeQueen(state2);
++state2->i;
StateStack_push(S, state2);
}
}
}
State_free(state); // Frees the board too.
} while (StateStack_pop(S, &state));
StateStack_free(S);
}
Functions you need to implement:
StateStack *StateStack_new(void)
void StateStack_free(StateStack *S)
void StateStack_push(StateStack *S, State *state)
int StateStack_pop(StateStack *S, State **p)
State *State_new(int **B, int n, int i) (Note: Clones B)
State *State_clone(const State *state) (Note: Clones state->B)
void State_free(State *state) (Note: Frees state->B)
Structures you need to implement:
StateStack
Tip:
It would be best if you replaced
int **B = malloc((n+1)*sizeof(int*));
for (int i=1; i<=n; ++i)
B[i] = calloc(n+1, sizeof(int));
...
for (int x = 1; x <= n; ++x)
...
B[i][x]
with
char *B = calloc(n*n, 1);
...
for (int x = 0; x < n; ++x)
...
B[(i-1)*n+(x-1)]
What you get by the recursive call is that you get stored the location of the queen in current row before you advance to next row. You will have to re-produce this in the non-recursive version of your function.
You might use another array storing these positions:
unsigned int* positions = calloc(n + 1, sizeof(unsigned int));
// need to initialise all positions to 1 yet:
for(unsigned int i = 1; i <= n; ++i)
{
positions[i] = 1;
}
I reserved a dummy element so that we can use the same indices...
You can now count up last position from 1 to n, and when reaching n there, you increment next position, restarting with current from 1 – just the same way as you increment numbers in decimal, hexadecimal or octal system: 1999 + 1 = 2000 (zero based in this case...).
for(;;)
{
for(unsigned int i = 1; i <= n; ++i)
{
placeQueen(B, n, i, positions[i]);
}
printBoard(B, n);
for(unsigned int i = 1; i <= n; ++i)
{
removeQueen(B, n, i, positions[i]);
}
for(unsigned int i = 1; i <= n; ++i)
{
if(++positions[i] <= n)
// break incrementing if we are in between the numbers:
// 1424 will get 1431 (with last position updated already before)
goto CONTINUE;
positions[i] = 1;
}
// we completed the entire positions list, i. e. we reset very
// last position to 1 again (comparable to an overflow: 4444 got 1111)
// so we are done -> exit main loop:
break;
CONTINUE: (void)0;
}
It's untested code, so you might find a bug in, but it should clearly illustrate the idea. It's the naive aproach, always placing the queens and removing them again.
You can do it a bit cleverer, though: place all queens at positions 1 initially and only move the queens if you really need:
for(unsigned int i = 1; i <= n; ++i)
{
positions[i] = 1;
placeQueen(B, n, i, 1);
}
for(;;)
{
printBoard(B, n);
for(unsigned int i = 1; i <= n; ++i)
{
removeQueen(B, n, i, positions[i]);
++positions[i]
if(++positions[i] <= n)
{
placeQueen(B, n, i, positions[i]);
goto CONTINUE;
}
placeQueen(B, n, i, 1);
positions[i] = 1;
}
break;
CONTINUE: (void)0;
}
// cleaning up the board again:
for(unsigned int i = 1; i <= n; ++i)
{
removeQueen(B, n, i, 1);
}
Again, untested...
You might discover that now the queens move within first row first, different to your recursive approach before. If that disturbs you, you can count down from n to 1 while incrementing the positions and you get original order back...
At the very end (after exiting the loop), don't forget to free the array again to avoid memory leak:
free(positions);
If n doesn't get too large (eight for a typical chess board?), you might use a VLA to prevent that problem.
Edit:
Above solutions will print any possible combinations to place eight queens on a chess board. For an 8x8 board, you get 88 possible combinations, which are more than 16 millions of combinations. You pretty sure will want to filter out some of these combinations, as you did in your original solution as well (if(B[i][x] == 0)), e. g.:
unsigned char* checks = malloc(n + 1);
for(;;)
{
memset(checks, 0, (n + 1));
for(unsigned int i = 1; i <= n; ++i)
{
if(checks[positions[i]] != 0)
goto SKIP;
checks[positions[i]] = 1;
}
// place queens and print board
SKIP:
// increment positions
}
(Trivial approach! Including the filter in the more elaborate approach will get more tricky!)
This will even be a bit more strict than your test, which would have allowed
_ Q _
Q _ _
_ Q _
on a 3x3 board, as you only compare against previous column, whereas my filter wouldn't (leaving a bit more than 40 000 boards to be printed for an 8x8 board).
Edit 2: The diagonals
To filter out those boards where the queens attack each other on the diagonals you'll need additional checks. For these, you'll have to find out what the common criterion is for the fields on the same diagonal. At first, we have to distinguish two types of diagonals, those starting at B[1][1], B[1][2], ... as well as B[2][1], B[3][1], ... – all these run from top left to bottom right direction. On the main diagonal, you'll discover that the difference between row and column index does not differ, on next neighbouring diagonals the indices differ by 1 and -1 respectively, and so on. So we'll have differences in the range [-(n-1); n-1].
If we make the checks array twice as large and shift all differences by n, can re-use do exactly the same checks as we did already for the columns:
unsigned char* checks = (unsigned char*)malloc(2*n + 1);
and after we checked the columns:
memset(checks, 0, (2 * n + 1));
for(unsigned int i = 1; i <= n; ++i)
{
if(checks[n + i - positions[i]] != 0)
goto SKIP;
checks[n + i - positions[i]] = 1;
}
Side note: Even if the array is larger, you still can just memset(checks, 0, n + 1); for the columns as we don't use the additional entries...
Now next we are interested in are the diagonals going from bottom left to top right. Similarly to the other direction, you'll discover that the difference between n - i and positions[i] remains constant for fields on the same diagonal. Again we shift by n and end up in:
memset(checks, 0, (2 * n + 1));
for(unsigned int i = 1; i <= n; ++i)
{
if(checks[2 * n - i - positions[i]] != 0)
goto SKIP;
checks[2 * n - i - positions[i]] = 1;
}
Et voilà, only boards on which queens cannot attack each other.
You might discover that some boards are symmetries (rotational or reflection) of others. Filtering these, though, is much more complicated...
I have this code so far. It works and does what I want it to. I'm wondering if I could make it better. I do not really care for user input or any other "finish touches," just want to make the code more efficient and maybe more useful for future projects.
Excessive comments are for my personal use, I find it easier to read when I go back to old projects for references and what not.
Thanks!
#include<stdio.h>
#include<stdlib.h>
void fabonacci(int * fibArr,int numberOfSeries){
int n;
//allocate memory size
fibArr = malloc (sizeof(int) * numberOfSeries);
//first val, fib = 0
*fibArr = 0;//100
fibArr++;
//second val, fib = 1
*fibArr = 1;//104
fibArr++;
//printing first two fib values 0 and 1
printf("%i\n%i\n", *(fibArr- 2),*(fibArr- 1));
//loop for fib arr
for(n=0;n<numberOfSeries -2;n++,fibArr++){
//108 looking back at 104 looking back at 100
//112 looking back at 108 looking back at 104
*fibArr = *(fibArr-1) + *(fibArr -2);
//printing fib arr
printf("%i\n", *fibArr);
}
}
int main(){
//can implm user input if want
int n = 10;
int *fib;
//calling
fabonacci(fib,n);
}
Your code is halfway between two possible interpretations and I can't tell which one you meant. If you want fibonacci(n) to just give the nth number and not have any external side effects, you should write it as follows:
int fibonacci(int n) {
int lo, hi;
lo = 0;
hi = 1;
while(n-- > 0) {
int tmp = hi;
lo = hi;
hi = lo + tmp;
}
return lo;
}
You need no mallocs or frees because this takes constant, stack-allocated space.
If you want, instead, to store the entire sequence in memory as you compute it, you may as well require that the memory already be allocated, because this allows the caller to control where the numbers go.
// n < 0 => undefined behavior
// not enough space allocated for (n + 1) ints in res => undefined behavior
void fibonacci(int *res, int n) {
res[0] = 0;
if(n == 0) { return; }
res[1] = 1;
if(n == 1) { return; }
for(int i = 2; i <= n; i++) {
res[i] = res[i-1] + res[i-2];
}
}
It is now the caller's job to allocate memory:
int main(){
int fib[10]; // room for F_0 to F_9
fibonacci(fib, 9); // fill up to F_9
int n = ...; // some unknown number
int *fib2 = malloc(sizeof(int) * (n + 2)); // room for (n + 2) values
if(fib2 == NULL) { /* error handling */ }
fibonacci(fib2 + 1, n); // leave 1 space at the start for other purposes.
// e.g. you may want to store the length into the first element
fib2[0] = n + 1;
// this fibonacci is more flexible than before
// remember to free it
free(fib2);
}
And you can wrap this to allocate space itself while still leaving the more flexible version around:
int *fibonacci_alloc(int n) {
int *fib = malloc(sizeof(int) * (n + 1));
if(fib == NULL) { return NULL; }
fibonacci(fib, n);
return fib;
}
One way to improve the code is to let the caller create the array, and pass the array to the fibonacci function. That eliminates the need for fibonacci to allocate memory. Note that the caller can allocate/free if desired, or the caller can just declare an array.
The other improvement is to use array notation inside of the fibonacci function. You may be thinking that the pointer solution has better performance. It doesn't matter. The maximum value for n is 47 before you overflow a 32-bit int, so n is not nearly big enough for performance to be a consideration.
Finally, the fibonacci function should protect itself from bad values of n. For example, if n is 1, then the function should put a 0 in the first array entry, and not touch any other entries.
#include <stdio.h>
void fibonacci(int *array, int length)
{
if (length > 0)
array[0] = 0;
if (length > 1)
array[1] = 1;
for (int i = 2; i < length; i++)
array[i] = array[i-1] + array[i-2];
}
int main(void)
{
int fib[47];
int n = sizeof(fib) / sizeof(fib[0]);
fibonacci(fib, n);
for (int i = 0; i < n; i++)
printf("fib[%d] = %d\n", i, fib[i]);
}
I am learning how to apply recursion to arrays.
For example, I usually read arrays itiratively, this way:
void read_array(int *a, int n){
int i;
for(i = 0; i < n; ++i)
scanf("%d", &a[i]);
return;
}
I would like to read an array recursively. I wrote the following function:
void read_array(int *a, int n){
int i = n - 1;
if (n < 0)
return;
else{
if(scanf("%d", &a[n - 1 - i]) == 1){
read_array(a, n - 1);
return;
}
}
}
It compiles, but when running it trows a segmentation fault error. It confuses me since the function contemplates a base case 0 that should stop it.
Your calculation of the array index is wrong. This line:
if(scanf("%d", &a[n - 1 - i]) == 1){
assumes the initial value of n, but at the same time, you decrease n with every recursion step. That being said, it shouldn't crash but just repeatedly write the first element of a, because with i = n - 1, n - 1 - i is always zero.
The idiomatic way to write such a recursion would be to recurse on i:
void read_array(int *a, int n, int i)
{
if (i < n)
{
if(scanf("%d", &a[i]) == 1)
{
read_array(a, n, i+1);
}
}
}
and call it with the initial value for i, e.g. read_array(a, 10, 0) for reading a 10-element array.
In practice, recursion in C is to be avoided.*
* Functional languages can typically optimize recursion, C just uses the call stack with a lot of overhead.
In this example, the theoretical purpose of recursion for writing a pure function is somewhat defeated with a function returning void. If this is just about learning the principle, the functions actually should return something. You could for example create a functional "list builder":
#include <stdio.h>
#include <stdlib.h>
// place the side effect in a separate function
int getValue(void)
{
// could have `scanf()` here:
return rand();
}
typedef struct List
{
int a[10];
size_t length;
} List;
// non-functional helper to get around limitations of C:
// (if it could initialize result directly with the new values, it would
// be functional)
List listAppend(List list, int val)
{
List result = list;
result.a[result.length++] = val;
return result;
}
// recursive function without side effects:
List buildList(List list, int (*value)())
{
if (list.length >= 10) return list;
return buildList(listAppend(list, value()), value);
}
int main(void)
{
List myList = buildList((List){0}, &getValue);
for (size_t i = 0; i < myList.length; ++i)
{
printf("myList.a[%zu] is %d\n", i, myList.a[i]);
}
}
There is a bug in the function.
As the variable i is initialized the following way
int i = n - 1;
then the second argument in this call
scanf("%d", &a[n - 1 - i])
is evaluated like
scanf("%d", &a[n - 1 - (n - 1)])
that is it is always equal to zero
scanf("%d", &a[0])
As the recursive function is called with the same value of the pointer a then all entered values are assigned to a[0]. All other elements of the array are still uninitialized.
Though this does not serve as a reason for the abnormal execution of the function.
It is possible that there is used a big array and the stack is too small to call the function recursively.
In any case the function can be defined more simply and correctly the following way
size_t read_array( int *a, size_t n )
{
return n && scanf( "%d", a ) == 1 ? 1 + read_array( a + 1, n - 1 ) : 0;
}
Take into account as the input can be interrupted by the user. In this case the function returns the number of initialized elements of the array.
Here is a demonstrative program.
#include <stdio.h>
size_t read_array( int *a, size_t n )
{
return n && scanf( "%d", a ) == 1 ? 1 + read_array( a + 1, n - 1 ) : 0;
}
#define N 10
int main(void)
{
int a[N];
size_t n = read_array( a, N );
for ( size_t i = 0; i < n; i++ ) printf( "%d ", a[i] );
putchar( '\n' );
return 0;
}
If to enter sequence of numbers
0 1 2 3 4 5 6 7 8 9
then the output will be
0 1 2 3 4 5 6 7 8 9
Example:
int read_array_aux(int *i, int *n) {
if (i == n) {
return 0;
}
if (scanf("%d", i) != 1) {
return -1;
}
return read_array_aux(i + 1, n);
}
int read_array_aux2(int *a, size_t i, size_t n) {
if (i == n) {
return 0;
}
if (scanf("%d", a + i) != 1) {
return -1;
}
return read_array_aux2(a, i + 1, n);
}
int read_array(int *a, size_t n) {
return read_array_aux(a, a + n);
// return read_array_aux2(a, 0, n);
}
First, condition n<0 is wrong. Probably this is the cause of segfault.
Also, why even bother about calculating the index? When processing any kind of list recursively it's worth to grasp the concept of head (first element of list) and tail (everything except head) of the list. So, filling an array recursively would be defined as (in pseudo code):
void read_array() {
read_head();
read_tail();
}
What is head? It's the first element of current array. What's the tail? The array starting from next element. So, read_tail is equivalent of read_array, but with the beginning moved forward by one element.
And, finally, to gather everything into one place:
void read_array(int *a, int n) {
if(n<=0) {
return;
} else {
if(scanf("%d", a) == 1) {
read_array(a+1,n-1);
}
}
}
As other answers have mentioned, your handling of n is leading to problems. You can return 0 from the base case of sz == 0, otherwise return the result of the next recursive call, or -1 if scanf() fails. At each recursive call, increment a and decrement sz. The value returned in the calling function should be checked for input errors: 0 on success, -1 on failure.
Note that this is a tail recursion, which should be optimized by most good compilers.
#include <stdio.h>
int read_array(int *a, size_t sz);
int main(void)
{
int arr[5];
puts("Enter array elements:");
if (read_array(arr, 5) != 0) {
fprintf(stderr, "Input error\n");
} else {
for (size_t i = 0; i < 5; i++) {
printf("%8d", arr[i]);
}
putchar('\n');
}
return 0;
}
int read_array(int *a, size_t sz)
{
if (sz == 0 ) {
return 0;
}
if (scanf("%d", a) == 1){
return read_array(a + 1, sz - 1);
} else {
return -1;
}
}
Sample interaction:
Enter array elements:
1 2 3 4 5
1 2 3 4 5
Enter array elements:
1 2 3 x 5
Input error
I am in trouble handling duplicated elements in arrays. For example, in the problem of finding all pairs of integers within an array which sum to a specified value, here is my implementation:
vector<pair<int, int>> find_all_pairs_with_sum(int data[], int length, int sum)
{
assert(data && length>1);
vector<pair<int, int>> res;
sort(data, data+length);
int first = 0;
int last = length - 1;
while (first < last)
{
int s = data[first] + data[last];
if (s == sum)
{
res.push_back(make_pair(data[first], data[last]));
++first;
--last;
}
else
{
if (s < sum)
++first;
else
--last;
}
}
return res;
}
The problem will occur when the array contains duplicated elements. For example, when
int data[] = {3, 4, 3, 4};
int sum = 7;
The program will only give two pairs (3,4) (3,4). However, in this case, the correct answer should be four pairs (3,4) (3,4) (3,4) (3,4) (as 4=2x2). How can I modify the code in order to correctly handle such cases (hopefully still in O(n logn))? It seems the change should be made in if (s==sum) scope while updating first and last, but I just cannot make it right.
Note that: I know another way that can handle this correctly by using a hash table to record occurrences of each elements. Please suggest how to work through this problem without using a hash table.
Your array gets sorted as
Index: 0 1 2 3
Element: 3 3 4 4
When you find a sum, you increment first and decrement last, so each pair is only added once, not twice. Additionally, steping inward at any rate will always prevent you from getting both 1-3 and 0-2 (by index). You could make a preliminary pass to find duplicates, and use that information to add the pairs correctly:
vector<pair<int, int>> find_all_pairs_with_sum(int data[], int length, int sum)
{
assert(data && length>1);
vector<pair<int, int>> res;
int i;
sort(data, data+length);
// there is more than one way to skin this cat...
vector<pair<int, int>> vettedData;
for(i = 0; i < length; i++) {
if(i == 0 || vettedData[vettedData.size() - 1].first != data[i])
vettedData.push_back(make_pair(data[i], 1));
else
vettedData[vettedData.size() - 1].second++;
}
int first = 0;
int last = vettedData.size() - 1;
while (first < last)
{
int s = vettedData[first].first + vettedData[last].first;
if (s == sum)
{
int iterations = vettedData[first].second * vettedData[last].second;
for(i = 0; i < iterations; i++)
res.push_back(make_pair(vettedData[first].first, vettedData[last].first));
++first;
--last;
}
else
{
if (s < sum)
++first;
else
--last;
}
}
return res;
}
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 ");
}