Python: Nesting an "If" statement inside a "while" loop? - python

I'm new to Python, which is why I'm having trouble on a problem which others might find easy.
Background to this problem: Euler Project, question 2. The problem essentially asks us to add all the even terms in the Fibonacci sequence, so long that each term is under 4,000,000. I decided to do the problem a little differently than what many solutions online show, by calculating the nth Fibonacci term from a closed formula. For now, suppose this function is called Fibonacci(n).
What I'd essentially like to do is loop through an unknown amount of integers that represent the indexes of the Fibonacci set (i.e., 1, 2, 3, 4... etc) and plug each value into Fibonacci(n). If the result has no remainder when divided by 2, then add this Fibonacci number to some value initially set at 0.
Here's what I have so far:
def Fibonacci(n):
return (1/(5**0.5))*((((1+5**0.5)/2)**n)-(((1-5**0.5)/2)**n))
i=0
FibSum = 0
nFib = 0
while (nFib <= 10):
nFib = Fibonacci(i)
if(nFib%2==0):
FibSum += nFib
i += 1
print FibSum
(Yes, as you can see, I'm constraining the Fibonacci sequence to end at 10 as opposed to 4,000,000; this is done merely for testing's sake.)
Now, here's my problem: when I run this code, I get 2.0 instead of 10.0 (2 and 8 are the two Fibonacci numbers that should be added together).
How come? My guess is that the loop stops after it gets to the third Fibonacci number (2) and doesn't continue beyond that. Does anyone see something wrong with my code?
Please comment if you have any further questions. Thanks in advance.

Solution provided by Gal Dreiman is fine but, conversion with in function is more better, below is your revised code:
def Fibonacci(n):
return int((1/(5**0.5))*((((1+5**0.5)/2)**n)-(((1-5**0.5)/2)**n)))

You have a floating point problem (which you can read on here)- the returned value 'nFib' is not an integer and not a rounded value. I ran your code and added print for this value in every iteration and got:
0.0
1.0
1.0
2.0
3.0000000000000004
5.000000000000001
8.000000000000002
13.000000000000002
The solution for this is to modify your code as the following:
nFib = int(Fibonacci(i))
After that I got the output: 10

The problem is with nFib%2==0 comparison. Here you try to compare the float LHS with integer 0. So either modify the if loop as below or modify the return as return int((1/(5**0.5))*((((1+5**0.5)/2)**n)-(((1-5**0.5)/2)**n))).
>>> def Fibonacci(n):
... return (1/(5**0.5))*((((1+5**0.5)/2)**n)-(((1-5**0.5)/2)**n))
...
>>> i=0
>>> FibSum = 0
>>> nFib = 0
>>> while (nFib <= 10):
... nFib = Fibonacci(i)
... if(int(nFib%2)==0):
... FibSum += nFib
... i += 1
...
>>> print FibSum
10.0

Related

Expanding taylor series using relation between successive terms with a specified tolerance in spyder

