Cos
Cos

Reputation: 129

How do you use a string to solve a math equation using python?

I'm trying to make a python program which takes in a user equation, for example: "168/24+8=11*3-16", and tries to make both sides of the equation equal to each other by removing any 2 characters from the user input. This is what I have so far:

def compute(side):
    val = int(side[0])
    x= val
    y=0
    z=None

    for i in range(1, len(side)-1):
        if side[i].isdigit():
                x= (x*10)+ int(side[i])
                if x == side[i].isdigit():
                    x= int(side[i])

        else:
            op = side[i]
            if op=="+":
                val += x
            elif op == "-":
                val -= x
            elif op == "*":
                val *= x
            else:
                val /=  x



    return print(val)

I have edited my compute function.

def evaluate(e):

    side1 = ""
    side2 = ""
    equalsign = e.index("=")
    side1= e[:equalsign - 1]
    side2= e[:equalsign + 1]
    if compute (side1) == compute(side2):
        return True
    else:
        return False

def solve():

# use a for loop with in a for loop to compare all possible pairs
    pass

def main():

    e= input("Enter an equation: ")
    evaluate(e)

main()

For the actual solve function I want to test all possible pairs for each side of the equation and with every pair removed check if the equation is equal to the other side. I was thinking of using a for loop that said:

    for i in side1:
        j= [:x]+[x+1:y]+[y+1:]
        if compute(j)==compute(side2):
            val= compute(j)    
            return val

How should I go about doing this? I'm getting a little confused on how to really approach this program.

Upvotes: 1

Views: 1861

Answers (2)

Asish M.
Asish M.

Reputation: 2647

Let's get to the preliminary issues.

  • e = raw_input("Enter an equation: ") # input is fine if you are using Python3.x

  • side1 = e[:equalsign] #note that a[start:end] does not include a[end]

  • side2 = e[equalsign + 1:] # not e[:equalsign + 1].

  • val = int(side[0]) # not val = side[0] which will make val a string

  • In the operations part, you are doing val += side # or -= / *= / /= .. remember side is a string

Edits:

  1. Yeah, I'm still stuck up with Python 2.7 (use input if Python 3)
  2. To solve for the value of each side, you could simply use eval(side1) # or eval(side2). There could be alternatives to using eval. (I am a novice myself). eval will also take care of PEMDAS.
  3. Added edit to side1 expression.
  4. Updated with code written so far.

    def compute(side):
    
        return eval(side)
    
    def evaluate(e):
    
        side1, side2 = e.split('=')
        if compute(side1) == compute(side2):
            return (True, e)
        else:
            return (False, 'Not Possible')
    
    def solve(e):
    
    
        for i in range(len(e)):  # loop through user input
            if e[i] in '=':  # you dont want to remove the equal sign
                continue
    
    
            for j in range(i+1, len(e)):  # loop from the next index, you dont want
    
                if e[j] in '=':           # to remove the same char
                    continue              # you dont want to remove '=' or operators
    
                new_exp = e[:i] + e[i+1:j] + e[j+1:]  # e[i] and e[j] are the removed chars
                #print e[i], e[j], new_exp             # this is the new expression    
    
                s1, s2 = new_exp.split('=')
    
                try:
                    if compute(s1) == compute(s2):
                        return (True, new_exp)
                except:
                    continue
        return (False, 'not possible')
    
    def main():
    
        e= raw_input("Enter an equation: ")
        print evaluate(e.replace(' ', ''))
    
    main()
    

This is what I have come up with so far (works for your example at least).

  • It assumes that operators are not to be removed

Final edit: Updated code taking into account @Chronical 's suggestions

  • Removed the try-except block in each loop and instead just use it after calculating each side

Upvotes: 2

Chronial
Chronial

Reputation: 70673

Here is code that does exactly what you want:

from itertools import combinations

def calc(term):
    try:
        return eval(term)
    except SyntaxError:
        return None

def check(e):
    sides = e.split("=")
    if len(sides) != 2:
        return False
    return calc(sides[0]) == calc(sides[1])

equation = "168/24+8 = 11*3-16".replace(" ", "")

for (a, b) in combinations(range(len(equation)), 2):
    equ = equation[:a] + equation[a+1:b] + equation[b+1:]
    if check(equ):
        print equ

Core tricks:

  • use eval() for evaluation. If you use this for anything, please be aware of the security implications of this trick.
  • use itertools.combinations to create all possible pairs of characters to remove
  • Do not try to handle = too specially – just catch it in check()

Upvotes: 1

Related Questions