"""
polystuff.py (Python 3.x)
For a curriculum segment when we're not yet wanting to build
user-defined classes.
showpoly -- return an evaluable string with x the variable
evalpoly -- return a numeric result given an evaluable string and x's value
multipoly -- return the product of two polynomials as a tuple of tuples
"""
from operator import itemgetter
def showpoly(A):
"""
Return a close-to-classic polynomial as an evaluable Python string
literal,
given a sequence of tuples for input (see multipoly below). Some
prettifying.
>>> p1 = ((4,2),(-4,1),(-7,0))
>>> showpoly(p1)
'4 * x**2 - 4 * x**1 - 7'
"""
terms = []
for coeff, exp in sorted(A, key=itemgetter(1), reverse=True):
terms.append( "{sign} {coeff}{var}".format(
sign = "+" if coeff > 0 else "-",
coeff = abs(coeff),
var = ' * x**{}'.format(exp) if exp>0 else ""
))
ans = " ".join(terms)
if ans[0] == "+": # prettify
ans = ans[1:].strip()
return ans
def evalpoly(strpoly, x):
"""
Evaluates a polynomial string literal for a given x value
>>> p1 = ((4,2),(-4,1),(-7,0))
>>> thestring = showpoly(p1)
>>> thestring
'4 * x**2 - 4 * x**1 - 7'
>>> evalpoly(thestring, 10)
353
"""
return eval(strpoly, {"x":x})
def multipoly(A, B):
"""
Multiply two polynomials, represented as sequences of tuples
e.g.: 3*x**3 + 2*x**2 - x - 1 would be
((3,3),(2,2),(-1,1),(-1,0))
with internal pairs in any order (term order is arbitrary)
>>> p1 = ((1,1),(-1,0))
>>> p2 = ((1,1),(1,0))
>>> multipoly(p1,p2)
[(-1, 0), (1, 2)]
>>> p1 = ((4,2),(-4,1),(-7,0))
>>> p2 = ((1,1),(3,0))
>>> multipoly(p1,p2)
[(-21, 0), (-19, 1), (8, 2), (4, 3)]
"""
results = []
termsAB = []
# Cartesian product of terms in poly A and poly B
# multiply coefficients, add exponents
for termA in A:
for termB in B:
termsAB.append((
termA[0] * termB[0], # coefficients
termA[1] + termB[1] # exponents
))
# find maximum exponent
degree = max([term[1] for term in termsAB])
# collect like terms (same exponent)
for exp in range(degree+1): # from 0 to degree inclusive
newterm = ( sum([term[0] for term in termsAB if term[1] == exp]),
exp)
if newterm[0] != 0:
results.append(newterm)
return results
def _test( ):
import doctest
doctest.testmod()
if __name__ == '__main__':
_test()