Optimising a fibonacci sequence generator python - python-3.x

I am trying to create a program which creates a Fibonacci sequence up to the value of the sequence being 200. I have the basic set up down where I can compute the sequence but I wish to display it in a certain way and I have forgotten how to achieve this.
I wish to write the numbers to an array which I have defined as empty initially, compute the numbers and assign them to the array and print said array. In my code below the computation is ok but when printed to screen, the array shows the value 233 which is above 200 and not what I'm looking for. I wish to print all the values under 200 which I've stored in an array.
Is there a better way to initially define the array for what I want and what is the correct way to print the array at the end with all elements below 200?
Code follows:
#This program calculates the fibonacci sequence up to the value of 200
import numpy as np
x = np.empty(14, float) #Ideally creates an empty array to deposit the fibonacci numbers in
f = 0.0 #Dummy variable to be edited in the while loop
#Here the first two values of the sequence are defined alongside a counter starting at i = 1
x[0] = 0.0
x[1] = 1.0
i = 1
#While loop which computes the values and writes them to the array x
while f <= 200:
f = x[i]+x[i-1] #calculates the sequence element
i += 1 #Increases the iteration counter by 1 for each loop
x[i] = f #set the array element equal to the calculated sequence number
print(x)
For reference here is a quick terminal output, Ideally I wish to remove the last element:
[ 0. 1. 1. 2. 3. 5. 8. 13. 21. 34. 55. 89.
144. 233.]

There are a number of stylistic points here. Firstly, you should probably use integers, rather than floats. Secondly, you should simply append each number to a list, rather than pre-define an array of a particular size.
Here's an interactive session:
>>> a=[0,1]
>>> while True:
b=a[-1]+a[-2]
if b<=200:
a.append(b)
else:
break
>>> a
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]

Here is a way without using indices:
a = 0
x = [a]
b = 1
while b <= 200:
x.append(b)
a, b = b, a+b
print(x)

Related

A Rule of Divisibility by 13 - Codewars python challenge (RecursionError)

