67 Fibonacci issues

Back to General discussions forum

FoxDie     2016-03-21 17:13:36

Hey there. I have been trying to solve this problem, but I am having issues. It works for the example but not the set given to solve.

Also, are there any methods that I can use to help me use the huge numbers? I can only go to 79 at the moment as Python starts giving me L numbers after this point. If someone could direct me to a source that would be awesome.

Edit:I have discovered that for some Reason python takes a -1 to the value at 80 index when it attaches L to the end. No idea why. I managed to solve it, but I feel like I cheated somehow. After retrying my code again it passed. Maybe I lucked out with the numbers.

Matthew Cole     2016-03-21 20:36:58

Hi FoxDie!

Here are some suggestions for you to make your code more Pythonic:

Input

I'm presuming that you format the input from the page manually. For example, the sample input is

5
610
34
0
1346269
10946

Which you then paste into the interpreter as 610 34 0 1346269 10946

If that's the case, try replacing everything until #print ("This is your array: " + str(array)) with this block of code:

import sys

num_to_process = int(input())
array = [int(x) for x in sys.stdin]

You'll find it does exactly the same thing, but is more Pythonic and doesn't require you to cut and paste!

Constructing the Fibonacci sequence

There are actually a lot of ways to do this (check out this StackOverflow question). The way you did it is fine, so we'll go with that. But let me show you some more elegant ways to do it using built-in functions, and slicing.

  • len() gives you the length of a sequence. Since you want to continue the while-loop until there are 1000 items in Fibbo, this will be helpful to measure the number of items in Fibbo already generated. You won't need the variable gen anymore!
  • slicing is one of the common sequence operations. We can use a slice to get just the last two elements of a sequence, forming a new sequence.
  • sum() gives you the sum of a sequence. When we combine it with a slice, we can get the sum of the last two elements currently in the Fibbo list!

So now, your first while-loop becomes just two lines, and you can delete the gen, count and a variables!

while len(Fibbo) < 1000:
    Fibbo.append( sum(Fibbo[-2:]) )

Finding index of a variable in the sequence

What you're doing is such a common problem that the Python language has a built-in function that will do the search on your behalf: sequence.index. Basically, you take the sequence you want searched, use dot-notation to access its index function, and provide the value you're searching for. Thus, your second while-loop can become a one line list comprehension!

index = [Fibbo.index(item) for item in Array]

There are three important things to know about the index function:

  • It's zero based. Searching for the first item in the sequence will return 0, searching for the second returns 1,... etc.
  • You can use the optional arguments i and j to specify a slice to search.
  • If the item isn't found, it raises a ValueError exception.

I'll reuse your error checking message to catch a possible ValueError and turn the comprehension into this:

try:
    index = [Fibbo.index(item) for item in array]
except ValueError as ve:
    print("I broke :[ " + str(item) + ve)

The mysterious L numbers!

What you're seeing might be Python2's representation of the long numeric type.

Python2 adopts C's limitations on the maximum magnitude of an unsigned integer as pow(2,32) - 1, or 4294967295. The 47th Fibonacci number is 2971215073, which fits. But the 48th Fibonacci number is 4807526976, which doesn't fit (let alone the 80th Fibonacci, 23416728348467685 !). So your interpreter is displaying those long integers with an L after the number, indicating that it is being store with long precision. If you switch to Python3, this should go away because Python3 stores all numbers with arbitrary precision.

FoxDie     2016-03-24 14:24:16

I have been using trinket.io for all my programs thus far. I have been teaching myself very slowly during my lunch breaks. I downloaded python.org software today. I tried using your code:

import sys

num_to_process = int(input())
array = [int(x) for x in sys.stdin]

but i keep getting the error

ValueError: invalid literal for int() with base 10: ''

Honestly, I am not even sure how sys.stdin works so it is probably affecting how I am inputing data. Also, should I get an IDE?

What does 've' do in

except ValueError as ve:         

Thanks for helping me thus far by the way.

FoxDie     2016-03-24 15:52:07

Update: When i post into trinket.io it autoformatted the newlines for me apparently.

Matthew Cole     2016-03-25 02:47:37

The ve in except ValueError as ve: allows us to capture the thrown exception for later use. Consider entering the following code in a Python3 environment:

#!/usr/bin/python3

try:
    raise ValueError("Oh no! This is a value error... ")
except ValueError as ve:
    print(ve, "so we can catch it and maybe try to do something about it.\n")
    raise Exception("... or just give up and raise it again as a different type of exception.") from ve
finally:
    print("No matter what exceptions happen, this gets executed before the interpreter begins Traceback.\n")

Go ahead and try it!

As you can see, we initially cause a ValueError exception to be raised. Usually, you wouldn't write code that intentionally causes an exception, but this is to show a point. We add a pithy message so you can see where it goes too.

In the except block, we catch that exception. In real applications, you'd consider some sort of logic that handles the exception by adjusting the data that caused the exception or you might adjust the program's control flow. In this case, the way we handle the code that caused the exception is to print it out.

Then we raise the same exception again as a different type of exception. Maybe in a real application, you tried to fix the problem automatically but couldn't. So you fail loudly for someone else (or yourself) to fix farther on downstream. Using the keyword from allows us to take the information from the original exception, which we stored in ve! If we hadn't stored the information from the original exception using the as keyword, it'd be lost now and we wouldn't be able to pass it on.

One important note is that there's nothing particularly special about ve. It's just a variable name (I tend to name my exception variables as acronyms of the exceptions they cover. IndexError is ie, Exception is e, etc. You can name them anything you want that isn't a reserved keyword or an existing variable and they'll work.

If you want to learn more about exception handling, check out this for Python2 and this for Python3

Matthew Cole     2016-03-25 02:56:38

As for the IDE question:

Yes! Get an IDE! Especially if you're going to be doing more coding besides here on Code Abbey.

Your follow-on question is probably going to be "well, which one?" To answer that question, we need to know what operating system you use.

Personally speaking, I use CodeRunner for Mac OSX on my personal machines. I use GNU Emacs with python-mode and the ElPy IDE on my Linux lab machines at school.

I've also heard great things about other IDEs too. This page has a list of great IDEs. I've personally used Komodo, PyCharm, PyDev, IDLE and XCode. Of those, IDLE should've come with the package you received from Python.org upon installation, but it's also the least featured of the bunch.

Please login and solve 5 problems to be able to post at forum