Fibonacci sequence using list in PYTHON? - python

I have a problem about making a fibonacci sequence to a list, I'm just new to python someone help me please.
This is my code. I know this is looking wrong or something because it says invalid syntax. I don't know what to do about this really :(
This code works for a normal code without using a list!
myArray1 = [0]
myArray2 = [1]
while myArray2 < 700:
myArray1, myArray2 = b[i], myArray1+myArray2[i]
print(myArray2)

This code puts the first 700 fibonacci numbers in a list. Using meaningful variable names helps improve readability!
fibonacci_numbers = [0, 1]
for i in range(2,700):
fibonacci_numbers.append(fibonacci_numbers[i-1]+fibonacci_numbers[i-2])
Note: If you're using Python < 3, use xrange instead of range.

You may want this:
In [77]: a = 0
...: b = 1
...: while b < 700:
...: a, b = b, a+b
...: print a, b
1 1
1 2
2 3
3 5
5 8
8 13
13 21
21 34
34 55
55 89
89 144
144 233
233 377
377 610
610 987
If you wanna store the results in a list, use list.append:
In [81]: a = 0
...: b = 1
...: fibo=[a, b]
...: while b < 70:
...: a, b = b, a+b
...: fibo.append(b)
...: print fibo
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

There are two kinds of mistakes you are making; mistakes that are creating errors and mistakes that are affecting readability
Both instances of the phrase [i] should be removed. I believe that you may be thinking it has something to do with iteration or tuples, but that is part of the reason you are getting errors:
myArray1 = [0]
myArray2 = [1]
while myArray2 < 700:
myArray1, myArray2 = b, myArray1+myArray2
print(myArray2)
the other part of the reason you are getting errors is because of the variable b. You don't declare it and it does not belong. This code will iterate correctly if you switch out b with myArray2:
myArray1 = [0]
myArray2 = [1]
while myArray2 < 700:
myArray1, myArray2 = myArray2, myArray1+myArray2
print(myArray2)
then there are some legibility issues. I would change the phrase myArray1 and 2 to a and b respectively. First because it is just too long; second because in python it is called lists, not arrays; third because you are referring to integers, not lists or arrays:
a = [0]
b = [1]
while b < 700:
a, b = b, a+b
print(b)
then, the variables that were myArray1 and 2, but are now a and b; those are integers and they do not need to be expressed as single object lists. so get rid of the brackets around them:
a = 0
b = 1
while b < 700:
a, b = b, a+b
print(b)
Then, the last phrase in this code says print(b). If you have it printing b then the fibonacci sequence you get is missing its first 1. It will read (on separate lines of course) 1,2,3,5,8,13 and so on. It should read 1,1,2,3,5,8,13. You are missing the first 1. So print(b) needs to be changed to print(a):
a = 0
b = 1
while b < 700:
a, b = b, a+b
print(a)
then, if you are expressing more than one variable you can just list all the variables separated by commas equal to all the values separated by commas like this:
a,b,c,d = 1,2,3,4
so for your code that would translate to:
a,b = 0,1
while b < 700:
a, b = b, a+b
print(a)
then get rid of that extra space, white space means something in python, though here it doesn't really make a difference:
a,b = 0,1
while b < 700:
a, b = b, a+b
print(a)
So all of this so far has just been enough to get you to your original problem: you are getting an iteration (each consecutive value on a seperate line). Below is how you can get a list to any number n:
def fibo(n):
fibo_list = []
a,b = 0,1
while b < n:
a,b = b,a+b
fibo_list.append(a)
print(fibo_list)
hope that helps

def fibonacci(number: int) -> int:
"""
>>> fibonacci(0)
0
>>> fibonacci(1)
1
>>> fibonacci(2)
1
>>> fibonacci(3)
2
>>> fibonacci(4)
3
>>> fibonacci(5)
5
>>> fibonacci(6)
8
>>> fibonacci(7)
13
>>> fibonacci(8)
21
"""
fibs = [0] * (number + 2)
fibs[0] = 0
fibs[1] = 1
for i in range(2, number + 1):
fibs[i] = fibs[i - 1] + fibs[i - 2]
return fibs[number]
if __name__ == "__main__":
from doctest import testmod
testmod()

