Nth number of fibonacci - python

I am learning python. I am working on printing the Nth number of the Fibonacci sequence. I am reading a solution but I don't understand it. Could someone please explain how this solution works. I don't understand why it is recursively returning the next term and the current term? Shouldn't it recursively add the previous two terms? Where is terms defined as a list? Thanks for any help.
def fib(N):
"""
Recursively return the next term and the current term in the Fibonacci
sequence.
"""
if N == 1:
return [1, 0]
else:
terms = fib(N - 1)
terms = [terms[0] + terms[1], terms[0]]
return terms
def validate_positive_integer():
"""
Ask the user for input and only return when a positive integer under
500 is given.
"""
while True:
s = raw_input("Which term in the Fibonacci sequence you want to see? ")
try:
N = int(s)
if N >= 500:
print "Enter a number smaller than 500."
elif N > 0:
return N
else:
print "Enter a positive integer."
except ValueError:
print "Enter a positive integer."
def main():
N = validate_positive_integer()
print fib(N)[1]
if __name__ == "__main__":
main()

If you let F(n) denote the nth Fibonacci number, you'll see that fib(n) returns both F(n+1) and F(n). That gives you the desired Fibonacci number as well as precomputing the value that fib(n+1) will need to return F(n+2) and F(n+1).

terms is being defined as a list here, terms = [terms[0] + terms[1], terms[0], using the values from terms = fib(N - 1). Since the sequence is defined as the sum of the previous two terms, the two previously returned terms are added. Comment any more questions here

Related

Function to generate a palindrome

I have this following that I can't seem to solve correctly.
I have to write a function that takes a positive integer n as an input and checks if it is a palindrome (a number that's the same forward and backward). If it is, I have to return this number. If it isn't, I have to calculate the sum of the original number with the reversed number. This step is repeated until the result is a palindrome. This is the code I have so far:
x = input("Enter a positive integer: ")
def generate_palindrome(n):
if n == n[::-1]:
return n
else:
while n != n[::-1]:
r = n[::-1]
int(n) += int(r)
return n
generate_palindrome(x)
Of course this returns an error, since int(n) += int(r) is not possible. However, when not using int, it adds it as a string and that's also incorrect.
I'm not sure how far I'm off with the solution. How can I implement this correctly?
You are close. You just need another variable for the integer version of your string.Then just be clear which holds a string and which holds an integer:
def generate_palindrome(n):
if n == n[::-1]:
return n
else:
while n != n[::-1]: # n needs to be a string for this to work
r = int(n[::-1]) # r and s need to be numbers for correct addition
s = int(n)
n = str(r + s) # n needs to still be a string for the next loop iteration
return n
generate_palindrome("989")
# '989'
generate_palindrome("98")
# '8813200023188'
FWIW, I don't know that this is always guaranteed to return a reasonably sized number for every input. For example, I gave up on generate_palindrome("5798").

Python Programming involving Side Effects

I'm new to this so I apologize for any of my mistakes.
This is my code:
def main():
global user_input
user_input = [0,1,2]
final = fibonacci(user_input)
return final
def append_fibonacci(integer_list):
new_list = []
while integer_list[1] < 40:
integer_list[0], integer_list[1] = integer_list[1], integer_list[0]+integer_list[1]
new_list.append(integer_list[0])
return(new_list)
def fibonacci(max):
final = append_fibonacci(max)
print("Enter a non-negative integer >")
print("The Fibonacci series starts with:",final)
My error is the outcome only prints:
The Fibonacci series starts with: [1, 1, 2, 3, 5, 8, 13, 21, 34]
When it's suppose to print whatever other inputs (such as inputs: 8 / outputs: The Fibonacci series starts with: [1, 1, 2, 3, 5, 8] , inputs: 0 / outputs: The Fibonacci series starts with: [], inputs: 1 / Output: The Fibonacci series starts with: [1, 1] & inputs: six / Output: six is not a non-negative integer ).
I'm unsure if and where to use the (if, else statements) and if to check if it (.isdigit) or (isinstance, str).
Can someone help me or give me the answer? Thank you for your time in assisting me.
This is the question below.
The main function must input a string. If the string does not represent a non-negative integer, then it should print a warning message. If it does represent a non-negative integer, then it should call the fibonacci function to create the list of Fibonacci numbers that are less than or equal to the non-negative integer and output this list. The fibonacci function should call the append_fibonacci function multiple times to create the Fibonacci list.
If you use a function from an imported module in your function, you must import that module inside your function.
The first problem is with this statement while integer_list[1] < 40. Independent of the input you pass to the function it will output Fibonacci numbers less than 40. Second problem is the user_input list you pass through functions which is completely unnecessary. You just need to pass max number and your program will output Fibonacci numbers less than or equal to max. Third problem is you do not have a mechanism to check whether the input is a valid non-negative integer.
Here is the code:
def main():
_max = ""
while not _max.isnumeric():
_max = input("Enter a non-negative integer >")
_max = int(_max)
final = append_fibonacci(max)
print("The Fibonacci series starts with:",final)
return final
def append_fibonacci(_max):
if _max==0:
return []
fibonacci = []
x=1
y=1
while y <= _max:
x, y = y, x+y
fibonaccis.append(x)
return fibonacci
main()
Get input from users, you should use input() method. In main() function, user_input = input("Enter a non-negative integer >") will work. Also avoid using global variables. You don't need input variable as a global variable in this code, simply delete that line.
Use int() to check if the input is integer or not. You can handle the error message using try...except. Use if...else to check if the number negative or not.
Your code should look something like this:
def main():
user_input = input("Enter a non-negative integer > ")
try:
if int(user_input) < 0:
print('{} is not a non-negative integer'.format(user_input))
else:
final = fibonacci(int(user_input))
print("The Fibonacci series integer_lists with: ", final)
except ValueError:
print('"{}" is not a non-negative integer'.format(user_input))
def append_fibonacci(integer_list):
if len(integer_list) < 2:
integer_list.append(1)
else:
integer_list.append(integer_list[-1] + integer_list[-2])
return integer_list
def fibonacci(max):
integer_list = []
if max == 0:
return integer_list
else:
while len(integer_list) < 2 or integer_list[-1] + integer_list[-2] <= max:
integer_list = append_fibonacci(integer_list)
return integer_list
def main():
user_input = input("Enter a non-negative integer >")
try:
if int(user_input) < 0:
print('{} is not a non-negative integer'.format(user_input))
else:
final = fibonacci(int(user_input))
print("The Fibonacci series starts with:", final)
except ValueError:
print('{} is not a non-negative integer'.format(user_input))
def append_fibonacci(integer_list):
if len(integer_list) < 2:
integer_list.append(1)
else:
integer_list.append(integer_list[-1] + integer_list[-2])
return integer_list
def fibonacci(max):
integer_list = []
if max == 0:
return integer_list
else:
while len(integer_list) < 2 or integer_list[-1] + integer_list[-2] <= max:
integer_list = append_fibonacci(integer_list)
return integer_list

How can I display all numbers in range 0-N that are "super numbers"

The program asks the user for a number N.
The program is supposed to displays all numbers in range 0-N that are "super numbers".
Super number: is a number such that the sum of the factorials of its
digits equals the number.
Examples:
12 != 1! + 2! = 1 + 2 = 3 (it's not super)
145 = 1! + 4! + 5! = 1 + 24 + 120 (is super)
The part I seem to be stuck at is when the program displays all numbers in range 0-N that are "super numbers". I have concluded I need a loop in order to solve this, but I do not know how to go about it. So, for example, the program is supposed to read all the numbers from 0-50 and whenever the number is super it displays it. So it only displays 1 and 2 since they are considered super
enter integer: 50
2 is super
1 is super
I have written two functions; the first is a regular factorial program, and the second is a program that sums the factorials of the digits:
number = int(input ("enter integer: "))
def factorial (n):
result = 1
i = n * (n-1)
while n >= 1:
result = result * n
n = n-1
return result
#print(factorial(number))
def breakdown (n):
breakdown_num = 0
remainder = 0
if n < 10:
breakdown_num += factorial(n)
return breakdown_num
else:
while n > 10:
digit = n % 10
remainder = n // 10
breakdown_num += factorial(digit)
#print (str(digit))
#print(str(breakdown_num))
n = remainder
if n < 10 :
#print (str(remainder))
breakdown_num += factorial(remainder)
#print (str(breakdown_num))
return breakdown_num
#print(breakdown(number))
if (breakdown(number)) == number:
print(str(number)+ " is super")
Existing answers already show how to do the final loop to tie your functions together. Alternatively, you can also make use of more builtin functions and libraries, like sum, or math.factorial, and for getting the digits, you can just iterate the characters in the number's string representation.
This way, the problem can be solved in a single line of code (though it might be better to move the is-super check to a separate function).
def issuper(n):
return sum(math.factorial(int(d)) for d in str(n)) == n
N = 1000
res = [n for n in range(1, N+1) if issuper(n)]
# [1, 2, 145]
First I would slightly change how main code is executed, by moving main parts to if __name__ == '__main__', which will execute after running this .py as main file:
if __name__ == '__main__':
number = int(input ("enter integer: "))
if (breakdown(number)) == number:
print(str(number)+ " is super")
After that it seems much clearer what you should do to loop over numbers, so instead of above it would be:
if __name__ == '__main__':
number = int(input ("enter integer: "))
for i in range(number+1):
if (breakdown(i)) == i:
print(str(i)+ " is super")
Example input and output:
enter integer: 500
1 is super
2 is super
145 is super
Small advice - you don't need to call str() in print() - int will be shown the same way anyway.
I haven't done much Python in a long time but I tried my own attempt at solving this problem which I think is more readable. For what it's worth, I'm assuming when you say "displays all numbers in range 0-N" it's an exclusive upper-bound, but it's easy to make it an inclusive upper-bound if I'm wrong.
import math
def digits(n):
return (int(d) for d in str(n))
def is_super(n):
return sum(math.factorial(d) for d in digits(n)) == n
def supers_in_range(n):
return (x for x in range(n) if is_super(x))
print(list(supers_in_range(150))) # [1, 2, 145]
I would create a lookup function that tells you the factorial of a single digit number. Reason being - for 888888 you would recompute the factorial of 8 6 times - looking them up in a dict is much faster.
Add a second function that checks if a number isSuper() and then print all that are super:
# Lookup table for single digit "strings" as well as digit - no need to use a recursing
# computation for every single digit all the time - just precompute them:
faks = {0:1}
for i in range(10):
faks.setdefault(i,faks.get(i-1,1)*i) # add the "integer" digit as key
faks.setdefault(str(i), faks [i]) # add the "string" key as well
def fakN(n):
"""Returns the faktorial of a single digit number"""
if n in faks:
return faks[n]
raise ValueError("Not a single digit number")
def isSuper(number):
"Checks if the sum of each digits faktorial is the same as the whole number"
return sum(fakN(n) for n in str(number)) == number
for k in range(1000):
if isSuper(k):
print(k)
Output:
1
2
145
Use range.
for i in range(number): # This iterates over [0, N)
if (breakdown(number)) == number:
print(str(number)+ " is super")
If you want to include number N as well, write as range(number + 1).
Not quite sure about what you are asking for. From the two functions you write, it seems you have solid knowledge about Python programming. But from your question, you don't even know how to write a simple loop.
By only answering your question, what you need in your main function is:
for i in range(0,number+1):
if (breakdown(i)) == i:
print(str(i)+ " is super")
import math
def get(n):
for i in range(n):
l1 = list(str(i))
v = 0
for j in l1:
v += math.factorial(int(j))
if v == i:
print(i)
This will print all the super numbers under n.
>>> get(400000)
1
2
145
40585
I dont know how efficient the code is but it does produce the desired result :
def facto():
minr=int(input('enter the minimum range :')) #asking minimum range
maxr=int(input('enter the range maximum range :')) #asking maximum range
i=minr
while i <= maxr :
l2=[]
k=str(i)
k=list(k) #if i=[1,4,5]
for n in k: #taking each element
fact=1
while int(n) > 0: #finding factorial of each element
n=int(n)
fact=fact*n
n=n-1
l2.append(fact) #keeping factorial of each element eg : [1,24,120]
total=sum(l2) # taking the sum of l2 list eg 1+24+120 = 145
if total==i: #checking if sum is equal to the present value of i.145=145
print(total) # if sum = present value of i than print the number
i=int(i)
i=i+1
facto()
input : minr =0 , maxr=99999
output :
1
2
145
40585

Next higher prime and palindrome number

Is there any suggestion on solving next higher prime and palindrome number from a given int.
Here is the snippet I am trying but its a kind of slow, please suggest if you ve any good algorithm that i can test.
#!/usr/bin/python
def next_higher(n):
while True:
s = str(n)
if not any([n % i == 0 \
for i in range(2, int(n**0.5))]) and s == s[::-1]:
return n
n = n + 1
print next_higher(2004)
print next_higher(20)
Output:
10201
101
Updated code testing for palindrome before prime. much faster than my previous code.
I am implementing the suggestion from user2357112.
#!/usr/bin/python
def next_higher(n):
while True:
s = str(n)
if s == s[::-1]:
if not any([n % i == 0 \
for i in range(2, int(n**0.5))]):
return n
n = n + 1
print next_higher(2004111)
print next_higher(2004)
print next_higher(2004)
print next_higher(20)
There are quite a few optimizations you could do:
Like user2357.. suggested in the comments, test palindromeness first, and then check if the number is prime, since prime check is more expensive.
You don't need to check even number divisibility once you check is the number is divisible by 2. So you can change it to [2] + range(3, int(n**0.5) + 1, 2) to check only odd numbers after 2. (Also you need to do sqrt + 1 like I mentioned in the comments)
You should use () instead of []. [] generates the entire list of factors first and only then checks for any. If you use (), it creates a generator, so it stops as soon as a True value is found without calculating the entire list.
You should also use xrange instead of range for the same reason (xrange gives a generator, range gives a list)
You can use the Sieve of Eratosthenes algorithm to significantly reduce the time taken for prime number check.
You can also see if the palindrome check can be made faster. You can actually skip a whole lot of numbers instead of doing just + 1 each time.
Here is a version with most of these optimizations except the last two:
def next_higher(n):
if n % 2 == 0:
n = n - 1
while True:
n = n + 2
s = str(n)
if s == s[::-1]:
if not any((n % i == 0 for i in xrange(3, int(n**0.5) + 1, 2))):
return n
This should be pretty fast for your needs I believe. But you can do the last 2 optimizations to make it much more faster if you want.
Other than what has already been suggested,
What I suggest is that you first get the first palindrome number that is just higher than the given integer.
You can do this by trying to match the centre digits outwards.
Also, you should only check for numbers with odd number of digits, since if a number has even number of digits and it is a palindrome, then it will always be divisible by 11 and cannot be prime.
Once you get the first palindrome number that has odd number of digits and that is just higher than the current number, test it for primality and find the next palindrome number higher than this one.
You can do this by incrementing the centre digit.
Keep doing this till it rolls over to zero. In that case start incrementing the two neighbouring digits.
Continue, till you reach a prime number.
I tried optimizing the palindrome check i.e to find odd palindrome's.
Since the first digit should be odd number, i focused on that part.
Here's the code below with the assumptions its greater than 1 digit.
def next_odd_palindrome(n):
"""to check the next odd palindrome number"""
if n%2==0:
n=n-1
while True:
n=n+2
s = str(n)
if int(s[0])%2==0:
n = int(str(int(s[0])+1)+ s[1:])
s = str(n)
if s==s[::-1]:
return n
let me know if anything wrong.
Just for the fun of it, I implemented all optimizations by Hari Shankar and Abhishek Bansal.
It first finds the higher odd length palindrome, then increment the palindrome in a way that keeps its palindromity. Then checks each number using prime numbers calculated by Sieve method in the beginning.
This can process up to n=10^14 (can be higher if you increase the CACHE size) under 1 second in my computer =D
primes = []
CACHE = int(10**7) # Cache size for Sieve
# Custom class for immediate printing of output
import sys
class Unbuf:
def __init__(self,stream):
self.stream = stream
def write(self,data):
self.stream.write(data)
self.stream.flush()
sys.stdout = Unbuf(sys.stdout)
def sieve():
global primes
is_prime = [False,False]+([True]*(CACHE-1))
for i in xrange(2,int(CACHE**0.5)):
if is_prime[i]:
is_prime[i*i::i] = [False]*((CACHE-i*i+i)/i)
primes = [num for num, bool_prime in enumerate(is_prime) if bool_prime]
def is_prime(n):
"""Checks whether n is prime"""
global primes
if n<2:
return False
if n==2:
return True
for prime in primes:
if prime>n**0.5+1:
return True
if n%prime==0:
return False
# For the case that the number is bigger than the square of our largest prime
for num in xrange(primes[-1]+2,n**0.5+1,2):
if n%num==0:
return False
return True
def next_higher_odd_length_palindrome(n):
n = str(n)
if len(n)%2==0: # Even length, take the smallest odd length (10(00)*1)
n = '1'+('0'*(len(n)-1))+'1'
else:
middle_idx = len(n)/2
left = int(n[:middle_idx+1])
left_cmp = n[middle_idx::-1]
right_cmp = n[middle_idx:]
# If mirroring left part to right part
# makes the number smaller or equal, then
if right_cmp>=left_cmp:
# Increase the left half number
left = left+1
# Mirror left part to the right part
n = str(left)+str(left)[-2::-1]
return n
def next_higher(n):
if n<=1:
return 2
# Ensure the number is a palindrome of odd length
n = next_higher_odd_length_palindrome(n)
while True:
if is_prime(int(n)):
return int(n)
n = next_higher_odd_length_palindrome(n)
if int(n[0])%2==0:
new_lead = str(int(n[0])+1)
n = new_lead+n[1:-1]+new_lead
import time
print 'Sieving...',
start_time = time.time()
sieve()
print 'Done in %.3fs' % (time.time() - start_time)
print next_higher(2004111)
print next_higher(2004)
print next_higher(20)
while True:
n = int(raw_input('Enter n: '))
start_time = time.time()
result = next_higher(n)
print 'Next higher prime palindrome: %d (calculated in %.3fs)' % (result, time.time() - start_time)
Which in my computer gives this output:
Sieving... Done in 1.444s
3007003
10301
101
Enter n: 1999999999
Next higher prime palindrome: 10000500001 (calculated in 0.004s)
Enter n: 1999999999999
Next higher prime palindrome: 3000002000003 (calculated in 0.051s)
Enter n: 1000000000000
Next higher prime palindrome: 1000008000001 (calculated in 0.030s)
Enter n:

Determining whether a number is prime or not

I know it's been discussed many times; I've read it, but somehow I can't get it.
I want to write a program that determines if the entered number is prime or not.
One of the implementations I found somewhere on the Internet:
from math import *
def main():
n = abs(input("Enter a number: "))
i = 2
msg = 'is a prime number.'
while i <= sqrt(n):
if n % i == 0:
msg = 'is not a prime number.'
i = i + 1
print n, msg
main()
A couple of questions here:
In the above, what is i, and why does it have a starting value of 2?
What does i = i + 1 do in this program?
How does the interpreter know when to print 'is a prime number.' even though it is out of the body loop?
A prime number is a number that's only divisible by 1 and itself. The method it's using is to try dividing your candidate number n by every other number from 2 up to itself; however if any number i is a divisor of your number n then so is n / i and at least one of them is less than or equal to sqrt(n) therefore we need only test up to sqrt(n) inclusive. In practice we need only test the divisors that are actually prime themselves but since we don't have a list of primes to hand we'll test every one.
what in the above i is? and why it got a 2 starting value?
i is the potential factor of n we're testing. It starts with 2 because we don't care if 1 divides n (and trivially it will) because the prime definition allows / expects that.
what is the i = i + 1 statement, in this concrete example for? Can't see its use in the program.
It's incrementing the i value at the end of the loop defined by the while i <= sqrt(n); it means we advance i to test the next candidate divisor of n.
and finally, how python knows when to print 'is a prime number.' although it is out of the body loop?
We initialise msg to "is a prime number" and if we find any divisor then we change it to "is not a prime number" inside the loop. If the loop doesn't find a divisor, or if the loop never runs, we'll use the initial value we set which is "is a prime number". Incidentally you could break out of the loop when you find a divisor; there's no point carrying on the test after that.
As another aside you probably want to compute sqrt(n) outside the while and store than in a variable to use in the while - you may be recalculating the square root for every iteration, which is relatively expensive.
I've added comments on the sides to explain what each line does:
from math import * # imports everything from the math module
def main():
n = abs(input("Enter a number: ")) # gets input from the user
i = 2 # starts off at 2 because all input is divisble by 1
msg = 'is a prime number.' # the message is initially set
while i <= sqrt(n):
if n % i == 0: # if 'i' divides evenly into n
msg = 'is not a prime number.' # only set if it isn't a prime
i = i + 1 # increases 'i' by 1 so it can check every value up to the square-root of 'n' (to see if it divides evenly)
print n, msg
main()
The program has to go through every value of i (up to the square-root of n) so that every possible factor is checked.
This is sort of a rough-prime checker, and inefficient for large numbers that aren't prime:
If the input was a number like 1234567890, it will iterate through every number up to the square root of that number, which is 35147 (rounded up).
Using return statements break the loop, so the first number you check, 2, it is declared not prime since it is evenly divisible by 2.
By using return, it will stop the function, and save you 35,146 calculations. That isn't a massive number (for computers, at least) but it's still more memory-efficient and takes less time.
def isPrime(n):
'''Checks if 'n' is prime.'''
from math import sqrt
if n == 0 or n == 1:
return False
else:
for check in range(2, int(sqrt(n))+1):
if n % check == 0: return False
return True

Categories