Instructions:
When you divide the successive powers of 10 by 13 you get the following remainders of the integer divisions:
1, 10, 9, 12, 3, 4.
Then the whole pattern repeats.
Hence the following method: Multiply the right most digit of the number with the left most number in the sequence shown above, the second right most digit to the second left most digit of the number in the sequence. The cycle goes on and you sum all these products. Repeat this process until the sequence of sums is stationary.
...........................................................................
Example: What is the remainder when 1234567 is divided by 13?
7×1 + 6×10 + 5×9 + 4×12 + 3×3 + 2×4 + 1×1 = 178
We repeat the process with 178:
8x1 + 7x10 + 1x9 = 87
and again with 87:
7x1 + 8x10 = 87
...........................................................................
From now on the sequence is stationary and the remainder of 1234567 by 13 is the same as the remainder of 87 by 13: 9
Call thirt the function which processes this sequence of operations on an integer n (>=0). thirt will return the stationary number.
thirt(1234567) calculates 178, then 87, then 87 and returns 87.
thirt(321) calculates 48, 48 and returns 48
My Code:
def thirt(n):
a = []
n = [int(i) for i in list(str(n))][::-1]
l = [1, 10, 9, 12, 3, 4][:len(n)]
y = sum([a * b for a,b in zip(n,l)])
a.append(y)
for c in a:
if a.count(c) == 1:
thirt(c)
else:
return c
thirt(5634)
When I run this I get an error
Traceback (most recent call last):
File "main.py", line 5, in <module>
Test.assert_equals(thirt(8529), 79)
File "/home/codewarrior/solution.py", line 9, in thirt
thirt(i)
File "/home/codewarrior/solution.py", line 9, in thirt
thirt(i)
File "/home/codewarrior/solution.py", line 9, in thirt
thirt(i)
[Previous line repeated 994 more times]
File "/home/codewarrior/solution.py", line 3, in thirt
n = [int(i) for i in list(str(n))][::-1]
RecursionError: maximum recursion depth exceeded while getting the str of an object
when I remove some part of the code and leave it like
def thirt(n):
n = [int(i) for i in list(str(n))][::-1]
l = [1, 10, 9, 12, 3, 4][:len(n)]
y = sum([a * b for a,b in zip(n,l)])
return y
thirt(5634)
I get 148 in the output, and then I thirt(148), I get 57, which is the desired answer, same goes for other examples as well.
so I just need a proper way to recur this function, and I just want it to stop as soon as the values start repeating, i.e. I want the loop of recursion to break as soon as I get two 57's in a row, and then I need it to return 57.
But I can't figure out a proper way to do it, because this is the first time I've applied recursion in a function, my code is really messed up, I'll really appreciate any help.
You are getting the error depth exceeded while getting the str of an object because you are assigning the list of digits n to the same variable name as the function parameter n. That means after the first recursive call, you are running [int(i) for i in list(str(n))][::-1] on a list of individual digits, and then a list of lists, and so on, rather than a single input number as you're expecting.
Once you fix that, you run into the issue of how you are checking for whether to make the recursive call:
a = []
a.append(y)
for c in a:
if a.count(c) == 1:
thirt(c)
I can see what you're trying to do, and it will not work in recursion because every time the function is called, a is reset to an empty list. That means a.count(c) == 1 is always true, and your function will go into an infinite recursive loop.
Instead, for this algorithm all you need to do is check whether your newly calculated y is equal to the number n that was passed to the function. If they're the same, that means you've gotten the same number twice in a row, so the algorithm is done.
After that is fixed, it will look like you're getting somewhere. You can use this logic:
if n != y:
thirt(y)
else:
print(y) # expected answer outputted to console
return y
Except when you call thirt(1234567), the value returned is None ! What the heck? I printed y and it's correct, it's right there! What is happening is, the inner-most call to thirt is returning the number you need, but then the next level up in the function call stack doesn't do anything with it. So the function ends and returns None. To fix this, you need each level of the recursive call to pass its return value up the chain. So use return thirt(y) instead of just thirt(y).
Finally, you need to account for the case when the number passed to the function is longer than 6 digits. Your l list needs to repeat in a cycle, not stop with the 6 numbers you've listed. You can get the list to be the length you need by multiplying it by the length of n divided by six, rounded up whenever there's a remainder.
After all that, you'll end up with something like the following:
def thirt(n):
nList = [int(i) for i in list(str(n))][::-1]
remainders = [1, 10, 9, 12, 3, 4] * (
len(nList) // 6 + min(1, len(nList) % 6)
)
y = sum([a * b for a,b in zip(nList,remainders)])
if n != y:
return thirt(y)
else:
return y
print(thirt(1234567)) #87
Isn't this what you mean?
def thirt(n_raw):
a = []
n = [int(i) for i in list(str(n_raw))][::-1]
l = [1, 10, 9, 12, 3, 4]*(len(n)//6+1)
y = sum([a * b for a,b in zip(n,l)])
if(y==n_raw): return y
else: return thirt(y)
I think you just went in a very wrong direction with the second half of your function, but I might misunderstood the premise behind...

Finding number is present in sequence

I need to find out whether a given number is present in a given sequence. Sequence is an arithmetic progression with common difference of 2
Ex Input1 - 5, 7, 9, 11, 13, 15, . . .
for this sequence key is 19 so it is present i the sequence output would be True.
For input2 - be 4,6,8,10...
Given key is 15 so it is not present output should be False.
I have written the code but it is only working for first set of input which is odd numbers .Its failing for input2 which is even
arr = 4,6,8
n=10
b=max(arr)
l=[]
if b>n:
c=b
else:
c=n
d=arr[1]-arr[0]
for i in range(1,c+d+1,d):
l.append(i)
if n in l:
print("True")
else:
print("False")
Output 1 - True
output2 - False
You can take advantage of range's smart implementation of __contains__ to get a one-liner O(1) solution:
print(6 in range(2, 10, 2))
# True
print(5 in range(2, 10, 2))
# False
And an extreme example to show how fast and scalable this is (the size of the range does not matter):
from timeit import Timer
print(min(Timer(lambda: 1_000_000_000 in range(2, 1_000_000_003, 2)).repeat(1000, 1000)))
# 00032309999999990957

How to return floating values using floor division

In Python 3, I want to return the units place of an integer value, then tens, then hundreds and so on. Suppose I have an integer 456, first I want to return 6, then 5 then 4. Is there any way? I tried floor division and for loop but didn't work.
If you look at the list of basic operators from the documentation, for example here,
Operator Description Example
% Modulus Divides left hand operand by right hand operand and returns remainder b % a = 1
// Floor Division - The division of operands where the result is the quotient in which the digits after the decimal point are removed. But if one of the operands is negative, the result is floored, i.e., rounded away from zero (towards negative infinity): 9//2 = 4 and 9.0//2.0 = 4.0, -11//3 = -4, -11.0//3 = -4.0
With that knowledge, you can get what you want as follows:
In [1]: a = 456
In [2]: a % 10
Out[2]: 6
In [3]: (a % 100) // 10
Out[3]: 5
In [4]: a // 100
Out[4]: 4
Write a generator if you want to retrieve digits in different places of your code based on requirement as follows.
If you are not much familiar with Python's generator, have a quick look at https://www.programiz.com/python-programming/generator.
» Here get_digits() is a generator.
def get_digits(n):
while str(n):
yield n % 10
n = n // 10
if not n:
break
digit = get_digits(1729)
print(next(digit)) # 9
print(next(digit)) # 2
print(next(digit)) # 7
print(next(digit)) # 1
» If you wish to iterate over digits, you can also do so as follows.
for digit in get_digits(74831965):
print(digit)
# 5
# 6
# 9
# 1
# 3
# 8
# 4
# 7
» Quick overview about its usage (On Python3's Interactive terminal).
>>> def letter(name):
... for ch in name:
... yield ch
...
>>>
>>> char = letter("RISHIKESH")
>>>
>>> next(char)
'R'
>>>
>>> "Second letter is my name is: " + next(char)
'Second letter is my name is: I'
>>>
>>> "3rd one: " + next(char)
'3rd one: S'
>>>
>>> next(char)
'H'
>>>

Ugly 2 dimensional list. Why?

I'm trying to figure out why my list looks ugly when printed:
alfa = []
alfa.append([])
alfa.append([])
a = 0
a = float(a)
print("Input the points, one per line as x,y.\nStop by entering an empty line.")
while a == 0:
start = input()
if start == '':
a = a + 1
else:
alfa[0].append(start.split(",")[0:1])
alfa[1].append(start.split(",")[1:2])
print(alfa)
with input of:
2,3
12,56
1,2
a
I get this:
[[['2'], ['12'], ['1']], [['3'], ['56'], ['2']]]
While if i try this simple Program found online:
elements = []
elements.append([])
elements.append([])
elements[0].append(1)
elements[0].append(2)
elements[1].append(3)
elements[1].append(4)
print(elements[0][0])
print(elements)
I get this:
[[1, 2], [3, 4]]
Why is this result much tidier than mine?
Try:
alfa[0].append(int(start.split(",")[0]))
alfa[1].append(int(start.split(",")[1]))
>>>[[2, 12, 1], [3, 56, 2]]
You're getting the quote marks because input() is interpreting the input as a string. It doesn't know that you want what you've typed to be a number, so it has to handle it in a default way. You have to tell the code that the input should be interpreted as an int.
Secondly, you're slicing the arrays when you use [0:1] to get an array consisting of the entries from 0 to 0, which is the same as getting element 0 directly, except you get an array with one element rather than just the element you want. Essentially, you are inserting [2] rather than 2.
The data from your input is strings, as shown by the quotation marks. Cast your strings to integers after the input. If you want to have the [1, 2] formatting without the extra brackets then you need to place numbers in alfa[0] and alfa[1] etc..
alfa = []
alfa.append([])
alfa.append([])
a = 0
a = float(a)
print("Input the points, one per line as x,y.\nStop by entering an empty line.")
while a == 0:
start = input()
if start == '':
a = a + 1
else:
alfa[0].append(int(start.split(",")[0]))
alfa[1].append(int(start.split(",")[1]))
print(alfa)
Oh, I see #Andrew McDowell has beat me to this. Well here you go anyway...

The error message TypeError: 'int' object does not support item assignment

factor = int(input("Which table would you like: "))
timestable = ([0,0])
for count in range(1,13):
timestable.append([0,0])
result = factor * count
timestable[count][0] = count
timestable [count][1] = result
for row in timestable:
print(row)
This is a program that allows a user to enter in a times table and prints out 1 * the number to 12 * the number. But whenever I go to run the code, I get this error message:
timestable[count][0] = count
TypeError: 'int' object does not support item assignment
Does anyone know what I have to change in my code?
As noted in comments, the problem is that the line timestable = ([0,0]) initializes timestable as just [0, 0]. Thus, after your first append, timestable looks like this: [0, 0, [0, 0]] instead of [[0, 0], [0, 0]], and the value behind timestable[count] is not the newly appended [0,0] but just the second 0 from initialization.
Maybe you wanted to create a one-tuple holding a list, but then you'd have to use ([0,0],) (note the trailing comma), but this won't do you any good, either, as you can not append to tuples. Instead, you should initialize it as a nested list. Also, you can shorten the body of the loop by not first appending zeros and then overwriting those zeros, but appending the correct values directly.
timestable = [[0,0]]
for count in range(1, 13):
timestable.append([count, factor * count])
However, you do not need the separate initialization and loop at all; you an just create timestable in a single list comprehension (note that here, the range starts from 0):
timestable = [[count, factor * count] for count in range(0, 13)]

Resources