How to add all even numbers in a given range recursively? - python

I have to find the sum of all even numbers between a given range x and y.
I have tried:
def sum_even(x, y):
if x == y:
return x
else:
if x % 2 == 0:
return x + sum_even(x+2, y)
If my given range is (5, 11) then my output should be 24.

Try this:
def sum_even(x, y):
if x >= y:
return 0
if x % 2 == 0:
return x + sum_even(x + 1, y)
return sum_even(x + 1, y)
Examples:
>>> sum_even(5, 11)
24
>>> sum_even(2, 3)
2
>>> sum_even(2, 4)
2
>>> sum_even(2, 5)
6
My code does not include the upper bound y in the sum (see the examples). It might or might not be the desired behavior, but that's depend on your case. If you want to include the upper bound use this code:
def sum_even(x, y):
if x > y:
return 0
if x % 2 == 0:
return x + sum_even(x + 1, y)
return sum_even(x + 1, y)
Examples:
>>> sum_even(5, 11)
24
>>> sum_even(2, 3)
2
>>> sum_even(2, 4)
6
>>> sum_even(2, 5)
6

You might even solve this problem with a O(1) solution. Indeed, you don't need to actually look at ALL the numbers in your range. All you need is a simple mathematical formula. For example, in order to sum all the numbers from 0 to 10^10, you can either do s = sum(x for x in range(10**10 + 1)) (i.e., s = sum(range(10**10 + 1))) or you can use the famous formula s = n * (n + 1) // 2 (i.e., s = 10**10 * (10**10 + 1) // 2). The second approach is much much faster, because you don't need to go through all the numbers in the range.
Similarly in this case you can do this:
def sum_even(x, y):
n1 = y // 2
n2 = (x - 1) // 2
return n1 * (n1 + 1) - n2 * (n2 + 1)
Examples:
>>> sum_even(5, 11)
24
>>> sum_even(2, 3)
2
>>> sum_even(2, 4)
6
>>> sum_even(2, 5)
6
So you don't need recursion and you don't need iteration to solve this problem. Just some math :)

This is your solution patched, I think it could be correct:
def sum_even(x, y):
if x == y or x == y-1:
return x
else:
if x % 2 == 0:
return x + sum_even(x+2, y)
else:
return sum_even(x+1, y)