I have used this code to determine the value of e^pi with a specified tolerance in spyder(Python 3.8).
from math import*
term=1
sum=0
n=1
while (abs(e**pi-term))>0.0001:
term=term*pi/n
sum+=term
n+=1
print(sum,e**pi)
I ran this code several times. But spyder is not showing anything when I run this code. I am new to python. So now I have no way to know whether this code is correct or not. It would be beneficial if you could verify whether this code is valid or not.
Okay, so the taylor series for e^x is sum n=0 to inf of x^n / n! which you seem to be doing correctly by multiplying by pi/n during each iteration.
One problem I noticed was with your while loop condition. To check the error of the function, you should be subtracting your current sum from the actual value. This is why you enter the infinite loop, because your term will approach 0, so the difference will approach the actual value, e^pi, which is always greater than .0001 or whatever your error is.
Additionally, since we start n at 1, we should also start sum at 1 because the 0th term of the taylor series is already 1. This is why you enter the infinite loop, because
Therefore, our code should look like this:
from math import*
term = 1
sum = 1
n = 1
while (abs(e ** pi - sum)) > 0.0001:
term = term * pi / n
sum += term
n += 1
print(sum,e**pi)
Output:
23.140665453179782 23.140692632779263
I hope this helped answer your question! Please let me know if you need any further clarification or details :)
The while loop does not end.
I have stuck in a condition to break out of the loop (at 10,000 cycles) to show this:
from math import*
term=1
sum=0
n=1
while (abs(e**pi-term))>0.0001:
term=term*pi/n
sum+=term
n+=1
if n > 10_000:
print('large n')
break
print(sum,e**pi)
If you replace the while loop with a for loop, then you can see each iteration as follows.
term=1
sum=0
for n in range(1, 101):
term=term*(math.pi)/n
sum+=term
print(n, sum, math.e**math.pi)
And this is the result for the first 10 items:
1 3.141592653589793 23.140692632779263
2 8.076394854134472 23.140692632779263
3 13.244107634184441 23.140692632779263
4 17.30281976060121 23.140692632779263
5 19.852983800478555 23.140692632779263
6 21.188246569333145 23.140692632779263
7 21.787511098653937 23.140692632779263
8 22.02284172901283 23.140692632779263
9 22.104987615623955 23.140692632779263
10 22.13079450701397 23.140692632779263
The numbers are getting larger, hence the while loop was never exited (and your laptop probably got quite hot in the process !!).

How do I count how many times I've divided in a recursion?