def fibonacci(n, results):
if n == 0:
return 0
elif n == 1:
return 1
else :
f = fibonacci(n-1, results) + fibonacci(n-2, results)
f1 = f[:]
results.appned(f1)
return results

You can use below code, your problem can be solve in just one line.
what are we doing is appending the
fib_nums
till your given limit i.e.,
700
and then adding the
fib_nums
with the second list which is of zero length which explicitly we doing, because it is containing
None
values, that we don't required.
#defining variable
fib_nums = [0, 1]
#just one line code
fib_nums = fib_nums + [fib_nums.append(fib_nums[i-1]+fib_nums[i-2]) for i in range(2,700)]*0
#printing the series
print (fib_nums)

It is not fast but it works as well:
def fibonacci(n):
# return a list of fibonacci numbers
if n == 0:
fibonacci_list = []
elif n == 1:
fibonacci_list = [0]
elif n == 2:
fibonacci_list = [0, 1]
elif n > 2:
fibonacci_list = [0, 1]
for i in range(n-2):
fibonacci_list += [0]
fibonacci_list[-1] = fibonacci_list[-2] + fibonacci_list[-3]
return fibonacci_list

Related

Strange bug. For loop code works fine for most values, but then appends 4 times with certain values

I am recreating the popular game minesweeper. Bombs are hidden in a grid, and where grids do not contain bombs, contain numbers of how many (if any ) bombs are connected to the grid. In order to achieve this in python, I have created a list of list of integers. this list of list acts as a set of coordinates, the number inside is then used as a key in a dictionary which is used in pygame to display an image. for example, if grid[i][j] = (0, 0) would be used in a dictionary to display the image for an empty box, 50 would be used to display a bomb, 1 would be used to display the number 1 within the box.
in order to display the numbers surrounding the bombs, I have made for loop with if statements to add tuples which correspond to the coordinates. when a bomb location has (14,x) in the first for loop it appends (13,x) 4 times. and I cannot figure out why. I am most curious to find help as to what the bug is, and would be even more appreciative if someone could suggest a more 'pythonic' way of achieving this. Please see the code below.
The code runs and produces a list of tuples. It might have to be run a couple of times to produce the results.
My code:
import random
bomb_count = 15
def set_grid():
grid = [[0 for x in range(30)] for x in range(15)]
num_columns = [x for x in range(30)]
num_rows = [x for x in range(15)]
counter = 0
while counter < bomb_count:
rndnum1 = random.choice(num_rows)
rndnum2 = random.choice(num_columns)
grid[rndnum1][rndnum2] = 50
counter += 1
return grid
def set_bomb_locations(grid):
grid_with_bombs = []
print("grid = ", grid)
for i in range(len(grid)):
for j in range(len(grid[i])):
if grid[i][j] == 50:
grid_with_bombs.append((i, j))
return grid_with_bombs
def number_layout(grid_with_bombs):
numbers_to_add_to_grid = []
for a, b in grid_with_bombs:
c = a + b
print(" this is", a, b)
if b < 29: # only if b isnt more than 29
c = a, b + 1
print("if statement 1: ", numbers_to_add_to_grid)
numbers_to_add_to_grid.append(c)
if b > 0: # only if b isnt 0
c = a, b - 1
print("if statement 2: ", numbers_to_add_to_grid)
numbers_to_add_to_grid.append(c)
if a > 0 and b > 0: # only if a isnt 0 and b isnt 0
c = a - 1, b - 1
print("if statement 3: ", numbers_to_add_to_grid)
numbers_to_add_to_grid.append(c)
if a > 0: # only if a isnt 0
c = a - 1, b
print("if statement 4: ", numbers_to_add_to_grid)
numbers_to_add_to_grid.append(c)
if a > 0 and b < 29: # only if a isnt 0 and b isnt more than 29
c = a - 1, b + 1 # error?
print("if statement 5: ", numbers_to_add_to_grid)
numbers_to_add_to_grid.append(c)
if a < 14 and b > 0: # only if a isnt more than 15 and b isnt 0
c = a + 1, b - 1
print("if statement 6: ", numbers_to_add_to_grid)
numbers_to_add_to_grid.append(c)
if a < 14: # only if a isnt more than 15
c = a + 1, b
print("if statement 7: ", numbers_to_add_to_grid)
numbers_to_add_to_grid.append(c)
if a < 14 and b < 29: # only if a isnt more than 15 and b isnt more than 29
c = a + 1, b + 1
print("if statement 8: ", numbers_to_add_to_grid)
numbers_to_add_to_grid.append(c)
for a, b in numbers_to_add_to_grid:
if grid[a][b] != 50:
grid[a][b] += 1
return grid
grid = set_grid()
grid2 = set_bomb_locations(grid)
grid_with_bombs = number_layout(grid2)
I realize these should be posted as comments, but I don't have enough reputation to comment.
[x for x in range(30)] can be changed to [*range(30)]
But that can be avoided by using random.randint() instead of random.choice.(), and the while loop isn't necessary, you can use a for loop since it's a set number:
from random import randint
for i in range(bomb_count):
grid[randint(0, 30)][randint(0, 15)] = 50
Instead of using len() and range() to iterate through the grid, just iterate through it:
#INSTEAD OF:
for i in range(len(grid)):
for j in range(len(grid[i])):
if grid[i][j] == 50:
grid_with_bombs.append((i, j))
#USE THIS:
for c_index, column in enumerate(grid):
for r_index, row in enumerate(column):
if row == 50:
grid_with_bombs.append((c_index, r_index))
i fixed it, by re writing the code to fit a "logic by exception" rule. to over come my problem. i simply added every tuple to a temporary list, and then removed the tuples that were not in the required parameters. I think the lesson here is, the more complex the logic, the more likely and, the harder fixing any bugs become. Below is the code that now works. sometimes a way to fix a bug, is to rewrite the logic. free to add further improvements. on a side note, i have found a grid created this way is very useful in creating games in pygame like snake, minsweeper, tetris, etc etc, i learned this approach from someone else and is really helping me learn how useful lists are in python, feel free to use and share.
my code below
from random import randint
def set_grid():
grid_with_bombs = []
grid_with_bombs_and_numbers = []
# create grid with all 0
grid = [[0 for x in range(30)] for x in range(15)]
# choose 15 random locations for bombs
for i in range(bomb_count):
grid[randint(0, 14)][randint(0, 29)] = 50
# create a list of bomb locations as tuples
for c_index, column in enumerate(grid):
for r_index, row in enumerate(column):
if row == 50:
grid_with_bombs.append((c_index, r_index))
# use tuples from above to mark out any grid cell as next to a bomb
# and create a temp list of tuples with those locations
temp_tuple_list = []
for a, b in grid_with_bombs:
c = a, b + 1
d = a, b - 1
e = a - 1, b - 1
f = a - 1, b
g = a - 1, b + 1
h = a + 1, b - 1
i = a + 1, b
j = a + 1, b + 1
temp_list = [c,d,e,f,g,h,i,j]
for i in temp_list:
temp_tuple_list.append(i)
# now remove tuples that correspond to a grid reference that does not exist. e.g (-1,29)
for a,b in temp_tuple_list:
c = a,b
if a == -1 or a >= 15:
continue
if b == -1 or b >= 30:
continue
else:
grid_with_bombs_and_numbers.append(c)
# every tuple that isnt 50( a bomb ) or 0 ( nothing ) is a number square,
# each time a tuple is in the list add 1 this will give us a value to display
for a,b in grid_with_bombs_and_numbers:
if grid[a][b] != 50:
grid[a][b] += 1
return grid