I assume you want to include x and y (if they're even). For instance, sum_even(2,6) would return 2+4+6.
If you want to exclude the upper bound instead, the code snippets below need a small correction.
# Using python builtin functions `sum` and `range`:
def f1(x, y):
return sum(range(x+x%2, y+1, 2))
# Using arithmetic:
def f2(x, y):
start, end = (x+1)//2, y//2
return end*(end+1) - start*(start-1)
# Using a `for`-loop:
def f3(x, y):
result = 0
for z in range(x, y+1):
if z % 2 == 0:
result += z
return result
# Using recursion:
def f4(x, y):
if x > y:
return 0
elif x % 2 == 1:
return f4(x+1, y)
else:
return x + f4(x+2, y)
# Testing:
print(' x, y --> f1,f2,f3,f4')
for (x, y) in [(5,11), (0,10), (2,6), (12, 17)]:
results = [f(x,y) for f in (f1,f2,f3,f4)]
print('{:2d},{:2d} --> {:2d},{:2d},{:2d},{:2d}'.format(x,y,*results))
# x, y --> f1,f2,f3,f4
# 5,11 --> 24,24,24,24
# 0,10 --> 30,30,30,30
# 2, 6 --> 12,12,12,12
# 12,17 --> 42,42,42,42

Related

Python function doesn't return any values

It works with certain values (e.g "100 12 2"), but fails at "102 12 2" for some reason.
Checked both on Windows and MacOS with different python versions, results are the same and are not affected by setup.
from math import floor
s, x, y = 102, 12, 2
def calc(s, x, y):
q = 0
if x > y:
while s - (s / x) > 0:
q += s / x
q1 = s / x
s = s - (s / x) * x
s += q1 * y
return floor(q)
else:
return 'Inf'
if type(calc(s, x, y)) is int:
print(calc(s, x, y))
else:
print('Inf')
Try replacing the zero in the condition with a small number, such as 1e-16:
from math import floor
s, x, y = 102, 12, 2
def calc(s, x, y):
q = 0
if x > y:
while s - (s / x) > 1e-16:
q += s / x
q1 = s / x
s = s - (s / x) * x
s += q1 * y
return floor(q)
else:
return float('Inf')
print(calc(s, x, y)) # 10
The reason of doing so is that the sequence s - s/x does not become exactly zero; it only gets arbitrarily close to zero. (Even if exact zero is guaranteed algebraically, float is subject to inherent imprecision, so you need some threshold anyways.)

function does't return a list as indented, but returns only one listelement instead

For the sake of practice, I am trying to calculate the following mathematical expression:
The x-value in the parameter is supposed to be a number - an int or float
The y-value in the parameter is supposed to be a list of numbers.
The function is supposed to return a list of values in the same length as the list y in the parameter.
For some embarrassing reason, I only manage to make the function return only one list element, that comes from the first of the two equations in the function.
The code in question is:
def f(x ,y):
list = []
for i in y:
if y[i] <= 0:
list.append(4 * (x ** 3) * y[i] - 2 * x * y[i])
if y[i] > 0:
list.append(4 * (x ** 3) * y[i] + 2 * x * y[i])
return list
x_value = 2
y_values = [1,-2, 3, -7]
print(f(x_value, y_values))
#wanted output: [28, -56, 85, -252]
#actual output: [-56]
My question is:
How do you make this function return a list with all the calculations? Like for example
[28, -56, 85, -252] instead of the current output which is [-56]
This is probably an easy fix, but for some reason I am stuck.
Is there anybody kind enough to help me sort this out?
First, when you have for i in y, i is the actual value in y, not the index, so you don't use y[i], you use i directly. Second, you should return the final list after the for i in y loop is over, so it needs to be outside the loop. And finally, don't use built-in names (such as list) as your own variable/function/class names, because it will overwrite the built-in names.
def f(x ,y):
L = []
for i in y:
if i <= 0:
L.append(4 * (x ** 3) * i - 2 * x * i)
if i > 0:
L.append(4 * (x ** 3) * i + 2 * x * i)
return L
To use i as an index, you need to change the loop to for i in range(len(y)), and use y[i] as you did previously.
Also, if you use numpy, you can solve this as:
>>> import numpy as np
>>> x_value = 2
>>> y_values = np.array([1,-2, 3, -7])
>>> 4 * x_value**3 * y_values + 2 * x_value * np.where(y_values <= 0, -y_values, y_values)
array([ 36, -56, 108, -196])
You can do it briefly with a list comprehension:
def f(x,y):
return [4 * (x ** 3) * yy - 2 * x * yy if yy <= 0
else 4 * (x ** 3) * yy + 2 * x * yy for yy in y]
OR
def f(x, y)
return [4 * (x ** 3) * yy + (int(yy > 0) - 0.5) * 4 * x * yy for yy in y]
To articulate the last example given that is could be a little bit cryptic: in both formulas, the two elements are always the same:
4 * (x ** 3) * yy
2 * x * yy
in the one case you sum them, in the other case you take the difference:
Hence we could write f(x, y) as:
def f(x, y):
lst = []
for yy in y:
a, b = 4 * (x ** 3) * yy, 2 * x * yy
lst.append(a + (1 if yy > 0 else -1) * b
return lst
While there is a case to be esplicit with proper if close, there is also the case for not rewriting the same code/formulas.
Then can go even more compact knowing that bool(yy > 0) is 1 if yy > 0 and 0 otherwise, so 2 * (bool(yy > 0) - 0.5) is 1 and -1 respectively:

The faculty of two numbers python 3

def choose (x, y):
if y > x:
print ("False")
elif y == 0 or y == x:
return 1
elif y == 1:
return x
else:
if (x-y) > y:
biggest = x-y
smallest = y
else:
biggest = y
smallest = x-y
resultatet = x * choose (x-1, biggest)
res = resultatet // smallest
return res
My function is working perfectly with whatever x input I insert but with bigger Y inputs like 8000 for example I'm getting
File "/home/nazel607/labb3b_2.py", line 20, in choose
resultatet = x * choose (x-1, biggest)
File "/home/nazel607/labb3b_2.py", line 3, in choose
if y > x:
RuntimeError: maximum recursion depth exceeded in comparison
Is there a way I can overcome this problem or is it impossible in python due to its limits? Is there another way than increasing the limit?
It seems that you can get rid of the recursion:
def choose2(x, y):
if y > x:
raise ValueError()
if y == 0 or y == x:
return 1
if y == 1:
return x
result = 1
while y != x:
big, small = max(x-y, y), min(x-y, y)
result *= x // small
x -= 1
y = big
return result
I've tested it over few examples:
for x, y in [
(4, 2),
(17, 9),
(125, 79),
(8005, 13),
(9005, 13),
# (19005, 7004) # exceeds max recursion depth on my machine
]:
assert choose(x, y) == choose2(x, y)
and seems to work fine.
You are not exiting the program ...
def choose (x, y):
if y > x:
print ("False")
return
# ...rest of your program

if assertion in z3py

i'm a new user for z3py. I need to write a program that check satisfaction of some rule like
IF room.temp < 18 THEN room.fireplace = on
IF room.temp > 24 THEN room.fireplace = off
IF room.CO > 180 THEN room.fireplace = off
IF room.temp > 28 THEN house.hvac = off
IF house.hvac == on THEN room.fireplace = off
also how to write this
bedroom.occupancy == true and bedroom.env_brightness <= 31.5 and bedroom.light.switch = on
thanks
You need a Z3 If-then-else which can be defined using If in z3.
>>> x = Int('x')
>>> y = Int('y')
>>> max = If(x>y, x, y)
>>> max
If(x > y, x, y)
For defining multiple constraints you can use And and Or
>>> max = If(And(x>y, x!=0), x, y)
>>> max
If(And(x > y, x != 0), x, y)
>>> simplify(max)
If(And(Not(x <= y), Not(x == 0)), x, y)
Hope this helps.
This is a great resource to start with z3py in general.

exercise 7.2: Think Python

"Encapsulate this loop in a function called square_root that takes a as a parameter, chooses a reasonable value of x, and returns an estimate of the square root of a."
def square_root(a):
x = 2
y = (x + a/x) / 2
epsilon = 0.00000000001
if abs(y - x) < epsilon:
print y
while abs(y - x) > epsilon:
x = x + 1
y = (x + a/x) / 2
break
else:
return
print y
square_root(33)
up to putting 33 for 'a', it estimates the correct square root. after that, it starts jumping exponentially, to the point where when I send 100 in for 'a', it guesses the square root to be approximately 18. I don't know if maybe this is the nature of estimating. I know of how to find the precise square root, but this is an exercise from the book "Think Python" and it's to practice with recursion and thinking algorithmically.
You shouldn't be incrementing x by 1 in the loop body. You should be setting x to y (look at the Wikipedia article and notice how x3 depends on x2, and so on):
while abs(y - x) > epsilon:
x = y
y = (x + a/x) / 2
You want to get rid of that break as well, as it makes your while loop pointless. Your final code will then be:
def square_root(a):
x = 2
y = (x + a/x) / 2
epsilon = 0.00000000001
if abs(y - x) < epsilon:
print y
while abs(y - x) > epsilon:
x = y
y = (x + a/x) / 2
print y
But there's still room for improvement. Here's how I'd write it:
def square_root(a, epsilon=0.001):
# Initial guess also coerces `a` to a float
x = a / 2.0
while True:
y = (x + a / x) / 2
if abs(y - x) < epsilon:
return y
x = y
Also, since Python's floating point type doesn't have infinite precision, you can only get about 15 digits of precision anyways, so you might as well just remove epsilon:
def square_root(a):
x = a / 2.0
while True:
y = (x + a / x) / 2
# You've reached Python's max float precision
if x == y:
return x
x = y
But this last version might not terminate if y oscillates between two values.
Here's another way; it just updates x instead of using a y.
def square_root(a):
x = a / 2.0
epsilon = 0.00000001
while abs(a - (x**2)) > epsilon:
x = (x + a/x) / 2
return x
If you want it more abstract create good-enough? and guess as primitives .. Refer to the classic text of SICP here http://mitpress.mit.edu/sicp/full-text/sicp/book/node108.html
so simple , just take x = a and then follow neuton formula , like this :
def square_root(a):
x = a
while True:
print x
y = (x+a/x)/2
if abs(y-x) < 0.0000001:
break
x = y

Categories

Resources