Finding the fibonacci numbers in a certain range using python - python-2.7

I am trying to write a function in python that returns a list of all the fibonacci numbers in a certain range but my code wont work it simply returns [0]. What is the problem?
from math import sqrt
def F(n):
return int(((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5)))
def Frange(x):
A = [0]
while max(A) < x:
H = 1
for i in range(H):
A.append(F(i))
H = H+1
return A

You set H = 1 as the first statement in your while loop; so every time you enter the for loop, H = 1 and you'll only get the Fibonacci number for n=0
You need to set H = 1 outside the while loop:
def Frange(x):
A = [0]
H = 1
while max(A) < x:
for i in range(H):
A.append(F(i))
H = H+1
return A
You could have solved this yourself very easily by printing various values inside the loops, such as print H.

I found another error and the improved code is:
from math import sqrt
def F(n):
return int(((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5)))
def Frange2(x):
A = [0]
H = 1
while max(A) < x:
if F(H) < x:
A.append(F(H))
else:
break
H = H+1
return A

The fastest and most popular and uncomplicated solution to calculating a list of fibonacci numbers in a range is
def fib3(n): #FASTEST YET
fibs= [0,1] #list from bottom up
for i in range(2, n+1):
fibs.append(fibs[-1]+fibs[-2])
return fibs
This function stores the computed fibonacci numbers in a list and later uses them as 'cached' numbers to compute further.
Hope it helps!

Related

Summation of Equation Program

So basically I'm trying to make a program that will do equation for every value of nStart to nEnd. This is my code so far
def summation(nStart , nEnd , eqn):
sum = 0
while nStart - 1 != nEnd:
sum = sum + eqn
nStart += 1
return sum
print summation(1 , 5 , n + 1)
I get that n is not defined in the last line. I guess it's because I have n + 1 but how do I solve that? I tried making n = 0 but then that doesn't help because then eqn is just 1 and not an equation.
You could use a lambda function as an argument. For example:
def summation(start, end, eqn):
sum = 0
# Note that the *end* value will not be used, since range stops at *end-1*
for i in range(start, end):
sum+=eqn(i)
return sum
print summation(0,10,lambda x: x+1)
print summation(0,10,lambda x: x**2)
Will return:
55
285
Since
Hope this gives you a useful tool to explore and modify if it doesn't do exactly what you are after.

Wrong answer when calculating binomial coefficients using modified formula