Python fibonacci series

I wrote a Fibonacci series using Python. Could not figure out why second program is giving wrong answer and first one right when both look same.
Below program gives right answer
def fib(n):
a,b=0,1
while b<n:
print b
a,b=b,a+b
fib(4)
1
1
2
3
Below program gives wrong answer:
def fib(n):
a = 0
b = 1
while b<n:
print b
a = b
b = a+b
fib(4)
1
2
In first one, a, b = b, a+b does the assigning simultanously.
In second one, you are first doing a = b and then doing b = a+b which actually is just b = 2*b.
How to achieve such behaviour in second one? Use temporary value to store a.
def fib(n):
a = 0
b = 1
while b<n:
print b
temp = a
a = b
b = temp+b
fib(4)
>>>1
>>>1
>>>2
>>>3
In the second code posted, you redefine the value of b after having changed a, resulting as
def fib(n):
a = 0
b = 1
while b<n:
print b #prints 1
a = b #a = 1
b = a+b #b = 1 + 1 = 2
In the second code, there is no problem, as python code generally reads equations from right to left, thus redefines b first, as is correct
def fib(n):
a,b=0,1 #a = 0, b = 1
while b<n:
print b
a,b=b,a+b #b = 0 + 1 = 1, #a = 1
fibonacci series using lambda function in python
n = int(input("Enter the range of numbers in fibonacci series:"))
F = [0,1]
list(map(lambda i: F.append(F[i-1] + F[i-2]), range(2, n)))
print(F)
fibonacci series using List Comprehension function in python
n = int(input("Enter the range of numbers in fibonacci series:"))
F = [0,1]
[F.append(F[i-1] + F[i-2]) for i in range(2,n)]
print(F)
In the first example, you've used this code:
a,b=b,a+b
While in the second, you've done this instead:
a = b
b = a+b
These are not the same thing.
For the sake of argument, let's say that a = 3 and b = 6. Let's run the working code first:
>>> a, b = 10, a + 1
>>> a
10
>>> b
4
The value of a + 1 is 4 rather than 11, because b's assignment is using the old value of a, so 3 + 1 == 4.
Now let's put a and b back to their starting values. Let's try the other method of assigning:
>>> a = 10
>>> b = a + 1
>>> a
10
>>> b
11
Now b is 11! That's because a was assigned before the assignment of b, so the addition uses a's new value.
The reason your second version isn't working is because the assignments don't happen simultaneously, so b is actually 2 * b because a has already been set to b by the time a+b is executed.
def fibonacci (n):
if n == 1 or n == 2:
return 1
return fibonacci (n-1) + fibonacci (n-2)
for i in range(1,50):
print (fibonacci(i))
n1 = 0
n2 = 1
c = 0
nTerms = int(input())
if nTerms <= 0:
print("Enter the valid value")
elif nTerms == 1:
print(a)
else:
while c < nTerms:
print(n1)
nth = n1 + n2
n1 = n2
n2 = nth
c += 1
Fibonacci Series Using Recursion
def f_recursion(n):
if n <= 1:
return n
else:
return(f_recursion(n-1) + f_recursion(n-2))
# Driver Code
nterms = int(input())
if nterms <= 0:
print("Enter the positive value")
else:
for i in range(0,nterms):
print (f_recursion(i))
n1=int(input("Enter Term"))
mylist=[0,1]
for a in range(n1):
sum=0
for b in mylist[len(mylist)-2:]:
sum+=b
mylist.append(sum)
print(mylist)
def fib(n):
a=0
b=1
sum=0
for i in range(0,n):
print(sum)
sum = a + b
b = a
a = sum
fib(10) // here you can add any n value from 1 to 100
# The below code will generate the fibonacci series as per desired range
# just put the number, you want the fibonaci series upto.
def fibonacci(num):
x,y = 0,1
if num==1:
print(x)
elif num==2:
print(x,y)
else:
print(x,y,end = " ")
for i in range(num-2):
z=x+y
x=y
y=z
print(z,end = " ")
def fib(n1, n2):
print(n1)
print(n2)
for i in range(n1, n2):
n1 += n2
n2 += n1
print(n1)
print(n2)
starting_number = int(input('Enter First Term: '))
ending_number = int(input('Enter Second Number: '))
fib(starting_number, ending_number)

