views:

674

answers:

9

I was asked the following question in an interview:

Is there any way in which Fibonacci series can be generated using only 1 variable ?

I didn't know what to answer. What should I have said?

+5  A: 

Yes, but you still need to remember 2 values. You could take a 64-bit variable and use it as 2 32-bit vars.

pablochan
can we do it without using Recursion ?
kantu
My answer doesn't use recursion.
pablochan
Your answer has also twisted the definition of 'one variable'. Multiplexing two values into a block of memory that you happen to have only have one explicit pointer to isn't *precisely* 'one' variable, any more than an array is 'one' variable. But given how tricksy the question is in the first place, perhaps your solution would have been a good place to start a conversation.
Alex Feinman
What about the whole stack of variables the recursive solution uses ;] ?
pablochan
@Alex, Using recusion also twists the defintion of one variable as it keeps the value of the Left Hand Side fib while it calculates the Right Hand Side fib value. There is actually a saved value for each level of recusion.
Peter Lawrey
@Peter, pablochan, I totally agree! Making use of multiple scopes is many variables, though slightly less explicit than this. I think the 'pure' answer is the one above using phi.
Alex Feinman
+10  A: 

Sure, using recursion:

public class Test {

    public static int fib(int n) {
        return n < 2 ? n : fib(n-1) + fib(n-2);
    }

    public static void main(String[] args) {
        for(int i = 0; i <= 10; i++) {
            System.out.print(fib(i)+", ");
        }
        System.out.println("...");
    }
}

// 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...
Bart Kiers
I was posting the same code... if it's for a homework (pure theory), it's ok, but I wouldn't use exponential recursion in production code. :-)
G B
can it be done without using recursion ? i was asked this in an interview today and was dumb struck came home and did some googling but couldnt find anything like that
kantu
@G B: I wouldn't know in what production code one needs to calculate the Fibonacci sequence! :)
Bart Kiers
@kantu, checkout @Mark Byers' answer. Besides, did the interviewer said you couldn't make use of recursion? If so, please include that in your original question.
Bart Kiers
@Bart K.: I would say a recursive version uses at least one variable for each level of recursion (not to mention all the other registers stacked). The only approach which really only uses one variable would be to convert n to F(n) by multiplying by ln(phi) and taking exp(n), and rounding/tweaking suitably, outputting the value, and then converting F(n) to n by taking ln(F), multiplying by 1/ln(phi), applying a suitable rounding tweak, and then adding 1. Seems more practical to just use three variables, though.
supercat
@supercat, I would say: I *see* just one variable. But really, who cares?
Bart Kiers
+4  A: 

The answer is "yes", but maybe you could be more specific.

The first example I could think of, using double recursion (that leads to an exponential complexity, not recommended):

int fib(int a) {
  if (a < 2) {
    return 1
  } else {
    return fib(a-1) + fib(a-2);
  }
}

Assuming a >= 0 (you could add a check for that).

(Edit - used the wrong convention of F(0) undefined, F(1) = 1)

G B
+20  A: 

Yes, you can used the closed-form expression:

where

You can calculate the expression using a double and round the result to the nearest integer. Because of the finite precision of floating point arithmetic this formula will give a wrong answer for large enough n, but I think it will work in the case when the result fits into a Java 32-bit integer.

Mark Byers
:) ` ` ` ` ` ` ` `
Bart Kiers
Showoff :-----)
Esko
+1 for magical math :D
pablochan
my god could you please explain it in lay man terms
kantu
@kantu: an explanation of this formula would belong in mathoverflow instead.
polygenelubricants
@kantu: the link leads to wikipedia explaining it, or look at my answer. (which uses the same math, but with a formula less intimidating)
Daniel Martin
@polygenelubricants: An explanation of this formula is too basic for mathoverflow.
Moron
@moron: agreed, though it'd be still fun to do with pretty latex imo :) on MO it'd be kind of like showing pro hockey players how to do a hockey stop.
ldog
@ldog: It is completely appropriate for math.stackexchange.com , which also has latex support.
Moron
+11  A: 