I am trying to write a function to calculate the binomial coefficients using this formula:
The problem I am having is that I can not mange to get the correct answer. This is an example of two ways I have tried to write the function.
def binomial(n, i):
total = 0
for j in range(1, (n-i+1)):
n = float(n)
i = float(i)
j = float(j)
product = (i+j) / j
if total == 0:
total = product
else:
total = total * product
print '%.f' %total
or like this using numpy
import numpy as np
def binomial_np(n, i):
array = np.zeros(n-i+1)
for j in range(1, (n-i+1)):
s = float(j)
n = float(n)
i = float(i)
array[j] = (i+s)/s
array = array[1 : ]
array = np.prod(array)
print '%.f' %array
Both of the functions produces almost the correct result. After looking around a bit on the forum I did find some other examples that do produce the correct result, like this one from Python Binomial Coefficient
import math
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
if y == x:
print(1)
elif y == 1: # see georg's comment
print(x)
elif y > x: # will be executed only if y != 1 and y != x
print(0)
else: # will be executed only if y != 1 and y != x and x <= y
a = math.factorial(x)
b = math.factorial(y)
c = math.factorial(x-y) # that appears to be useful to get the correct result
div = a // (b * c)
print(div)
The real question I have from this is if there is something wrong with the way I have written the formulas, or if it just isnt possible to get the correct answer this way because of how float's and number of decimals work in Python. Hope someone can point me in the right direction on what I am doing wrong here.
The slight discrepancies seem to come from using floating point arithmetic. However, if you are sure that n and i are integers, there is no need at all for floating point values in your routine. You can just do
def binomial(n, i):
result = 1
for j in range(1, n-i+1):
result = result * (i+j) // j
return result
This works because the product of 2 consecutive numbers is divisible by 1*2, the product of 3 consecutive numbers is divisible by 1*2*3, ... the product of n-i consecutive numbers is divisible by (n-i)!. The calculations in the code above are ordered to that only integers result, so you get an exact answer. This because my code does not calculate (i+j)/j as your code does; it calculates result * (i+j) and only then divides by j. This code also does a fairly good job of keeping the integer values as small as possible, which should increase speed.
If course, if n or i is float rather than integer, this may not work. Also note this code does not check that 0 <= i <= n, which should be done.
I would indeed see float precision as the main problem here. You do floating point division, which means your integers may get rounded. I suggest you maintain the numerator and denominator as separate numbers, and do the division in the end. Or, if the numbers get too big using this approach, write some gcd computation and cancel common factors along the way. But only do integer divisions (//) to avoid loss of precision.

What is the most efficient way to find amicable numbers in python?

I've written code in Python to calculate sum of amicable numbers below 10000:
def amicable(a, b):
total = 0
result = 0
for i in range(1, a):
if a % i == 0:
total += i
for j in range(1, b):
if b % j == 0:
result += j
if total == b and result == a:
return True
return False
sum_of_amicables = 0
for m in range (1, 10001):
for n in range (1, 10001):
if amicable(m, n) == True and m != n:
sum_of_amicables = sum_of_amicables + m + n
Code is running more than 20 minutes in Python 2.7.11. Is it ok? How can I improve it?
optimized to O(n)
def sum_factors(n):
result = []
for i in xrange(1, int(n**0.5) + 1):
if n % i == 0:
result.extend([i, n//i])
return sum(set(result)-set([n]))
def amicable_pair(number):
result = []
for x in xrange(1,number+1):
y = sum_factors(x)
if sum_factors(y) == x and x != y:
result.append(tuple(sorted((x,y))))
return set(result)
run it
start = time.time()
print (amicable_pair(10000))
print time.time()-start
result
set([(2620, 2924), (220, 284), (6232, 6368), (1184, 1210), (5020, 5564)])
0.180204153061
takes only 0.2 seconds on macbook pro
Lets break down the code and improve the parts of code that is taking so much time.
1-
If you replace if amicable(m, n) == True and m != n: with if m != n and amicable(m, n) == True:, it will save you 10000 calls to amicable method (the most expensive method) for which m != n will be false.
2- In the amicable method you are looping 1 to n to find all the factors for both of the numbers. You need a better algorithm to find the factors. You can use the one mentioned here. It will reduce your O(n) complexity to O(sqrt(n)) for finding factors.
def factors(n):
return set(reduce(list.__add__,
([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))
Considering both the points above your code will be
def amicable(a, b):
if sum(factors(a) - {a}) == b and sum(factors(b) - {b}) == a:
return True
return False
sum_of_amicables = 0
for m in range (1, 10001):
for n in range (1, 10001):
if m!= n and amicable(m, n) == True:
sum_of_amicables = sum_of_amicables + m + n
This final code took 10 minutes to run for me, which is half the time you have mentioned.
I was further able to optimize it to 1:30 minutes by optimizing factors method.
There are 10000 * 10000 calls to factors method. And factors is called for each number 10000 times. That is, it calculates factors 10000 times for the same number. So we can optimize it by caching the results of previous factors calculation instead of calculating them at every call.
Here is how I modified factors to cache the results.
def factors(n, cache={}):
if cache.get(n) is not None:
return cache[n]
cache[n] = set(reduce(list.__add__,
([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))
return cache[n]
Full Code: (Runtime 1:30 minutes)
So the full and final code becomes
def factors(n, cache={}):
if cache.get(n) is not None:
return cache[n]
cache[n] = set(reduce(list.__add__,
([i, n//i] for i in range(1, int(n**0.5) + 1) if n % i == 0)))
return cache[n]
def amicable(a, b):
if sum(factors(a) - {a}) == b and sum(factors(b) - {b}) == a:
return True
return False
sum_of_amicables = 0
for m in range (1, 10001):
for n in range (1, 10001):
if m!= n and amicable(m, n) == True:
sum_of_amicables = sum_of_amicables + m + n
You can still further improve it.
Hint: sum is also called 10000 times for each number.
Note that you don't need to have a double loop. Just loop M from 1 to 10000,
factorize each M and calculate sum of divisors: S(M). Then check that N = S(M)-M has the same sum of divisors. This is a straight-forward algorithm derived from the definition of an amicable pair.
There are a lot of further tricks to optimize amicable pairs search. It's possible to find all amicable numbers below 1,000,000,000 in just a fraction of a second. Read this in-depth article, you can also check reference C++ code from that article.
Adding to the answer:
def sum_factors(self, n):
s = 1
for i in range(2, int(math.sqrt(n))+1):
if n % i == 0:
s += i
s += n/i
return s
def amicable_pair(self, number):
result = 0
for x in range(1,number+1):
y = self.sum_factors(x)
if self.sum_factors(y) == x and x != y:
result += x
return result
No need for sets or arrays. Improvinging storage and clarity.
#fetching two numbers from the user
num1=int(input("Enter first number"));
num2=int(input("enter the second number"));
fact1=[];
fact2=[];
factsum1=0;
factsum2=0;
#finding the factors of the both numbers
for i in range(1,num1):
if(num1%i==0):
fact1.append(i)
for j in range(1,num2):
if(num2%j==0):
fact2.append(j)
print ("factors of {} is {}".format(num1,fact1));
print ("factors of {} is {}".format(num2,fact2));
#add the elements in the list
for k in range(len(fact1)):
factsum1=factsum1+fact1[k]
for l in range(len(fact2)):
factsum2=factsum2+fact2[l]
print (factsum1);
print (factsum2);
#compare them
if(factsum1==num2 and factsum2==num1 ):
print "both are amicable";
else:
print "not amicable ";
this is my owm understanding of the concept
hi all read code and comments carefully you can easily understand
def amicable_number(number):
list_of_tuples=[]
amicable_pair=[]
for i in range(2,number+1): # in which range you want to find amicable
divisors = 1 # initialize the divisor
sum_of_divisors=0 #here we add the divisors
while divisors < i: # here we take one number and add their divisors
if i%divisors ==0: #checking condition of complete divison
sum_of_divisors += divisors
divisors += 1
list_of_tuples.append((i,sum_of_divisors)) #append that value and sum of there divisors
for i in list_of_tuples:
#with the help of these loops we find amicable with duplicacy
for j in list_of_tuples:
if i[0] == j[1] and i[1] == j[0] and j[0] != j[1]: #condition of amicable number
amicable_pair.append((j[0],i[0])) # append the amicable pair
# i write this for_loop for removing the duplicacy if i will mot use this for loop this
# be print both (x,y) and (y,x) but we need only one among them
for i in amicable_pair:
for j in amicable_pair[1:len(amicable_pair)]: #subscript the list
if i[0] == j[1]:
amicable_pair.remove(i) # remove the duplicacy
print('list of amicable pairs number are: \n',amicable_pair)
amicable_number(284) #call the function
Simple solution to find amicable numbers with loops
I found all the friendly pairs in 9 seconds using this algorithm:
sum_of, friendly, sum_them_all = 0, 0, 0
friendly_list = []
for k in range(1, 10001):
# Let's find the sum of divisors (k not included)
for l in range(1, k):
if k%l == 0:
sum_of += l
# Let's find the sum of divisors for previously found sum of divisors
for m in range(1, sum_of):
if sum_of%m == 0:
friendly += m
# If the sum of divisors of sum of divisors of the first number equals
# with the first number then we add it to the friendly list
if k == friendly and k != sum_of:
if [sum_of, k] in friendly_list:
continue
else:
friendly_list.append([k, sum_of])
# Reset the variables for the next round
sum_of = 0
friendly = 0
# Let's loop through the list, print out the items and also sum all of them
for n in friendly_list:
print(n)
for m in n:
sum_them_all += m
print(sum_them_all)
Full code runtime 10 seconds in Lenovo IdeaPad5 (Ryzen5)

Finding the two closest numbers in a list using sorting

If I am given a list of integers/floats, how would I find the two closest numbers using sorting?
Such a method will do what you want:
>>> def minDistance(lst):
lst = sorted(lst)
index = -1
distance = max(lst) - min(lst)
for i in range(len(lst)-1):
if lst[i+1] - lst[i] < distance:
distance = lst[i+1] - lst[i]
index = i
for i in range(len(lst)-1):
if lst[i+1] - lst[i] == distance:
print lst[i],lst[i+1]
In the first for loop we find out the minimum distance, and in the second loop, we print all the pairs with this distance. Works as below:
>>> lst = (1,2,3,6,12,9,1.4,145,12,83,53,12,3.4,2,7.5)
>>> minDistance(lst)
2 2
12 12
12 12
>>>
It could be more than one possibilities. Consider this list
[0,1, 20, 25, 30, 200, 201]
[0,1] and [200, 201] are equal closest.
Jose has a valid point. However, you could just consider these cases equal and not care about returning one or the other.
I don't think you need a sorting algorithm, per say, but maybe just a sort of 'champion' algorithm like this one:
def smallestDistance(self, arr):
championI = -1
championJ = -1
champDistance = sys.maxint
i = 0
while i < arr.length:
j = i + 1
while j < arr.length:
if math.fabs(arr[i] - arr[j]) < champDistance:
championI = i
championJ = j
champDistance = math.fabs(arr[i] - arr[j])
j += 1
i += 1
r = [arr[championI], arr[championJ]]
return r
This function will return a sub array with the two values that are closest together. Note that this will only work given an array of at least two long. Otherwise, you will throw some error.
I think the popular sorting algorithm known as bubble sort would do this quite well. Though running at possible O(n^2) time if that kind of thing matters to you...
Here is standard bubble sort based on the sorting of arrays by integer size.
def bubblesort( A ):
for i in range( len( A ) ):
for k in range( len( A ) - 1, i, -1 ):
if ( A[k] < A[k - 1] ):
swap( A, k, k - 1 )
def swap( A, x, y ):
tmp = A[x]
A[x] = A[y]
A[y] = tmp
You can just modify the algorithm slightly to fit your purposes if you insist on doing this using a sorting algorithm. However, I think the initial function works as well...
hope that helps.

Struggling with Euler 12, Slow Code - Python

I'm struggling with Euler Problem 12. I do not want the answer or exact code changes that'll get me there. I'm just looking to be pointed in the right direction. I ran this code for about 10 minutes and came up with an answer which was incorrect. This leads me to believe that my assumption that a triangle number with > 500 divisors would not have any factors > 10000 is incorrect. I'm thinking I need to use a faster prime generator AND get the program to stop iterating through lists so much. I am not sure how to do the latter.
def eratosthenes_sieve(limit):
primes = {}
listofprimes = []
for i in range(2, limit + 1):
primes[i] = True
for i in primes:
factors = range(i, limit + 1, i)
for f in factors[1:limit + 1]:
primes[f] = False
for i in primes:
if primes[i] == True:
listofprimes.append(i)
return listofprimes
def prime_factorization(n):
global primal
prime_factors = {}
for i in primal:
if n < i:
i = primal[0]
if n % i == 0:
if i not in prime_factors.keys():
prime_factors[i] = 1
else:
prime_factors[i] += 1
n = n / i
if n in primal:
if n not in prime_factors.keys():
prime_factors[n] = 1
else:
prime_factors[n] += 1
return prime_factors
return prime_factors
def divisor_function(input):
x = 1
for exp in input.values():
x *= exp + 1
return x
def triangle(th):
terms = []
for each in range(1, th+1):
terms.append(each)
return sum(terms)
z = 1
primal = eratosthenes_sieve(10000)
found = False
while found == False:
triz = triangle(z)
number_of_divisors = divisor_function(prime_factorization(triz))
if number_of_divisors > 300:
print "GETTING CLOSE!! ********************************"
if number_of_divisors > 400:
print "SUPER DUPER CLOSE!!! *********************************************************"
if number_of_divisors < 501:
print "Nope. Not %s...Only has %s divisors." % (triz, number_of_divisors)
z += 1
else:
found = True
print "We found it!"
print "The first triangle number with over 500 divisors is %s!" % triangle(z)
Of course I figure it out minutes after posting.
In my prime_factorization function.
if n % i == 0: should have been while n % i == 0.
That was causing the program to miss factors and run through the entire list of primes.