Python, recursion : give all possible tuple combinations who meet a boolean expression - python

So, for school, I got an exercise on recursion, which goes as follows:
I'm given a string and a random int value 'N'. The string is a boolean expression, for example '3*x - 2* y <0' . The result has to be a list of tuples(x, y), (-N < x < N and -N < y < N), from all the possible tuple combinations who meet the expression. I did this exercise first with for loops etc and that was not so difficult, but then I had to do it recursively, and here's where I got stuck:
As you can see, I just add up x and y by '1' at the end of the code, which will give me all tuple combinations where X and Y are the same. For example, if N = 5, my code only evaluates the combinations (-4,-4), (-3,-3) ... (4,4) but not (-2,1) or (1,3) for example. So my question is: can anyone help me writing a recursive code which evaluates the boolean expression in all the possible tuple combinations?
My code has to be written recursively and I can't use functions as 'itertools' etc, it's not allowed in our school.
**MY CODE:**
def solution(expression, N,x=None,y=None):
if x is None: x = -N + 1
if y is None: y = -N + 1
res = []
if x >= N and y >= N:
return []
if eval(expression) == True:
res.append((x, y))
return res + solution(expression, N, x+1, y+1)

I have modified your code and I think it works now:
UPDATE: I have corrected this expression if x < N - 1 : to that one if x < N - 1 or y < N - 1:
def solution(expression, N, x=None, y=None):
if x is None: x = -N + 1
if y is None: y = -N + 1
res = []
if eval(expression) == True:
res.append((x, y))
# if x < N - 1 :
if x < N - 1 or y < N - 1:
if y < N - 1:
y += 1
else:
x += 1
y = - N + 1
return res + solution(expression, N, x, y)
else:
return res
print(solution('3*x - 2* y <0', 4))

Slightly different approach building on getting permutations for a list and in the end checking the expression. Not the prettiest code but does the job.
results = []
def check(expression, items):
x = y = None
if len(items) == 1:
x = y = items[0]
if eval(expression) and (x, y) not in results:
results.append((x, y))
if len(items) == 2:
x = items[0]
y = items[1]
if eval(expression) and (x, y) not in results:
results.append((x, y))
x = items[1]
y = items[0]
if eval(expression) and (x, y) not in results:
results.append((x, y))
if len(items) > 2:
for i in items:
remaining_elements = [x for x in items if x != i]
check(expression, remaining_elements)
expression = "3*x - 2*y < 0"
N = 4
items = range(-N + 1, N)
check(expression, items)
print(results)

Related

Function comparison

I was doing this leetcode question:
https://leetcode.com/problems/find-positive-integer-solution-for-a-given-equation/
My code was:
res = []
for x in range(1,1001):
for y in range(1000,0,-1):
test = customfunction.f(x,y)
if test == z:
res.append([x,y])
return res
but this timed out,
a solution was:
def findSolution(self, customfunction, z):
res = []
y = 1000
for x in xrange(1, 1001):
while y > 1 and customfunction.f(x, y) > z:
y -= 1
if customfunction.f(x, y) == z:
res.append([x, y])
return res
given the for loop and the while loop. it seems like these two functions do exactly the same thing.
Why does my code time out but the while loop doesn't?
The working version breaks out of the inner loop once the result of the custom function is reaches z.
You can get the same result using a break in the for loop.
for x in range(1,1001):
for y in range(1000,0,-1):
test = customfunction.f(x,y)
if test == z:
res.append([x,y])
elif test < z:
break

Python: Print largest even number from 3 inputs without using list and max()

The program first asks for 3 integers then computes for the largest even from the set. It will print None if there are no even numbers. We are not allowed to use built-in functions (like max()) and not allowed to import math libraries.
What code can I use so it does not print None when I input x = 11, y = 11, z = 8? The correct output should be 8.
def getMaximum(x,y,z):
if x >= y and x >= z:
return x
elif y >= x and y >= z:
return y
else:
return z
def getLargestEven(x,y,z):
LargestVal = getMaximum(x,y,z)
if LargestVal%2 == 0:
return LargestVal
elif x%2 == 0 and (x > y or x > z):
return x
elif y%2 == 0 and (y > x or y > z):
return y
elif z%2 == 0 and (z > x or z > y):
return z
else:
return None
x = int(input("Enter x: "))
y = int(input("Enter y: "))
z = int(input("Enter z: "))
print("Largest Even:", getLargestEven(x,y,z))
You can also use a simple loop structure to test for the maximum even number among three
def getLargestEven(x,y,z):
max_num = -99999999999999
for num in [x,y,z]:
if num%2==0:
if num>max_num:
max_num = num
return None if max_num ==-99999999999999 else max_num

How would I write this using set comprehension?

It works using a regular loop but I want it to work using set comprehension.
def setComp():
result = set()
for n in range(1, 101):
x = n
y = x**2
if y%x == 0 and y%3 == 0:
tup = (x,y)
result.add(tup)
return result
print(setComp())
This is what I have:
result = { x = n, y = x**2 for n in range(1, 101)if n%x == 0 and y%3 == 0 }
Try it
{(x, x**2) for x in range(1,101) if (x**2) %3 == 0}
You can do this with a one-liner list comprehension
result = {(n, n ** 2) for n in range(1, 101) if (n ** 2 % n) == 0 and ((n ** 2) % 3 == 0)}
However the downside to this is that is has to calculate n**2 three times during the comprehensive. For better performance, generate two list and use zip in the comprehension
xs = range(1, 101)
ys = [n ** 2 for n in q]
reuslts = {(x, y) for x, y in zip(xs, ys) if (y % x) == 0 and (y % 3 == 0)}
The latter option provides better performance than the former
import timeit
xs = range(1, 101)
ys = [n ** 2 for n in xs]
def l():
return {(n, n ** 2) for n in xs if (n ** 2 % n) == 0 and ((n ** 2) % 3 == 0)}
def f():
return {(x, y) for x, y in zip(xs, ys) if (y % x) == 0 and (y % 3 == 0)}
print('l', timeit.timeit(l))
>>> 68.20
print('f', timeit.timeit(f))
>>> 19.67