Up to a point, yes (though in C, you could convert it to Java - it would look much uglier).

#include <stdio.h>
#include <stdlib.h>

int main (void) {
    unsigned long i = 1;
    printf ("0\n");
    while (((i & 0xffff0000) >> 16) + (i & 0xffff) <= 0xffff) {
        printf ("%d\n", i & 0xffff);
        i = ((i & 0xffff) << 16) | ((i >> 16) + (i & 0xffff));
    }
    return 0;
}

which produces:

0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
28657

:-)

The real question, of course, is: Why would you want to?

paxdiablo
WoW :-).........
Prasoon Saurav
I will have to find a datatype with size = 8 Bytes to generate Fibonacci for an int :)..
Aamir
@Aamir, just use a struct with as many fields as you want, or even an array of two ints). That's still technically declaring one variable :-)
paxdiablo
+3  A: 

After the initial 1 1, it is in theory possible to generate one value from the previous one (until machine precision comes around to bite you) via:

f = Math.round(f * PHI)

where PHI is the constant defined in another comment:

static final double PHI = (1 + Math.sqrt(5))/2;

Daniel Martin
+3  A: 

You can always do something like this:

    String theOneVar = "100;0;1";
    while (true) {
        if (theOneVar.split(";")[0].equals("0")) break;
        System.out.println(theOneVar.split(";")[1]);
        theOneVar = String.format("%s;%s;%s",
            Integer.parseInt(theOneVar.split(";")[0]) - 1,
            theOneVar.split(";")[2],
            new BigInteger(theOneVar.split(";")[1]).add(
                new BigInteger(theOneVar.split(";")[2])
            )
        );
    }

This prints (as seen on ideone.com):

0
1
1
2
3
5
8
13
:
:
83621143489848422977
135301852344706746049
218922995834555169026

This uses only one explicit variable, and it's essentially a linear non-recursive algorithm. It needs to be said that this is an abuse of String, though.

polygenelubricants
Ach mein Gott! I'm going to vote this up just because it gave me a headache :-)
paxdiablo
@paxdiablo: I believe others have suggested this, and I haven't carefully examined your answer to see if it's essentially the same, but basically the "one variable" notion is abused to essentially store multiple things. I think someone mentioned two 32-bit numbers in a 64-bit variable, etc. Here we essentially have `"int;BigInteger;BigInteger"` in a `String`.
polygenelubricants
Creative solution! :-)
Jesper
+1  A: 

Here's an example in C#. Shows the first 100 terms. The ratio between terms in the Fibonacci approaches the golden ratio (1.618033...), so a single variable approach simply requires a multiplication by a constant for each term.

Yay math!

double fib = 1;
for (int i = 0; i < 100; i++)
{
    Console.WriteLine("" + fib);
    fib = Math.Round(fib *= 1.6180339887d);
}
Andy Holt
Except you need to add an extra `WriteLine` outside the loop to write the first "1" since the series usually begins with 1, 1, 2, 3, ...
Daniel Martin
Yep, you could hard code that in for properness. Also, I guess the index variable "i" also counts as a variable, so that's cheating. You could however use a while loop instead and test that "fib" is lower than a certain value.
Andy Holt
+2  A: 

So this is evil, but:

static String fibRecord = "x;";

static int nextFib() {
  try {
    return fibRecord.indexOf(';');
  } finally {
    fibRecord = fibRecord.replaceAll("(x*);(x*)", "$1$2;$1");
  }
}

public static void main(String[] ignored) {
  for (int i=0; i < 30; i++) {
    System.out.println(nextFib());
  }
}

My machine here starts to fall over around the 38th Fibonacci number.

Daniel Martin
+1; evil GENIUS that is...
polygenelubricants