Python Forum
Thread Rating:
  • 2 Vote(s) - 3.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Solve an equation
#1
Hello,
I am stuck with printing the wrong result and I have not found out how to fix it. I am asked to write a program that when you input something like:
print(solve('x', (('a', '-', 'x'), '=', 'c')))
it will solve for x:
('x', '=', ('a', '-', 'c')) 
However, I have to determine whether x is in the equation, say q, or not. If it is, I have to find out whether it is on the left or right of the operator '='. Here is my code:

import types
def left(e):
    return e[0]

def op(e):
    return e[1]

def right(e):
    return e[2]

def isInside(v,e):
    if type(e) == tuple:
        return isInside(v,left(e)) or isInside(v,right(e))
    else:
        if v == e:
            return True
        else:
            return False

def solve(v,q):
    if isInside(v,left(q)):
        return solving(v,q)
    elif isInside(v,right(q)):
        w = (right(q),'=', left(q))
        return solving(v,w)
    else:
        return None
def solving(v,q):
    if type(q) == tuple:
        if op(q)=='+':
            return solvingAdd(v,q)
        elif op(q)=='-':
            return solvingSubtract(v,q)
        elif op(q)=='*':
            return solvingMultiply(v,q)
        elif op(q)=='/':
            return solvingDivide(v,q)
    else:
        return None

def solvingAdd(v,q):
    if v == left(left(q)):
        return (right(q),'-',right(left(q)))
    elif v == right(left(q)):
        return (right(q),'-',left(left(q)))

def solvingSubtract(v,q):
    if v == left(left(q)):
        return (right(q),'+',right(left(q)))
    elif v == right(left(q)):
        return (left(left(q)),'-',right(q))

def solvingMultiply(v,q):
    if v == left(q):
        return (right(q),'/',left(left(q)))
    elif v == right(left(q)):
        return (right(q),'/',right(left(q)))

def solvingDivide(v,q):
    if v == left(q):
        return (right(q),'*',right(left(q)))
    elif v == right(left(q)):
        return (left(left(q)),'/',right(q))
When I run it, it keeps giving me None for these test cases:
print(solve('x', (('a', '+', 'x'), '=', 'c')))
#  ('x', '=', ('c', '-', 'a'))  

print(solve('x', (('x', '+', 'b'), '=', 'c')))
#  ('x', '=', ('c', '-', 'b'))  

print(solve('x', (('a', '-', 'x'), '=', 'c')))
#  ('x', '=', ('a', '-', 'c'))  

print(solve('x', (('x', '-', 'b'), '=', 'c')))
#  ('x', '=', ('c', '+', 'b'))  

print(solve('x', (('a', '*', 'x'), '=', 'c')))
#  ('x', '=', ('c', '/', 'a'))  

print(solve('x', (('x', '*', 'b'), '=', 'c')))
#  ('x', '=', ('c', '/', 'b'))  

print(solve('x', (('a', '/', 'x'), '=', 'c')))
#  ('x', '=', ('a', '/', 'c'))  

print(solve('x', (('x', '/', 'b'), '=', 'c')))
#  ('x', '=', ('c', '*', 'b'))  

print(solve('y', ('y', '=', (('m', '*', 'x'), '+', 'b'))))
# ('y', '=', (('m', '*', 'x'), '+', 'b'))  

print(solve('x', ('y', '=', (('m', '*', 'x'), '+', 'b'))))
# ('x', '=', (('y', '-', 'b'), '/', 'm'))  

print(solve('a', (('b', '+', 'c'), '=', ('d', '*', (('a', '/', 'e'), '-', 'f')))))
# ('a', '=', (((('b', '+', 'c'), '/', 'd'), '+', 'f'), '*', 'e'))  
I took C++ but Python seems pretty odd to me at this point. Thank you!
Reply
#2
In solving(v, q), q is always a tuple of the whole equation you are trying to solve. In the first test case it would be (('a', '+', 'x'), '=', 'c'). So op(q), which is the same as q[1], is always '='. There is no condition in the if/elif chain for op(q) == '='. So it always returns None. I think you want to be testing op(left(q)).

Your Python code is overly complicated. For example:

if v == e:
    return True
else:
    return False
Means "if the boolean v == e is True, return True; if it is False, return False. You can simply say:

return v == e
for the same result. Also note that:

'x' in 'x'
is true. So you could really replace all of isInside with:

v in e
The use of functions just for indexing seems a bit excessive to me. I could understand if it was meant to make the code clearer, but if you want to make your code clearer I would start with replacing all of the single letter variable names. Also, I would replace:

if type(e) == tuple:
with:

if isinstance(e, tuple):
It's the preferred way to type check (if you're not duck typing). Although, if that's how your instructor taught you to do it, I would stick with it.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
Thank you so much. I appreciate it. At this point, I have learned Python for two days ^^, so forgive my inexperience. I will try to fix my code basing on your advice.

So right now, I have fixed part of the code, and thank you for understanding that I have to stick with what my instructor has been teaching in class.
import types
def left(e):
    return e[0]

def op(e):
    return e[1]

def right(e):
    return e[2]

def isInside(x,e):
    if type(e) == tuple:
        return isInside(x,left(e)) or isInside(x,right(e))
    else:
        if x == e:
            return True
        else:
            return False