distance from root search of tree fails

The tree is as follows:
(1,1)
/ \
(2,1) (1,2)
/ \ / \
(3,1)(2,3) (3,2)(1,3)
and onward
The root is (1,1), all values in the tree are tuples.
Where (x,y) is an element of the tree:
The leftChild will be (x+y,y)
The rightChild will be (x,x+y)
I am building a function that finds the distance from the root (1,1). I cannot build the tree from scratch as it will be too time consuming.
I have found that 1 distance from the tuple being searched for we must subtract the the max with the min. We can work backward.
1 2
(3,2)->(1,2)->(1,1)
(3,2)->(3-2,2) = (1,2)->(1,2-1) = (1,1)
given this is always true:
if x > y:
newtuple = (x-y,y)
distance += 1
else if y > x:
newtuple = (x,y-x)
distance += 1
Yet because possible test cases can go up to even x = 10^50, this is even too slow.
So I have found a formally to find the amount of subtractions of x with y or vice versa to make a x > y change to y < x and vice versa until (x,y) = (1,1).
So X - Y(a certain amount of times, say z) will make x less than y...
X - Y*z = y
find z via algebra... z = (Y-X)/(-Y)
This is my code so far:
from decimal import Decimal
import math
def answer(M,F):
M = int(M)
F = int(F)
i = 0
while True:
if M == 1 and F == 1:
return str(i)
if M > F:
x = math.ceil((F-M)/(-F))
M -= F*x
elif F > M:
x = math.ceil((M-F)/(-M))
F -= M*x
else:
if F == M and F != 1:
return "impossible"
i += x
if M < 1 or F < 1:
return "impossible"
return str(i)
And it's not passing some unknown test cases, yet passes all the test cases I can think of. What test cases could I be failing? Where is my code wrong?
p.s. used Decimal module, just removed from code to make more readible.
Floor division allows for no loss, but maybe -1 in error which I consider for the code below.
def answer(M,F):
M = int(M)
F = int(F)
i = 0
while True:
if M == 1 and F == 1:
return str(i)
if M > F:
x = F-M
x = x//(-F)
if F < M-(F*x):
x += 1
M -= F*x
elif F > M:
x = M-F
x = x//(-M)
if M < F-(M*x):
x += 1
F -= M*x
else:
if F == M and F != 1:
return "impossible"
i += x
if M < 1 or F < 1:
return "impossible"
return str(i)

IndexError: list index out of range in Python for function

I tried looking on this site but i can't find exactly what's going wrong with my program. It makes it all the way to 13 or the data_list[25] but then it spits out that IndexError message.
def rlEncode(n, z, data_list):
while data_list[n] == data_list[n+1]:
z = z + 1
n = n + 1
while data_list[n] != data_list[n+1]:
return (n, z)
def unitTest( ):
counter = 0
n = 0
z = 1
data_list = [1,1,1,1,1,3,3,5,5,5,5,5,5,6,8,8,1,1,1,5,5,5,5,13,14, 14]
compress_list = [ ]
while counter < len(data_list):
rlEncode(n, z, data_list)
x, y = rlEncode(n, z, data_list)
compress = [data_list[x], y]
counter = counter + 1
compress_list = compress_list + compress
n = x+1
z = 1
continue
print("list: ", data_list)
print("compressed: ", compress_list)
In your rlEncode function, you are checking the while condition after incrementing n too high:
def rlEncode(n, z, data_list):
while data_list[n] == data_list[n+1]:
z = z + 1
n = n + 1
The first time you check data_list[n] == data_list[n + 1] it's ok ... but then you do n = n + 1, and go back to check the while condition. At this point, if n is 25, data_list[n + 1] will give you an index error, because data_list[25 + 1] does not exist.
You can check this by adding a print line like print(n, len(data_list)) just after n = n + 1.
So either make sure you only iterate from 0 to 24, or make sure you do something like:
if n == len(data_list) - 1:
break
You always have to keep the upper bounds of your arrays in mind when you are doing things like list[n + 1] anywhere in your algorithm.
Spoilers: Solution below:
In order to get your code working, I made two changes:
def rlEncode(n, z, data_list):
# Make sure we don't overrun our list length:
while n < len(data_list) - 1 and data_list[n] == data_list[n + 1]:
z += 1
n += 1
return (n, z)
def unitTest( ):
counter = 0
n = 0
z = 1
data_list = [1,1,1,1,1,3,3,5,5,5,5,5,5,6,8,8,1,1,1,5,5,5,5,13,14,14]
compress_list = []
while n < len(data_list) - 1: # Use n here, not counter
rlEncode(n, z, data_list)
x, y = rlEncode(n, z, data_list)
compress = [data_list[x], y]
counter = counter + 1
compress_list = compress_list + compress
n = x + 1
z = 1
print("list: ", data_list)
print("compressed: ", compress_list)
unitTest()
('list: ', [1,1,1,1,1, 3,3, 5,5,5,5,5,5, 6, 8,8, 1,1,1, 5,5,5,5, 13, 14,14])
('compressed: ', [1,5, 3,2, 5,6, 6,1, 8,2, 1,3, 5,4, 13,1, 14,2])

Categories

Resources