Reduce and print poly ok!

This commit is contained in:
lafrite 2014-11-11 21:00:45 +01:00
parent 693c982cbe
commit 2b67fc682c
3 changed files with 104 additions and 75 deletions

View File

@ -41,15 +41,15 @@ class Expression(object):
## --------------------- ## ---------------------
## Mechanism functions ## Mechanism functions
def simplify(self): def simplify(self, render=STR_RENDER):
""" Generator which return steps for computing the expression """ """ Generator which return steps for computing the expression """
if not self.can_go_further(): if not self.can_go_further():
yield self.STR_RENDER(self.postfix_tokens) yield render(self.postfix_tokens)
else: else:
self.compute_exp() self.compute_exp()
old_s = '' old_s = ''
for s in self.steps: for s in self.steps:
new_s = self.STR_RENDER(s) new_s = render(s)
# Astuce pour éviter d'avoir deux fois la même étape (par exemple pour la transfo d'une division en fraction) # Astuce pour éviter d'avoir deux fois la même étape (par exemple pour la transfo d'une division en fraction)
if new_s != old_s: if new_s != old_s:
old_s = new_s old_s = new_s

View File

@ -264,7 +264,23 @@ def spe_zip(l1,l2):
ans.append(j) ans.append(j)
return ans return ans
def transpose_fill(list_lists):
"""Transpose a list of list and if inside list have not the same length, fill with last token
:list_lists: a list of list to transpose
:returns: generator which generate lines of the transposed matrix
>>> Polynom.transpose_fill([[1], [2, 3], [4, 5, 6]])
[[1, 2, 4] , [1, 3, 5], [1, 3, 6]]
"""
for i in range(max([len(l) for l in list_lists])):
col = []
for l in list_lists:
try:
col.append(l[i])
except IndexError:
col.append(l[-1])
yield col
def isOperator(exp): def isOperator(exp):
"""Check if the expression is an opération in "+-*/:^" """Check if the expression is an opération in "+-*/:^"

View File