how to use two variables in for loop?

Define a function calls addFirstAndLast(x) that takes in a list of numbers and returns the sum of the first and last numbers.
Examples
>>> addFirstAndLast([])
0
>>> addFirstAndLast([2, 7, 3])
5
>>> addFirstAndLast([10])
10
My question is this that i can not use two variables in for loop, so what should i do , how to fix the error. and what could be the improved code of this problem.
def addFirstAndLast(x):
total = 0
total1 = 0
total2 = 0
pos_last = []
for num, last in x:
num = str(num)
num = num[0]
total1 += int(num)
last = last % 10
pos_last = pos_last.append(last)
total = sum(pos_last)
total2 = total+total1
return total2
print addFirstAndLast([2, 7, 3])
3 distinct cases: 1) the list is empty, 2) the list has one element, 3) the list has two or more elements.
Try without loop:
def addFirstAndLast(x):
if len(x) == 0:
return 0
elif len(x) < 2:
return x[0]
else:
return x[0]+x[-1]
>>> print addFirstAndLast([2, 7, 3])
5
>>> print addFirstAndLast([2, 3])
5
>>> print addFirstAndLast([3])
3
x is a list of integers, when using x in a for loop , each iteration would get a single integer. But when you do -
for num, last in x:
You are trying to unpack a single integer into 2 places, this cannot happen, and it is causing your issue.
I am not even sure what the rest of your logic does , you can do this simply using -
def addFirstAndLast(x):
l = len(x)
return x[0] + x[-1] if l > 1 else x[0] if l > 0 else 0
Examples -
>>> addFirstAndLast([])
0
>>> addFirstAndLast([2, 7, 3])
5
>>> addFirstAndLast([10])
10
Explanation of the logic - The expression is -
((x[0] + x[-1]) if l > 1 else x[0]) if l > 0 else 0
It first checks the outer most if condition, if length is 0 it returns 0 , if not it goes onto inner if condition.
In the inner if condition, if length is greater than 1(meaning there are 2 or more elements) it returns sum of first and last, otherwise (which means length is greater than 0 but less than 2 , meaning its 1) it returns first element.

