0

Is there a way to solve a simple linear equation like

 -x+3 = x+5

Using binary search? or any other numerical method?

BACKGROUND:
My question comes because I want to solve equations like "2x+5-(3x+2)=x+5" Possible operators are: *, -, + and brackets.

I thought first of converting it to infix notation both sides of the equation, and then performing some kind of binary search.

What do you think of this approach? I'm supposed to solve this in less than 40 min in an interview.

Jodes
  • 14,118
  • 26
  • 97
  • 156
capsula
  • 498
  • 1
  • 7
  • 21
  • If you don't get answer you can post your question on either one of two web (1) [Computer Science beta](http://cs.stackexchange.com/questions), (2) [Mathematics](http://math.stackexchange.com/) good luck – Grijesh Chauhan Mar 08 '13 at 20:12
  • 2
    Are you sure the purpose of this interview is to check your ability to ask SO questions? – Sebastian Mar 08 '13 at 20:14
  • 2
    What I think of your proposed approach is that I wouldn't hire you if that was the best you could come up with in 40 minutes. I suggest you start by thinking how you would solve such equations with pencil and paper. – High Performance Mark Mar 08 '13 at 20:18

3 Answers3

1
  1. It is not hard to write a simple parser that solves $-x+3 -(x+5) = 0$ or any other similar expression algebraically to $a*x + b = 0$ for cumulated constants $a$ and $b$. Then, one could easily compute the exact solution to be $x = -b/a$.

  2. If you really want a numerical approach, observe that both sides describe their own linear function graph, i.e., $y_l = -x_l+3$ on the left an $y_r = x_r + 5$ on the right. Thus, finding a solution to this equation is the same as finding an intersection point of both functions. Therefore you can start with any value $x=x_l=x_r$ and evaluate both sides to get the corresponding left and right $y$-values $y_l$ and $y_r$. If their difference is $0$, then you found a solution (either the unique intersection point by luck, or both lines are equal as in $2x = 2x$). Otherwise, check, e.g., position $x+1$. If the new difference $y_l - y_r$ is unchanged to before, both lines are parallel (for example $2x = 2x + 7$). Otherwise the difference has gone farer away or nearer towards 0 (from positive or negative side). So, now you have all that you need to numerically test further points $x$ (e.g., in a binary search fashion if you at first look for some $x$ that achieves a positive $y$-difference and another $x$ that achieves a negative $y$-difference and then run binary search between them) to approximate the $x$-value for which the difference $y_l - y_r$ is $0$. (Of course, you could alternatively compute the solution algebraically again, since evaluating the lines at two positions gives you all information that you need to compute the intersection point exactly).

Thus, the numerical approach is quite absurd here, but it motivates this algorithmic way of thinking.

cubic lettuce
  • 6,301
  • 3
  • 18
  • 25
0

Do you really need to solve it with a numerical approach? I'm pretty sure you can, but it's not so hard to parse the expression to solve it analytically. I mean, if it is indeed a linear equation, it's just a matter to discover what is the coeficient of x and the free term when the equation is reduced. In the 26 minutes of this question, I made a simple parser to do that, by hand:

import re, sys, json

TOKENS = {
    'FREE': '[0-9]+', 
    'XTERM': '[0-9]*x', 
    'ADD': '\+', 
    'SUB': '-', 
    'POW': '\^',
    'MUL': '\*', 
    'EQL': '=',
    'LPAREN': '\(',
    'RPAREN': '\)',
    'EOF': '$'
}

class Token:
    EOF = lambda p: Token('EOF', '', p)

    def __init__(self, name, raw, position):
        self.name = name
        self.image = raw.strip()
        self.raw = raw
        self.position = position

class Expr:
    def __init__(self, x, c):
        self.x = x
        self.c = c

    def add(self, e):
        return Expr(self.x + e.x, self.c + e.c)

    def sub(self, e):
        return Expr(self.x - e.x, self.c - e.c)

    def mul(self, e):
        return Expr(self.x * e.c + e.x * self.c, self.c * e.c)

    def neg(self):
        return Expr(-self.x, -self.c)


class Scanner:
    def __init__(self, expr):
        self.expr = expr
        self.position = 0

    def match(self, name):
        match = re.match('^\s*'+TOKENS[name], self.expr[self.position:])
        return Token(name, match.group(), self.position) if match else None

    def peek(self, *allowed):
        for match in map(self.match, allowed):
            if match: return match

    def next(self, *allowed):
        token = self.peek(*TOKENS)
        self.position += len(token.raw)
        return token

    def maybe(self, *allowed):
        if self.peek(*allowed):
            return self.next(*allowed)

    def following(self, value, *allowed):
        self.next(*allowed)
        return value

    def expect(self, **actions):
        token = self.next(*actions.keys())
        return actions[token.name](token)

def evaluate(expr, variables={}):
    tokens = Scanner(expr)

    def Binary(higher, **ops):
        e = higher()        
        while tokens.peek(*ops):
            e = ops[tokens.next(*ops).name](e, higher())
        return e

    def Equation():
       left = Add()
       tokens.next('EQL')
       right = Add()
       return left.sub(right)

    def Add(): return Binary(Mul, ADD=Expr.add, SUB=Expr.sub)
    def Mul(): return Binary(Neg, MUL=Expr.mul)

    def Neg():
        return Neg().neg() if tokens.maybe('SUB') else Primary()

    def Primary():
        return tokens.expect(
            FREE = lambda x: Expr(0, float(x.image)),
            XTERM = lambda x: Expr(float(x.image[:-1] or 1), 0),
            LPAREN = lambda x: tokens.following(Add(), 'RPAREN')) 


    expr = tokens.following(Equation(), 'EOF')
    return -expr.c / float(expr.x)

print evaluate('2+2 = x')
print evaluate('-x+3 = x+5')
print evaluate('2x+5-(3x+2)=x+5')
Juan Lopes
  • 10,143
  • 2
  • 25
  • 44
-1

First, your question must be related to Solving Binary Tree. A method that you can use is to construct a binary try putting the root the operator with highest priority, following lower priority operators and operations are leaf nodes. You can learn about this method in solving equation.

Community
  • 1
  • 1
Mihai8
  • 3,113
  • 1
  • 21
  • 31