@ -3,8 +3,11 @@
from .expression import Expression from .expression import Expression
from .generic import spe_zip, sum_postfix, expand_list, isNumber from .operator import op
from .generic import spe_zip, expand_list, isNumber, transpose_fill, flatten_list
#from .generic import spe_zip, sum_postfix, expand_list, isNumber
from .render import txt from .render import txt
from itertools import chain
__all__ = ["Polynom"] __all__ = ["Polynom"]
@ -23,6 +26,14 @@ class Polynom(object):
- a: a Expression. [1, Expression("2+3"), 4] designate 1 + (2+3)x + 4x^2 - a: a Expression. [1, Expression("2+3"), 4] designate 1 + (2+3)x + 4x^2
:param letter: the string describing the unknown :param letter: the string describing the unknown
>>> Polynom([1,2,3]).mainOp
'+'
>>> Polynom([1]).mainOp
'*'
>>> Polynom([1,2, 3])._letter
'x'
>>> Polynom([1, 2, 3], "y")._letter
'y'
""" """
self.feed_coef(coef) self.feed_coef(coef)
self._letter = letter self._letter = letter
@ -33,7 +44,7 @@ class Polynom(object):
else: else:
self.mainOp = "+" self.mainOp = "+"
self._isPolynom self._isPolynom = 1
def feed_coef(self, l_coef): def feed_coef(self, l_coef):
"""Feed coef of the polynom. Manage differently whether it's a number or an expression """Feed coef of the polynom. Manage differently whether it's a number or an expression
@ -52,12 +63,22 @@ class Polynom(object):
:returns: the degree of the polynom :returns: the degree of the polynom
>>> Polynom([1, 2, 3]).get_degree()
2
>>> Polynom([1]).get_degree()
0
""" """
return len(self._coef) - 1 return len(self._coef) - 1
def is_monom(self): def is_monom(self):
"""is the polynom a monom (only one coefficent) """is the polynom a monom (only one coefficent)
:returns: 1 if yes 0 otherwise :returns: 1 if yes 0 otherwise
>>> Polynom([1, 2, 3]).is_monom()
0
>>> Polynom([1]).is_monom()
1
""" """
if len([i for i in self._coef if i != 0])==1: if len([i for i in self._coef if i != 0])==1:
return 1 return 1
@ -65,8 +86,7 @@ class Polynom(object):
return 0 return 0
def __str__(self): def __str__(self):
# TODO: Voir si on peut utiliser un render |sam. juin 14 08:56:16 CEST 2014 return txt(self.postfix)
return txt(self.get_postfix())
def __repr__(self): def __repr__(self):
return "< Polynom " + str(self._coef) + ">" return "< Polynom " + str(self._coef) + ">"
@ -74,7 +94,7 @@ class Polynom(object):
def coef_postfix(self, a, i): def coef_postfix(self, a, i):
"""Return the postfix display of a coeficient """Return the postfix display of a coeficient
:param a: value for the coeficient (/!\ as a list) :param a: value for the coeficient (/!\ as a postfix list)
:param i: power :param i: power
:returns: postfix tokens of coef :returns: postfix tokens of coef
@ -86,46 +106,34 @@ class Polynom(object):
if i == 0: if i == 0:
ans = a ans = a
elif i == 1: elif i == 1:
ans = a * (a!=[1]) + [self._letter] + ["*"] * (a!=[1]) ans = a * (a!=[1]) + [self._letter] + [op.mul] * (a!=[1])
else: else:
ans = a * (a!=[1]) + [self._letter, i, "^"] + ["*"] * (a!=[1]) ans = a * (a!=[1]) + [self._letter, i, op.pw] + [op.mul] * (a!=[1])
return ans return ans
def get_postfix(self): @property
def postfix(self):
"""Return the postfix form of the polynom """Return the postfix form of the polynom
:returns: the postfix list of polynom's tokens :returns: the postfix list of polynom's tokens
""" """
self._postfix = [] postfix = []
first_elem = 1
for (i,a) in list(enumerate(self._coef))[::-1]: for (i,a) in list(enumerate(self._coef))[::-1]:
if type(a) == list and str(a[-1]) in "+-*^/": if type(a) == Expression:
# case coef is an arithmetic expression # case coef is an arithmetic expression
self._postfix += self.coef_postfix(a,i) postfix.append(self.coef_postfix(a.postfix_tokens,i))
if not first_elem:
self._postfix.append("+")
first_elem = 0
elif type(a) == list and str(a[-1]) not in "+-*^/": elif type(a) == list:
# case need to repeat the x^i # case need to repeat the x^i
for b in a: for b in a:
if type(b) == list: postfix.append(self.coef_postfix([b],i))
self._postfix += self.coef_postfix(b,i)
else:
self._postfix += self.coef_postfix([b],i)
if not first_elem:
self._postfix.append("+")
first_elem = 0
elif a != 0: elif a != 0:
self._postfix += self.coef_postfix([a],i) postfix.append(self.coef_postfix([a],i))
if not first_elem:
self._postfix.append("+")
first_elem = 0
return self._postfix return flatten_list(self.postfix_add(postfix))
def conv2poly(self, other): def conv2poly(self, other):
"""Convert anything number into a polynom""" """Convert anything number into a polynom"""
@ -149,53 +157,54 @@ class Polynom(object):
:returns: new Polynom with numbers coefficients :returns: new Polynom with numbers coefficients
""" """
steps = [] steps = []
for a in self._coef: # gather steps for every coeficients
coefs_steps = []
for coef in self._coef:
coef_steps = [] coef_steps = []
if type(a) == Expression: if type(coef) != Expression:
# case coef is an arithmetic expression # On converti en postfix avec une addition
coef_steps = list(a.simplify(render = lambda x:x)) postfix_add = self.postfix_add(coef)
# On converti en Expression
steps.append(coef_steps) coef_exp = Expression(postfix_add)
elif type(a) == list:
# case need to repeat the x^i
if [i for i in a if type(i) == list] != []:
# first we simplify arithmetic exp
# Et hop un coup de sorcelerie!
elem = [list(Expression(i).simplify(render = lambda x:self.list_or_num(x))) if type(i) == list else i for i in a ]
elem = expand_list(elem)
coef_steps += elem
exp = elem[-1]
else: else:
exp = a coef_exp = coef
exp = sum_postfix(exp) # On fait réduire l'expression puis on ajoute dans steps
exp = Expression(exp) coef_steps = list(coef_exp.simplify(render = lambda x:Expression(x)))
coef_steps += list(exp.simplify(render = lambda x:x)) # On ajoute toutes ces étapes
coefs_steps.append(coef_steps)
steps.append(coef_steps) # On retourne la matrice
else: for coefs in transpose_fill(coefs_steps):
steps.append(a) yield Polynom(coefs, self._letter)
steps = expand_list(steps)
return [Polynom(s) for s in steps]
@staticmethod @staticmethod
def list_or_num(x): def postfix_add(numbers):
if len(x) == 1: """Convert a list of numbers into a postfix addition
return x[0]
else:
return x
:numbers: list of numbers
:returns: Postfix list of succecive attition of number
>>> Polynom.postfix_add([1])
[1]
>>> Polynom.postfix_add([1, 2])
[1, 2, '+']
>>> Polynom.postfix_add([1, 2, 3])
[1, 2, '+', 3, '+']
>>> Polynom.postfix_add(1)
[1]
"""
if not type(numbers) == list:
return [numbers]
else:
ans = [[a, op.add] if i!=0 else [a] for (i,a) in enumerate(numbers)]
return list(chain.from_iterable(ans))
def simplify(self): def simplify(self):
"""Same as reduce """ """Same as reduce """
return self.reduce() return self.reduce()
def __eq__(self, other): def __eq__(self, other):
o_poly = self.conv2poly(other) o_poly = self.conv2poly(other)
return self._coef == o_poly._coef return self._coef == o_poly._coef
@ -275,23 +284,24 @@ def test(p,q):
print("\n Plus ------") print("\n Plus ------")
for i in (p + q): for i in (p + q):
#print(repr(i)) #print(repr(i))
#print("\t", str(i.get_postfix())) #print("\t", str(i.postfix))
print(i) print(i)
print("\n Moins ------") print("\n Moins ------")
for i in (p - q): for i in (p - q):
#print(repr(i)) #print(repr(i))
#print("\t", str(i.get_postfix())) #print("\t", str(i.postfix))
print(i) print(i)
print("\n Multiplier ------") print("\n Multiplier ------")
for i in (p * q): for i in (p * q):
#print(repr(i)) #print(repr(i))
#print("\t", str(i.get_postfix())) #print("\t", str(i.postfix))
print(i) print(i)
if __name__ == '__main__': if __name__ == '__main__':
from .fraction import Fraction
p = Polynom([1, -2 ]) p = Polynom([1, -2 ])
q = Polynom([4, 7]) q = Polynom([4, 7])
#test(p,q) #test(p,q)
@ -304,10 +314,10 @@ if __name__ == '__main__':
#print("-- Poly étrange --") #print("-- Poly étrange --")
#p = Polynom([1, [[2, 3, "*"],3], 4], "x") p = Polynom([1, [2, 3], 4], "x")
#print(repr(p)) print(repr(p))
#for i in p.simplify(): for i in p.simplify():
# print(repr(i)) print(i)
#print("-- Poly étrange --") #print("-- Poly étrange --")
#p = Polynom([1, [[2, 3, "*"], [4,5,"*"]], 4], "x") #p = Polynom([1, [[2, 3, "*"], [4,5,"*"]], 4], "x")
#print(repr(p)) #print(repr(p))
@ -315,6 +325,9 @@ if __name__ == '__main__':
#for i in p.simplify(): #for i in p.simplify():
# print(repr(i)) # print(repr(i))
import doctest
doctest.testmod()
# ----------------------------- # -----------------------------
# Reglages pour 'vim' # Reglages pour 'vim'