How to count number of combinations?

I have the problem that I want to count the number of combinations that fulfill the following condition:
a < b < a+d < c < b+d
Where a, b, c are elements of a list, and d is a fixed delta.
Here is a vanilla implementation:
def count(l, d):
s = 0
for a in l:
for b in l:
for c in l:
if a < b < a + d < c < b + d:
s += 1
return s
Here is a test:
def testCount():
l = [0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 5, 7, 7, 8, 9, 9, 10, 10]
assert(32 == count(l, 4)) # Gone through everything by hand.
Question
How can I speed this up? I am looking at list sizes of 2 Million.
Supplementary Information
I am dealing with floats in the range of [-pi, pi]. For example, this limits a < 0.
What I have so far:
I have some implementation where I build indices that I use for b and c. However, the below code fails some cases. (i.e. This is wrong).
def count(l, d=pi):
low = lower(l, d)
high = upper(l, d)
s = 0
for indA in range(len(l)):
for indB in range(indA+1, low[indA]+1):
s += low[indB] + 1 - high[indA]
return s
def lower(l, d=pi):
'''Returns ind, s.t l[ind[i]] < l[i] + d and l[ind[i]+1] >= l[i] + d, for all i
Input must be sorted!
'''
ind = []
x = 0
length = len(l)
for elem in l:
while x < length and l[x] < elem + d:
x += 1
if l[x-1] < elem + d:
ind.append(x-1)
else:
assert(x == length)
ind.append(x)
return ind
def upper(l, d=pi):
''' Returns first index where l[i] > l + d'''
ind = []
x = 0
length = len(l)
for elem in l:
while x < length and l[x] <= elem + d:
x += 1
ind.append(x)
return ind
Original Problem
The original problem is from a well known math/comp-sci competition. The competition asks that you don't post solutions on the net. But it is from two weeks ago.
I can generate the list with this function:
def points(n):
x = 1
y = 1
for _ in range(n):
x = (x * 1248) % 32323
y = (y * 8421) % 30103
yield atan2(x - 16161, y - 15051)
def C(n):
angles = points(n)
angles.sort()
return count(angles, pi)
There is an approach to your problem that yields an O(n log n) algorithm. Let X be the set of values. Now let's fix b. Let A_b be the set of values { x in X: b - d < x < b } and C_b be the set of values { x in X: b < x < b + d }. If we can find |{ (x,y) : A_b X C_b | y > x + d }| fast, we solved the problem.
If we sort X, we can represent A_b and C_b as pointers into the sorted array, because they are contiguous. If we process the b candidates in non-decreasing order, we can thus maintain these sets using a sliding window algorithm. It goes like this:
sort X. Let X = { x_1, x_2, ..., x_n }, x_1 <= x_2 <= ... <= x_n.
Set left = i = 1 and set right so that C_b = { x_{i + 1}, ..., x_right }. Set count = 0
Iterate i from 1 to n. In every iteration we find out the number of valid triples (a,b,c) with b = x_i. To do that, increase left and right as much as necessary so that A_b = { x_left, ..., x_{i-1} } and C_b = { x_{i + 1}, ..., x_right } still holds. In the process, you basically add and remove elements from the imaginary sets A_b and C_b.
If you remove or add an element to one of the sets, check how many pairs (a, c) with c > a + d, a from A_b and c from C_b you add or destroy (this can be achieved by a simple binary search in the other set). Update count accordingly so that the invariant count = |{ (x,y) : A_b X C_b | y > x + d }| still holds.
sum up the values of count in every iteration. This is the final result.
The complexity is O(n log n).
If you want to solve the Euler problem with this algorithm, you have to avoid floating point issues. I suggest sorting the points by angle using a custom comparison function that uses integer arithmetics only (using 2D vector geometry). Implementing the |a-b| < d comparisons can also be done using integer operations only. Also, since you are working modulo 2*pi, you would probably have to introduce three copies of every angle a: a - 2*pi, a and a + 2*pi. You then only look for b in the range [0, 2*pi) and divide the result by three.
UPDATE OP implemented this algorithm in Python. Apparently it contains some bugs but it demonstrates the general idea:
def count(X, d):
X.sort()
count = 0
s = 0
length = len(X)
a_l = 0
a_r = 1
c_l = 0
c_r = 0
for b in X:
if X[a_r-1] < b:
# find boundaries of A s.t. b -d < a < b
while a_r < length and X[a_r] < b:
a_r += 1 # This adds an element to A_b.
ind = bisect_right(X, X[a_r-1]+d, c_l, c_r)
if c_l <= ind < c_r:
count += (ind - c_l)
while a_l < length and X[a_l] <= b - d:
a_l += 1 # This removes an element from A_b
ind = bisect_right(X, X[a_l-1]+d, c_l, c_r)
if c_l <= ind < c_r:
count -= (c_r - ind)
# Find boundaries of C s.t. b < c < b + d
while c_l < length and X[c_l] <= b:
c_l += 1 # this removes an element from C_b
ind = bisect_left(X, X[c_l-1]-d, a_l, a_r)
if a_l <= ind <= a_r:
count -= (ind - a_l)
while c_r < length and X[c_r] < b + d:
c_r += 1 # this adds an element to C_b
ind = bisect_left(X, X[c_r-1]-d, a_l, a_r)
if a_l <= ind <= a_r:
count += (ind - a_l)
s += count
return s
from bisect import bisect_left, bisect_right
from collections import Counter
def count(l, d):
# cdef long bleft, bright, cleft, cright, ccount, s
s = 0
# Find the unique elements and their counts
cc = Counter(l)
l = sorted(cc.keys())
# Generate a cumulative sum array
cumulative = [0] * (len(l) + 1)
for i, key in enumerate(l, start=1):
cumulative[i] = cumulative[i-1] + cc[key]
# Pregenerate all the left and right lookups
lefthand = [bisect_right(l, a + d) for a in l]
righthand = [bisect_left(l, a + d) for a in l]
aright = bisect_left(l, l[-1] - d)
for ai in range(len(l)):
bleft = ai + 1
# Search only the values of a that have a+d in range
if bleft > aright:
break
# This finds b such that a < b < a + d.
bright = righthand[ai]
for bi in range(bleft, bright):
# This finds the range for c such that a+d < c < b+d.
cleft = lefthand[ai]
cright = righthand[bi]
if cleft != cright:
# Find the count of c elements in the range cleft..cright.
ccount = cumulative[cright] - cumulative[cleft]
s += cc[l[ai]] * cc[l[bi]] * ccount
return s
def testCount():
l = [0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 5, 7, 7, 8, 9, 9, 10, 10]
result = count(l, 4)
assert(32 == result)
testCount()
gets rid of repeated, identical values
iterates over only the required range for a value
uses a cumulative count across two indices to eliminate the loop over c
cache lookups on x + d
This is no longer O(n^3) but more like O(n^2)`.
This clearly does not yet scale up to 2 million. Here are my times on smaller floating point data sets (i.e. few or no duplicates) using cython to speed up execution:
50: 0:00:00.157849 seconds
100: 0:00:00.003752 seconds
200: 0:00:00.022494 seconds
400: 0:00:00.071192 seconds
800: 0:00:00.253750 seconds
1600: 0:00:00.951133 seconds
3200: 0:00:03.508596 seconds
6400: 0:00:10.869102 seconds
12800: 0:00:55.986448 seconds
Here is my benchmarking code (not including the operative code above):
from math import atan2, pi
def points(n):
x, y = 1, 1
for _ in range(n):
x = (x * 1248) % 32323
y = (y * 8421) % 30103
yield atan2(x - 16161, y - 15051)
def C(n):
angles = sorted(points(n))
return count(angles, pi)
def test_large():
from datetime import datetime
for n in [50, 100, 200, 400, 800, 1600, 3200, 6400, 12800]:
s = datetime.now()
C(n)
elapsed = datetime.now() - s
print("{1}: {0} seconds".format(elapsed, n))
if __name__ == '__main__':
testCount()
test_large()
Since l is sorted and a < b < c must be true, you could use itertools.combinations() to do fewer loops:
sum(1 for a, b, c in combinations(l, r=3) if a < b < a + d < c < b + d)
Looking at combinations only reduces this loop to 816 iterations.
>>> l = [0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 5, 7, 7, 8, 9, 9, 10, 10]
>>> d = 4
>>> sum(1 for a, b, c in combinations(l, r=3))
816
>>> sum(1 for a, b, c in combinations(l, r=3) if a < b < a + d < c < b + d)
32
where the a < b test is redundant.
1) To reduce amount of iterations on each level you can remove elements from list that dont pass condition on each level
2) Using set with collections.counter you can reduce iterations by removing duplicates:
from collections import Counter
def count(l, d):
n = Counter(l)
l = set(l)
s = 0
for a in l:
for b in (i for i in l if a < i < a+d):
for c in (i for i in l if a+d < i < b+d):
s += (n[a] * n[b] * n[c])
return s
>>> l = [0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 5, 7, 7, 8, 9, 9, 10, 10]
>>> count(l, 4)
32
Tested count of iterations (a, b, c) for your version:
>>> count1(l, 4)
18 324 5832
my version:
>>> count2(l, 4)
9 16 7
The basic ideas are:
Get rid of repeated, identical values
Have each value iterate only over the range it has to iterate.
As a result you can increase s unconditionally and the performance is roughly O(N), with N being the size of the array.
import collections
def count(l, d):
s = 0
# at first we get rid of repeated items
counter = collections.Counter(l)
# sort the list
uniq = sorted(set(l))
n = len(uniq)
# kad is the index of the first element > a+d
kad = 0
# ka is the index of a
for ka in range(n):
a = uniq[ka]
while uniq[kad] <= a+d:
kad += 1
if kad == n:
return s
for kb in range( ka+1, kad ):
# b only runs in the range [a..a+d)
b = uniq[kb]
if b >= a+d:
break
for kc in range( kad, n ):
# c only rund from (a+d..b+d)
c = uniq[kc]
if c >= b+d:
break
print( a, b, c )
s += counter[a] * counter[b] * counter[c]
return s
EDIT: Sorry, I messed up the submission. Fixed.

Python Fibonacci Generator

I need to make a program that asks for the amount of Fibonacci numbers printed and then prints them like 0, 1, 1, 2... but I can't get it to work. My code looks the following:
a = int(raw_input('Give amount: '))
def fib():
a, b = 0, 1
while 1:
yield a
a, b = b, a + b
a = fib()
a.next()
0
for i in range(a):
print a.next(),
I would use this method:
Python 2
a = int(raw_input('Give amount: '))
def fib(n):
a, b = 0, 1
for _ in xrange(n):
yield a
a, b = b, a + b
print list(fib(a))
Python 3
a = int(input('Give amount: '))
def fib(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
print(list(fib(a)))
You are giving a too many meanings:
a = int(raw_input('Give amount: '))
vs.
a = fib()
You won't run into the problem (as often) if you give your variables more descriptive names (3 different uses of the name a in 10 lines of code!):
amount = int(raw_input('Give amount: '))
and change range(a) to range(amount).
Since you are writing a generator, why not use two yields, to save doing the extra shuffle?
import itertools as it
num_iterations = int(raw_input('How many? '))
def fib():
a,b = 0,1
while True:
yield a
b = a+b
yield b
a = a+b
for x in it.islice(fib(), num_iterations):
print x
.....
Really simple with generator:
def fin(n):
a, b = 0, 1
for i in range(n):
yield a
a, b = b, a + b
ln = int(input('How long? '))
print(list(fin(ln))) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...]
Python is a dynamically typed language. the type of a variable is determined at runtime and it can vary as the execution is in progress.
Here at first, you have declared a to hold an integer type and later you have assigned a function to it and so its type now became a function.
you are trying to apply 'a' as an argument to range() function which expects an int arg but you have in effect provided a function variable as argument.
the corrected code should be
a = int(raw_input('Give amount: '))
def fib():
a, b = 0, 1
while 1:
yield a
a, b = b, a + b
b = fib()
b.next()
for i in range(a):
print b.next(),
this will work
def fibonacci(n):
fn = [0, 1,]
for i in range(2, n):
fn.append(fn[i-1] + fn[i-2])
return fn
To get the fibonacci numbers till any number (100 in this case) with generator, you can do this.
def getFibonacci():
a, b = 0, 1
while True:
yield b
b = a + b
a = b - a
for num in getFibonacci():
if num > 100:
break
print(num)
def genFibanocciSeries():
a=0
b=1
for x in range(1,10):
yield a
a,b = b, a+b
for fib_series in genFibanocciSeries():
print(fib_series)
Your a is a global name so-to-say.
a = int(raw_input('Give amount: '))
Whenever Python sees an a, it thinks you are talking about the above one. Calling it something else (elsewhere or here) should help.
Also you can use enumerate infinite generator:
for i,f in enumerate(fib()):
print i, f
if i>=n: break
Also you can try the closed form solution (no guarantees for very large values of n due to rounding/overflow errors):
root5 = pow(5, 0.5)
ratio = (1 + root5)/2
def fib(n):
return int((pow(ratio, n) - pow(1 - ratio, n))/root5)
You had the right idea and a very elegant solution, all you need to do fix is your swapping and adding statement of a and b. Your yield statement should go after your swap as well
a, b = b, a + b #### should be a,b = a+b,a #####
`###yield a`
Simple way to print Fibonacci series till n number
def Fib(n):
i=a=0
b=1
while i<n:
print (a)
i=i+1
c=a+b
a=b
b=c
Fib(input("Please Enter the number to get fibonacci series of the Number : "))
a = 3 #raw_input
def fib_gen():
a, b = 0, 1
while 1:
yield a
a, b = b, a + b
fs = fib_gen()
next(fs)
for i in range(a):
print (next(fs))
I've build this a while ago:
a = int(raw_input('Give amount: '))
fab = [0, 1, 1]
def fab_gen():
while True:
fab.append(fab[-1] + fab[-2])
yield fab[-4]
fg = fab_gen()
for i in range(a): print(fg.next())
No that fab will grow over time, so it isn't a perfect solution.
It looks like you are using the a twice. Try changing that to a different variable name.
The following seems to be working great for me.
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a+b
f = fib()
for x in range(100):
print(f.next())
i like this version:
array = [0,1]
for i in range(20):
x = array[0]+array[1]
print(x)
array[0] = array[1]
array[1] = x
Below are two solution for fiboncci generation:
def fib_generator(num):
'''
this will works as generator function and take yield into account.
'''
assert num > 0
a, b = 1, 1
while num > 0:
yield a
a, b = b, a+b
num -= 1
times = int(input('Enter the number for fib generaton: '))
fib_gen = fib_generator(times)
while(times > 0):
print(next(fib_gen))
times = times - 1
def fib_series(num):
'''
it collects entires series and then print it.
'''
assert num > 0
series = []
a, b = 1, 1
while num > 0:
series.append(a)
a, b = b, a+b
num -= 1
print(series)
times = int(input('Enter the number for fib generaton: '))
fib_series(times)
Why do you go for complex here is one of my snippet to work on!!
n = int(input('Enter your number..: '))
a = 0
b = 1
c = 0
print(a)
print(b)
for i in range(3, n+1):
c = a+b
print(c)
a,b=b,c
check out my git - rohith-sreedharan
We can use it in a short way without through 'yield and 'next' statements
def fib(n):
return n if n <= 1 else fib(n - 1) + fib(n - 2)

Categories