def solve(x,q):
    if isInside(x,left(q)):
        return solving(x,q)
    elif isInside(x,right(q)):
        w = (right(q),'=', left(q))
        return solving(x,w)
    else:
        return None
def solving(x,q):
    if type(q) == tuple:
        if op(left(q))=='+':
            return solvingAdd(x,q)
        elif op(left(q))=='-':
            return solvingSubtract(x,q)
        elif op(left(q))=='*':
            return solvingMultiply(x,q)
        elif op(left(q))=='/':
            return solvingDivide(x,q)
    else:
        return None

def solvingAdd(x,q):
    if x == left(left(q)):
        return ('x','=',right(q),'-',right(left(q)))
    elif x == right(left(q)):
        return ('x','=',right(q),'-',left(left(q)))

def solvingSubtract(x,q):
    if x == left(left(q)):
        return ('x','=',right(q),'+',right(left(q)))
    elif x == right(left(q)):
        return ('x','=',left(left(q)),'-',right(q))

def solvingMultiply(x,q):
    if x == left(q):
        return ('x','=',right(q),'/',left(left(q)))
    elif x == right(left(q)):
        return ('x','=',right(q),'/',right(left(q)))

def solvingDivide(x,q):
    if x == left(q):
        return ('x','=',right(q),'*',right(left(q)))
    elif x == right(left(q)):
        return ('x','=',left(left(q)),'/',right(q))

print(isInside('x', 'x'))                          #  True   1 point
print(isInside('x', 'y'))                          #  False  1 point
print(isInside('x', ('x', '+', 'y')))              #  True   2 points
print(isInside('x', ('a', '+', 'b')))              #  False  2 points
print(isInside('+', ('a', '+', 'b')))              #  False  2 points
print(isInside('x', (('m', '*', 'x'), '+', 'b')))  #  True   2 points

print(solve('x', (('a', '+', 'x'), '=', 'c')))
#  ('x', '=', ('c', '-', 'a'))  2 points

print(solve('x', (('x', '+', 'b'), '=', 'c')))
#  ('x', '=', ('c', '-', 'b'))  2 points

print(solve('x', (('a', '-', 'x'), '=', 'c')))
#  ('x', '=', ('a', '-', 'c'))  2 points

print(solve('x', (('x', '-', 'b'), '=', 'c')))
#  ('x', '=', ('c', '+', 'b'))  2 points

print(solve('x', (('a', '*', 'x'), '=', 'c')))
#  ('x', '=', ('c', '/', 'a'))  2 points

print(solve('x', (('x', '*', 'b'), '=', 'c')))
#  ('x', '=', ('c', '/', 'b'))  2 points

print(solve('x', (('a', '/', 'x'), '=', 'c')))
#  ('x', '=', ('a', '/', 'c'))  2 points

print(solve('x', (('x', '/', 'b'), '=', 'c')))
#  ('x', '=', ('c', '*', 'b'))  2 points

print(solve('y', ('y', '=', (('m', '*', 'x'), '+', 'b'))))
# ('y', '=', (('m', '*', 'x'), '+', 'b'))  2 points

print(solve('x', ('y', '=', (('m', '*', 'x'), '+', 'b'))))
# ('x', '=', (('y', '-', 'b'), '/', 'm'))  2 points

print(solve('a', (('b', '+', 'c'), '=', ('d', '*', (('a', '/', 'e'), '-', 'f')))))
# ('a', '=', (((('b', '+', 'c'), '/', 'd'), '+', 'f'), '*', 'e'))  5 points
I failed that last test case and I am not sure why i got an error message in line 6 when I defined right, left and op.
Traceback (most recent call last):
  File "/Users/HughNguyen/Google Drive/Notability/UMN Spring 2017/CSCI 1913 Lab/Lab 1.py", line 96, in <module>
    print(solve('y', ('y', '=', (('m', '*', 'x'), '+', 'b'))))
  File "/Users/HughNguyen/Google Drive/Notability/UMN Spring 2017/CSCI 1913 Lab/Lab 1.py", line 22, in solve
    return solving(x,q)
  File "/Users/HughNguyen/Google Drive/Notability/UMN Spring 2017/CSCI 1913 Lab/Lab 1.py", line 30, in solving
    if op(left(q))=='+':
  File "/Users/HughNguyen/Google Drive/Notability/UMN Spring 2017/CSCI 1913 Lab/Lab 1.py", line 6, in op
    return e[1]
IndexError: string index out of range
Reply
#4
Ah, I did not look through the test cases. I see now why tuples are treated differently for isInside. "return x == e" would still work, but whatever.

You have problems before you get to the IndexError. For the fifth test case of solve, your code is giving ('x', '=', 'c', '/', 'x'). You should be getting ('x', '=', 'c', '/', 'a'). The error is in solvingMultiply. Think through how that input is going to go through the program and see if you can figure out why 'x' is getting put on the right side of the equation in solvingMultiply.

If you can figure that out, I would next look at the test inputs after that. They're all giving the wrong answer too. Walk through the code for each of them to try to track down the error. These are two common patterns in debugging. First, walk through the code by hand to find the error. Second, solve the small errors first. Often the larger errors the smaller errors being compounded on each other. I'm not sure if that's the case here. However, you still want to fix the small errors first. You don't want them getting in the way when you try to fix the complicated error.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  solve equation haye 1 2,817 Oct-27-2017, 04:39 PM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020