I'm currently taking a course in Computer Science, I got an assignment to use either Python or pseudocode to ask the user to enter a digit, then divide it by 2, and then count how many divisions it takes to reach 1 (and add 1 more as it reaches 1). I've never coded before but I came up with this; but it only returns a 1 no matter what I input.
def divTime (t):
if d <= 1:
return t + 1
else:
return t + 1, divTime(d / 2)
d = input("Enter a number:")
t = 0
print (divTime)(t)
You can add 1 to the recursive call with the input number floor-divided by 2, until the input number becomes 1, at which point return 1:
def divTime(d):
if d == 1:
return 1
return 1 + divTime(d // 2)
so that:
print(divTime(1))
print(divTime(3))
print(divTime(9))
outputs:
1
2
4
This works:
def div_time(d, t=0):
if d < 1:
return t
else:
return div_time(d/2, t+1)
d = input("Enter a number:")
print(f"t = {div_time(int(d))}")
It always returns 1 because you're always passing it 0.
It looks like you're "thinking in loops" – you don't need a separate counter variable.
How many times does it take to divide:
k smaller than 2? None.
k greater than or equal to 2? One more than it takes to divide k // 2.
That is,
def divTime(x):
if x < 2:
return 0
return 1 + divTime(x // 2)
or
def divTime(x):
return 0 if x < 2 else 1 + divTime(x //2)
Instead of providing a straight forward answer, I'll break the problem out into a few steps for students:
Ignore the input and edge cases for now, let's focus on writing a function that solves the problem at hand, then we may come back to providing an input to this function.
Problem statement confusion - You will often divide an odd number with a remainder, skipping the exact number 1 due to remainders. There is ambiguity with your problem from dealing with remainders - we will reword the problem statement:
Write a function that returns the number of times it takes to divide an input integer to become less than or equal to 1.
The next part is identifying the type of algorithm that can solve this type of problem. Since we want to run the function an unknown amount of times using the same function, this seems to be a perfect use case of recursion.
Say I provide 10 as an input. We then want to say 10/2=5 (count 1), 5/2=2.5 (count 2), 2.5/2=1.25 (count 3), 1.25/2=0.625 (count 4), return [4] counts.
Now we know we need a counter (x = x+1), recursion, and a return/print statement.
class solution:
''' this class will print the number of times it takes to divide an integer by 2 to become less than or equal to 1 '''
def __init__(self):
#this global counter will help us keep track of how many times we divide by two. we can use it in functions inside of this class.
self.counter=0
def counter_2(self, input_integer):
#if the input number is less than or equal to 1 (our goal), then we finish by printing the counter.
if input_integer<=1:
print(self.counter, input_integer)
#if the input is greater than 1, we need to keep dividing by 2.
else:
input_integer=input_integer/2
#we divided by two, so make our counter increase by +1.
self.counter=self.counter+1
#use recursion to call our function again, using our current inputer_integer that we just divided by 2 and reassigned the value.
self.counter_2(input_integer)
s=solution()
s.counter_2(10)

HackerRank gives 'Wrong Answer' for all hidden test cases

I was trying Project Euler Challenge #2 on the HackerRank, and my Python code passed the sample test case but failed the hidden test cases, with the compiler displaying 'Wrong Answer' for all of them. Here is the link to the challenge-
https://www.hackerrank.com/contests/projecteuler/challenges/euler002/problem
What is the mistake I have committed?
I have tried various inputs (including huge values and many test cases). It had given me correct answers when I executed them in PyCharm editor. I think I have covered all range of inputs. If not, please let me know.
t=int(input().rstrip())
n=[]
for i in range(t):
n.append(int(input().rstrip()))
inp=sorted(n)
f1=1
f2=2
sf=2 #sum of fibonacci
it=iter(inp)
value=next(it)
out=[None]*len(n)
maxi=max(inp)
while f2<=maxi:
f1=f1+f2
f2=f1+f2
f1=f2-f1
f2=f2-f1
if f2>value:
out[n.index(value)]=sf
try:
value=next(it)
except StopIteration:
pass
if f2%2==0:
sf=sf+f2
print(*out,sep='\n')
I'm not sure this answer will help future readers, but let's go though your code quickly.
Let's try a different input:
3
10
11
12
For the new examples, the outputs should be 10 as well (the next number in the sequence after 8 is 13):
10
10
10
If we run your program with this input, we get:
10
None
None
Oops! That looks like a bug. Where is the None coming from? The list of outputs is filled with None when the program initializes: out=[None]*len(n) so it seems like the correct value is not put in the output list.
The line where the values are filled in: out[n.index(value)]=sf only runs once for each item in the input list. The problem seems to be that inputs that have the same output will only be computed once.
I'm guessing you were trying to reduce the runtime complexity by calculating all values in one iteration, instead of generating the Fibonacci sequence for each input. That's smart!
So, we noticed that inputs with the same output value only updates the first value in output. What if we do for all values smaller than f2 instead?
t=int(input().rstrip())
n=[]
for i in range(t):
n.append(int(input().rstrip()))
inp=sorted(n)
f1=1
f2=2
sf=2 #sum of fibonacci
it=iter(inp)
value=next(it)
out=[None]*len(n)
maxi=max(inp)
while f2<=maxi:
f1=f1+f2
f2=f1+f2
f1=f2-f1
f2=f2-f1
while f2>value:
out[n.index(value)]=sf
try:
value=next(it)
except StopIteration:
break
if f2%2==0:
sf=sf+f2
print(*out,sep='\n')
Only two things changed, the if f2>value: is now while f2 > value: and instead of pass when there are no more values, we break out of the while loop instead. That takes care of the first problem, it seems. The output is now what we expected:
10
10
10
Ok, let's try another input. Remember, it doesn't say anywhere that the inputs are unique. They might occur more than once - what will happen if they do? Let's try this input:
2
100
100
The output should just be 44 twice, right? With the new version above, we get:
44
None
Oh no, another bug. The problem seems to be on the line that updates the output, again: out[n.index(value)]=sf. It's clear that if the input is something like [100, 100], the output should be [44, 44] but n.index(100) will always be 0. The index method will only return the first index that matches a value. Now we have more than one and this will not work.
There are obviously many solutions to this, but let's put the answers in a dictionary called results instead and create out at the end once we know what all the outputs are supposed to be:
t=int(input().rstrip())
n=[]
for i in range(t):
n.append(int(input().rstrip()))
inp=sorted(n)
f1=1
f2=2
sf=2 #sum of fibonacci
it=iter(inp)
value=next(it)
results = {}
maxi=max(inp)
while f2<=maxi:
f1=f1+f2
f2=f1+f2
f1=f2-f1
f2=f2-f1
while f2>value:
results[value] = sf
try:
value=next(it)
except StopIteration:
break
if f2%2==0:
sf=sf+f2
out = [results[x] for x in n]
print(*out, sep='\n')
This one passes all the HackerRank test cases as well.
You were so close, nice!
The problem in your print(*out,sep='\n'). You should call print in loop
Try this. All tests passed
#!/bin/python3
import sys
t = int(input().strip())
for a0 in range(t):
n = int(input().strip())
if (n < 2) :
print(0)
continue
# Initialize first two even prime numbers and their sum
ef1, ef2 = 0, 2
sm = ef1 + ef2
# calculating sum of even Fibonacci value
while ef2 <= n:
# get next even value of Fibonacci sequence
ef3 = 4 * ef2 + ef1
# If we go beyond limit, we break loop
if ef3 > n:
break
# Move to next even number and update sum
ef1, ef2 = ef2, ef3
sm = sm + ef2
print(sm)

How do I write an iterative function that computes the sum of the first n odd numbers it returns 1 + 3 + .... + (2n - 1), using a for loop?

Assuming that n is a positive integer
this is my code:
def sum_odd_n(n):
x =1
for x in range(n):
if x%2==1:
continue
return x + 2
but when I run it on Python it gives me the answer 2. Could you help me by telling me what's wrong and what I should do to solve this?
Since you want to find the sum of first 'n' odd numbers, I suggest you to use range function with step=2. I'll elaborate:
def sum_n(n):
addition=0
for x in range(1,2*n,2):
addition+=x
return addition
s=sum_n(5)
print(s)
This gives output as: 25
Here, in range function, 1st attribute provides starting point, 2nd attribute provides the end point, and 3rd attribute gives the Difference between each number in the sequence.
I hope this helps.
There are a few problems with your code.
The first is that you have a return statement inside the for loop.
Secondly, you just visit the first n integers and check which of them are odd. You won't visit all the first n odd integers.
A list comprehension solution solution is as follows.
def sum_odd_n(n):
# sum up the first n odd numbers
return sum([2*i + 1 for i in range(n)])
Check this program it will work:
a=int(input("how many first odd number sum you want"))
x=1
i=0
def OddSum():
global i
global x
while i<=a:
x+=2
i+=1
print(x)
OddSum()

Project Euler using Python, Regarding definition of multiples

I started programming recently, my first language being python. I know just the basics of the language including conditionals, loops, range and some other functions.
I tried to solve project euler's problem 1 using python. The problem statement is as follows:
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
Here's my solution:
z=0
for x in range(0,1000,1):
if type(x%3)==int or type(x%5)==int:
z=x+z
print z
The answer i get is 499500 which is wrong. I tried searching for an answer and found that replacing the third line of my solution:
if type(x%3)==int or type(x%5)==int
with
if x%3==0 or x%5==0
yields the correct answer which is 233168.
Why is my code wrong? So far as I'm aware, a multiple need not leave the remainder as zero. For instance, 255 is a multiple of 5. But 255%5 does not leave the remainder as zero. So how does the line if x%3==0 or x%5==0 correct the answer when in fact, it ignores the definition of multiples.
Or perhaps I have wrongly assumed what multiples are. Please help me.
Thank you.
The problem with your original code, is that Modulo operation with natural numbers always yields a natural number.
print type(4%3)
#print <type 'int'>
print type(4%3)==int
#print True
So, what you are doing is basically summing all numbers between 0 and 1000:
print sum(range(0,1000,1))
#prints 499500
Hope that helps
a is a multiple of b iff a = k b with k an integer. Then % is modulo, which is defined like that:
a % b = z iff a = k b + z with k (and z) integers (and 0 <= z < b)
Therefore if z= 0, then a = k b and a is a multiple of b.

Categories