Skip to content

Instantly share code, notes, and snippets.

@goldsborough
Created August 18, 2015 18:28
Show Gist options
  • Save goldsborough/49545cd9bac5ae9e70b9 to your computer and use it in GitHub Desktop.
Save goldsborough/49545cd9bac5ae9e70b9 to your computer and use it in GitHub Desktop.
Polynomial parser and calculator using Horner's rule
import re
from collections import namedtuple
def split_equation(equation):
match = re.match(r'^\s*\w+\((\w+)\)\s*=\s*(.*)$', equation)
return match.groups()
def find_terms(equation, var='x'):
pattern = re.compile(r'(-?\s*\d+)?' # coefficient
r'\s*\*?\s*(' + var + r')' # variable
r'(?:\s*\^\s*\(?(\d+)\)?)?' # exponent
r'|(-?\s*\d+)') # constant
Term = namedtuple('Term', ['coef', 'exp'])
terms = []
match = pattern.search(equation)
while match:
coef, var, exp, const = match.groups()
coef = coef if coef else const if const else '1'
exp = int(exp) if exp else 1 if var else 0
terms.append(Term(float(coef.replace(' ', '')), int(exp)))
match = pattern.search(equation, match.end())
return terms
def calculate(equation, value):
var, polynomial = split_equation(equation)
terms = find_terms(polynomial, var)
if not terms:
raise RuntimeError("Equation is ill-formed!")
terms.sort(key=lambda t: t.exp)
y = 0
n = max(terms, key=lambda t: t.exp).exp
j = len(terms) - 1
for i in range(n, -1, -1):
if j >= 0 and terms[j].exp == i:
y = float(terms[j].coef) + value * y
j -= 1
else:
y *= value
return y
def main():
equation = "f(t) = 5t^2 + 3 t^10 - 5 * t + 2"
result = calculate(equation, 2)
print(result)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment