diff --git a/mapytex/__init__.py b/mapytex/__init__.py index 7463527..ffaf601 100644 --- a/mapytex/__init__.py +++ b/mapytex/__init__.py @@ -1,9 +1,9 @@ #!/usr/bin/env python # encoding: utf-8 -from .calculus import Expression, Polynom, Fraction, random_str, txt, Equation -from .stat import Dataset, WeightedDataset -from .geometry import random_pythagore +#from .calculus import Expression, Polynom, Fraction, random_str, txt, Equation +#from .stat import Dataset, WeightedDataset +#from .geometry import random_pythagore # ----------------------------- # Reglages pour 'vim' diff --git a/mapytex/calculus/abstract_polynom.py b/mapytex/calculus/abstract_polynom.py deleted file mode 100644 index 28305ea..0000000 --- a/mapytex/calculus/abstract_polynom.py +++ /dev/null @@ -1,754 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -from .explicable import Explicable -from .expression import Expression -from .step import Step -from .renderable import Renderable -from .operator import op -from .generic import spe_zip, isNumber, transpose_fill, flatten_list, isPolynom, postfix_op -from functools import wraps - - -def power_cache(fun): - """Decorator which cache calculated powers of polynoms """ - cache = {} - - @wraps(fun) - def cached_fun(self, power): - if (tuple(self._coef), power) in cache.keys(): - return cache[(tuple(self._coef), power)] - else: - poly_powered = fun(self, power) - cache[(tuple(self._coef), power)] = poly_powered - return poly_powered - return cached_fun - - -class AbstractPolynom(Explicable): - - """The mathematic definition of a polynom. It will be the parent class of Polynom (classical polynoms) and later of SquareRoot polynoms""" - - def __init__(self, coefs=[1], letter="x", name="P"): - """Initiate the polynom - - :param coef: coefficients of the polynom (ascending degree sorted) - 3 possibles type of coefficent: - - a : simple "number". [1,2] designate 1 + 2x - - [a,b,c]: list of coeficient for same degree. [1,[2,3],4] designate 1 + 2x + 3x + 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 name: Name of the polynom - - >>> P = AbstractPolynom([1, 2, 3]) - >>> P.mainOp - + - >>> P.name - 'P' - >>> P._letter - 'x' - >>> AbstractPolynom([1]).mainOp - * - >>> AbstractPolynom([0, 0, 3]).mainOp - * - >>> AbstractPolynom([1, 2, 3])._letter - 'x' - >>> AbstractPolynom([1, 2, 3], "y")._letter - 'y' - >>> AbstractPolynom([1, 2, 3], name = "Q").name - 'Q' - """ - try: - # Remove 0 at the end of the coefs - while coefs[-1] == 0: - coefs = coefs[:-1] - except IndexError: - pass - - if coefs == []: - coefs = [0] - - self.feed_coef(coefs) - self._letter = letter - self.name = name - - if self.is_monom(): - self.mainOp = op.mul - else: - self.mainOp = op.add - - self._isPolynom = 1 - - pstf_tokens = self.compute_postfix_tokens() - super(AbstractPolynom, self).__init__(pstf_tokens) - - def feed_coef(self, l_coef): - """Feed coef of the polynom. Manage differently whether it's a number or an expression - - :l_coef: list of coef - """ - self._coef = [] - for coef in l_coef: - if isinstance(coef, list) and len(coef) == 1: - self._coef.append(coef[0]) - else: - self._coef.append(coef) - - @property - def degree(self): - """Getting the degree fo the polynom - - :returns: the degree of the polynom - - >>> AbstractPolynom([1, 2, 3]).degree - 2 - >>> AbstractPolynom([1]).degree - 0 - """ - return len(self._coef) - 1 - - def is_monom(self): - """is the polynom a monom (only one coefficent) - - :returns: 1 if yes 0 otherwise - - >>> AbstractPolynom([1, 2, 3]).is_monom() - 0 - >>> AbstractPolynom([1]).is_monom() - 1 - """ - if len([i for i in self._coef if i != 0]) == 1: - return 1 - else: - return 0 - - def give_name(self, name): - self.name = name - - def __str__(self): - return str(Expression(self.postfix_tokens)) - - def __repr__(self): - return "< {cls} {letter} {coefs}>".format( - cls = str(self.__class__).split('.')[-1][:-2], - letter = str(self._letter), - coefs = str(self._coef)) - - def coef_postfix(self, a, i): - """Return the postfix display of a coeficient - - :param a: value for the coeficient (/!\ as a postfix list) - :param i: power - :returns: postfix tokens of coef - - >>> p = AbstractPolynom() - >>> p.coef_postfix([3],2) - [3, 'x', 2, ^, *] - >>> p.coef_postfix([0],1) - [] - >>> p.coef_postfix([3],0) - [3] - >>> p.coef_postfix([3],1) - [3, 'x', *] - >>> p.coef_postfix([1],1) - ['x'] - >>> p.coef_postfix([1],2) - ['x', 2, ^] - - """ - if a == [0]: - ans = [] - elif i == 0: - ans = a - elif i == 1: - ans = a * (a not in [[1], [-1]]) + \ - [self._letter] + \ - [op.mul] * (a not in [[1], [-1]]) + \ - [op.sub1] * (a == [-1]) - else: - ans = a * (a not in [[1], [-1]]) + \ - [self._letter, i, op.pw] + \ - [op.mul] * (a not in [[1], [-1]]) + \ - [op.sub1] * (a == [-1]) - - return ans - - def coefs_postifx(self): - """ Return list of postfix coef with the the right power letter - - >>> p = AbstractPolynom([1, 2]) - >>> p.coefs_postifx() - [[1], [2, 'x', *]] - >>> p = AbstractPolynom([1, -2]) - >>> p.coefs_postifx() - [[1], [-2, 'x', *]] - >>> p = AbstractPolynom([1,2,3]) - >>> p.coefs_postifx() - [[1], [2, 'x', *], [3, 'x', 2, ^, *]] - >>> p = AbstractPolynom([1]) - >>> p.coefs_postifx() - [[1]] - >>> p = AbstractPolynom([0]) - >>> p.coefs_postifx() - [[0]] - >>> p = AbstractPolynom([0, 1, 1, 0]) - >>> p.coefs_postifx() - [['x'], ['x', 2, ^]] - >>> p = AbstractPolynom([1,[2,3]]) - >>> p.coefs_postifx() - [[1], [3, 'x', *], [2, 'x', *]] - >>> p = AbstractPolynom([1,[2,-3]]) - >>> p.coefs_postifx() - [[1], [-3, 'x', *], [2, 'x', *]] - >>> p = AbstractPolynom([1,[-2,-3]]) - >>> p.coefs_postifx() - [[1], [-3, 'x', *], [-2, 'x', *]] - >>> p = AbstractPolynom([1,[-2,0]]) - >>> p.coefs_postifx() - [[1], [-2, 'x', *]] - >>> from mapytex.calculus.expression import Expression - >>> from mapytex.calculus.operator import op - >>> e = Expression([2,3,op.add]) - >>> p = AbstractPolynom([1,e]) - >>> p.coefs_postifx() - [[1], [2, 3, +, 'x', *]] - """ - if not [i for i in self._coef if i!= 0]: - return [[0]] - - raw_coefs = [] - for (pw, coef) in enumerate(self._coef): - if isinstance(coef, list): - for c in coef[::-1]: - try: - raw_coefs.append(self.coef_postfix(c.postfix_tokens, pw)) - except AttributeError: - raw_coefs.append(self.coef_postfix([c], pw)) - elif coef != 0: - try: - raw_coefs.append(self.coef_postfix(coef.postfix_tokens, pw)) - except AttributeError: - raw_coefs.append(self.coef_postfix([coef], pw)) - - - return [i for i in raw_coefs if i != []] - - def compute_postfix_tokens(self): - """Return the postfix form of the polynom - - :returns: the postfix list of polynom's tokens - - >>> p = AbstractPolynom([1, 2]) - >>> p.postfix_tokens - [2, 'x', *, 1, +] - >>> p = AbstractPolynom([1, -2]) - >>> p.postfix_tokens - [-2, 'x', *, 1, +] - >>> p = AbstractPolynom([1,2,3]) - >>> p.postfix_tokens - [3, 'x', 2, ^, *, 2, 'x', *, +, 1, +] - >>> p = AbstractPolynom([1]) - >>> p.postfix_tokens - [1] - >>> p = AbstractPolynom([0]) - >>> p.postfix_tokens - [0] - >>> p = AbstractPolynom([1,[2,3]]) - >>> p.postfix_tokens - [2, 'x', *, 3, 'x', *, +, 1, +] - >>> p = AbstractPolynom([1,[2,-3]]) - >>> p.postfix_tokens - [2, 'x', *, -3, 'x', *, +, 1, +] - >>> p = AbstractPolynom([1,[-2,-3]]) - >>> p.postfix_tokens - [-2, 'x', *, -3, 'x', *, +, 1, +] - >>> from mapytex.calculus.expression import Expression - >>> from mapytex.calculus.operator import op - >>> e = Expression([2,3,op.add]) - >>> p = AbstractPolynom([1,e]) - >>> p.postfix_tokens - [2, 3, +, 'x', *, 1, +] - - """ - raw_coefs = self.coefs_postifx() - - pstfx = postfix_op(raw_coefs[::-1], op.add) - return flatten_list(pstfx) - - def conv2poly(self, other): - """Convert anything number into a polynom - - >>> P = AbstractPolynom([1,2,3]) - >>> P.conv2poly(1) - < AbstractPolynom x [1]> - >>> P.conv2poly(0) - < AbstractPolynom x [0]> - >>> Q = AbstractPolynom([3, 2, 1], 'x') - >>> P.conv2poly(Q) - < AbstractPolynom x [3, 2, 1]> - >>> Q = AbstractPolynom([3, 2, 1], 'y') - >>> P.conv2poly(Q) - < AbstractPolynom x [< AbstractPolynom y [3, 2, 1]>]> - """ - if (isNumber(other) and not isPolynom(other)) or \ - (isPolynom(other) and self._letter != other._letter): - #ans = self.__class__([other], letter=self._letter) - ans = AbstractPolynom([other], letter=self._letter) - ans.steal_history(other) - return ans - elif isPolynom(other): - return other - else: - raise ValueError( - type(other) + - " can't be converted into a polynom" - ) - - def reduce(self): - """Compute coefficients which have same degree - - :returns: new AbstractPolynom with numbers coefficients - - >>> P = AbstractPolynom([1,2,3]) - >>> Q = P.reduce() - >>> Q - < AbstractPolynom x [1, 2, 3]> - >>> Q.steps - [< Step [3, 'x', 2, ^, *, 2, 'x', *, +, 1, +]>, < Step [3, 'x', 2, ^, *, 2, 'x', *, +, 1, +]>] - >>> P = AbstractPolynom([[1,2], [3,4,5], 6]) - >>> Q = P.reduce() - >>> Q - < AbstractPolynom x [3, 12, 6]> - >>> for i in Q.explain(): - ... print(i) - 6 x^{ 2 } + 3 x + 4 x + 5 x + 1 + 2 - 6 x^{ 2 } + ( 3 + 4 + 5 ) x + 1 + 2 - 6 x^{ 2 } + ( 7 + 5 ) x + 3 - 6 x^{ 2 } + 12 x + 3 - >>> Q.steps - [< Step [6, 'x', 2, ^, *, 3, 'x', *, +, 4, 'x', *, +, 5, 'x', *, +, 1, +, 2, +]>, < Step [6, 'x', 2, ^, *, 3, 4, +, 5, +, 'x', *, +, 1, 2, +, +]>, < Step [6, 'x', 2, ^, *, 7, 5, +, 'x', *, +, 3, +]>, < Step [6, 'x', 2, ^, *, 12, 'x', *, +, 3, +]>] - >>> P = AbstractPolynom([[1,2], [3,4,5], 6], 'y') - >>> Q = P.reduce() - >>> Q - < AbstractPolynom y [3, 12, 6]> - >>> for i in Q.explain(): - ... print(i) - 6 y^{ 2 } + 3 y + 4 y + 5 y + 1 + 2 - 6 y^{ 2 } + ( 3 + 4 + 5 ) y + 1 + 2 - 6 y^{ 2 } + ( 7 + 5 ) y + 3 - 6 y^{ 2 } + 12 y + 3 - >>> P = AbstractPolynom([1,2]) - >>> Q = AbstractPolynom([P,3], 'y') - >>> Q - < AbstractPolynom y [< AbstractPolynom x [1, 2]>, 3]> - >>> Q = Q.reduce() - >>> for i in Q.explain(): - ... print(i) - 3 y + 2 x + 1 - >>> P = AbstractPolynom([1,2]) - >>> Q = AbstractPolynom([[P,1],3], 'y') - >>> Q - < AbstractPolynom y [[< AbstractPolynom x [1, 2]>, 1], 3]> - >>> Q = Q.reduce() - >>> for i in Q.explain(): - ... print(i) - 3 y + 2 x + 1 + 1 - 3 y + 2 x + 2 - """ - smpl_coef = [] - for coef in self._coef: - - if isinstance(coef, list): - coef_exp = AbstractPolynom.smpl_coef_list(coef) - - else: - try: - coef_exp = coef.simplify() - except AttributeError: - coef_exp = coef - - smpl_coef.append(coef_exp) - - ans = AbstractPolynom(smpl_coef, self._letter) - - ini_step = [Step(self)] - for s in Explicable.merge_history(smpl_coef): - ini_step.append(Step(AbstractPolynom(s, self._letter))) - - ans.this_append_before( - ini_step - #AbstractPolynom(s) - #for s in Expression.develop_steps(smpl_coef) - ) - - return ans - - def simplify(self): - """Same as reduce """ - if isNumber(self._letter): - return self.replace_letter(self._letter).simplify() - return self.reduce() - - @classmethod - def smpl_coef_list(cls, coef_list): - """ Simplify the coef when it is a list - - :param coef_list: the list discribing the coef - :returns: the simplify coef - - >>> c = AbstractPolynom.smpl_coef_list([1, 2, 3]) - >>> c - 6 - >>> c.steps - [< Step [1, 2, +, 3, +]>, < Step [1, 2, +, 3, +]>, < Step [3, 3, +]>, < Step [3, 3, +]>, < Step [6]>] - >>> c = AbstractPolynom.smpl_coef_list([Expression('2*2'), 3]) - >>> c - 7 - >>> c.steps - [< Step [2, 2, *, 3, +]>, < Step [4, 3, +]>, < Step [4, 3, +]>, < Step [7]>] - >>> c = AbstractPolynom.smpl_coef_list([0, 2, 0]) - >>> c - 2 - >>> c.steps - [< Step [2]>] - """ - # Simplify each element before adding them - smpl_elem = [] - for c in coef_list: - try: - smpl_c = c.simplify() - except AttributeError: - smpl_c = c - smpl_elem.append(smpl_c) - - pstfx_add = postfix_op( - [i for i in smpl_elem if i != 0], - op.add - ) - - steps = Expression.develop_steps(pstfx_add) - - ans = Expression(pstfx_add).simplify() - ans.this_append_before(steps) - return ans - - def replace_letter(self, letter): - r""" Replace the letter in the expression - - :param letter: the new letter. - :returns: The expression with the new letter. - - >>> A = AbstractPolynom([1, 2]) - >>> A - < AbstractPolynom x [1, 2]> - >>> B = A.replace_letter("y") - >>> B - < Expression [2, < Polynom y [0, 1]>, *, 1, +]> - >>> C = A.replace_letter(2) - >>> C - < Expression [2, 2, *, 1, +]> - >>> e = Expression('2+3').simplify() - >>> D = A.replace_letter(e) - >>> D - < Expression [2, 5, *, 1, +]> - >>> for i in D.explain(): - ... print(i) - 2 ( 2 + 3 ) + 1 - 2 \times 5 + 1 - - """ - exp_to_replace = Expression(letter) - exp_to_replace.steal_history(letter) - - postfix_exp = [ - exp_to_replace if i == self._letter - else i - for i in self.postfix_tokens - ] - ini_step = Expression.develop_steps(postfix_exp) - - ans = Expression(postfix_exp) - ans.this_append_before(ini_step) - - return ans - - def __eq__(self, other): - try: - o_poly = self.conv2poly(other) - return self._coef == o_poly._coef - except TypeError: - return 0 - - def __add__(self, other): - """ Overload + - - >>> P = AbstractPolynom([1,2,3]) - >>> Q = AbstractPolynom([4,5]) - >>> R = P+Q - >>> R - < AbstractPolynom x [5, 7, 3]> - >>> for i in R.explain(): - ... print(i) - 3 x^{ 2 } + 2 x + 1 + 5 x + 4 - 3 x^{ 2 } + 2 x + 5 x + 1 + 4 - 3 x^{ 2 } + ( 2 + 5 ) x + 1 + 4 - 3 x^{ 2 } + 7 x + 5 - >>> R.steps - [< Step [3, 'x', 2, ^, *, 2, 'x', *, +, 1, +, 5, 'x', *, 4, +, +]>, < Step [3, 'x', 2, ^, *, 2, 'x', *, +, 5, 'x', *, +, 1, +, 4, +]>, < Step [3, 'x', 2, ^, *, 2, 5, +, 'x', *, +, 1, 4, +, +]>, < Step [3, 'x', 2, ^, *, 7, 'x', *, +, 5, +]>] - >>> Q = AbstractPolynom([4,5], letter = 'y') - >>> R = P+Q - >>> R - < AbstractPolynom x [< AbstractPolynom y [5, 5]>, 2, 3]> - >>> for i in R.explain(): - ... print(i) - 3 x^{ 2 } + 2 x + 1 + 5 y + 4 - 3 x^{ 2 } + 2 x + 5 y + 1 + 4 - 3 x^{ 2 } + 2 x + 5 y + 5 - - """ - o_poly = self.conv2poly(other) - - n_coef = spe_zip(self._coef, o_poly._coef) - p = AbstractPolynom(n_coef, letter=self._letter) - - ini_step = [Step([self, o_poly, op.add])] - - ans = p.simplify() - ans.this_append_before(ini_step) - return ans - - def __radd__(self, other): - o_poly = self.conv2poly(other) - return o_poly.__add__(self) - - def __neg__(self): - """ overload - (as arity 1 operator) - - >>> P = AbstractPolynom([1,2,3]) - >>> Q = -P - >>> Q - < AbstractPolynom x [-1, -2, -3]> - >>> for i in Q.explain(): - ... print(i) - - ( 3 x^{ 2 } + 2 x + 1 ) - -3 x^{ 2 } - 2 x - 1 - >>> Q.steps - [< Step [3, 'x', 2, ^, *, 2, 'x', *, +, 1, +, -]>, < Step [-3, 'x', 2, ^, *, -2, 'x', *, +, -1, +]>, < Step [-3, 'x', 2, ^, *, -2, 'x', *, +, -1, +]>] - """ - ini_step = [Step(self.postfix_tokens + [op.sub1])] - ans = AbstractPolynom([-i for i in self._coef], - letter=self._letter).simplify() - ans.this_append_before(ini_step) - return ans - - def __sub__(self, other): - """ overload - - - >>> P = AbstractPolynom([1,2,3]) - >>> Q = AbstractPolynom([4,5,6]) - >>> R = P - Q - >>> R - < AbstractPolynom x [-3, -3, -3]> - >>> for i in R.explain(): - ... print(i) - 3 x^{ 2 } + 2 x + 1 - ( 6 x^{ 2 } + 5 x + 4 ) - 3 x^{ 2 } + 2 x + 1 - 6 x^{ 2 } - 5 x - 4 - 3 x^{ 2 } - 6 x^{ 2 } + 2 x - 5 x + 1 - 4 - ( 3 - 6 ) x^{ 2 } + ( 2 - 5 ) x + 1 - 4 - -3 x^{ 2 } - 3 x - 3 - >>> R.steps - [< Step [3, 'x', 2, ^, *, 2, 'x', *, +, 1, +, 6, 'x', 2, ^, *, 5, 'x', *, +, 4, +, -]>, < Step [3, 'x', 2, ^, *, 2, 'x', *, +, 1, +, -6, 'x', 2, ^, *, -5, 'x', *, +, -4, +, +]>, < Step [3, 'x', 2, ^, *, -6, 'x', 2, ^, *, +, 2, 'x', *, +, -5, 'x', *, +, 1, +, -4, +]>, < Step [3, -6, +, 'x', 2, ^, *, 2, -5, +, 'x', *, +, 1, -4, +, +]>, < Step [-3, 'x', 2, ^, *, -3, 'x', *, +, -3, +]>] - """ - o_poly = self.conv2poly(other) - ini_step = [Step(self.postfix_tokens + - o_poly.postfix_tokens + [op.sub])] - o_poly = -o_poly - - ans = self + o_poly - ans.this_append_before(ini_step) - - return ans - - def __rsub__(self, other): - o_poly = self.conv2poly(other) - - return o_poly.__sub__(self) - - def __mul__(self, other): - r""" Overload * - - >>> p = AbstractPolynom([1,2]) - >>> p*3 - < AbstractPolynom x [3, 6]> - >>> for i in (p*3).explain(): - ... print(i) - ( 2 x + 1 ) \times 3 - 2 \times 3 x + 3 - 6 x + 3 - >>> (p*3).steps - [< Step [2, 'x', *, 1, +, 3, *]>, < Step [2, 3, *, 'x', *, 3, +]>, < Step [2, 3, *, 'x', *, 3, +]>, < Step [6, 'x', *, 3, +]>] - >>> q = AbstractPolynom([0,0,4]) - >>> q*3 - < AbstractPolynom x [0, 0, 12]> - >>> for i in (q*3).explain(): - ... print(i) - 4 x^{ 2 } \times 3 - 4 \times 3 x^{ 2 } - 12 x^{ 2 } - >>> (q*3).steps - [< Step [4, 'x', 2, ^, *, 3, *]>, < Step [4, 3, *, 'x', 2, ^, *]>, < Step [4, 3, *, 'x', 2, ^, *]>, < Step [12, 'x', 2, ^, *]>] - >>> r = AbstractPolynom([0,1]) - >>> r*3 - < AbstractPolynom x [0, 3]> - >>> (r*3).steps - [< Step ['x', 3, *]>, < Step [3, 'x', *]>, < Step [3, 'x', *]>] - >>> p*q - < AbstractPolynom x [0, 0, 4, 8]> - >>> (p*q).steps - [< Step [2, 'x', *, 1, +, 4, 'x', 2, ^, *, *]>, < Step [2, 4, *, 'x', 3, ^, *, 4, 'x', 2, ^, *, +]>, < Step [2, 4, *, 'x', 3, ^, *, 4, 'x', 2, ^, *, +]>, < Step [8, 'x', 3, ^, *, 4, 'x', 2, ^, *, +]>] - >>> for i in (p*q).explain(): - ... print(i) - ( 2 x + 1 ) \times 4 x^{ 2 } - 2 \times 4 x^{ 3 } + 4 x^{ 2 } - 8 x^{ 3 } + 4 x^{ 2 } - >>> p*r - < AbstractPolynom x [0, 1, 2]> - >>> P = AbstractPolynom([1,2,3]) - >>> Q = AbstractPolynom([4,5,6]) - >>> P*Q - < AbstractPolynom x [4, 13, 28, 27, 18]> - """ - o_poly = self.conv2poly(other) - - coefs = [0] * (self.degree + o_poly.degree + 1) - for (i, a) in enumerate(self._coef): - for (j, b) in enumerate(o_poly._coef): - if a == 0 or b == 0: - elem = 0 - elif a == 1: - elem = b - elif b == 1: - elem = a - else: - elem = Expression([a, b, op.mul]) - - if coefs[i + j] == 0: - coefs[i + j] = elem - elif elem != 0: - if isinstance(coefs[i + j], list): - coefs[i + j] += [elem] - else: - coefs[i + j] = [coefs[i + j], elem] - - p = AbstractPolynom(coefs, letter=self._letter) - ini_step = [Step(self.postfix_tokens + - o_poly.postfix_tokens + [op.mul])] - ans = p.simplify() - - ans.this_append_before(ini_step) - return ans - - def __rmul__(self, other): - o_poly = self.conv2poly(other) - - return o_poly.__mul__(self) - - def __truediv__(self, other): - r""" Overload / - - >>> P = AbstractPolynom([1, 2, 4]) - >>> P / 2 - < AbstractPolynom x [< Fraction 1 / 2>, 1, 2]> - >>> for i in (P/2).explain(): - ... print(i) - \frac{ 4 x^{ 2 } + 2 x + 1 }{ 2 } - \frac{ 4 }{ 2 } x^{ 2 } + \frac{ 2 }{ 2 } x + \frac{ 1 }{ 2 } - 2 x^{ 2 } + x + \frac{ 1 }{ 2 } - - - """ - ans_coefs = [Expression([c, other, op.div]) if c != 0 - else 0 - for c in self._coef - ] - - ans = AbstractPolynom(ans_coefs, letter=self._letter) - ini_step = [Step( - self.postfix_tokens + - [other, op.div] - )] - - ans = ans.simplify() - ans.this_append_before(ini_step) - return ans - - @power_cache - def __pow__(self, power): - r""" Overload ** - - >>> p = AbstractPolynom([0,0,3]) - >>> p**2 - < AbstractPolynom x [0, 0, 0, 0, 9]> - >>> (p**2).steps - [< Step [3, 'x', 2, ^, *, 2, ^]>, < Step [3, 2, ^, 'x', 4, ^, *]>, < Step [3, 2, ^, 'x', 4, ^, *]>, < Step [9, 'x', 4, ^, *]>] - >>> for i in (p**2).explain(): - ... print(i) - ( 3 x^{ 2 } )^{ 2 } - 3^{ 2 } x^{ 4 } - 9 x^{ 4 } - >>> p = AbstractPolynom([1,2]) - >>> p**2 - < AbstractPolynom x [1, 4, 4]> - >>> (p**2).steps - [< Step [2, 'x', *, 1, +, 2, ^]>, < Step [2, 'x', *, 1, +, 2, 'x', *, 1, +, *]>, < Step [2, 2, *, 'x', 2, ^, *, 2, 'x', *, +, 2, 'x', *, +, 1, +]>, < Step [2, 2, *, 'x', 2, ^, *, 2, 2, +, 'x', *, +, 1, +]>, < Step [4, 'x', 2, ^, *, 4, 'x', *, +, 1, +]>] - >>> for i in (p**2).explain(): - ... print(i) - ( 2 x + 1 )^{ 2 } - ( 2 x + 1 ) ( 2 x + 1 ) - 2 \times 2 x^{ 2 } + 2 x + 2 x + 1 - 2 \times 2 x^{ 2 } + ( 2 + 2 ) x + 1 - 4 x^{ 2 } + 4 x + 1 - >>> p = AbstractPolynom([0,0,1]) - >>> p**3 - < AbstractPolynom x [0, 0, 0, 0, 0, 0, 1]> - >>> p = AbstractPolynom([1,2,3]) - >>> p**2 - < AbstractPolynom x [1, 4, 10, 12, 9]> - - """ - if not type(power): - raise ValueError( - "Can't raise {obj} to {pw} power".format( - obj=self.__class__, pw=str(power))) - - ini_step = [Step(self.postfix_tokens + [power, op.pw])] - - if self.is_monom(): - if self._coef[self.degree] == 1: - coefs = [0] * self.degree * power + [1] - p = AbstractPolynom(coefs, letter=self._letter) - ans = p - else: - coefs = [0] * self.degree * power + \ - [Expression([self._coef[self.degree], power, op.pw])] - p = AbstractPolynom(coefs, letter=self._letter) - ans = p.simplify() - else: - if power == 2: - ans = self * self - else: - # TODO: faudrait changer ça c'est pas très sérieux |ven. févr. - # 27 22:08:00 CET 2015 - raise AttributeError( - "__pw__ not implemented yet when power is greatter than 2") - - ans.this_append_before(ini_step) - return ans - - def __xor__(self, power): - return self.__pow__(power) - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/arithmetic.py b/mapytex/calculus/arithmetic.py deleted file mode 100644 index 2ba5e27..0000000 --- a/mapytex/calculus/arithmetic.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -__all__ = ['gcd'] - - -def gcd(a, b): - """Compute gcd(a,b) - - :param a: first number - :param b: second number - :returns: the gcd - - """ - pos_a, _a = (a >= 0), abs(a) - pos_b, _b = (b >= 0), abs(b) - - gcd_sgn = (-1 + 2 * (pos_a or pos_b)) - - if _a > _b: - c = _a % _b - else: - c = _b % _a - - if c == 0: - return gcd_sgn * min(_a, _b) - elif _a == 1: - return gcd_sgn * _b - elif _b == 1: - return gcd_sgn * _a - else: - return gcd_sgn * gcd(min(_a, _b), c) - -if __name__ == '__main__': - print(gcd(3, 15)) - print(gcd(3, 15)) - print(gcd(-15, -3)) - print(gcd(-3, -12)) - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/core/tree.py b/mapytex/calculus/core/tree.py index acf580c..9f16103 100644 --- a/mapytex/calculus/core/tree.py +++ b/mapytex/calculus/core/tree.py @@ -104,7 +104,7 @@ class Tree(object): >>> t.node '+' >>> type(t.left_value) - + >>> t.right_value 2 diff --git a/mapytex/calculus/decorators.py b/mapytex/calculus/decorators.py deleted file mode 100644 index 4763ae7..0000000 --- a/mapytex/calculus/decorators.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -from functools import wraps - -def no_repetition(equals=lambda x,y: x == y, old = ""): - """ Remove yield values which has already been yield - - :param equals: test for equality - :param old: initiate form of data. - :returns: same generator with no repetitions - - >>> norep = no_repetition() - >>> def str_gene(string): - ... for i in string: - ... yield i - >>> norep_str_gene = norep(str_gene) - >>> [i for i in norep_str_gene("aaabraabbbere")] - ['a', 'b', 'r', 'a', 'b', 'e', 'r', 'e'] - - """ - def wrapper(fun): - @wraps(fun) - def dont_repeat(*args, **kwrds): - gen = fun(*args, **kwrds) - old_s = old - while True: - try: - new_s = next(gen) - except StopIteration: - break - else: - if not equals(new_s, old_s): - old_s = new_s - yield new_s - - return dont_repeat - return wrapper - - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/equation.py b/mapytex/calculus/equation.py deleted file mode 100644 index bbb6067..0000000 --- a/mapytex/calculus/equation.py +++ /dev/null @@ -1,306 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -from .explicable import Explicable -from .expression import Expression -from .step import Step -from .decorators import no_repetition -from .polynom import Polynom -from .fraction import Fraction - -from .random_expression import RdExpression - -__all__ = ['Equation'] - -def equals(new, old): - print("new -> ", new) - print("old -> ", old) - return new, old - - - -class Equation(object): - """A calculus expression. Today it can andle only expression with numbers later it will be able to manipulate unknown""" - - @classmethod - def random(self, form="", conditions=[], val_min=2, val_max=30): - """Create a random expression from form and with conditions - - :param form: the form of the expression (/!\ variables need to be in brackets {}) - :param conditions: condition on variables (/!\ variables need to be in brackets {}) - :param val_min: min value for generate variables - :param val_max: max value for generate variables - - >>> Equation.random("{a}x + {b} = 0") # doctest:+ELLIPSIS - < Equation [..., 0]> - >>> Equation.random("{a}x + {b} = _", conditions = ["{a}==2"]) # doctest:+ELLIPSIS - < Equation [2 x ...]> - - """ - random_generator = RdExpression(form, conditions) - return Equation(random_generator(val_min, val_max)) - - - def __init__(self, exp_str = "", left_poly = Expression([0]), right_poly = Expression([0])): - """Create the equation - - :param exp_str: the equality string which represent the equation - :param left_poly: the left polynom of the equation - :param right_poly: the right polynom of the equation - - >>> e = Equation("2x+3 = 4x+5") - >>> e - < Equation [2 x + 3, 4 x + 5]> - >>> Pl = Polynom([1, 2]) - >>> Pr = Polynom([3, 4]) - >>> e = Equation(left_poly = Pl) - >>> e - < Equation [2 x + 1, 0]> - >>> e = Equation(right_poly = Pr) - >>> e - < Equation [0, 4 x + 3]> - >>> e = Equation(left_poly = Pl, right_poly = Pr) - >>> e - < Equation [2 x + 1, 4 x + 3]> - - """ - if exp_str: - l_part, r_part = exp_str.split("=") - self.l_exp = Expression(l_part) - self.r_exp = Expression(r_part) - else: - self.l_exp = left_poly - self.r_exp = right_poly - - self.smpl_each_part() - - def smpl_each_part(self): - """ Simplify left and right part, transform them into polynom and stock them in smpl_*_exp - """ - self.smpl_l_exp = self.l_exp.simplify() - self.smpl_l_exp.steal_history(self.l_exp) - self.smpl_r_exp = self.r_exp.simplify() - self.smpl_r_exp.steal_history(self.r_exp) - - try: - self.smpl_r_exp = self.smpl_l_exp.conv2poly(self.smpl_r_exp) - except AttributeError: - pass - - try: - self.smpl_l_exp = self.smpl_r_exp.conv2poly(self.smpl_l_exp) - except AttributeError: - raise EquationError("None of left and right parts are polynoms. \ - Can't use it to make an equation.") - - # TODO: On pourrait rajouter des tests sur les inconnues |mar. mars 22 10:17:12 EAT 2016 - - def __str__(self): - return str(self.l_exp) + " = " + str(self.r_exp) - - def __repr__(self): - return "< {cls} [{l}, {r}]>".format( - cls = str(self.__class__).split('.')[-1][:-2], - l = self.l_exp, - r = self.r_exp, - ) - - @no_repetition(lambda x, y: (x[0] == y[0]) & (x[1] == y[1]), ['','']) - def solve(self): - r"""Solve the equation but yielding each steps - - >>> e = Equation("x + 123 = 0") - >>> for i in e.solve(): - ... print(" = ".join([str(j) for j in i])) - x + 123 = 0 - x + 123 - 123 = 0 - 123 - x + 123 - 123 = -123 - x = -123 - >>> e = Equation("2x = x + 2") - >>> for i in e.solve(): - ... print(" = ".join([str(j) for j in i])) - 2 x = x + 2 - 2 x - x = x + 2 - x - ( 2 - 1 ) x = x - x + 2 - x = ( 1 - 1 ) x + 2 - x = 2 - >>> e = Equation("2x = 1") - >>> for i in e.solve(): - ... print(" = ".join([str(j) for j in i])) - 2 x = 1 - \frac{ 2 x }{ 2 } = \frac{ 1 }{ 2 } - \frac{ 2 }{ 2 } x = \frac{ 1 }{ 2 } - x = \frac{ 1 }{ 2 } - >>> e = Equation("2x + 1 = 4x + 2") - >>> for i in e.solve(): - ... print(" = ".join([str(j) for j in i])) - 2 x + 1 = 4 x + 2 - 2 x + 1 - 1 = 4 x + 2 - 1 - 2 x = 4 x + 1 - 2 x - 4 x = 4 x + 1 - 4 x - ( 2 - 4 ) x = 4 x - 4 x + 1 - -2 x = ( 4 - 4 ) x + 1 - -2 x = 1 - \frac{ -2 x }{ -2 } = \frac{ 1 }{ -2 } - \frac{ -2 }{ -2 } x = \frac{ -1 }{ 2 } - x = \frac{ -1 }{ 2 } - >>> e = Equation("2x + 3x + 1 = 4x + 2") - >>> for i in e.solve(): - ... print(" = ".join([str(j) for j in i])) - 2 x + 3 x + 1 = 4 x + 2 - ( 2 + 3 ) x + 1 = 4 x + 2 - 5 x + 1 = 4 x + 2 - 5 x + 1 - 1 = 4 x + 2 - 1 - 5 x = 4 x + 1 - 5 x - 4 x = 4 x + 1 - 4 x - ( 5 - 4 ) x = 4 x - 4 x + 1 - x = ( 4 - 4 ) x + 1 - x = 1 - """ - yield from self.gene_smpl_steps() - - if self.smpl_l_exp._coef[0] != 0: - eq = Equation( - left_poly = self.smpl_l_exp - self.smpl_l_exp._coef[0], - right_poly = self.smpl_r_exp - self.smpl_l_exp._coef[0] - ) - yield from eq.solve() - return - - try: - poly_r_part = Polynom([0, self.smpl_r_exp._coef[1]]) - except IndexError: - pass - else: - if self.smpl_r_exp._coef[1] != 0: - yield from Equation( - left_poly = self.smpl_l_exp - poly_r_part, - right_poly = self.smpl_r_exp - poly_r_part - ).solve() - return - - if self.smpl_l_exp._coef[1] != 1: - yield from Equation( - left_poly = self.smpl_l_exp / self.smpl_l_exp._coef[1], - right_poly = self.smpl_r_exp / self.smpl_l_exp._coef[1] - ).solve() - return - - @no_repetition() - def gene_smpl_steps(self): - r"""Generate simplification steps of the equation - - >>> e = Equation("2x + 3x + 1 = 4x + 2") - >>> e.gene_smpl_steps() # doctest:+ELLIPSIS - - >>> for i in e.gene_smpl_steps(): - ... print(i) - [< Step [2, 'x', *, 3, 'x', *, +, 1, +]>, < Step [4, 'x', *, 2, +]>] - [< Step [2, 3, +, 'x', *, 1, +]>, < Step [4, 'x', *, 2, +]>] - [< Step [5, 'x', *, 1, +]>, < Step [4, 'x', *, 2, +]>] - >>> e = Equation("2x + 3x + 1 = 4x + 2") - >>> for i in e.gene_smpl_steps(): - ... print(" = ".join([str(j) for j in i])) - 2 x + 3 x + 1 = 4 x + 2 - ( 2 + 3 ) x + 1 = 4 x + 2 - 5 x + 1 = 4 x + 2 - >>> e = Equation("3x / 3 = 5 / 3") - >>> for i in e.gene_smpl_steps(): - ... print(" = ".join([str(j) for j in i])) - 3 \times \frac{ x }{ 3 } = \frac{ 5 }{ 3 } - \frac{ x }{ 3 } \times 3 = \frac{ 5 }{ 3 } - \frac{ x \times 3 }{ 1 \times 3 } = \frac{ 5 }{ 3 } - \frac{ x }{ 1 } = \frac{ 5 }{ 3 } - x = \frac{ 5 }{ 3 } - - """ - #yield [Step(self.l_exp), Step(self.r_exp)] - - for s in Explicable.merge_history( - [self.smpl_l_exp, self.smpl_r_exp] - ): - yield s - - def solution(self): - """Return the solution of the equation - - :returns: the solution - - >>> e = Equation("2x + 1 = x + 2") - >>> e.solution() - 1 - >>> e = Equation("2x + 1 = 1") - >>> e.solution() - 0 - >>> e = Equation("1 = 2x + 1") - >>> e.solution() - 0 - >>> e = Equation("3x = 2x") - >>> e.solution() - 0 - >>> e = Equation("3x + 1 = 0") - >>> e.solution() - < Fraction -1 / 3> - >>> e = Equation("6x + 2 = 0") - >>> e.solution() - < Fraction -1 / 3> - - """ - num = self.smpl_r_exp._coef[0] - self.smpl_l_exp._coef[0] - - try: - denom = self.smpl_l_exp._coef[1] - except IndexError: - denom = 0 - try: - denom -= self.smpl_r_exp._coef[1] - except IndexError: - pass - - if denom == 0 and num == 0: - raise EquationError("All number are solution") - elif denom == 0: - raise NoSolutionError("This equation has no solution") - - return Fraction(num, denom).simplify() - - def is_solution(self, num): - """ Tell if a number is a solution. - - :param num: the number to test - - >>> e = Equation("2x + 1 = x + 2") - >>> e.is_solution(2) - False - >>> e.is_solution(1) - True - >>> e = Equation("3x = 2x") - >>> e.is_solution(1) - False - >>> e.is_solution(0) - True - >>> e = Equation("3x + 1 = 0") - >>> e.is_solution(0) - False - >>> e.is_solution(Fraction(-1, 3)) - True - >>> e.is_solution(Fraction(-2, 6)) - True - - """ - l_part = self.smpl_l_exp.replace_letter(num).simplify() - r_part = self.smpl_r_exp.replace_letter(num).simplify() - return l_part == r_part - -class EquationError(Exception): - pass - - -class NoSolutionError(EquationError): - pass - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/explicable.py b/mapytex/calculus/explicable.py deleted file mode 100644 index 9e46d74..0000000 --- a/mapytex/calculus/explicable.py +++ /dev/null @@ -1,259 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -from .renderable import Renderable -from .step import Step -from decimal import Decimal -from .generic import transpose_fill -from .decorators import no_repetition - - -class Explicable(Renderable): - - """ An Explicable object is an object which can be explicable! - - It's a parent class of a more classical Expression, Fraction and Polynom (and later square root) - Child class will have the following method - * explain: Generator which return steps which leed to himself - - """ - - def __init__(self, pstf_tokens): - super(Explicable, self).__init__(pstf_tokens) - self.steps = [] - self.explained = 0 - - def explain(self): - r""" Generate and render steps which leed to itself - - After beening explained, the Explicable become amnesiac. It will return itself in a list. - See 'history_generator' to explain it once again. - - >>> action = Explicable(['42']) - >>> from .expression import Expression - >>> action.this_append_before([Expression('2+10*4'), Expression('2+40')]) - >>> for i in action.explain(): - ... print(i) - 2 + 10 \times 4 - 2 + 40 - 42 - >>> # Now action is amnesiac - >>> for i in action.explain(): - ... print(i) - 42 - >>> action = Explicable(['42']) - >>> for i in action.explain(): - ... print(i) - 42 - - """ - if self.explained: - return self.self_generator() - else: - self.explained = 1 - return self.history_generator() - - def self_generator(self): - """ Generator which yield itself rendered """ - yield self.STR_RENDER(self.postfix_tokens) - - @no_repetition() - def history_generator(self): - r""" Generator for rendered steps which leed to itself - - This is the called method in explain which create the generator. - It create a new generator at each call. - - >>> action = Explicable(['42']) - >>> from .expression import Expression - >>> for i in action.history_generator(): - ... print(i) - 42 - >>> action.this_append_before([Expression('2+10*4'), Expression('2+40')]) - >>> for i in action.history_generator(): - ... print(i) - 2 + 10 \times 4 - 2 + 40 - 42 - >>> for i in action.history_generator(): - ... print(i) - 2 + 10 \times 4 - 2 + 40 - 42 - """ - try: - for s in self.steps: - try: - new_s = self.STR_RENDER(s.postfix_tokens) - except AttributeError: - new_s = self.STR_RENDER(s) - yield new_s - - except AttributeError: - pass - - # if noself: - new_s = self.STR_RENDER(self.postfix_tokens) - yield new_s - - def this_append_before(self, steps): - """ Add steps at the beginning of self.steps - - :param steps: list of steps that append before - - >>> e = Explicable(['Actions']) - >>> s = ['eat', 'sleep'] - >>> e.this_append_before(s) - >>> print(e.steps) - ['eat', 'sleep'] - >>> s0 = ['cook'] - >>> e.this_append_before(s0) - >>> print(e.steps) - ['cook', 'eat', 'sleep'] - """ - self.steps = list(steps) + self.steps - - def steal_history(self, arg1): - """ Steal the history of arg1 for itself - - :param arg1: a potential Explicable - - >>> e = Explicable(['Actions']) - >>> s = [Step(['eat']), Step(['sleep'])] - >>> e.this_append_before(s) - >>> f = Explicable(['Stolen actions']) - >>> f.steal_history(e) - >>> for i in e.explain(): - ... print(i) - Actions - >>> for i in f.explain(): - ... print(i) - eat - sleep - Actions - Stolen actions - - - """ - try: - with Step.tmp_render(): - self.this_append_before(list(arg1.explain())) - except AttributeError: - pass - - @classmethod - def merge_history(cls, explicables): - r""" Take a list of Explicable objects, explain where they are from and merge their history - - This method try to use 'explain' method from Explicable. This means that after using this method, those objects will become amnesiac. - - :param explicables: list - :returns: the list of steps - - >>> from .expression import Expression - >>> action1 = Explicable(['42']) - >>> action1.this_append_before([['2 + 4 * 10'], ['2 + 40']]) - >>> action2 = Explicable(['24']) - >>> action2.this_append_before([['12 * 2']]) - >>> m_history = Explicable.merge_history([action1, action2]) - >>> m_history - - >>> for i in m_history: - ... print(i) - [< Step ['2 + 4 * 10']>, < Step ['12 * 2']>] - [< Step ['2 + 40']>, < Step ['24']>] - [< Step ['42']>, < Step ['24']>] - >>> # Now they are amnesiac - >>> for i in action1.explain(): - ... print(i) - 42 - >>> m_history = Explicable.merge_history([action1, action2]) - >>> for i in m_history: - ... print(i) - [< Step ['42']>, < Step ['24']>] - >>> action1 = Explicable(['42']) - >>> action1.this_append_before([['2+10*4'], ['2+40']]) - >>> m_history = Explicable.merge_history([action1, 12]) - >>> m_history - - >>> for i in m_history: - ... print(i) - [< Step ['2+10*4']>, < Step [12]>] - [< Step ['2+40']>, < Step [12]>] - [< Step ['42']>, < Step [12]>] - >>> action1 = Explicable(['42']) - >>> action1.this_append_before([['2+10*4'], ['2+40']]) - >>> action2 = Explicable(['24']) - >>> action2.this_append_before([['2*12']]) - >>> action3 = Explicable(['0']) - >>> action3.this_append_before([['3-3']]) - >>> m_history = Explicable.merge_history([action1, action2, action3]) - >>> for i in m_history: - ... print(i) - [< Step ['2+10*4']>, < Step ['2*12']>, < Step ['3-3']>] - [< Step ['2+40']>, < Step ['24']>, < Step ['0']>] - [< Step ['42']>, < Step ['24']>, < Step ['0']>] - >>> m_history = Explicable.merge_history([1,2,3]) - >>> for i in m_history: - ... print(i) - [< Step [1]>, < Step [2]>, < Step [3]>] - """ - steps = [] - for expl in explicables: - try: - with Step.tmp_render(): - steps.append(list(expl.explain())) - except AttributeError: - steps.append([Step([expl])]) - - return transpose_fill(steps) - - -class Explicable_int(int, Explicable): - - """ An Explicable_int is an int which can be explain """ - - isNumber = True - - def __init__(self, val): - super(Explicable_int, self).__init__(val) - self._val = val - self.postfix_tokens = [self] - self.steps = [] - - def simplify(self): - return Explicable_int(self._val) - - def __txt__(self): - return str(self._val) - - def __tex__(self): - return str(self._val) - - -class Explicable_Decimal(Decimal, Explicable): - - """ An Explicable_Decimal is an decimal which can be explain """ - - isNumber = True - - def __init__(self, val): - super(Explicable_Decimal, self).__init__(val) - self._val = val - self.postfix_tokens = [self] - self.steps = [] - - def simplify(self): - return Explicable_Decimal(self._val) - - def __txt__(self): - return str(self._val) - - def __tex__(self): - return str(self._val) - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/expression.py b/mapytex/calculus/expression.py deleted file mode 100644 index 9fb6f38..0000000 --- a/mapytex/calculus/expression.py +++ /dev/null @@ -1,338 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -# debuging -# from debug.tools import report - -from .generic import flatten_list, expand_list, isOperator, isNumerand -from .str2tokens import str2tokens -from .operator import op -from .explicable import Explicable, Explicable_int, Explicable_Decimal -from .step import Step -from decimal import Decimal - -from .random_expression import RdExpression - -__all__ = ['Expression'] - - -class Expression(Explicable): - """A calculus expression. Today it can andle only expression with numbers later it will be able to manipulate unknown""" - - @classmethod - def random(self, form="", conditions=[], val_min=-10, val_max=10): - """Create a random expression from form and with conditions - - :param form: the form of the expression (/!\ variables need to be in brackets {}) - :param conditions: condition on variables (/!\ variables need to be in brackets {}) - :param val_min: min value for generate variables - :param val_max: max value for generate variables - - """ - random_generator = RdExpression(form, conditions) - return Expression(random_generator(val_min, val_max)) - - - def __init__(self, exp): - """Create Expression objects - - :param exp: the expression. It can be a string or a list of postfix tokens. - - """ - - if isinstance(exp, str): - pstf_tokens = str2tokens(exp) - - elif isinstance(exp, list): - # Ici on ne peut convertir les "+-*/..." en opérateur que s'ils sont - # d'arité 2. - exp_mod_op = [ - op.get_op(i) if op.can_be_operator(i) else i for i in exp - ] - pstf_tokens = flatten_list( - [tok.postfix_tokens if Expression.isExpression(tok) - else tok - for tok in exp_mod_op - ] - ) - - elif isinstance(exp, Expression): - pstf_tokens = exp.postfix_tokens - - elif isNumerand(exp): - pstf_tokens = [exp] - - else: - raise ValueError( - "Can't build Expression with {} object".format( - type(exp) - ) - ) - - super(Expression, self).__init__(pstf_tokens) - self._isExpression = 1 - - def simplify(self): - """ Compute entirely the expression and return the result with .steps attribute """ - try: - self.compute_exp() - except ComputeError: - try: - self.simplified = self.postfix_tokens[0].simplify() - except AttributeError: - if isinstance(self.postfix_tokens[0], int): - self.simplified = Explicable_int(self.postfix_tokens[0]) - elif isinstance(self.postfix_tokens[0], Decimal): - self.simplified = Explicable_Decimal(self.postfix_tokens[0]) - else: - self.simplified = self - - else: - self.simplified = self.child.simplify() - self.simplified.this_append_before(self.child.steps) - return self.simplified - - def compute_exp(self): - """ Create self.child with and stock steps in it """ - if len(self.postfix_tokens) == 1: - raise ComputeError("Nothing to compute in {}".format(self.postfix_tokens)) - else: - ini_step = Step(self.postfix_tokens) - - tokenList = self.postfix_tokens.copy() - tmpTokenList = [] - - while len(tokenList) > 2: - # on va chercher les motifs du genre A B +, quand l'operateur est - # d'arité 2, pour les calculer - if isNumerand(tokenList[0]) and isNumerand(tokenList[1]) \ - and isOperator(tokenList[2]) and tokenList[2].arity == 2: - - # S'il y a une opération à faire - op1 = tokenList[0] - op2 = tokenList[1] - operator = tokenList[2] - - res = operator(op1, op2) - - tmpTokenList.append(res) - - # Comme on vient de faire le calcul, on peut détruire aussi les - # deux prochains termes - del tokenList[0:3] - - # Et les motifs du gens A -, quand l'operateur est d'arité 1 - elif isNumerand(tokenList[0]) \ - and isOperator(tokenList[1]) and tokenList[1].arity == 1: - - # S'il y a une opération à faire - op1 = tokenList[0] - operator = tokenList[1] - - res = operator(op1) - - tmpTokenList.append(res) - - # Comme on vient de faire le calcul, on peut détruire aussi les - # deux prochains termes - del tokenList[0:2] - - else: - tmpTokenList.append(tokenList[0]) - - del tokenList[0] - - if len(tokenList) == 2 and isNumerand(tokenList[0]) \ - and isOperator(tokenList[1]) and tokenList[1].arity == 1: - # S'il reste deux éléments dont un operation d'arité 1 - op1 = tokenList[0] - operator = tokenList[1] - - res = operator(op1) - - tmpTokenList.append(res) - - # Comme on vient de faire le calcul, on peut détruire aussi les - # deux prochains termes - del tokenList[0:2] - - tmpTokenList += tokenList - self.child = Expression(tmpTokenList) - - steps = Expression.develop_steps(tmpTokenList) - - if self.child.postfix_tokens == ini_step.postfix_tokens: - self.child.steps = steps - else: - self.child.this_append_before([ini_step] + steps) - - @classmethod - def develop_steps(cls, tokenList): - r""" - From a list of tokens, it develops steps of each tokens and transpose it into steps respecting the stucture of the tokenList. - - It try to use 'explain' method for every tokens. After using this methode, tokens becom amnesiac. - - >>> e = Expression('1+2') - >>> e1 = e.simplify() - >>> f = Expression('3*4+5') - >>> f1 = f.simplify() - >>> dev_steps = Expression.develop_steps([e1, f1, op.add]) - >>> dev_steps - [< Step [1, 2, +, 3, 4, *, 5, +, +]>, < Step [3, 12, 5, +, +]>, < Step [3, 17, +]>] - >>> for i in dev_steps: - ... print(i) - 1 + 2 + 3 \times 4 + 5 - 3 + 12 + 5 - 3 + 17 - >>> e = Expression('1+2') - >>> e1 = e.simplify() - >>> f = Expression('3*4+5') - >>> f1 = f.simplify() - >>> g = Expression('6+7') - >>> g1 = g.simplify() - >>> Expression.develop_steps([e1, f1, op.add, g1, op.mul]) - [< Step [1, 2, +, 3, 4, *, 5, +, +, 6, 7, +, *]>, < Step [3, 12, 5, +, +, 13, *]>, < Step [3, 17, +, 13, *]>] - """ - with Step.tmp_render(): - tmp_steps = list(Explicable.merge_history(tokenList)) - - steps = [Step(s) for s in tmp_steps] - return steps - - @classmethod - def isExpression(cls, other): - try: - other._isExpression - except AttributeError: - return 0 - return 1 - - # ----------- - # Expression act as container from self.postfix_tokens - - def __getitem__(self, index): - return self.postfix_tokens[index] - - def __setitem__(self, index, value): - self.postfix_tokens[index] = value - - # ----------- - # Some math manipulations - - def operate(self, other, operator): - if isinstance(other, Expression): - return Expression( - self.postfix_tokens + - other.postfix_tokens + - [operator]) - elif isinstance(other, list): - return Expression(self.postfix_tokens + other + [operator]) - else: - return Expression(self.postfix_tokens + [other] + [operator]) - - def roperate(self, other, operator): - if isinstance(other, Expression): - return Expression( - other.postfix_tokens + - self.postfix_tokens + - [operator]) - elif isinstance(other, list): - return Expression(other + self.postfix_tokens + [operator]) - else: - return Expression([other] + self.postfix_tokens + [operator]) - - def __add__(self, other): - """ Overload + - - >>> a = Expression("1+2") - >>> print(a.postfix_tokens) - [1, 2, +] - >>> b = Expression("3+4") - >>> print(b.postfix_tokens) - [3, 4, +] - >>> c = a + b - >>> print(c.postfix_tokens) - [1, 2, +, 3, 4, +, +] - """ - return self.operate(other, op.add) - - def __radd__(self, other): - return self.roperate(other, op.add) - - def __sub__(self, other): - """ Overload - - - >>> a = Expression("1+2") - >>> print(a.postfix_tokens) - [1, 2, +] - >>> b = Expression("3+4") - >>> print(b.postfix_tokens) - [3, 4, +] - >>> c = a - b - >>> print(c.postfix_tokens) - [1, 2, +, 3, 4, +, -] - """ - return self.operate(other, op.sub) - - def __rsub__(self, other): - return self.roperate(other, op.sub) - - def __mul__(self, other): - """ Overload * - - >>> a = Expression("1+2") - >>> print(a.postfix_tokens) - [1, 2, +] - >>> b = Expression("3+4") - >>> print(b.postfix_tokens) - [3, 4, +] - >>> c = a * b - >>> print(c.postfix_tokens) - [1, 2, +, 3, 4, +, *] - """ - return self.operate(other, op.mul) - - def __rmul__(self, other): - return self.roperate(other, op.mul) - - def __truediv__(self, other): - """ Overload / - - >>> a = Expression("1+2") - >>> print(a.postfix_tokens) - [1, 2, +] - >>> b = Expression("3+4") - >>> print(b.postfix_tokens) - [3, 4, +] - >>> c = a / b - >>> print(c.postfix_tokens) - [1, 2, +, 3, 4, +, /] - >>> - """ - return self.operate(other, op.div) - - def __rtruediv__(self, other): - return self.roperate(other, op.div) - - def __pow__(self, other): - return self.operate(other, op.pw) - - def __xor__(self, other): - return self.operate(other, op.pw) - - def __neg__(self): - return Expression(self.postfix_tokens + [op.sub1]) - - -class ExpressionError(Exception): - pass - - -class ComputeError(Exception): - pass - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/fraction.py b/mapytex/calculus/fraction.py deleted file mode 100644 index 4dad6a8..0000000 --- a/mapytex/calculus/fraction.py +++ /dev/null @@ -1,558 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -from .arithmetic import gcd -from .generic import isNumber, postfix_op -from .operator import op -from .expression import Expression -from .explicable import Explicable -from .step import Step -from copy import copy - - -__all__ = ['Fraction'] - - -class Fraction(Explicable): - """Fractions!""" - - def __init__(self, num, denom=1): - """To initiate a fraction we need a numerator and a denominator - - :param num: the numerator - :param denom: the denominator - - """ - self._num = num - if denom == 0: - raise ZeroDivisionError("Can't create Fraction: division by zero") - self._denom = denom - - self.isNumber = 1 - pstf_tokens = self.compute_postfix_tokens() - super(Fraction, self).__init__(pstf_tokens) - - def simplify(self): - """Simplify the fraction - - :returns: steps to simplify the fraction or the fraction if there is nothing to do - - >>> f = Fraction(3, 6) - >>> f.simplify() - < Fraction 1 / 2> - >>> for i in f.simplify().explain(): - ... print(i) - \\frac{ 3 }{ 6 } - \\frac{ 1 \\times 3 }{ 2 \\times 3 } - \\frac{ 1 }{ 2 } - >>> f = Fraction(6,9) - >>> f.simplify() - < Fraction 2 / 3> - >>> f.simplify().steps - [< Step [6, 9, /]>, < Step [2, 3, *, 3, 3, *, /]>] - >>> for i in f.simplify().explain(): - ... print(i) - \\frac{ 6 }{ 9 } - \\frac{ 2 \\times 3 }{ 3 \\times 3 } - \\frac{ 2 }{ 3 } - >>> f = Fraction(0,3) - >>> f.simplify() - 0 - - """ - ini_step = [Step(self.postfix_tokens)] - - if self._num == 0: - return Expression([0]).simplify() - - elif isinstance(self._num, Fraction) or isinstance(self._denom, Fraction): - return self._num / self._denom - - elif self._denom < 0: - n_frac = Fraction(-self._num, -self._denom) - ans = n_frac.simplify() - ans.this_append_before(ini_step) - return ans - - gcd_ = gcd(abs(self._num), abs(self._denom)) - if gcd_ == self._denom: - n_frac = self._num // gcd_ - return Expression([n_frac]).simplify() - - elif gcd_ != 1: - n_frac = Fraction(self._num // gcd_, self._denom // gcd_) - ini_step += [Step([ - n_frac._num, gcd_, op.mul, - n_frac._denom, gcd_, op.mul, - op.div - ])] - - n_frac.this_append_before(ini_step) - return n_frac - - else: - return copy(self) - - def compute_postfix_tokens(self): - """Postfix form of the fraction - - >>> f = Fraction(3, 5) - >>> f.postfix_tokens - [3, 5, /] - - """ - if self._denom == 1: - return [self._num] - else: - return [self._num, self._denom, op.div] - - def __str__(self): - return str(Expression(self.postfix_tokens)) - - def __repr__(self): - return "< Fraction {num} / {denom}>".format( - num=self._num, denom=self._denom) - - def __float__(self): - return self._num / self._denom - - def convert2fraction(self, other): - """ Convert a other into a fraction """ - if isinstance(other, Fraction): - # cool - number = other - else: - number = Fraction(other) - - return number - - def __add__(self, other): - """ overload + - - >>> f = Fraction(1, 2) - >>> g = Fraction(2, 3) - >>> f + g - < Fraction 7 / 6> - >>> print("\\n".join([repr(i) for i in (f+g).steps])) - < Step [1, 2, /, 2, 3, /, +]> - < Step [1, 3, *, 2, 3, *, /, 2, 2, *, 3, 2, *, /, +]> - < Step [3, 6, /, 4, 6, /, +]> - < Step [3, 6, /, 4, 6, /, +]> - < Step [3, 6, /, 4, 6, /, +]> - < Step [3, 6, /, 4, 6, /, +]> - < Step [3, 6, /, 4, 6, /, +]> - < Step [3, 4, +, 6, /]> - < Step [7, 6, /]> - >>> f + 2 - < Fraction 5 / 2> - >>> print("\\n".join([repr(i) for i in (f+2).steps])) - < Step [1, 2, /, 2, +]> - < Step [1, 1, *, 2, 1, *, /, 2, 2, *, 1, 2, *, /, +]> - < Step [1, 2, /, 4, 2, /, +]> - < Step [1, 2, /, 4, 2, /, +]> - < Step [1, 2, /, 4, 2, /, +]> - < Step [1, 2, /, 4, 2, /, +]> - < Step [1, 2, /, 4, 2, /, +]> - < Step [1, 4, +, 2, /]> - < Step [5, 2, /]> - >>> f = Fraction(3, 4) - >>> g = Fraction(5, 4) - >>> f + g - 2 - >>> print("\\n".join([repr(i) for i in (f+g).steps])) - < Step [3, 4, /, 5, 4, /, +]> - < Step [3, 5, +, 4, /]> - < Step [8, 4, /]> - < Step [8, 4, /]> - < Step [8, 4, /]> - >>> f+0 - < Fraction 3 / 4> - >>> (f+0).steps - [] - - """ - - if other == 0: - return copy(self) - - number = self.convert2fraction(other) - - if self._denom == number._denom: - com_denom = self._denom - num1 = self._num - num2 = number._num - - exp = Expression([num1, num2, op.add, com_denom, op.div]) - - else: - gcd_denom = gcd(self._denom, number._denom) - coef1 = number._denom // gcd_denom - coef2 = self._denom // gcd_denom - - exp = Expression([self._num, - coef1, - op.mul, - self._denom, - coef1, - op.mul, - op.div, - number._num, - coef2, - op.mul, - number._denom, - coef2, - op.mul, - op.div, - op.add]) - - ans = exp.simplify() - ini_step = Step(self.postfix_tokens + - number.postfix_tokens + [op.add]) - ans.this_append_before([ini_step]) - return ans - - def __radd__(self, other): - if other == 0: - return Expression(self.postfix_tokens) - - number = self.convert2fraction(other) - - return number + self - - def __sub__(self, other): - """ overload - - - >>> f = Fraction(1, 2) - >>> g = Fraction(2, 3) - >>> f - g - < Fraction -1 / 6> - >>> print("\\n".join([repr(i) for i in (f-g).steps])) - < Step [1, 2, /, 2, 3, /, -]> - < Step [1, 3, *, 2, 3, *, /, 2, 2, *, 3, 2, *, /, -]> - < Step [3, 6, /, 4, 6, /, -]> - < Step [3, 6, /, 4, 6, /, -]> - < Step [3, 6, /, 4, 6, /, -]> - < Step [3, 6, /, 4, 6, /, -]> - < Step [3, 6, /, 4, 6, /, -]> - < Step [3, 4, -, 6, /]> - < Step [-1, 6, /]> - >>> f - 0 - < Fraction 1 / 2> - >>> (f-0).steps - [] - - """ - if other == 0: - return copy(self) - - number = self.convert2fraction(other) - - if self._denom == number._denom: - com_denom = self._denom - num1 = self._num - num2 = number._num - - exp = Expression([num1, num2, op.sub, com_denom, op.div]) - - else: - gcd_denom = gcd(self._denom, number._denom) - coef1 = number._denom // gcd_denom - coef2 = self._denom // gcd_denom - - exp = Expression([self._num, - coef1, - op.mul, - self._denom, - coef1, - op.mul, - op.div, - number._num, - coef2, - op.mul, - number._denom, - coef2, - op.mul, - op.div, - op.sub]) - - ini_step = Step(self.postfix_tokens + - number.postfix_tokens + [op.sub]) - ans = exp.simplify() - ans.this_append_before([ini_step]) - return ans - - def __rsub__(self, other): - if other == 0: - return copy(self) - - number = self.convert2fraction(other) - - return number - self - - def __neg__(self): - """ overload - (as arity 1 operator) - - >>> f = Fraction(1, 2) - >>> -f - < Fraction -1 / 2> - >>> (-f).steps - [] - >>> f = Fraction(1, -2) - >>> f - < Fraction 1 / -2> - >>> -f - < Fraction 1 / 2> - >>> (-f).steps - [< Step [-1, -2, /]>] - - """ - f = Fraction(-self._num, self._denom) - ans = f.simplify() - - return ans - - def __mul__(self, other): - """ overload * - - >>> f = Fraction(1, 2) - >>> g = Fraction(2, 3) - >>> f*g - < Fraction 1 / 3> - >>> print("\\n".join([repr(i) for i in (f*g).steps])) - < Step [1, 2, /, 2, 3, /, *]> - < Step [1, 2, *, 2, 3, *, /]> - < Step [1, 3, /]> - < Step [1, 3, /]> - >>> f * 0 - 0 - >>> (f*0).steps - [< Step [1, 2, /, 0, *]>] - >>> f*1 - < Fraction 1 / 2> - >>> (f*1).steps - [< Step [1, 2, /, 1, *]>] - >>> f*4 - 2 - >>> print("\\n".join([repr(i) for i in (f*4).steps])) - < Step [1, 2, /, 4, *]> - < Step [1, 2, *, 2, *, 1, 2, *, /]> - < Step [1, 2, *, 1, /]> - < Step [2, 1, /]> - < Step [2, 1, /]> - < Step [2]> - - """ - steps = [Step([self, other, op.mul])] - - if other == 0: - exp = Expression([0]) - elif other == 1: - exp = copy(self) - - elif isinstance(other, int): - gcd1 = gcd(other, self._denom) - if gcd1 != 1: - num_s = [self._num] + \ - [int(other / gcd1), op.mul] * (int(other / gcd1) != 1) + \ - [gcd1, op.mul] - denom_s = [int(self._denom / gcd1), gcd1, op.mul] - steps.append(Step(num_s + denom_s + [op.div])) - - num = [self._num] + [int(other / gcd1), op.mul] * (int(other / gcd1) != 1) - denom = [int(self._denom / gcd1)] - else: - num = [self._num, other, op.mul] - denom = [self._denom] - - exp = Expression(num + denom + [op.div]) - - else: - number = self.convert2fraction(other) - - gcd1 = gcd(self._num, number._denom) - if gcd1 != 1: - num1_s = [gcd1] + [int(self._num / gcd1), op.mul] * (int(self._num / gcd1) != 1) - denom2_s = [gcd1] + [int(number._denom / gcd1), op.mul] * (int(number._denom / gcd1) != 1) - - num1 = [int(self._num / gcd1)] * (int(self._num / gcd1) != 1) - denom2 = [int(number._denom / gcd1)] * (int(self._denom / gcd1) != 1) - else: - num1_s = [self._num] - denom2_s = [number._denom] - - num1 = [self._num] - denom2 = [number._denom] - - gcd2 = gcd(self._denom, number._num) - if gcd2 != 1: - num2_s = [gcd2] + [int(number._num / gcd2), op.mul] * (int(number._num / gcd2) != 1) - denom1_s = [gcd2] + [int(self._denom / gcd2), op.mul] * (int(self._denom / gcd2) != 1) - - num2 = [int(number._num / gcd2)] * (int(number._num / gcd2) != 1) - denom1 = [int(self._denom / gcd2)] * (int(number._denom / gcd2) != 1) - else: - num2_s = [number._num] - denom1_s = [self._denom] - - num2 = [number._num] - denom1 = [self._denom] - - steps.append(Step(num1_s + num2_s + [op.mul] + - denom1_s + denom2_s + [op.mul, op.div])) - - exp = Expression(postfix_op(num1 + num2, op.mul, 1) + - postfix_op(denom1 + denom2, op.mul, 1) + - [op.div]) - - ans = exp.simplify() - ans.steps = steps + ans.steps - return ans - - def __rmul__(self, other): - return self * other - - def __truediv__(self, other): - """ overload / - - >>> f = Fraction(1,2) - >>> g = Fraction(3,4) - >>> f / 0 - Traceback (most recent call last): - ... - ZeroDivisionError: division by zero - >>> f / 1 - < Fraction 1 / 2> - >>> (f/1).steps - [] - >>> f / g - < Fraction 2 / 3> - - """ - if other == 0: - raise ZeroDivisionError("division by zero") - elif other == 1: - return copy(self) - - number = self.convert2fraction(other) - - ini_step = Step(self.postfix_tokens + - number.postfix_tokens + [op.div]) - - number = Fraction(number._denom, number._num) - ans = self * number - - ans.this_append_before([ini_step]) - return ans - - def __rtruediv__(self, other): - number = self.convert2fraction(other) - - return number / self - - def __pow__(self, power): - """ overload ** - - >>> f = Fraction(3, 4) - >>> f**0 - 1 - >>> (f**0).steps - [< Step [3, 4, /, 0, ^]>] - >>> f**1 - < Fraction 3 / 4> - >>> (f**1).steps - [< Step [3, 4, /, 1, ^]>] - >>> f**3 - < Fraction 27 / 64> - >>> print("\\n".join([repr(i) for i in (f**3).steps])) - < Step [3, 4, /, 3, ^]> - < Step [3, 3, ^, 4, 3, ^, /]> - < Step [27, 64, /]> - < Step [27, 64, /]> - < Step [27, 64, /]> - >>> f = Fraction(6, 4) - >>> f**3 - < Fraction 27 / 8> - >>> print("\\n".join([repr(i) for i in (f**3).steps])) - < Step [6, 4, /, 3, ^]> - < Step [6, 3, ^, 4, 3, ^, /]> - < Step [216, 64, /]> - < Step [216, 64, /]> - < Step [216, 64, /]> - < Step [216, 64, /]> - < Step [27, 8, *, 8, 8, *, /]> - - """ - if not isinstance(power, int): - raise ValueError( - "Can't raise fraction to power {}".format( - str(power))) - - ini_step = Step([self, power, op.pw]) - if power == 0: - exp = Expression([1]) - elif power == 1: - exp = copy(self) - else: - exp = Expression([ - self._num, power, op.pw, - self._denom, power, op.pw, - op.div - ]) - - ans = exp.simplify() - ans.this_append_before([ini_step]) - return ans - - def __xor__(self, power): - """ overload ^ - - Work like ** - - >>> f = Fraction(3, 4) - >>> f^0 - 1 - >>> f^1 - < Fraction 3 / 4> - >>> f^3 - < Fraction 27 / 64> - """ - - return self.__pow__(power) - - def __abs__(self): - return Fraction(abs(self._num), abs(self._denom)) - - def __eq__(self, other): - """ == """ - if isNumber(other): - number = self.convert2fraction(other) - - return self._num * number._denom == self._denom * number._num - else: - return 0 - - def __lt__(self, other): - """ < """ - return float(self) < float(other) - - def __le__(self, other): - """ <= """ - return float(self) <= float(other) - - def __gt__(self, other): - """ > """ - return float(self) > float(other) - - def __ge__(self, other): - """ >= """ - return float(self) >= float(other) - - def __copy__(self): - """ Copying the fraction removing steps where it is from """ - return Fraction(self._num, self._denom) - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/generic.py b/mapytex/calculus/generic.py deleted file mode 100644 index d435083..0000000 --- a/mapytex/calculus/generic.py +++ /dev/null @@ -1,399 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -from itertools import zip_longest, chain - - -class Stack(object): - """Docstring for Stack """ - - def __init__(self): - self.items = [] - - def pushFromList(self, list): - """Push the list in the stack - - :param list: a list - """ - for i in list[::-1]: - self.push(i) - - def isEmpty(self): - """ Says if the stack is empty - - """ - return self.items == [] - - def push(self, item): - """Push an item in the stack - - """ - self.items.append(item) - - def pop(self): - """Getting the last item and remove it - :returns: last item - - """ - return self.items.pop() - - def peek(self, posi=0): - """Getting the last item - :param posi: which item to peek 0 (last) 1 (the onebefore the last)... - :returns: the item - - """ - return self.items[-1 - posi] - - def __len__(self): - return len(self.items) - - def __str__(self): - return str(self.items) + " -> " - - def __add__(self, addList): - return self.items + addList - - -def flatten_list(a, result=None): - """Flattens a nested list. - - >>> flatten_list([ [1, 2, [3, 4] ], [5, 6], 7]) - [1, 2, 3, 4, 5, 6, 7] - """ - if result is None: - result = [] - - for x in a: - if isinstance(x, list): - flatten_list(x, result) - else: - result.append(x) - - return result - - -def first_elem(ll): - """Get the first element in imbricates lists - # TODO: Fonction pourrie mais j'ai pas le temps de faire mieux! |mar. janv. 28 22:32:22 CET 2014 - - :param list: list of lists of lists... - :returns: the first element - - >>> first_elem(1) - 1 - >>> first_elem([1,2]) - 1 - >>> first_elem([["abc"]]) - 'a' - >>> first_elem("abc") - 'a' - >>> first_elem([[[1,2],[3,4]], [5,6]]) - 1 - >>> first_elem([[["ab",2],[3,4]], [5,6]]) - 'a' - - """ - if hasattr(ll, '__contains__'): - if len(ll) == 1 and isinstance(ll, str): - return ll[0] - else: - return first_elem(ll[0]) - else: - return ll - - -def last_elem(ll): - """Get the last element in imbricates lists - # TODO: Fonction pourrie mais j'ai pas le temps de faire mieux! |mar. janv. 28 22:32:22 CET 2014 - - :param list: list of lists of lists... - :returns: the last element - - >>> last_elem(1) - 1 - >>> last_elem([1,2]) - 2 - >>> last_elem([["abc"]]) - 'c' - >>> last_elem("abc") - 'c' - >>> last_elem([[[1,2],[3,4]], [5,6]]) - 6 - >>> last_elem([[["ab",2],[3,4]], [5,6]]) - 6 - - """ - if hasattr(ll, '__contains__'): - if len(ll) == 1 and isinstance(ll, str): - return ll[-1] - else: - return last_elem(ll[-1]) - else: - return ll - - -def add_in_dict(dict1, dict2): - """Merge dictionary keys and add the content from dict1 and dict2 - - :param dict1: first dictionary - :param dict2: second dictionary - :returns: merged and added dictionary - - >>> add_in_dict({'a':1, 'b':2}, {'c':3, 'd': 4}) == {'d': 4, 'a': 1, 'c': 3, 'b': 2} - True - >>> add_in_dict({'a':1, 'b':2}, {'a':3, 'b': 4}) == {'a': 4, 'b': 6} - True - >>> add_in_dict({'a':1, 'b':2}, {'a':3, 'c': 4}) == {'a': 4, 'b': 2, 'c': 4} - True - - """ - new_dict = {} - new_dict.update(dict1) - for (k, v) in dict2.items(): - if k in new_dict.keys(): - new_dict[k] += v - else: - new_dict[k] = v - - return new_dict - - -def remove_in_dict(d, value=0): - """ In a dictionary, remove keys which have certain value - - :param d: the dictionary - :param value: value to remove - :returns: new dictionary whithout unwanted value - - >>> remove_in_dict({'b': 1, 'a': 0}) == {'b': 1} - True - >>> remove_in_dict({'b': 1, 'a': 0}, 1) == {'a': 0} - True - """ - new_dict = {} - for (k, v) in d.items(): - if v != value: - new_dict[k] = v - return new_dict - - -def convolution_dict(D1, D2, op=lambda x, y: x * y, - op_key=lambda x, y: x + y, - commutative=True, op_twice=lambda x, y: x + y): - """Convolution of two dictionaries - - :param D1: First dictionary - :param D2: Second dictionary - :param op: Operation of perform in value - :param commutative: keys are commutative? - :param op_twice: operation on value if the key appear twice - - >>> convolution_dict({"a": 1, "b":3}, {"a":2, "":4}) == {"aa":2, "a": 4, "ba":6, "b":12} - True - >>> convolution_dict({"a": 1, "b":3}, {"a":2, "b":4}) == {"aa":2, "ab":10, "bb":12} - True - >>> convolution_dict({"a": 1, "b":3}, {"a":2, "b":4}, commutative = False) == {"aa":2, "ab":10, "bb":12} - False - >>> convolution_dict({"a": 1, "b":3}, {"a":2, "b":4}, commutative = False) == {"aa":2, "ab":4,"ba":6, "bb":12} - True - >>> convolution_dict({"a": 1, "b":3}, {"a":2, "b":4}, \ - op_twice = lambda x,y:[x,y]) == {"aa":2, "ab":[4,6], "bb":12} - True - - """ - new_dict = {} - - for k1 in sorted(D1.keys()): - for k2 in sorted(D2.keys()): - if op_key(k1, k2) in new_dict.keys(): - key = op_key(k1, k2) - new_dict[key] = op_twice(new_dict[key], op(D1[k1], D2[k2])) - - elif op_key(k2, k1) in new_dict.keys() and commutative: - key = op_key(k2, k1) - new_dict[key] = op_twice(new_dict[key], op(D1[k1], D2[k2])) - - else: - key = op_key(k1, k2) - new_dict[key] = op(D1[k1], D2[k2]) - - return new_dict - - -def spe_zip(l1, l2): - """Zip two lists, if a list is longer, only it's element are taken - - >>> spe_zip([1,2], [3,4]) - [[1, 3], [2, 4]] - >>> spe_zip([1,2], [3,4,5]) - [[1, 3], [2, 4], 5] - """ - tmp = list(zip_longest(l1, l2)) - ans = [] - for i in tmp: - if None in i: - j = [a for a in i if a is not None][-1] - else: - j = list(i) - ans.append(j) - return ans - - -def expand_list(list_list): - """Expand list of list - - >>> expand_list([1,2,[3,4],5,[6,7,8]]) - [[1, 2, 3, 5, 6], [1, 2, 4, 5, 7], [1, 2, 4, 5, 8]] - >>> expand_list([1,2,4,5,6,7,8]) - [[1, 2, 4, 5, 6, 7, 8]] - - """ - list_in_list = [ - i if isinstance(i,list) - else [i] - for i in list_list - ] - - return list(transpose_fill(list_in_list)) - - -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 - - >>> list(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 postfix_op(numbers, operator, neutral = 0): - """Convert a list of numbers into a postfix addition - - :numbers: list of numbers - :operator: the operator to join with - :neutral: default value if the list is empty - :returns: Postfix list of succecive attition of number - - >>> from .operator import op - >>> postfix_op([1], op.add) - [1] - >>> postfix_op([1, 2], op.add) - [1, 2, +] - >>> postfix_op([1, 2, 3], op.add) - [1, 2, +, 3, +] - >>> postfix_op([1, 2, 3], op.mul) - [1, 2, *, 3, *] - >>> postfix_op(1, op.add) - [1] - >>> postfix_op([], op.add) - [0] - >>> postfix_op([], op.mul, 1) - [1] - """ - if not isinstance(numbers, list): - return [numbers] - elif numbers == []: - return [neutral] - else: - ans = [[a, operator] if i != 0 else [a] - for (i, a) in enumerate(numbers)] - return list(chain.from_iterable(ans)) - -def isOperator(exp): - """Check if the expression is an opération in "+-*/:^" - - :param exp: an expression - :returns: boolean - - """ - - # return (type(exp) == str and exp in "+-*/:^") - try: - exp.isOperator - except AttributeError: - return 0 - return 1 - - -def isNumber(exp): - """Check if the expression can be a number - - :param exp: an expression - :returns: True if the expression can be a number and false otherwise - - """ - try: - exp.isNumber - except AttributeError: - if isinstance(exp, int): - return 1 - else: - return 0 - return 1 - - -def isPolynom(exp): - """Check if the expression can be a polynom - - :param exp: an expression - :returns: True if the expression can be a polynom and false otherwise - - >>> from mapytex.calculus.polynom import Polynom - >>> p = Polynom([1,2]) - >>> isPolynom(p) - 1 - >>> isPolynom(1) - 0 - >>> isPolynom("a") - 0 - - """ - try: - exp._isPolynom - except AttributeError: - return 0 - return 1 - - -def isNumerand(exp): - """Check is the expression is something we can compute with - - >>> isNumerand(1) - 1 - >>> from mapytex.calculus.polynom import Polynom - >>> p = Polynom([1,2]) - >>> isNumerand(p) - 1 - >>> from mapytex.calculus.fraction import Fraction - >>> f = Fraction(12) - >>> isNumerand(f) - 1 - >>> isNumerand("a") - 0 - - - """ - return isNumber(exp) or isPolynom(exp) - -if __name__ == '__main__': - import doctest - doctest.testmod() - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/operator/__init__.py b/mapytex/calculus/operator/__init__.py deleted file mode 100644 index ccf3861..0000000 --- a/mapytex/calculus/operator/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -from .operator_set import op -from .operator import save_mainOp - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/operator/add.py b/mapytex/calculus/operator/add.py deleted file mode 100644 index 1d9a40a..0000000 --- a/mapytex/calculus/operator/add.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -from .operator import Operator, save_mainOp - - -class Add(Operator): - r""" The operator + - - >>> add = Add() - >>> add - + - >>> add(1, 2) - 3 - >>> add.__tex__('1','2') - '1 + 2' - >>> add.__tex__('-1','2') - '-1 + 2' - >>> add.__tex__('1','-2') - '1 - 2' - >>> add.__txt__('1','2') - '1 + 2' - >>> add.__txt__('-1','2') - '-1 + 2' - >>> add.__txt__('1','-2') - '1 - 2' - """ - - _CARACT = { - "operator": "+", - "name": "add", - "priority": 1, - "arity": 2, - "actions": ("__add__", "__radd__"), - "txt": "{op1} + {op2}", - "tex": "{op1} + {op2}", - } - - def __init__(self): - """ Initiate Add Operator """ - super(Add, self).__init__(**self._CARACT) - - def _render(self, link, *args): - """Global step for __txt__ and __tex__ - - :param link: the link between operators - :param *args: the operands - :returns: the string with operator and operands - - """ - if args[1][0] == "-": - op1 = self.l_parenthesis(args[0], True) - op2 = self.r_parenthesis(args[1][1:], True) - ans = link.replace('+', '-').format(op1=op1, op2=op2) - - ans = save_mainOp(ans, self) - return ans - else: - op1 = self.l_parenthesis(args[0], True) - op2 = self.r_parenthesis(args[1], True) - ans = link.format(op1=op1, op2=op2) - - ans = save_mainOp(ans, self) - return ans - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/operator/div.py b/mapytex/calculus/operator/div.py deleted file mode 100644 index de04956..0000000 --- a/mapytex/calculus/operator/div.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -from .operator import Operator, save_mainOp - - -class Div(Operator): - r""" The operator / - - >>> div = Div() - >>> div - / - >>> div(1, 2) - < Fraction 1 / 2> - >>> div.__tex__('1','2') - '\\frac{ 1 }{ 2 }' - >>> div.__tex__('-1','2') - '\\frac{ -1 }{ 2 }' - >>> div.__tex__('1','-2') - '\\frac{ 1 }{ -2 }' - >>> div.__txt__('1','2') - '1 / 2' - >>> div.__txt__('-1','2') - '-1 / 2' - >>> div.__txt__('1','-2') - '1 / ( -2 )' - """ - - _CARACT = { - "operator": "/", - "name": "div", - "priority": 5, - "arity": 2, - "txt": "{op1} / {op2}", - "tex": "\\frac{{ {op1} }}{{ {op2} }}", - } - - def __init__(self): - """ Initiate Div Operator """ - super(Div, self).__init__(**self._CARACT) - - def __call__(self, op1, op2): - if op2 == 1: - return op1 - else: - from ..fraction import Fraction - return Fraction(op1, op2) - - def __tex__(self, *args): - # Pas besoin de parenthèses en plus pour \frac - replacement = {"op"+str(i+1): op for (i, op) in enumerate(args)} - - ans = self.tex.format(**replacement) - ans = save_mainOp(ans, self) - return ans - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/operator/mul.py b/mapytex/calculus/operator/mul.py deleted file mode 100644 index 4df886b..0000000 --- a/mapytex/calculus/operator/mul.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -from .operator import Operator, save_mainOp - - -class Mul(Operator): - r""" The operator * - - >>> mul = Mul() - >>> mul - * - >>> mul(1, 2) - 2 - >>> mul.__tex__('1','2') - '1 \\times 2' - >>> mul.__tex__('2','a') - '2 a' - >>> mul.__tex__('1','-2') - '1 \\times ( -2 )' - - >>> mul.__txt__('1','2') - '1 * 2' - >>> mul.__txt__('2','a') - '2 a' - >>> mul.__txt__('a','2') - 'a * 2' - >>> mul.__txt__('1','-2') - '1 * ( -2 )' - """ - - _CARACT = { - "operator": "*", - "name": "mul", - "priority": 4, - "arity": 2, - "actions": ("__mul__", "__rmul__"), - "txt": "{op1} * {op2}", - "tex": "{op1} \\times {op2}", - } - - def __init__(self): - """ Initiate Mul Operator """ - super(Mul, self).__init__(**self._CARACT) - - # TODO: Add self.visibility |sam. nov. 8 17:00:08 CET 2014 - self.visibility = 1 - - def is_visible(self, op1, op2): - """ Tells whether self has to be visible or not - - :param op1: left operande - :param op2: rigth operande - - - >>> m = Mul() - >>> m.is_visible(2, 3) - True - >>> m.is_visible(2, -3) - True - >>> m.is_visible(-2, 3) - True - >>> m.is_visible('a', 2) - True - >>> m.is_visible('(2a + 1)', 2) - True - >>> m.is_visible(2, '(-2)') - True - >>> m.is_visible(2, '2a') - True - >>> m.is_visible(2, '(-2a)') - True - >>> m.is_visible(2, '(-2abc)') - True - - >>> m.is_visible(2, 'a') - False - >>> m.is_visible(2, '(2a + 1)') - False - >>> m.is_visible('(3x - 1)', '(2a + 1)') - False - >>> m.is_visible(2, '(-2x + 1)(3x + 2)') - False - """ - # TODO: À finir!!! |lun. mars 9 00:03:40 CET 2015 - if type(op2) == int: - # op2 est maintenant une chaine de caractères - return True - elif op2.isdecimal(): - return True - elif op2.isalpha(): - return False - elif op2[0].isdecimal(): - return True - elif op2[0] == "(" and not ("+" in op2 or "-" in op2[3:]): - return True - # Giga bricolage... - elif "frac" in op2: - return True - else: - return False - - def _render(self, link, *args): - - op1 = self.l_parenthesis(args[0], True) - op2 = self.r_parenthesis(args[1], True) - - if not self.is_visible(op1, op2): - ans = "{op1} {op2}".format(op1=op1, op2=op2) - else: - ans = link.format(op1=op1, op2=op2) - - ans = save_mainOp(ans, self) - return ans - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/operator/operator.py b/mapytex/calculus/operator/operator.py deleted file mode 100644 index 6ac72df..0000000 --- a/mapytex/calculus/operator/operator.py +++ /dev/null @@ -1,234 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -# from debug.tools import report - -from ..generic import flatten_list - - -class Operator(): - - """The operator class, is a string (representation of the operator) with its arity""" - - def __init__(self, operator="", name="", priority=0, actions=("", ""), txt="", tex="", arity=2, **kwrds): - """ Create an Operator """ - self.operator = operator - self.name = name - self.arity = arity - self.priority = priority - self.actions = actions - self.txt = txt - self.tex = tex - - self.isOperator = 1 - - def __call__(self, *args): - """ Calling this operator performs the rigth calculus """ - if self.arity == 1: - return getattr(args[0], self.actions)() - - elif self.arity == 2: - if issubclass(type(args[1]), int): - return getattr(args[0], self.actions[0])(args[1]) - else: - return getattr(args[1], self.actions[1])(args[0]) - - def _render(self, link, *args): - """Global step for __txt__ and __tex__ - - :param link: the link between operators - :param *args: the operands - :returns: the string with operator and operands - - """ - if self.arity == 1: - op1 = self.l_parenthesis(args[0], True) - ans = link.format(op1=op1) - - elif self.arity == 2: - op1 = self.l_parenthesis(args[0], True) - op2 = self.r_parenthesis(args[1], True) - ans = link.format(op1=op1, op2=op2) - - ans = save_mainOp(ans, self) - return ans - - def __repr__(self): - return str(self.operator) - - def __str__(self): - return str(self.operator) - - def __txt__(self, *args): - """Txt rendering for the operator - - :*args: Operands for this operation - :returns: String with operator and his operands - - >>> from .mul import Mul - >>> mul= Mul() - >>> from .add import Add - >>> add = Add() - >>> from .sub import Sub - >>> sub = Sub() - >>> from .sub1 import Sub1 - >>> sub1 = Sub1() - >>> mul.__txt__('1','2') - '1 * 2' - >>> add.__txt__('1','2') - '1 + 2' - >>> f = save_mainOp('2 + 3',add) - >>> mul.__txt__(f, '4') - '( 2 + 3 ) * 4' - >>> f = save_mainOp('-3',sub1) - >>> sub1.__txt__(f) - '- ( -3 )' - >>> sub1.__txt__('-3') - '- ( -3 )' - >>> f = save_mainOp('2 + 3',add) - >>> sub1.__txt__(f) - '- ( 2 + 3 )' - """ - return self._render(self.txt, *args) - - def __tex__(self, *args): - """Tex rendering for the operator - - :*args: Operands for this operation - :returns: String with operator and his operands - - >>> from .mul import Mul - >>> mul= Mul() - >>> from .add import Add - >>> add = Add() - >>> from .sub import Sub - >>> sub = Sub() - >>> from .sub1 import Sub1 - >>> sub1 = Sub1() - >>> mul.__tex__('1','2') - '1 \\\\times 2' - >>> add.__tex__('1','2') - '1 + 2' - >>> f = save_mainOp('2 + 3',add) - >>> mul.__tex__(f, '4') - '( 2 + 3 ) \\\\times 4' - >>> f = save_mainOp('-3',sub1) - >>> sub1.__tex__(f) - '- ( -3 )' - >>> sub1.__tex__('-3') - '- ( -3 )' - >>> f = save_mainOp('2 + 3',add) - >>> sub1.__tex__(f) - '- ( 2 + 3 )' - """ - return self._render(self.tex, *args) - - def __p2i__(self, *args): - """Fix list transformation for the operator - - :*args: Operands for this operation - :returns: list with the operator surrounded by operands - - >>> from .mul import Mul - >>> mul= Mul() - >>> from .add import Add - >>> add = Add() - >>> from .sub import Sub - >>> sub = Sub() - >>> from .sub1 import Sub1 - >>> sub1 = Sub1() - >>> mul.__p2i__(1,2) - [1, *, 2] - >>> f = save_mainOp([2, add, 3],add) - >>> mul.__p2i__(f, 4) - ['(', 2, +, 3, ')', *, 4] - >>> f = save_mainOp([sub1, 3],sub1) - >>> sub1.__p2i__(f) - [-, '(', -, 3, ')'] - >>> sub1.__p2i__(-3) - [-, '(', -3, ')'] - >>> f = save_mainOp([2, add, 3],add) - >>> sub1.__p2i__(f) - [-, '(', 2, +, 3, ')'] - """ - if self.arity == 1: - op1 = self.l_parenthesis(args[0]) - ans = flatten_list([self, op1]) - - elif self.arity == 2: - op1 = self.l_parenthesis(args[0]) - op2 = self.r_parenthesis(args[1]) - ans = flatten_list([op1, self, op2]) - - ans = save_mainOp(ans, self) - return ans - - def l_parenthesis(self, opl, str_join=False): - """ Add parenthesis for left operand if necessary """ - ans = opl - try: - if opl.mainOp.name == "sub1": - ans = opl - elif opl.mainOp.priority < self.priority: - ans = flatten_list(["(", opl, ")"]) - except AttributeError: - # op has not the attribute priority - pass - - ans = flatten_list([ans]) - if str_join: - ans = ' '.join([str(i) for i in ans]) - return ans - - def r_parenthesis(self, opr, str_join=False): - """ Add parenthesis for rigth operand if necessary """ - ans = opr - try: - if opr.mainOp.priority < self.priority or \ - (opr.mainOp.name == 'mul' and opr[0] == '-'): - ans = flatten_list(["(", ans, ")"]) - except AttributeError: - # op has not the attribute priority - try: - if int(ans) < 0: - ans = ['(', ans, ')'] - except ValueError: - pass - ans = flatten_list([ans]) - if str_join: - ans = ' '.join([str(i) for i in ans]) - return ans - - def uniq_desc(self): - """ Return the uniq description of the operator - :returns: (self.name, self.arity) - - """ - return (self.operator, self.arity) - - def __eq__(self, op2): - """ op1 == op2 """ - try: - return self.name == op2.name and self.arity == op2.arity - except AttributeError: - return False - - -def save_mainOp(obj, mainOp): - """Create a temporary class build over built-in type to stock the main operation of a calculus - - :obj: the object to add the attribute - :mainOp: the main operator - :returns: the same object with the main operation attribute - """ - # TODO: À mettre avec render? |mar. févr. 23 09:45:22 EAT 2016 - # TODO: On pourrait mettre un try avant de créer une nouvelle classe |mar. févr. 23 09:44:45 EAT 2016 - Fake = type('fake_'+str(type(obj)), (type(obj),), {'mainOp': mainOp}) - - return Fake(obj) - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/operator/operator_set.py b/mapytex/calculus/operator/operator_set.py deleted file mode 100644 index 300251e..0000000 --- a/mapytex/calculus/operator/operator_set.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -from .add import Add -from .div import Div -from .mul import Mul -from .par import Par -from .pw import Pw -from .sub import Sub -from .sub1 import Sub1 -from .operator import Operator - - -class Operator_set(object): - """ Class for sets of operators""" - - def __init__(self): - """ Initiate the operator_set """ - self._operators = {} - - def get_op(self, op, arity=2): - r"""Return the corresponding operator - - :op: symbole of the op - :arity: the arity (default is 2) - - >>> op = Operator_set() - >>> op.store_operator(Add()) - >>> op.get_op('+') - + - >>> mul = op.get_op('*') - Traceback (most recent call last): - ... - KeyError: '* (arity: 2) is not available' - >>> op.store_operator(Mul()) - >>> mul = op.get_op('*') - >>> mul.tex - '{op1} \\times {op2}' - >>> mul.txt - '{op1} * {op2}' - >>> op.store_operator(Sub1()) - >>> sub1 = op.get_op('-') - Traceback (most recent call last): - ... - KeyError: '- (arity: 2) is not available' - >>> sub1 = op.get_op('-', 1) - >>> sub1.tex - '- {op1}' - """ - try: - return getattr(self, self._operators[(op, arity)]) - except KeyError: - raise KeyError("{theOp} (arity: {arity}) is not available".format(theOp=op, arity=arity)) - - def available_op(self): - """ Get the set of available operators strings - - >>> op = Operator_set() - >>> op.available_op() - set() - >>> op.store_operator(Add()) - >>> '+' in op.available_op() - True - >>> '*' in op.available_op() - False - >>> op.store_operator(Mul()) - >>> '*' in op.available_op() - True - """ - return set([i[0] for i in self._operators]) - - def can_be_operator(cls, symbole): - r"""Tell if the symbole can be an operator - - >>> op = Operator_set() - >>> op.can_be_operator("+") - False - >>> op.store_operator(Add()) - >>> op.can_be_operator("+") - True - - """ - if type(symbole) == str: - return symbole in [i[0] for i in cls._operators] - else: - return False - - def store_operator(self, operator): - """ Save the operator as a method and - - :param operator: the operator (the class) (it will be accessible through .name method name. - - >>> op = Operator_set() - >>> op._operators - {} - >>> op.store_operator(Add()) - >>> op._operators - {('+', 2): 'add'} - >>> a = op.add - >>> a - + - >>> a.tex - '{op1} + {op2}' - >>> op.store_operator("+") - Traceback (most recent call last): - ... - ValueError: + is not en Operator it's a - """ - if isinstance(operator, Operator): - self._operators[operator.uniq_desc()] = operator.name - setattr(self, operator.name, operator) - else: - raise ValueError("{} is not en Operator it's a {}".format(operator, type(operator))) - - -op = Operator_set() -op.store_operator(Add()) -op.store_operator(Div()) -op.store_operator(Mul()) -op.store_operator(Par()) -op.store_operator(Pw()) -op.store_operator(Sub()) -op.store_operator(Sub1()) - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/operator/par.py b/mapytex/calculus/operator/par.py deleted file mode 100644 index 6d07969..0000000 --- a/mapytex/calculus/operator/par.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -from .operator import Operator - - -class Par(Operator): - - """ The operator ( """ - - _CARACT = { - "operator": "(", - "name": "par", - "priority": 0, - "arity": 0, - } - - def __init__(self): - """ Initiate Par Operator """ - super(Par, self).__init__(**self._CARACT) - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/operator/pw.py b/mapytex/calculus/operator/pw.py deleted file mode 100644 index 1b83d65..0000000 --- a/mapytex/calculus/operator/pw.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -from .operator import Operator -from ..generic import flatten_list - - -class Pw(Operator): - - """ The operator ^ - - >>> pw = Pw() - >>> pw - ^ - >>> pw(2, 3) - 8 - >>> pw.__tex__('2','3') - '2^{ 3 }' - >>> pw.__tex__('2','-3') - '2^{ -3 }' - >>> pw.__tex__('-2','3') - '( -2 )^{ 3 }' - >>> pw.__txt__('2','3') - '2 ^ 3' - >>> pw.__txt__('-2','3') - '( -2 ) ^ 3' - >>> pw.__txt__('2','-3') - '2 ^ ( -3 )' - """ - - _CARACT = { - "operator": "^", - "name": "pw", - "priority": 6, - "arity": 2, - "actions": ("__pow__", ""), - "txt": "{op1} ^ {op2}", - "tex": "{op1}^{{ {op2} }}", - } - - def __init__(self): - """ Initiate Pw Operator """ - super(Pw, self).__init__(**self._CARACT) - - def __call__(self, op1, op2): - """ Calling this operator performs the rigth calculus """ - return getattr(op1, "__pow__")(op2) - - def l_parenthesis(self, opl, str_join=False): - """ Add parenthesis for left operand if necessary """ - ans = opl - try: - if opl.mainOp.priority < self.priority: - ans = flatten_list(["(", opl, ")"]) - except AttributeError: - # op has not the attribute priority - pass - try: - if int(opl) < 0: - ans = ["(", opl, ")"] - except ValueError: - pass - - ans = flatten_list([ans]) - if str_join: - ans = ' '.join([str(i) for i in ans]) - return ans - - def __tex__(self, *args): - """Tex rendering for ^ - - :*args: Operands for this operation - :returns: String with operator and his operands - - """ - op1 = self.l_parenthesis(args[0], True) - op2 = args[1] - ans = self.tex.format(op1=op1, op2=op2) - - return ans - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/operator/sub.py b/mapytex/calculus/operator/sub.py deleted file mode 100644 index 2bc2c8c..0000000 --- a/mapytex/calculus/operator/sub.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -from .operator import Operator -from ..generic import flatten_list - - -class Sub(Operator): - - """ The operator - - - >>> sub = Sub() - >>> sub - - - >>> sub(1, 2) - -1 - >>> sub.__tex__('1','2') - '1 - 2' - >>> sub.__tex__('1','-2') - '1 - ( -2 )' - >>> sub.__tex__('-1','2') - '-1 - 2' - >>> sub.__txt__('1','2') - '1 - 2' - >>> sub.__txt__('1','-2') - '1 - ( -2 )' - >>> sub.__txt__('-1','2') - '-1 - 2' - """ - _CARACT = { - "operator": "-", - "name": "sub", - "priority": 2, - "arity": 2, - "actions": ("__sub__", "__rsub__"), - "txt": "{op1} - {op2}", - "tex": "{op1} - {op2}", - } - - def __init__(self): - """ Initiate Sub Operator """ - super(Sub, self).__init__(**self._CARACT) - - def l_parenthesis(self, op, str_join=False): - return op - - def r_parenthesis(self, op, str_join=False): - try: - if op.mainOp.priority <= self.priority: - op = flatten_list(["(", op, ")"]) - elif op[0] == '-': - op = flatten_list(["(", op, ")"]) - except AttributeError: - # op has not the attribute priority - try: - if int(op) < 0: - op = ['(', op, ')'] - except ValueError: - pass - ans = flatten_list([op]) - if str_join: - ans = ' '.join([str(i) for i in ans]) - return ans - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/operator/sub1.py b/mapytex/calculus/operator/sub1.py deleted file mode 100644 index e4e9447..0000000 --- a/mapytex/calculus/operator/sub1.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -from .operator import Operator -from ..generic import flatten_list - - -class Sub1(Operator): - - """ The operator - - - >>> sub1 = Sub1() - >>> sub1 - - - >>> sub1(1) - -1 - >>> sub1.__tex__('1') - '- 1' - >>> sub1.__tex__('-1') - '- ( -1 )' - >>> sub1.__txt__('1') - '- 1' - >>> sub1.__txt__('-1') - '- ( -1 )' - """ - - _CARACT = { - "operator": "-", - "name": "sub1", - "priority": 3, - "arity": 1, - "actions": "__neg__", - "txt": "- {op1}", - "tex": "- {op1}", - } - - def __init__(self): - """ Initiate Sub1 Operator """ - super(Sub1, self).__init__(**self._CARACT) - - def l_parenthesis(self, op, str_join=False): - """ Add parenthesis if necessary """ - try: - if op.mainOp.priority <= self.priority: - op = flatten_list(["("] + [op] + [")"]) - except AttributeError: - # op has not the attribute priority - try: - if int(op) < 0: - op = ['(', op, ')'] - except ValueError: - pass - - ans = flatten_list([op]) - if str_join: - ans = ' '.join([str(i) for i in ans]) - return ans - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/polynom.py b/mapytex/calculus/polynom.py deleted file mode 100644 index 1aabd7b..0000000 --- a/mapytex/calculus/polynom.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -from .expression import Expression -from .operator import op -from .random_expression import RdExpression -from .abstract_polynom import AbstractPolynom - -from functools import wraps -import inspect - -__all__ = ["Polynom"] - - -def polynom_factory(func): - """ - Decorator which specify the type of polynom that the function returns - """ - @wraps(func) - def wrapper(*args, **kwrds): - P = func(*args, **kwrds) - if issubclass(type(P), AbstractPolynom) and P.degree == 2: - from .polynomDeg2 import Polynom_deg2 - new_P = Polynom_deg2(poly=P) - new_P.steps = P.steps - return new_P - elif issubclass(type(P), AbstractPolynom): - new_P = Polynom(poly=P) - new_P.steps = P.steps - return new_P - else: - return P - return wrapper - - -class Polynom(AbstractPolynom): - - """Polynom view as a function. - - It can be initiate like a AbstractPolynom - # Put example - Randomly - # Put example - It can be evaluate - # Put example - And derivate - # Put example - - """ - - @classmethod - def random( - self, - coefs_form=[], - conditions=[], - letter="x", - degree=0, - name="P"): - """ Create a random polynom from coefs_form and conditions - - :param coefs_form: list of forms (one by coef) (ascending degree sorted) - :param conditions: condition on variables - :param letter: the letter for the polynom - :param degree: degree of the polynom (can't be used with coefs_form, it will be overwrite) - can't be higher than 26 (number of letters in alphabet) - - /!\ variables need to be in brackets {} - - >>> Polynom.random(["{b}", "{a}"]) # doctest:+ELLIPSIS - < Polynom x ... - >>> Polynom.random(degree = 2) # doctest:+ELLIPSIS - < Polynom_deg2 x ...> - >>> Polynom.random(degree = 3) # doctest:+ELLIPSIS - < Polynom x ...> - >>> Polynom.random(degree = 2, conditions=["{b**2-4*a*c}>0"]) # Polynom deg 2 with positive Delta (ax^2 + bx + c) - < Polynom_deg2 x ...> - >>> Polynom.random(["{c}", "{b}", "{a}"], conditions=["{b**2-4*a*c}>0"]) # Same as above - < Polynom_deg2 x ...> - - """ - if (degree > 0 and degree < 26): - # Générer assez de lettre pour les coefs - coefs_name = map(chr, range(97, 98 + degree)) - coefs_form = ["{" + i + "}" for i in coefs_name][::-1] - - form = str(coefs_form) - # On créé les valeurs toutes concaténées dans un string - coefs = RdExpression(form, conditions)() - # On "parse" ce string pour créer les coefs - coefs = [eval(i) if isinstance(i, str) else i for i in eval(coefs)] - # Création du polynom - return Polynom(coefs=coefs, letter=letter, name=name) - - def __init__(self, coefs=[1], letter="x", name="P", poly=0): - """Initiate the polynom - - :param coef: coefficients of the polynom (ascending degree sorted) - 3 possibles type of coefficent: - - a : simple "number". [1,2] designate 1 + 2x - - [a,b,c]: list of coeficient for same degree. [1,[2,3],4] designate 1 + 2x + 3x + 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 name: Name of the polynom - - >>> P = Polynom([1, 2, 3]) - >>> P.mainOp - + - >>> P.name - 'P' - >>> P._letter - 'x' - >>> Polynom([1]).mainOp - * - >>> Polynom([0, 0, 3]).mainOp - * - >>> Polynom([1, 2, 3])._letter - 'x' - >>> Polynom([1, 2, 3], "y")._letter - 'y' - >>> Polynom([1, 2, 3], name = "Q").name - 'Q' - """ - if poly: - coefs = poly._coef - letter = poly._letter - name = poly.name - - super(Polynom, self).__init__(coefs, letter, name) - - def __call__(self, value): - """ Evaluate the polynom in value - - :returns: Expression ready to be simplify - - >>> P = Polynom([1, 2, 3]) - >>> P(2) - 17 - >>> for i in P(2).explain(): - ... print(i) - 3 \\times 2^{ 2 } + 2 \\times 2 + 1 - 3 \\times 4 + 4 + 1 - 12 + 4 + 1 - 16 + 1 - 17 - >>> Q = P("1+h") - >>> print(Q) - 3 h^{ 2 } + 8 h + 6 - >>> R = P(Q) - """ - eval_exp = self.replace_letter(value) - - return eval_exp.simplify() - - def derivate(self): - """ Return the derivated polynom - - >>> P = Polynom([1, 2, 3]) - >>> Q = P.derivate() - >>> Q - < Polynom x [2, 6]> - >>> print(Q.name) - P' - >>> for i in Q.explain(): - ... print(i) - 2 \\times 3 x + 1 \\times 2 - 6 x + 2 - """ - derv_coefs = [] - for (i, c) in enumerate(self._coef): - derv_coefs += [Expression([i, c, op.mul])] - - ans = Polynom(derv_coefs[1:]).simplify() - ans.name = self.name + "'" - return ans - -# Decorate methods which may return Polynoms -methods_list = ["__add__", "__call__", "__mul__", "__neg__", "__pow__", - "__radd__", "__rmul__", "__rsub__", "__sub__", "derivate", - "reduce", "simplify", "random"] -for name, func in inspect.getmembers(Polynom): - if name in methods_list: - setattr(Polynom, name, polynom_factory(func)) - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/polynomDeg2.py b/mapytex/calculus/polynomDeg2.py deleted file mode 100644 index 4cef1f2..0000000 --- a/mapytex/calculus/polynomDeg2.py +++ /dev/null @@ -1,248 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -from .polynom import Polynom -from .expression import Expression -from .fraction import Fraction -from .operator import op -from .random_expression import RdExpression - -from sympy import sqrt, latex -# from sympy.fractions import Fraction as sp.Fraction - -__all__ = ["Polynom_deg2"] - - -class Polynom_deg2(Polynom): - - """ Degree 2 polynoms - Child of Polynom with some extra tools - """ - - @classmethod - def random( - self, - coefs_form=[ - "{c}", - "{b}", - "{a}"], - conditions=[], - letter="x", - name="P"): - """ Create a 2nd degree poly from coefs_form ans conditions - - :param coefs_form: list of forms (one by coef) (ascending degree sorted) - :param conditions: condition on variables - :param letter: the letter for the polynom - - """ - if len(coefs_form) != 3: - raise ValueError( - "Polynom_deg2 have to be degree 2 polynoms, they need 3 coefficients, {} are given".format( - len(coefs_form))) - - form = str(coefs_form) - # On créé les valeurs toutes concaténées dans un string - coefs = RdExpression(form, conditions)() - # On "parse" ce string pour créer les coefs - coefs = [eval(i) if isinstance(i, str) else i for i in eval(coefs)] - # Création du polynom - return Polynom_deg2(coefs=coefs, letter=letter, name=name) - - def __init__(self, coefs=[0, 0, 1], letter="x", name="P", poly=0): - if poly: - coefs = poly._coef - letter = poly._letter - name = poly.name - - if len(coefs) < 3 or len(coefs) > 4: - raise ValueError( - "Polynom_deg2 have to be degree 2 polynoms, they need 3 coefficients, {} are given".format( - len(coefs))) - if coefs[2] == 0: - raise ValueError( - "Polynom_deg2 have to be degree 2 polynoms, coefficient of x^2 can't be 0") - Polynom.__init__(self, coefs, letter, name=name) - - @property - def a(self): - return self._coef[2] - - @property - def b(self): - return self._coef[1] - - @property - def c(self): - return self._coef[0] - - @property - def delta(self): - """Compute the discriminant expression - :returns: discriminant expression - - >>> P = Polynom_deg2([1,2,3]) - >>> P.delta - -8 - >>> for i in P.delta.explain(): - ... print(i) - 2^{ 2 } - 4 \\times 3 \\times 1 - 4 - 4 \\times 3 - 4 - 12 - -8 - """ - - return Expression([self.b, 2, op.pw, 4, self.a, - self.c, op.mul, op.mul, op.sub]).simplify() - - @property - def alpha(self): - """ Compute alpha the abcisse of the extremum - - >>> P = Polynom_deg2([1,2,3]) - >>> P.alpha - < Fraction -1 / 3> - >>> for i in P.alpha.explain(): - ... print(i) - \\frac{ - 2 }{ 2 \\times 3 } - \\frac{ -2 }{ 6 } - \\frac{ -1 \\times 2 }{ 3 \\times 2 } - \\frac{ -1 }{ 3 } - """ - return Expression([self.b, op.sub1, 2, self.a, - op.mul, op.div]).simplify() - - @property - def beta(self): - r""" Compute beta the extremum of self - - >>> P = Polynom_deg2([1,2,3]) - >>> P.beta - < Fraction 2 / 3> - >>> for i in P.beta.explain(): # Ça serait bien que l'on puisse enlever des étapes maintenant... - ... print(i) - 3 \times ( \frac{ -1 }{ 3 } )^{ 2 } + 2 \times \frac{ -1 }{ 3 } + 1 - 3 \times ( \frac{ -1 }{ 3 } )^{ 2 } + \frac{ -1 }{ 3 } \times 2 + 1 - 3 \times \frac{ ( -1 )^{ 2 } }{ 3^{ 2 } } + \frac{ -1 \times 2 }{ 3 } + 1 - 3 \times \frac{ 1 }{ 9 } + \frac{ -2 }{ 3 } + 1 - \frac{ 1 }{ 9 } \times 3 + \frac{ -2 }{ 3 } + 1 - \frac{ 1 \times 3 }{ 3 \times 3 } + \frac{ -2 }{ 3 } + 1 - \frac{ 1 }{ 3 } + \frac{ -2 }{ 3 } + 1 - \frac{ 1 - 2 }{ 3 } + 1 - \frac{ -1 }{ 3 } + 1 - \frac{ -1 \times 1 }{ 3 \times 1 } + \frac{ 1 \times 3 }{ 1 \times 3 } - \frac{ -1 }{ 3 } + \frac{ 3 }{ 3 } - \frac{ -1 + 3 }{ 3 } - \frac{ 2 }{ 3 } - """ - return self(self.alpha) - - def roots(self, after_coma=2): - """ Compute roots of the polynom - - /!\ Can't manage nice rendering because of sqrt. - It use sympy to compute roots - - # TODO: Pymath has to know how to compute with sqare root |mar. févr. 24 18:40:04 CET 2015 - - >>> P = Polynom_deg2([1, 1, 1]) - >>> P.roots() - [] - >>> P = Polynom_deg2([1, 2, 1]) - >>> P.roots() - [-1] - >>> P = Polynom_deg2([-1, 0, 1]) - >>> P.roots() - ['-1', '1'] - >>> P = Polynom_deg2([1, 4, 1]) - >>> P.roots() - ['-2 - \\\\sqrt{3}', '-2 + \\\\sqrt{3}'] - """ - if self.delta > 0: - self._roots = [latex((-self.b - sqrt(self.delta)) / (2 * self.a)), - latex((-self.b + sqrt(self.delta)) / (2 * self.a))] - elif self.delta == 0: - self._roots = [Fraction(-self.b, 2 * self.a).simplify()] - else: - self._roots = [] - return self._roots - - def tbl_sgn_header(self): - """ Return header of the sign line for tkzTabLine""" - if self.delta > 0: - return "{$-\\infty$, $" + str(min(self.roots())) + \ - "$ , $" + str(max(self.roots())) + "$ , $+\\infty$}" - elif self.delta == 0: - return "{$-\\infty$, $" + str(self.roots()[0]) + "$ , $+\\infty$}" - else: - return "{$-\\infty$, $+\\infty$}" - - def tbl_sgn(self): - """ Return the sign line for tkzTabLine - - >>> P = Polynom_deg2([2, 5, 2]) - >>> print(P.tbl_sgn()) - \\tkzTabLine{, +, z, -, z , +,} - >>> P = Polynom_deg2([2, 1, -2]) - >>> print(P.tbl_sgn()) - \\tkzTabLine{, -, z, +, z , -,} - >>> P = Polynom_deg2([1, 2, 1]) - >>> print(P.tbl_sgn()) - \\tkzTabLine{, +, z, +,} - >>> P = Polynom_deg2([0, 0, -2]) - >>> print(P.tbl_sgn()) - \\tkzTabLine{, -, z, -,} - >>> P = Polynom_deg2([1, 0, 1]) - >>> print(P.tbl_sgn()) - \\tkzTabLine{, +,} - >>> P = Polynom_deg2([-1, 0, -1]) - >>> print(P.tbl_sgn()) - \\tkzTabLine{, -,} - """ - if self.delta > 0: - if self.a > 0: - return "\\tkzTabLine{, +, z, -, z , +,}" - else: - return "\\tkzTabLine{, -, z, +, z , -,}" - elif self.delta == 0: - if self.a > 0: - return "\\tkzTabLine{, +, z, +,}" - else: - return "\\tkzTabLine{, -, z, -,}" - else: - if self.a > 0: - return "\\tkzTabLine{, +,}" - else: - return "\\tkzTabLine{, -,}" - - def tbl_variation(self, limits=False): - """Return the variation line for tkzTabVar - - :param limit: Display or not limits in tabular - - >>> P = Polynom_deg2([1,2,3]) - >>> print(P.tbl_variation()) - \\tkzTabVar{+/{}, -/{$\\frac{ 2 }{ 3 }$}, +/{}} - >>> print(P.tbl_variation(limits = True)) - \\tkzTabVar{+/{$+\\infty$}, -/{$\\frac{ 2 }{ 3 }$}, +/{$+\\infty$}} - - """ - beta = self.beta - if limits: - if self.a > 0: - return "\\tkzTabVar{+/{$+\\infty$}, -/{$" + \ - str(beta) + "$}, +/{$+\\infty$}}" - else: - return "\\tkzTabVar{-/{$-\\infty$}, +/{$" + \ - str(beta) + "$}, -/{$-\\infty$}}" - else: - if self.a > 0: - return "\\tkzTabVar{+/{}, -/{$" + str(beta) + "$}, +/{}}" - else: - return "\\tkzTabVar{-/{}, +/{$" + str(beta) + "$}, -/{}}" - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/random_expression.py b/mapytex/calculus/random_expression.py deleted file mode 100644 index 2a84c46..0000000 --- a/mapytex/calculus/random_expression.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -from random import randint -import re -import pyparsing -from .generic import flatten_list - -# Below import are needed for conditions in varia generation. -from .arithmetic import gcd - - -def random_str(form, conditions=[], val_min=-10, val_max=10): - """ Create a random string using RdExpression class """ - random_str_generator = RdExpression(form, conditions) - return random_str_generator(val_min, val_max) - - -class RdExpression(object): - """ - - A generator of random expression builder - - """ - - def __init__(self, form, conditions=[]): - """Initiate the generator - - :param form: the form of the expression (/!\ variables need to be in brackets {}) - :param conditions: condition on variables (/!\ variables need to be in brackets {}) - - """ - self._form = self.mod_underscores(form) - self._conditions = conditions - - self._letters = self.get_letters() - self._gene_varia = {} - self._gene_2replaced = {} - - def get_2replaced(self): - """Get elements of self._form which will have to be replaced - :returns: set for elements which have to be replaced - - """ - # TODO: Bug with varia with spaces |dim. nov. 23 10:44:34 CET 2014 - varia_form = flatten_list([eval(str(i[0])) for i in pyparsing.nestedExpr( - '{', '}').searchString(self._form)]) - varia_form = set(varia_form) - - varia_cond = set() - for c in self._conditions: - c_varia_cond = flatten_list( - [eval(str(i[0])) for i in pyparsing.nestedExpr('{', '}').searchString(c)]) - varia_cond = varia_cond | set(c_varia_cond) - - self._2replaced = varia_cond | varia_form - - return self._2replaced - - def get_letters(self): - """Find letters in the form - :returns: list of letters - - """ - v2replaced = self.get_2replaced() - varia = set() - - pattern = "([a-zA-Z]+)" - for v in v2replaced: - lvar = set(re.findall(pattern, v)) - varia = varia | lvar - - return varia - - def mod_underscores(self, form): - """ Transform underscores of string to {...} forme with capital letters - - :param form: the form string with _ to replace - :returns: the string with _ replaced - - """ - i = 64 - new_form = form - while "_" in new_form: - i += 1 - new_form = new_form.replace("_", "{" + chr(i) + "}", 1) - - return new_form - - def __call__(self, val_min=-10, val_max=10): - """RdExpression once it is initiate act like a function which create random expressions. - - :param val_min: minimum value random generation - :param val_max: maximum value random generation - :returns: an formated random expression - - """ - return self.raw_str(val_min, val_max) - - def raw_str(self, val_min=-10, val_max=10): - """Return raw string (don't use Expression for rendering or parsing) - - :param val_min: minimum value random generation - :param val_max: maximum value random generation - :returns: an random Expression object - - """ - self.gene_varia(val_min, val_max) - - while not(self.val_conditions()): - self.gene_varia(val_min, val_max) - - exp = self._form.format(**self._gene_2replaced) - - return exp - - def gene_varia(self, val_min=-10, val_max=10): - """Randomly generates variables/letters - - Varia can't be equal to 0 - - """ - for l in self._letters: - self._gene_varia[l] = randint(val_min, val_max) - while self._gene_varia[l] == 0: - self._gene_varia[l] = randint(val_min, val_max) - - for e in self._2replaced: - self._gene_2replaced[e] = eval(e, globals(), self._gene_varia) - - def val_conditions(self): - """Tells whether or not conditions are validates - :returns: boolean - - """ - if self._conditions != []: - return eval( - " and ".join( - self._conditions).format( - **self._gene_2replaced)) - else: - return True - - -def desc_rdExp(rdExp): - print("--------------------") - print("form: ", rdExp._form) - print("Conditions: ", rdExp._conditions) - print("Letters: ", rdExp._letters) - print("2replaced: ", rdExp._2replaced) - print("Call : ", rdExp()) - print("type: ", type(rdExp())) - print("Gene varia: ", rdExp._gene_varia) - print("Gene 2replaced: ", rdExp._gene_2replaced) - print('') - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/render.py b/mapytex/calculus/render.py deleted file mode 100644 index 942fd03..0000000 --- a/mapytex/calculus/render.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -from .generic import Stack, isOperator - -__all__ = ['txt', 'tex', 'p2i'] - - -class Render(object): - """ Create functions which know how to render postfix tokens lists """ - - def __init__(self, render): - """Initiate the render - - :param render: function which take an operator and return a function to render the operator with his operands - """ - self.render = render - - def __call__(self, postfix_tokens): - """Make the object acting like a function - - :param postfix_tokens: the list of postfix tokens to be render - :returns: the render string - - """ - operandeStack = Stack() - for token in postfix_tokens: - - if isOperator(token): - if token.arity == 1: - - op1 = operandeStack.pop() - - operandeStack.push(self.render(token)(op1)) - elif token.arity == 2: - op1 = operandeStack.pop() - op2 = operandeStack.pop() - # Switch op1 and op2 to respect order - operandeStack.push(self.render(token)(op2, op1)) - else: - operandeStack.push(self.render(token)()) - - if len(operandeStack) > 1: - raise ValueError("This postfix_tokens is not a valid expression") - else: - return operandeStack.pop() - - -def txt_render(token): - def render(*args): - try: - return getattr(token, '__txt__')(*args) - except AttributeError: - return str(token) - return render - -txt = Render(txt_render) - - -def tex_render(token): - def render(*args): - try: - return getattr(token, '__tex__')(*args) - except AttributeError: - return str(token) - return render -tex = Render(tex_render) - - -def p2i_render(token): - def render(*args): - try: - return getattr(token, '__p2i__')(*args) - except AttributeError: - return token - return render -p2i = Render(p2i_render) - -if __name__ == '__main__': - from .operator import op - from itertools import permutations - from mapytex import Polynom - from mapytex import Expression - from mapytex import Fraction - coefs_p = [[(i - 2), (j - 2)] for i, j in permutations(range(5), 2)] - coefs_q = [[2 * (i - 2), 2 * (j - 2)] - for i, j in permutations(range(5), 2)] - l_p = [Polynom(i) for i in coefs_p] - l_q = [Fraction(i, j) for i, j in coefs_q if j != 0] - operations = [Expression([l_p[i], l_q[j], op.mul]) - for i, j in permutations(range(len(l_q)), 2)] - for i in operations: - print(i) - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/renderable.py b/mapytex/calculus/renderable.py deleted file mode 100644 index 4583aa6..0000000 --- a/mapytex/calculus/renderable.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -from .render import tex, txt - -__all__ = ['Renderable'] - -class Renderable(object): - """ - A Renderable object is an object which can work with Render class. It means that it has to have attribute postfix_tokens. - """ - STR_RENDER = tex - DEFAULT_RENDER = tex - - @classmethod - def set_render(cls, render): - cls.STR_RENDER = render - - @classmethod - def get_render(cls): - return cls.STR_RENDER - - @classmethod - def set_default_render(cls): - cls.set_render(cls.DEFAULT_RENDER) - - @classmethod - def tmp_render(cls, render=tex): - """ Create a container in which Expression render is temporary modify - - The default temporary render is Expression in order to perform calculus inside numbers - - >>> from .expression import Expression - >>> from .explicable import Explicable - >>> exp = Expression("2*3/5") - >>> print(exp) - 2 \\times \\frac{ 3 }{ 5 } - >>> for i in exp.simplify().explain(): - ... print(i) - 2 \\times \\frac{ 3 }{ 5 } - \\frac{ 3 }{ 5 } \\times 2 - \\frac{ 3 \\times 2 }{ 5 } - \\frac{ 6 }{ 5 } - >>> with Explicable.tmp_render(txt): - ... for i in exp.simplify().explain(): - ... print(i) - 2 * 3 / 5 - 3 / 5 * 2 - ( 3 * 2 ) / 5 - 6 / 5 - >>> for i in exp.simplify().explain(): - ... print(i) - 2 \\times \\frac{ 3 }{ 5 } - \\frac{ 3 }{ 5 } \\times 2 - \\frac{ 3 \\times 2 }{ 5 } - \\frac{ 6 }{ 5 } - - # TODO: essayer de ne pas afficher ce changement de position. |lun. avril 6 17:29:56 CEST 2015 - - """ - class TmpRenderEnv(object): - - def __enter__(self): - self.old_render = Renderable.get_render() - Renderable.set_render(render) - - def __exit__(self, type, value, traceback): - Renderable.set_render(self.old_render) - return TmpRenderEnv() - - def __init__(self, pstf_tokens): - """Initiate the renderable objet - - :param pstf_tokens: the postfix list of tokens - - """ - self.postfix_tokens = pstf_tokens - - def __str__(self): - """ - Overload str - - If you want to changer render use Expression.set_render(...) or use tmp_render context manager. - """ - return self.STR_RENDER(self.postfix_tokens) - - def __repr__(self): - return "< {cls} {pstf_tokens}>".format( - cls = str(self.__class__).split('.')[-1][:-2], - pstf_tokens = str(self.postfix_tokens) - ) - - def __eq__(self, other): - """ Two Renderable objects are the same if they have same postfix_tokens """ - try: - return self.postfix_tokens == other.postfix_tokens - except AttributeError: - return False - - def __txt__(self): - try: - return txt(self.postfix_tokens) - except AttributeError: - return self - - def __tex__(self): - try: - return tex(self.postfix_tokens) - except AttributeError: - return self - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/step.py b/mapytex/calculus/step.py deleted file mode 100644 index a431e82..0000000 --- a/mapytex/calculus/step.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -from .renderable import Renderable - -__all__ = ['Step'] - -class Step(Renderable): - """ - A step is a Renderable which his only goal is to be render. - """ - - @classmethod - def tmp_render(cls): - """ Create a container in which the method explain return only Step object. - - >>> from .expression import Expression - >>> exp = Expression("2*3/5") - >>> print(exp) - 2 \\times \\frac{ 3 }{ 5 } - >>> for i in exp.simplify().explain(): - ... print(i) - 2 \\times \\frac{ 3 }{ 5 } - \\frac{ 3 }{ 5 } \\times 2 - \\frac{ 3 \\times 2 }{ 5 } - \\frac{ 6 }{ 5 } - >>> with Step.tmp_render(): - ... for i in exp.simplify().explain(): - ... print(repr(i)) - < Step [2, 3, 5, /, *]> - < Step [3, 5, /, 2, *]> - < Step [3, 2, *, 5, /]> - < Step [6, 5, /]> - >>> for i in exp.simplify().explain(): - ... print(i) - 2 \\times \\frac{ 3 }{ 5 } - \\frac{ 3 }{ 5 } \\times 2 - \\frac{ 3 \\times 2 }{ 5 } - \\frac{ 6 }{ 5 } - - """ - return super(Step, cls).tmp_render(Step) - - def __init__(self, exp): - """Initiate the renderable objet - - :param pstf_tokens: the postfix list of tokens - - >>> s = Step([2, 3, '+']) - >>> s - < Step [2, 3, '+']> - >>> s1 = Step([s, 5, '*']) - >>> s1 - < Step [2, 3, '+', 5, '*']> - - """ - if isinstance(exp, Renderable): - self.postfix_tokens = exp.postfix_tokens - elif isinstance(exp, list): - self.postfix_tokens = [] - for t in exp: - try: - self.postfix_tokens += t.postfix_tokens - except AttributeError: - self.postfix_tokens.append(t) - else: - raise ValueError( - "Can't initiate Step with {}".format( - exp - )) - - def __eq__(self, other): - try: - if self.postfix_tokens == other.postfix_tokens: - return True - except AttributeError: - pass - - try: - if str(self).replace(' ', '') == str(other).replace(' ',''): - return True - except TypeError: - pass - - return False - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/str2tokens.py b/mapytex/calculus/str2tokens.py deleted file mode 100644 index 3d58a1c..0000000 --- a/mapytex/calculus/str2tokens.py +++ /dev/null @@ -1,277 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -from .generic import Stack, isNumber, isPolynom -from .operator import op -from decimal import Decimal - -import logging -# logging.basicConfig(filename='str2tokens_debug.log',level=logging.DEBUG) - - -def str2tokens(exp): - """ Parse the string into tokens then turn it into postfix form - - >>> str2tokens('2+3*4') - [2, 3, 4, *, +] - >>> str2tokens('2*3+4') - [2, 3, *, 4, +] - >>> str2tokens('2x+4') - [2, < Polynom x [0, 1]>, *, 4, +] - """ - in_tokens = str2in_tokens(exp) - post_tokens = in2post_fix(in_tokens) - - return post_tokens - - -def str2in_tokens(exp): - """ Parse the expression, ie tranform a string into a list of tokens - - :param exp: The expression (a string) - :returns: list of token - - >>> str2in_tokens('2+3*4') - [2, '+', 3, '*', 4] - >>> str2in_tokens('2*3+4') - [2, '*', 3, '+', 4] - >>> str2in_tokens('12*3+4') - [12, '*', 3, '+', 4] - >>> str2in_tokens('2.3*3+4') - [Decimal('2.3'), '*', 3, '+', 4] - >>> str2in_tokens('a*3+4') - [< Polynom a [0, 1]>, '*', 3, '+', 4] - """ - tokens = ['', ''] - - for character in exp: - if character.isdigit(): - tokens += feed_digit(character, tokens.pop(), tokens[-1]) - - elif character == "(": - tokens += hidden_meaning_time(tokens[-1]) - tokens.append("(") - - elif character in op.available_op(): - tokens.append(character) - - elif character == ")": - tokens.append(character) - - elif character.isalpha(): - tokens += hidden_meaning_time(tokens[-1]) - tokens.append(feed_alpha(character)) - - elif character == ".": - tokens.append(feed_dot(tokens.pop())) - - elif character != " ": - raise ValueError("{} is an unvalid character".format(character)) - - return tokens[2:] - - -def feed_digit(character, tok_b, tok_bb): - """ Feed token when a digit is detected - - :param character: the character - :param tok_b: the token before - :param tok_bb: the token before before - :returns: list of token to replace - - >>> feed_digit(1, '-', 2) - ['-', 1] - >>> feed_digit(1, '', '') - ['', 1] - >>> feed_digit(1, 2, '') - [21] - >>> feed_digit(1, Decimal(2), '') - [Decimal('2.1')] - >>> feed_digit(1, Decimal('2.3'), '') - [Decimal('2.31')] - >>> feed_digit(1, -2, '') - [-21] - >>> feed_digit(1, Decimal('-2'), '') - [Decimal('-2.1')] - >>> feed_digit(1, '-', '') - [-1] - >>> feed_digit(1, '-', '+') - [-1] - >>> feed_digit(1, '-', '(') - [-1] - >>> feed_digit(1, '-', 2) - ['-', 1] - >>> from mapytex.calculus.polynom import Polynom - >>> feed_digit(1, '-', Polynom([0,1])) - ['-', 1] - - """ - if isinstance(tok_b, int): - return [tok_b * 10 + int(tok_b/abs(tok_b)) * int(character)] - - elif isinstance(tok_b, Decimal): - return [tok_b + int(tok_b/abs(tok_b)) * int(character) * Decimal('10') ** (tok_b.as_tuple().exponent - 1)] - - # TODO: WTF!!! |sam. févr. 27 17:11:53 EAT 2016 - elif tok_b == "-" and (str(tok_bb) in op.available_op() or str(tok_bb) == ""): - return [- int(character)] - else: - return [tok_b, int(character)] - - -def hidden_meaning_time(tok_b): - """ Return a "*" character if it is hidden meaning - - :param tok_b: the token before - - >>> hidden_meaning_time(4) - ['*'] - >>> hidden_meaning_time(')') - ['*'] - >>> from mapytex.calculus.polynom import Polynom - >>> hidden_meaning_time(Polynom([0,1])) - ['*'] - >>> hidden_meaning_time("+") - [] - >>> hidden_meaning_time("*") - [] - - """ - if isNumber(tok_b) \ - or tok_b == ")" \ - or isPolynom(tok_b): - return ["*"] - return [] - - -def feed_alpha(character): - """ Feed token when an alpha character is detected - - :param character: the alpha character - :param tok_b: the token before - :returns: tokens to add - - """ - from mapytex.calculus.polynom import Polynom - return Polynom([0, 1], letter=character) - - -def feed_dot(tok_b): - r""" Build Decimal with the previous token - - :param tok_b: the previous token - :returns: the Decimal - - >>> feed_dot(2) - Decimal('2') - >>> feed_dot(Decimal('2.3')) - Traceback (most recent call last): - ... - ValueError: A number has 2 points...! We have 2.3 before the dot - >>> feed_dot('+') - Traceback (most recent call last): - ... - ValueError: Try to make decimal but + before the dot - - """ - if isinstance(tok_b, int): - return Decimal(tok_b) - elif isinstance(tok_b, Decimal): - raise ValueError("A number has 2 points...! We have {} before the dot".format(tok_b)) - else: - raise ValueError("Try to make decimal but {} before the dot".format(tok_b)) - - -def in2post_fix(infix_tokens): - """ From the infix_tokens list compute the corresponding postfix_tokens list - - @param infix_tokens: the infix list of tokens to transform into postfix form. - @return: the corresponding postfix list of tokens. - - >>> in2post_fix(['(', 2, '+', 5, '-', 1, ')', '/', '(', 3, '*', 4, ')']) - [2, 5, 1, -, +, 3, 4, *, /] - >>> in2post_fix(['-', '(', '-', 2, ')']) - [2, -, -] - >>> in2post_fix(['-', '(', '-', 2, '+', 3, '*', 4, ')']) - [2, -, 3, 4, *, +, -] - """ - logging.debug("New start with {}".format(infix_tokens)) - # Stack where operator will be stocked - opStack = Stack() - # final postfix list of tokens - postfix_tokens = [] - # stack with the nbr of tokens still to compute in postfix_tokens - arity_Stack = Stack() - arity_Stack.push(0) - - for (pos_token, token) in enumerate(infix_tokens): - - logging.debug(str(postfix_tokens) + - " | " + str(opStack) + - " | " + str(infix_tokens[(pos_token+1):]) + - " | " + str(arity_Stack) - ) - if token == ")": - next_op = opStack.pop() - while next_op != op.par: - postfix_tokens.append(next_op) - next_op = opStack.pop() - - # Go back to old arity - arity_Stack.pop() - # Raise the arity - arity = arity_Stack.pop() - arity_Stack.push(arity + 1) - - elif op.can_be_operator(token): - if token == "(": - opStack.push(op.get_op(token, 0)) - # Set next arity counter - arity_Stack.push(0) - else: - arity = arity_Stack.pop() - token_op = op.get_op(token, arity + 1) - # Reset arity to 0 in case there is other operators (the real - # operation would be "-op.arity + 1") - arity_Stack.push(0) - while (not opStack.isEmpty()) and opStack.peek( - ).priority >= token_op.priority: - next_op = opStack.pop() - postfix_tokens.append(next_op) - - opStack.push(token_op) - logging.debug("--" + token + " -> " + str(arity + 1)) - else: - postfix_tokens.append(token) - arity = arity_Stack.pop() - arity_Stack.push(arity + 1) - - logging.debug(str(postfix_tokens) + - " | " + str(opStack) + - " | " + str(infix_tokens[(pos_token+1):]) + - " | " + str(arity_Stack) - ) - - while not opStack.isEmpty(): - next_op = opStack.pop() - postfix_tokens.append(next_op) - - logging.debug(str(postfix_tokens) + - " | " + str(opStack) + - " | " + str(infix_tokens[(pos_token+1):]) + - " | " + str(arity_Stack) - ) - - if arity_Stack.peek() != 1: - raise ValueError( - "Unvalid expression. The arity Stack is ", - str(arity_Stack)) - - logging.debug("Fini!") - return postfix_tokens - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/test/__init__.py b/mapytex/calculus/test/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/mapytex/calculus/test/mass_test.py b/mapytex/calculus/test/mass_test.py deleted file mode 100644 index edc10aa..0000000 --- a/mapytex/calculus/test/mass_test.py +++ /dev/null @@ -1,1524 +0,0 @@ -POLY_ADD_VALID_RESULTS = [ - '- x - 2 - 4', - '- x - 2 + 2 x - 4', - '- x - 2 + 4 x - 4', - '- x - 2 - 4 x - 2', - '- x - 2 - 2', - '- x - 2 + 2 x - 2', - '- x - 2 + 4 x - 2', - '- x - 2 - 4 x', - '- x - 2 - 2 x', - '- x - 2 + 2 x', - '- x - 2 + 4 x', - '- x - 2 - 4 x + 2', - '- x - 2 - 2 x + 2', - '- x - 2 + 2', - '- x - 2 + 4 x + 2', - '- x - 2 - 4 x + 4', - '- x - 2 - 2 x + 4', - '- x - 2 + 4', - '- x - 2 + 2 x + 4', - '-2 - 2 x - 4', - '-2 + 2 x - 4', - '-2 + 4 x - 4', - '-2 - 4 x - 2', - '-2 - 2', - '-2 + 2 x - 2', - '-2 + 4 x - 2', - '-2 - 4 x', - '-2 - 2 x', - '-2 + 2 x', - '-2 + 4 x', - '-2 - 4 x + 2', - '-2 - 2 x + 2', - '-2 + 2', - '-2 + 4 x + 2', - '-2 - 4 x + 4', - '-2 - 2 x + 4', - '-2 + 4', - '-2 + 2 x + 4', - 'x - 2 - 2 x - 4', - 'x - 2 - 4', - 'x - 2 + 4 x - 4', - 'x - 2 - 4 x - 2', - 'x - 2 - 2', - 'x - 2 + 2 x - 2', - 'x - 2 + 4 x - 2', - 'x - 2 - 4 x', - 'x - 2 - 2 x', - 'x - 2 + 2 x', - 'x - 2 + 4 x', - 'x - 2 - 4 x + 2', - 'x - 2 - 2 x + 2', - 'x - 2 + 2', - 'x - 2 + 4 x + 2', - 'x - 2 - 4 x + 4', - 'x - 2 - 2 x + 4', - 'x - 2 + 4', - 'x - 2 + 2 x + 4', - '2 x - 2 - 2 x - 4', - '2 x - 2 - 4', - '2 x - 2 + 2 x - 4', - '2 x - 2 - 4 x - 2', - '2 x - 2 - 2', - '2 x - 2 + 2 x - 2', - '2 x - 2 + 4 x - 2', - '2 x - 2 - 4 x', - '2 x - 2 - 2 x', - '2 x - 2 + 2 x', - '2 x - 2 + 4 x', - '2 x - 2 - 4 x + 2', - '2 x - 2 - 2 x + 2', - '2 x - 2 + 2', - '2 x - 2 + 4 x + 2', - '2 x - 2 - 4 x + 4', - '2 x - 2 - 2 x + 4', - '2 x - 2 + 4', - '2 x - 2 + 2 x + 4', - '-2 x - 1 - 2 x - 4', - '-2 x - 1 - 4', - '-2 x - 1 + 2 x - 4', - '-2 x - 1 + 4 x - 4', - '-2 x - 1 - 2', - '-2 x - 1 + 2 x - 2', - '-2 x - 1 + 4 x - 2', - '-2 x - 1 - 4 x', - '-2 x - 1 - 2 x', - '-2 x - 1 + 2 x', - '-2 x - 1 + 4 x', - '-2 x - 1 - 4 x + 2', - '-2 x - 1 - 2 x + 2', - '-2 x - 1 + 2', - '-2 x - 1 + 4 x + 2', - '-2 x - 1 - 4 x + 4', - '-2 x - 1 - 2 x + 4', - '-2 x - 1 + 4', - '-2 x - 1 + 2 x + 4', - '-1 - 2 x - 4', - '-1 - 4', - '-1 + 2 x - 4', - '-1 + 4 x - 4', - '-1 - 4 x - 2', - '-1 + 2 x - 2', - '-1 + 4 x - 2', - '-1 - 4 x', - '-1 - 2 x', - '-1 + 2 x', - '-1 + 4 x', - '-1 - 4 x + 2', - '-1 - 2 x + 2', - '-1 + 2', - '-1 + 4 x + 2', - '-1 - 4 x + 4', - '-1 - 2 x + 4', - '-1 + 4', - '-1 + 2 x + 4', - 'x - 1 - 2 x - 4', - 'x - 1 - 4', - 'x - 1 + 2 x - 4', - 'x - 1 + 4 x - 4', - 'x - 1 - 4 x - 2', - 'x - 1 - 2', - 'x - 1 + 4 x - 2', - 'x - 1 - 4 x', - 'x - 1 - 2 x', - 'x - 1 + 2 x', - 'x - 1 + 4 x', - 'x - 1 - 4 x + 2', - 'x - 1 - 2 x + 2', - 'x - 1 + 2', - 'x - 1 + 4 x + 2', - 'x - 1 - 4 x + 4', - 'x - 1 - 2 x + 4', - 'x - 1 + 4', - 'x - 1 + 2 x + 4', - '2 x - 1 - 2 x - 4', - '2 x - 1 - 4', - '2 x - 1 + 2 x - 4', - '2 x - 1 + 4 x - 4', - '2 x - 1 - 4 x - 2', - '2 x - 1 - 2', - '2 x - 1 + 2 x - 2', - '2 x - 1 - 4 x', - '2 x - 1 - 2 x', - '2 x - 1 + 2 x', - '2 x - 1 + 4 x', - '2 x - 1 - 4 x + 2', - '2 x - 1 - 2 x + 2', - '2 x - 1 + 2', - '2 x - 1 + 4 x + 2', - '2 x - 1 - 4 x + 4', - '2 x - 1 - 2 x + 4', - '2 x - 1 + 4', - '2 x - 1 + 2 x + 4', - '-2 x - 2 x - 4', - '-2 x - 4', - '-2 x + 2 x - 4', - '-2 x + 4 x - 4', - '-2 x - 4 x - 2', - '-2 x - 2', - '-2 x + 2 x - 2', - '-2 x + 4 x - 2', - '-2 x - 2 x', - '-2 x + 2 x', - '-2 x + 4 x', - '-2 x - 4 x + 2', - '-2 x - 2 x + 2', - '-2 x + 2', - '-2 x + 4 x + 2', - '-2 x - 4 x + 4', - '-2 x - 2 x + 4', - '-2 x + 4', - '-2 x + 2 x + 4', - '- x - 2 x - 4', - '- x - 4', - '- x + 2 x - 4', - '- x + 4 x - 4', - '- x - 4 x - 2', - '- x - 2', - '- x + 2 x - 2', - '- x + 4 x - 2', - '- x - 4 x', - '- x + 2 x', - '- x + 4 x', - '- x - 4 x + 2', - '- x - 2 x + 2', - '- x + 2', - '- x + 4 x + 2', - '- x - 4 x + 4', - '- x - 2 x + 4', - '- x + 4', - '- x + 2 x + 4', - 'x - 2 x - 4', - 'x - 4', - 'x + 2 x - 4', - 'x + 4 x - 4', - 'x - 4 x - 2', - 'x - 2', - 'x + 2 x - 2', - 'x + 4 x - 2', - 'x - 4 x', - 'x - 2 x', - 'x + 4 x', - 'x - 4 x + 2', - 'x - 2 x + 2', - 'x + 2', - 'x + 4 x + 2', - 'x - 4 x + 4', - 'x - 2 x + 4', - 'x + 4', - 'x + 2 x + 4', - '2 x - 2 x - 4', - '2 x - 4', - '2 x + 2 x - 4', - '2 x + 4 x - 4', - '2 x - 4 x - 2', - '2 x - 2', - '2 x + 2 x - 2', - '2 x + 4 x - 2', - '2 x - 4 x', - '2 x - 2 x', - '2 x + 2 x', - '2 x - 4 x + 2', - '2 x - 2 x + 2', - '2 x + 2', - '2 x + 4 x + 2', - '2 x - 4 x + 4', - '2 x - 2 x + 4', - '2 x + 4', - '2 x + 2 x + 4', - '-2 x + 1 - 2 x - 4', - '-2 x + 1 - 4', - '-2 x + 1 + 2 x - 4', - '-2 x + 1 + 4 x - 4', - '-2 x + 1 - 4 x - 2', - '-2 x + 1 - 2', - '-2 x + 1 + 2 x - 2', - '-2 x + 1 + 4 x - 2', - '-2 x + 1 - 4 x', - '-2 x + 1 - 2 x', - '-2 x + 1 + 2 x', - '-2 x + 1 + 4 x', - '-2 x + 1 - 2 x + 2', - '-2 x + 1 + 2', - '-2 x + 1 + 4 x + 2', - '-2 x + 1 - 4 x + 4', - '-2 x + 1 - 2 x + 4', - '-2 x + 1 + 4', - '-2 x + 1 + 2 x + 4', - '- x + 1 - 2 x - 4', - '- x + 1 - 4', - '- x + 1 + 2 x - 4', - '- x + 1 + 4 x - 4', - '- x + 1 - 4 x - 2', - '- x + 1 - 2', - '- x + 1 + 2 x - 2', - '- x + 1 + 4 x - 2', - '- x + 1 - 4 x', - '- x + 1 - 2 x', - '- x + 1 + 2 x', - '- x + 1 + 4 x', - '- x + 1 - 4 x + 2', - '- x + 1 + 2', - '- x + 1 + 4 x + 2', - '- x + 1 - 4 x + 4', - '- x + 1 - 2 x + 4', - '- x + 1 + 4', - '- x + 1 + 2 x + 4', - '1 - 2 x - 4', - '1 - 4', - '1 + 2 x - 4', - '1 + 4 x - 4', - '1 - 4 x - 2', - '1 - 2', - '1 + 2 x - 2', - '1 + 4 x - 2', - '1 - 4 x', - '1 - 2 x', - '1 + 2 x', - '1 + 4 x', - '1 - 4 x + 2', - '1 - 2 x + 2', - '1 + 4 x + 2', - '1 - 4 x + 4', - '1 - 2 x + 4', - '1 + 4', - '1 + 2 x + 4', - '2 x + 1 - 2 x - 4', - '2 x + 1 - 4', - '2 x + 1 + 2 x - 4', - '2 x + 1 + 4 x - 4', - '2 x + 1 - 4 x - 2', - '2 x + 1 - 2', - '2 x + 1 + 2 x - 2', - '2 x + 1 + 4 x - 2', - '2 x + 1 - 4 x', - '2 x + 1 - 2 x', - '2 x + 1 + 2 x', - '2 x + 1 + 4 x', - '2 x + 1 - 4 x + 2', - '2 x + 1 - 2 x + 2', - '2 x + 1 + 2', - '2 x + 1 - 4 x + 4', - '2 x + 1 - 2 x + 4', - '2 x + 1 + 4', - '2 x + 1 + 2 x + 4', - '-2 x + 2 - 2 x - 4', - '-2 x + 2 - 4', - '-2 x + 2 + 2 x - 4', - '-2 x + 2 + 4 x - 4', - '-2 x + 2 - 4 x - 2', - '-2 x + 2 - 2', - '-2 x + 2 + 2 x - 2', - '-2 x + 2 + 4 x - 2', - '-2 x + 2 - 4 x', - '-2 x + 2 - 2 x', - '-2 x + 2 + 2 x', - '-2 x + 2 + 4 x', - '-2 x + 2 - 4 x + 2', - '-2 x + 2 - 2 x + 2', - '-2 x + 2 + 2', - '-2 x + 2 + 4 x + 2', - '-2 x + 2 - 2 x + 4', - '-2 x + 2 + 4', - '-2 x + 2 + 2 x + 4', - '- x + 2 - 2 x - 4', - '- x + 2 - 4', - '- x + 2 + 2 x - 4', - '- x + 2 + 4 x - 4', - '- x + 2 - 4 x - 2', - '- x + 2 - 2', - '- x + 2 + 2 x - 2', - '- x + 2 + 4 x - 2', - '- x + 2 - 4 x', - '- x + 2 - 2 x', - '- x + 2 + 2 x', - '- x + 2 + 4 x', - '- x + 2 - 4 x + 2', - '- x + 2 - 2 x + 2', - '- x + 2 + 2', - '- x + 2 + 4 x + 2', - '- x + 2 - 4 x + 4', - '- x + 2 + 4', - '- x + 2 + 2 x + 4', - '2 - 2 x - 4', - '2 - 4', - '2 + 2 x - 4', - '2 + 4 x - 4', - '2 - 4 x - 2', - '2 - 2', - '2 + 2 x - 2', - '2 + 4 x - 2', - '2 - 4 x', - '2 - 2 x', - '2 + 2 x', - '2 + 4 x', - '2 - 4 x + 2', - '2 - 2 x + 2', - '2 + 2', - '2 + 4 x + 2', - '2 - 4 x + 4', - '2 - 2 x + 4', - '2 + 2 x + 4', - 'x + 2 - 2 x - 4', - 'x + 2 - 4', - 'x + 2 + 2 x - 4', - 'x + 2 + 4 x - 4', - 'x + 2 - 4 x - 2', - 'x + 2 - 2', - 'x + 2 + 2 x - 2', - 'x + 2 + 4 x - 2', - 'x + 2 - 4 x', - 'x + 2 - 2 x', - 'x + 2 + 2 x', - 'x + 2 + 4 x', - 'x + 2 - 4 x + 2', - 'x + 2 - 2 x + 2', - 'x + 2 + 2', - 'x + 2 + 4 x + 2', - 'x + 2 - 4 x + 4', - 'x + 2 - 2 x + 4', - 'x + 2 + 4'] -POLY_SUB_VALID_RESULTS = [ - '- x - 2 - ( -4 )', - '- x - 2 - ( 2 x - 4 )', - '- x - 2 - ( 4 x - 4 )', - '- x - 2 - ( -4 x - 2 )', - '- x - 2 - ( -2 )', - '- x - 2 - ( 2 x - 2 )', - '- x - 2 - ( 4 x - 2 )', - '- x - 2 - ( -4 x )', - '- x - 2 - ( -2 x )', - '- x - 2 - 2 x', - '- x - 2 - 4 x', - '- x - 2 - ( -4 x + 2 )', - '- x - 2 - ( -2 x + 2 )', - '- x - 2 - 2', - '- x - 2 - ( 4 x + 2 )', - '- x - 2 - ( -4 x + 4 )', - '- x - 2 - ( -2 x + 4 )', - '- x - 2 - 4', - '- x - 2 - ( 2 x + 4 )', - '-2 - ( -2 x - 4 )', - '-2 - ( 2 x - 4 )', - '-2 - ( 4 x - 4 )', - '-2 - ( -4 x - 2 )', - '-2 - ( -2 )', - '-2 - ( 2 x - 2 )', - '-2 - ( 4 x - 2 )', - '-2 - ( -4 x )', - '-2 - ( -2 x )', - '-2 - 2 x', - '-2 - 4 x', - '-2 - ( -4 x + 2 )', - '-2 - ( -2 x + 2 )', - '-2 - 2', - '-2 - ( 4 x + 2 )', - '-2 - ( -4 x + 4 )', - '-2 - ( -2 x + 4 )', - '-2 - 4', - '-2 - ( 2 x + 4 )', - 'x - 2 - ( -2 x - 4 )', - 'x - 2 - ( -4 )', - 'x - 2 - ( 4 x - 4 )', - 'x - 2 - ( -4 x - 2 )', - 'x - 2 - ( -2 )', - 'x - 2 - ( 2 x - 2 )', - 'x - 2 - ( 4 x - 2 )', - 'x - 2 - ( -4 x )', - 'x - 2 - ( -2 x )', - 'x - 2 - 2 x', - 'x - 2 - 4 x', - 'x - 2 - ( -4 x + 2 )', - 'x - 2 - ( -2 x + 2 )', - 'x - 2 - 2', - 'x - 2 - ( 4 x + 2 )', - 'x - 2 - ( -4 x + 4 )', - 'x - 2 - ( -2 x + 4 )', - 'x - 2 - 4', - 'x - 2 - ( 2 x + 4 )', - '2 x - 2 - ( -2 x - 4 )', - '2 x - 2 - ( -4 )', - '2 x - 2 - ( 2 x - 4 )', - '2 x - 2 - ( -4 x - 2 )', - '2 x - 2 - ( -2 )', - '2 x - 2 - ( 2 x - 2 )', - '2 x - 2 - ( 4 x - 2 )', - '2 x - 2 - ( -4 x )', - '2 x - 2 - ( -2 x )', - '2 x - 2 - 2 x', - '2 x - 2 - 4 x', - '2 x - 2 - ( -4 x + 2 )', - '2 x - 2 - ( -2 x + 2 )', - '2 x - 2 - 2', - '2 x - 2 - ( 4 x + 2 )', - '2 x - 2 - ( -4 x + 4 )', - '2 x - 2 - ( -2 x + 4 )', - '2 x - 2 - 4', - '2 x - 2 - ( 2 x + 4 )', - '-2 x - 1 - ( -2 x - 4 )', - '-2 x - 1 - ( -4 )', - '-2 x - 1 - ( 2 x - 4 )', - '-2 x - 1 - ( 4 x - 4 )', - '-2 x - 1 - ( -2 )', - '-2 x - 1 - ( 2 x - 2 )', - '-2 x - 1 - ( 4 x - 2 )', - '-2 x - 1 - ( -4 x )', - '-2 x - 1 - ( -2 x )', - '-2 x - 1 - 2 x', - '-2 x - 1 - 4 x', - '-2 x - 1 - ( -4 x + 2 )', - '-2 x - 1 - ( -2 x + 2 )', - '-2 x - 1 - 2', - '-2 x - 1 - ( 4 x + 2 )', - '-2 x - 1 - ( -4 x + 4 )', - '-2 x - 1 - ( -2 x + 4 )', - '-2 x - 1 - 4', - '-2 x - 1 - ( 2 x + 4 )', - '-1 - ( -2 x - 4 )', - '-1 - ( -4 )', - '-1 - ( 2 x - 4 )', - '-1 - ( 4 x - 4 )', - '-1 - ( -4 x - 2 )', - '-1 - ( 2 x - 2 )', - '-1 - ( 4 x - 2 )', - '-1 - ( -4 x )', - '-1 - ( -2 x )', - '-1 - 2 x', - '-1 - 4 x', - '-1 - ( -4 x + 2 )', - '-1 - ( -2 x + 2 )', - '-1 - 2', - '-1 - ( 4 x + 2 )', - '-1 - ( -4 x + 4 )', - '-1 - ( -2 x + 4 )', - '-1 - 4', - '-1 - ( 2 x + 4 )', - 'x - 1 - ( -2 x - 4 )', - 'x - 1 - ( -4 )', - 'x - 1 - ( 2 x - 4 )', - 'x - 1 - ( 4 x - 4 )', - 'x - 1 - ( -4 x - 2 )', - 'x - 1 - ( -2 )', - 'x - 1 - ( 4 x - 2 )', - 'x - 1 - ( -4 x )', - 'x - 1 - ( -2 x )', - 'x - 1 - 2 x', - 'x - 1 - 4 x', - 'x - 1 - ( -4 x + 2 )', - 'x - 1 - ( -2 x + 2 )', - 'x - 1 - 2', - 'x - 1 - ( 4 x + 2 )', - 'x - 1 - ( -4 x + 4 )', - 'x - 1 - ( -2 x + 4 )', - 'x - 1 - 4', - 'x - 1 - ( 2 x + 4 )', - '2 x - 1 - ( -2 x - 4 )', - '2 x - 1 - ( -4 )', - '2 x - 1 - ( 2 x - 4 )', - '2 x - 1 - ( 4 x - 4 )', - '2 x - 1 - ( -4 x - 2 )', - '2 x - 1 - ( -2 )', - '2 x - 1 - ( 2 x - 2 )', - '2 x - 1 - ( -4 x )', - '2 x - 1 - ( -2 x )', - '2 x - 1 - 2 x', - '2 x - 1 - 4 x', - '2 x - 1 - ( -4 x + 2 )', - '2 x - 1 - ( -2 x + 2 )', - '2 x - 1 - 2', - '2 x - 1 - ( 4 x + 2 )', - '2 x - 1 - ( -4 x + 4 )', - '2 x - 1 - ( -2 x + 4 )', - '2 x - 1 - 4', - '2 x - 1 - ( 2 x + 4 )', - '-2 x - ( -2 x - 4 )', - '-2 x - ( -4 )', - '-2 x - ( 2 x - 4 )', - '-2 x - ( 4 x - 4 )', - '-2 x - ( -4 x - 2 )', - '-2 x - ( -2 )', - '-2 x - ( 2 x - 2 )', - '-2 x - ( 4 x - 2 )', - '-2 x - ( -2 x )', - '-2 x - 2 x', - '-2 x - 4 x', - '-2 x - ( -4 x + 2 )', - '-2 x - ( -2 x + 2 )', - '-2 x - 2', - '-2 x - ( 4 x + 2 )', - '-2 x - ( -4 x + 4 )', - '-2 x - ( -2 x + 4 )', - '-2 x - 4', - '-2 x - ( 2 x + 4 )', - '- x - ( -2 x - 4 )', - '- x - ( -4 )', - '- x - ( 2 x - 4 )', - '- x - ( 4 x - 4 )', - '- x - ( -4 x - 2 )', - '- x - ( -2 )', - '- x - ( 2 x - 2 )', - '- x - ( 4 x - 2 )', - '- x - ( -4 x )', - '- x - 2 x', - '- x - 4 x', - '- x - ( -4 x + 2 )', - '- x - ( -2 x + 2 )', - '- x - 2', - '- x - ( 4 x + 2 )', - '- x - ( -4 x + 4 )', - '- x - ( -2 x + 4 )', - '- x - 4', - '- x - ( 2 x + 4 )', - 'x - ( -2 x - 4 )', - 'x - ( -4 )', - 'x - ( 2 x - 4 )', - 'x - ( 4 x - 4 )', - 'x - ( -4 x - 2 )', - 'x - ( -2 )', - 'x - ( 2 x - 2 )', - 'x - ( 4 x - 2 )', - 'x - ( -4 x )', - 'x - ( -2 x )', - 'x - 4 x', - 'x - ( -4 x + 2 )', - 'x - ( -2 x + 2 )', - 'x - 2', - 'x - ( 4 x + 2 )', - 'x - ( -4 x + 4 )', - 'x - ( -2 x + 4 )', - 'x - 4', - 'x - ( 2 x + 4 )', - '2 x - ( -2 x - 4 )', - '2 x - ( -4 )', - '2 x - ( 2 x - 4 )', - '2 x - ( 4 x - 4 )', - '2 x - ( -4 x - 2 )', - '2 x - ( -2 )', - '2 x - ( 2 x - 2 )', - '2 x - ( 4 x - 2 )', - '2 x - ( -4 x )', - '2 x - ( -2 x )', - '2 x - 2 x', - '2 x - ( -4 x + 2 )', - '2 x - ( -2 x + 2 )', - '2 x - 2', - '2 x - ( 4 x + 2 )', - '2 x - ( -4 x + 4 )', - '2 x - ( -2 x + 4 )', - '2 x - 4', - '2 x - ( 2 x + 4 )', - '-2 x + 1 - ( -2 x - 4 )', - '-2 x + 1 - ( -4 )', - '-2 x + 1 - ( 2 x - 4 )', - '-2 x + 1 - ( 4 x - 4 )', - '-2 x + 1 - ( -4 x - 2 )', - '-2 x + 1 - ( -2 )', - '-2 x + 1 - ( 2 x - 2 )', - '-2 x + 1 - ( 4 x - 2 )', - '-2 x + 1 - ( -4 x )', - '-2 x + 1 - ( -2 x )', - '-2 x + 1 - 2 x', - '-2 x + 1 - 4 x', - '-2 x + 1 - ( -2 x + 2 )', - '-2 x + 1 - 2', - '-2 x + 1 - ( 4 x + 2 )', - '-2 x + 1 - ( -4 x + 4 )', - '-2 x + 1 - ( -2 x + 4 )', - '-2 x + 1 - 4', - '-2 x + 1 - ( 2 x + 4 )', - '- x + 1 - ( -2 x - 4 )', - '- x + 1 - ( -4 )', - '- x + 1 - ( 2 x - 4 )', - '- x + 1 - ( 4 x - 4 )', - '- x + 1 - ( -4 x - 2 )', - '- x + 1 - ( -2 )', - '- x + 1 - ( 2 x - 2 )', - '- x + 1 - ( 4 x - 2 )', - '- x + 1 - ( -4 x )', - '- x + 1 - ( -2 x )', - '- x + 1 - 2 x', - '- x + 1 - 4 x', - '- x + 1 - ( -4 x + 2 )', - '- x + 1 - 2', - '- x + 1 - ( 4 x + 2 )', - '- x + 1 - ( -4 x + 4 )', - '- x + 1 - ( -2 x + 4 )', - '- x + 1 - 4', - '- x + 1 - ( 2 x + 4 )', - '1 - ( -2 x - 4 )', - '1 - ( -4 )', - '1 - ( 2 x - 4 )', - '1 - ( 4 x - 4 )', - '1 - ( -4 x - 2 )', - '1 - ( -2 )', - '1 - ( 2 x - 2 )', - '1 - ( 4 x - 2 )', - '1 - ( -4 x )', - '1 - ( -2 x )', - '1 - 2 x', - '1 - 4 x', - '1 - ( -4 x + 2 )', - '1 - ( -2 x + 2 )', - '1 - ( 4 x + 2 )', - '1 - ( -4 x + 4 )', - '1 - ( -2 x + 4 )', - '1 - 4', - '1 - ( 2 x + 4 )', - '2 x + 1 - ( -2 x - 4 )', - '2 x + 1 - ( -4 )', - '2 x + 1 - ( 2 x - 4 )', - '2 x + 1 - ( 4 x - 4 )', - '2 x + 1 - ( -4 x - 2 )', - '2 x + 1 - ( -2 )', - '2 x + 1 - ( 2 x - 2 )', - '2 x + 1 - ( 4 x - 2 )', - '2 x + 1 - ( -4 x )', - '2 x + 1 - ( -2 x )', - '2 x + 1 - 2 x', - '2 x + 1 - 4 x', - '2 x + 1 - ( -4 x + 2 )', - '2 x + 1 - ( -2 x + 2 )', - '2 x + 1 - 2', - '2 x + 1 - ( -4 x + 4 )', - '2 x + 1 - ( -2 x + 4 )', - '2 x + 1 - 4', - '2 x + 1 - ( 2 x + 4 )', - '-2 x + 2 - ( -2 x - 4 )', - '-2 x + 2 - ( -4 )', - '-2 x + 2 - ( 2 x - 4 )', - '-2 x + 2 - ( 4 x - 4 )', - '-2 x + 2 - ( -4 x - 2 )', - '-2 x + 2 - ( -2 )', - '-2 x + 2 - ( 2 x - 2 )', - '-2 x + 2 - ( 4 x - 2 )', - '-2 x + 2 - ( -4 x )', - '-2 x + 2 - ( -2 x )', - '-2 x + 2 - 2 x', - '-2 x + 2 - 4 x', - '-2 x + 2 - ( -4 x + 2 )', - '-2 x + 2 - ( -2 x + 2 )', - '-2 x + 2 - 2', - '-2 x + 2 - ( 4 x + 2 )', - '-2 x + 2 - ( -2 x + 4 )', - '-2 x + 2 - 4', - '-2 x + 2 - ( 2 x + 4 )', - '- x + 2 - ( -2 x - 4 )', - '- x + 2 - ( -4 )', - '- x + 2 - ( 2 x - 4 )', - '- x + 2 - ( 4 x - 4 )', - '- x + 2 - ( -4 x - 2 )', - '- x + 2 - ( -2 )', - '- x + 2 - ( 2 x - 2 )', - '- x + 2 - ( 4 x - 2 )', - '- x + 2 - ( -4 x )', - '- x + 2 - ( -2 x )', - '- x + 2 - 2 x', - '- x + 2 - 4 x', - '- x + 2 - ( -4 x + 2 )', - '- x + 2 - ( -2 x + 2 )', - '- x + 2 - 2', - '- x + 2 - ( 4 x + 2 )', - '- x + 2 - ( -4 x + 4 )', - '- x + 2 - 4', - '- x + 2 - ( 2 x + 4 )', - '2 - ( -2 x - 4 )', - '2 - ( -4 )', - '2 - ( 2 x - 4 )', - '2 - ( 4 x - 4 )', - '2 - ( -4 x - 2 )', - '2 - ( -2 )', - '2 - ( 2 x - 2 )', - '2 - ( 4 x - 2 )', - '2 - ( -4 x )', - '2 - ( -2 x )', - '2 - 2 x', - '2 - 4 x', - '2 - ( -4 x + 2 )', - '2 - ( -2 x + 2 )', - '2 - 2', - '2 - ( 4 x + 2 )', - '2 - ( -4 x + 4 )', - '2 - ( -2 x + 4 )', - '2 - ( 2 x + 4 )', - 'x + 2 - ( -2 x - 4 )', - 'x + 2 - ( -4 )', - 'x + 2 - ( 2 x - 4 )', - 'x + 2 - ( 4 x - 4 )', - 'x + 2 - ( -4 x - 2 )', - 'x + 2 - ( -2 )', - 'x + 2 - ( 2 x - 2 )', - 'x + 2 - ( 4 x - 2 )', - 'x + 2 - ( -4 x )', - 'x + 2 - ( -2 x )', - 'x + 2 - 2 x', - 'x + 2 - 4 x', - 'x + 2 - ( -4 x + 2 )', - 'x + 2 - ( -2 x + 2 )', - 'x + 2 - 2', - 'x + 2 - ( 4 x + 2 )', - 'x + 2 - ( -4 x + 4 )', - 'x + 2 - ( -2 x + 4 )', - 'x + 2 - 4'] -TEX_POLY_MUL_VALID_RESULTS = [ - '( - x - 2 ) \\times ( -4 )', - '( - x - 2 ) ( 2 x - 4 )', - '( - x - 2 ) ( 4 x - 4 )', - '( - x - 2 ) ( -4 x - 2 )', - '( - x - 2 ) \\times ( -2 )', - '( - x - 2 ) ( 2 x - 2 )', - '( - x - 2 ) ( 4 x - 2 )', - '( - x - 2 ) \\times ( -4 x )', - '( - x - 2 ) \\times ( -2 x )', - '( - x - 2 ) \\times 2 x', - '( - x - 2 ) \\times 4 x', - '( - x - 2 ) ( -4 x + 2 )', - '( - x - 2 ) ( -2 x + 2 )', - '( - x - 2 ) \\times 2', - '( - x - 2 ) ( 4 x + 2 )', - '( - x - 2 ) ( -4 x + 4 )', - '( - x - 2 ) ( -2 x + 4 )', - '( - x - 2 ) \\times 4', - '( - x - 2 ) ( 2 x + 4 )', - '-2 ( -2 x - 4 )', - '-2 ( 2 x - 4 )', - '-2 ( 4 x - 4 )', - '-2 ( -4 x - 2 )', - '-2 \\times ( -2 )', - '-2 ( 2 x - 2 )', - '-2 ( 4 x - 2 )', - '-2 \\times ( -4 x )', - '-2 \\times ( -2 x )', - '-2 \\times 2 x', - '-2 \\times 4 x', - '-2 ( -4 x + 2 )', - '-2 ( -2 x + 2 )', - '-2 \\times 2', - '-2 ( 4 x + 2 )', - '-2 ( -4 x + 4 )', - '-2 ( -2 x + 4 )', - '-2 \\times 4', - '-2 ( 2 x + 4 )', - '( x - 2 ) ( -2 x - 4 )', - '( x - 2 ) \\times ( -4 )', - '( x - 2 ) ( 4 x - 4 )', - '( x - 2 ) ( -4 x - 2 )', - '( x - 2 ) \\times ( -2 )', - '( x - 2 ) ( 2 x - 2 )', - '( x - 2 ) ( 4 x - 2 )', - '( x - 2 ) \\times ( -4 x )', - '( x - 2 ) \\times ( -2 x )', - '( x - 2 ) \\times 2 x', - '( x - 2 ) \\times 4 x', - '( x - 2 ) ( -4 x + 2 )', - '( x - 2 ) ( -2 x + 2 )', - '( x - 2 ) \\times 2', - '( x - 2 ) ( 4 x + 2 )', - '( x - 2 ) ( -4 x + 4 )', - '( x - 2 ) ( -2 x + 4 )', - '( x - 2 ) \\times 4', - '( x - 2 ) ( 2 x + 4 )', - '( 2 x - 2 ) ( -2 x - 4 )', - '( 2 x - 2 ) \\times ( -4 )', - '( 2 x - 2 ) ( 2 x - 4 )', - '( 2 x - 2 ) ( -4 x - 2 )', - '( 2 x - 2 ) \\times ( -2 )', - '( 2 x - 2 ) ( 2 x - 2 )', - '( 2 x - 2 ) ( 4 x - 2 )', - '( 2 x - 2 ) \\times ( -4 x )', - '( 2 x - 2 ) \\times ( -2 x )', - '( 2 x - 2 ) \\times 2 x', - '( 2 x - 2 ) \\times 4 x', - '( 2 x - 2 ) ( -4 x + 2 )', - '( 2 x - 2 ) ( -2 x + 2 )', - '( 2 x - 2 ) \\times 2', - '( 2 x - 2 ) ( 4 x + 2 )', - '( 2 x - 2 ) ( -4 x + 4 )', - '( 2 x - 2 ) ( -2 x + 4 )', - '( 2 x - 2 ) \\times 4', - '( 2 x - 2 ) ( 2 x + 4 )', - '( -2 x - 1 ) ( -2 x - 4 )', - '( -2 x - 1 ) \\times ( -4 )', - '( -2 x - 1 ) ( 2 x - 4 )', - '( -2 x - 1 ) ( 4 x - 4 )', - '( -2 x - 1 ) \\times ( -2 )', - '( -2 x - 1 ) ( 2 x - 2 )', - '( -2 x - 1 ) ( 4 x - 2 )', - '( -2 x - 1 ) \\times ( -4 x )', - '( -2 x - 1 ) \\times ( -2 x )', - '( -2 x - 1 ) \\times 2 x', - '( -2 x - 1 ) \\times 4 x', - '( -2 x - 1 ) ( -4 x + 2 )', - '( -2 x - 1 ) ( -2 x + 2 )', - '( -2 x - 1 ) \\times 2', - '( -2 x - 1 ) ( 4 x + 2 )', - '( -2 x - 1 ) ( -4 x + 4 )', - '( -2 x - 1 ) ( -2 x + 4 )', - '( -2 x - 1 ) \\times 4', - '( -2 x - 1 ) ( 2 x + 4 )', - '-1 ( -2 x - 4 )', - '-1 \\times ( -4 )', - '-1 ( 2 x - 4 )', - '-1 ( 4 x - 4 )', - '-1 ( -4 x - 2 )', - '-1 ( 2 x - 2 )', - '-1 ( 4 x - 2 )', - '-1 \\times ( -4 x )', - '-1 \\times ( -2 x )', - '-1 \\times 2 x', - '-1 \\times 4 x', - '-1 ( -4 x + 2 )', - '-1 ( -2 x + 2 )', - '-1 \\times 2', - '-1 ( 4 x + 2 )', - '-1 ( -4 x + 4 )', - '-1 ( -2 x + 4 )', - '-1 \\times 4', - '-1 ( 2 x + 4 )', - '( x - 1 ) ( -2 x - 4 )', - '( x - 1 ) \\times ( -4 )', - '( x - 1 ) ( 2 x - 4 )', - '( x - 1 ) ( 4 x - 4 )', - '( x - 1 ) ( -4 x - 2 )', - '( x - 1 ) \\times ( -2 )', - '( x - 1 ) ( 4 x - 2 )', - '( x - 1 ) \\times ( -4 x )', - '( x - 1 ) \\times ( -2 x )', - '( x - 1 ) \\times 2 x', - '( x - 1 ) \\times 4 x', - '( x - 1 ) ( -4 x + 2 )', - '( x - 1 ) ( -2 x + 2 )', - '( x - 1 ) \\times 2', - '( x - 1 ) ( 4 x + 2 )', - '( x - 1 ) ( -4 x + 4 )', - '( x - 1 ) ( -2 x + 4 )', - '( x - 1 ) \\times 4', - '( x - 1 ) ( 2 x + 4 )', - '( 2 x - 1 ) ( -2 x - 4 )', - '( 2 x - 1 ) \\times ( -4 )', - '( 2 x - 1 ) ( 2 x - 4 )', - '( 2 x - 1 ) ( 4 x - 4 )', - '( 2 x - 1 ) ( -4 x - 2 )', - '( 2 x - 1 ) \\times ( -2 )', - '( 2 x - 1 ) ( 2 x - 2 )', - '( 2 x - 1 ) \\times ( -4 x )', - '( 2 x - 1 ) \\times ( -2 x )', - '( 2 x - 1 ) \\times 2 x', - '( 2 x - 1 ) \\times 4 x', - '( 2 x - 1 ) ( -4 x + 2 )', - '( 2 x - 1 ) ( -2 x + 2 )', - '( 2 x - 1 ) \\times 2', - '( 2 x - 1 ) ( 4 x + 2 )', - '( 2 x - 1 ) ( -4 x + 4 )', - '( 2 x - 1 ) ( -2 x + 4 )', - '( 2 x - 1 ) \\times 4', - '( 2 x - 1 ) ( 2 x + 4 )', - '-2 x ( -2 x - 4 )', - '-2 x \\times ( -4 )', - '-2 x ( 2 x - 4 )', - '-2 x ( 4 x - 4 )', - '-2 x ( -4 x - 2 )', - '-2 x \\times ( -2 )', - '-2 x ( 2 x - 2 )', - '-2 x ( 4 x - 2 )', - '-2 x \\times ( -2 x )', - '-2 x \\times 2 x', - '-2 x \\times 4 x', - '-2 x ( -4 x + 2 )', - '-2 x ( -2 x + 2 )', - '-2 x \\times 2', - '-2 x ( 4 x + 2 )', - '-2 x ( -4 x + 4 )', - '-2 x ( -2 x + 4 )', - '-2 x \\times 4', - '-2 x ( 2 x + 4 )', - '- x ( -2 x - 4 )', - '- x \\times ( -4 )', - '- x ( 2 x - 4 )', - '- x ( 4 x - 4 )', - '- x ( -4 x - 2 )', - '- x \\times ( -2 )', - '- x ( 2 x - 2 )', - '- x ( 4 x - 2 )', - '- x \\times ( -4 x )', - '- x \\times 2 x', - '- x \\times 4 x', - '- x ( -4 x + 2 )', - '- x ( -2 x + 2 )', - '- x \\times 2', - '- x ( 4 x + 2 )', - '- x ( -4 x + 4 )', - '- x ( -2 x + 4 )', - '- x \\times 4', - '- x ( 2 x + 4 )', - 'x ( -2 x - 4 )', - 'x \\times ( -4 )', - 'x ( 2 x - 4 )', - 'x ( 4 x - 4 )', - 'x ( -4 x - 2 )', - 'x \\times ( -2 )', - 'x ( 2 x - 2 )', - 'x ( 4 x - 2 )', - 'x \\times ( -4 x )', - 'x \\times ( -2 x )', - 'x \\times 4 x', - 'x ( -4 x + 2 )', - 'x ( -2 x + 2 )', - 'x \\times 2', - 'x ( 4 x + 2 )', - 'x ( -4 x + 4 )', - 'x ( -2 x + 4 )', - 'x \\times 4', - 'x ( 2 x + 4 )', - '2 x ( -2 x - 4 )', - '2 x \\times ( -4 )', - '2 x ( 2 x - 4 )', - '2 x ( 4 x - 4 )', - '2 x ( -4 x - 2 )', - '2 x \\times ( -2 )', - '2 x ( 2 x - 2 )', - '2 x ( 4 x - 2 )', - '2 x \\times ( -4 x )', - '2 x \\times ( -2 x )', - '2 x \\times 2 x', - '2 x ( -4 x + 2 )', - '2 x ( -2 x + 2 )', - '2 x \\times 2', - '2 x ( 4 x + 2 )', - '2 x ( -4 x + 4 )', - '2 x ( -2 x + 4 )', - '2 x \\times 4', - '2 x ( 2 x + 4 )', - '( -2 x + 1 ) ( -2 x - 4 )', - '( -2 x + 1 ) \\times ( -4 )', - '( -2 x + 1 ) ( 2 x - 4 )', - '( -2 x + 1 ) ( 4 x - 4 )', - '( -2 x + 1 ) ( -4 x - 2 )', - '( -2 x + 1 ) \\times ( -2 )', - '( -2 x + 1 ) ( 2 x - 2 )', - '( -2 x + 1 ) ( 4 x - 2 )', - '( -2 x + 1 ) \\times ( -4 x )', - '( -2 x + 1 ) \\times ( -2 x )', - '( -2 x + 1 ) \\times 2 x', - '( -2 x + 1 ) \\times 4 x', - '( -2 x + 1 ) ( -2 x + 2 )', - '( -2 x + 1 ) \\times 2', - '( -2 x + 1 ) ( 4 x + 2 )', - '( -2 x + 1 ) ( -4 x + 4 )', - '( -2 x + 1 ) ( -2 x + 4 )', - '( -2 x + 1 ) \\times 4', - '( -2 x + 1 ) ( 2 x + 4 )', - '( - x + 1 ) ( -2 x - 4 )', - '( - x + 1 ) \\times ( -4 )', - '( - x + 1 ) ( 2 x - 4 )', - '( - x + 1 ) ( 4 x - 4 )', - '( - x + 1 ) ( -4 x - 2 )', - '( - x + 1 ) \\times ( -2 )', - '( - x + 1 ) ( 2 x - 2 )', - '( - x + 1 ) ( 4 x - 2 )', - '( - x + 1 ) \\times ( -4 x )', - '( - x + 1 ) \\times ( -2 x )', - '( - x + 1 ) \\times 2 x', - '( - x + 1 ) \\times 4 x', - '( - x + 1 ) ( -4 x + 2 )', - '( - x + 1 ) \\times 2', - '( - x + 1 ) ( 4 x + 2 )', - '( - x + 1 ) ( -4 x + 4 )', - '( - x + 1 ) ( -2 x + 4 )', - '( - x + 1 ) \\times 4', - '( - x + 1 ) ( 2 x + 4 )', - '1 ( -2 x - 4 )', - '1 \\times ( -4 )', - '1 ( 2 x - 4 )', - '1 ( 4 x - 4 )', - '1 ( -4 x - 2 )', - '1 \\times ( -2 )', - '1 ( 2 x - 2 )', - '1 ( 4 x - 2 )', - '1 \\times ( -4 x )', - '1 \\times ( -2 x )', - '1 \\times 2 x', - '1 \\times 4 x', - '1 ( -4 x + 2 )', - '1 ( -2 x + 2 )', - '1 ( 4 x + 2 )', - '1 ( -4 x + 4 )', - '1 ( -2 x + 4 )', - '1 \\times 4', - '1 ( 2 x + 4 )', - '( 2 x + 1 ) ( -2 x - 4 )', - '( 2 x + 1 ) \\times ( -4 )', - '( 2 x + 1 ) ( 2 x - 4 )', - '( 2 x + 1 ) ( 4 x - 4 )', - '( 2 x + 1 ) ( -4 x - 2 )', - '( 2 x + 1 ) \\times ( -2 )', - '( 2 x + 1 ) ( 2 x - 2 )', - '( 2 x + 1 ) ( 4 x - 2 )', - '( 2 x + 1 ) \\times ( -4 x )', - '( 2 x + 1 ) \\times ( -2 x )', - '( 2 x + 1 ) \\times 2 x', - '( 2 x + 1 ) \\times 4 x', - '( 2 x + 1 ) ( -4 x + 2 )', - '( 2 x + 1 ) ( -2 x + 2 )', - '( 2 x + 1 ) \\times 2', - '( 2 x + 1 ) ( -4 x + 4 )', - '( 2 x + 1 ) ( -2 x + 4 )', - '( 2 x + 1 ) \\times 4', - '( 2 x + 1 ) ( 2 x + 4 )', - '( -2 x + 2 ) ( -2 x - 4 )', - '( -2 x + 2 ) \\times ( -4 )', - '( -2 x + 2 ) ( 2 x - 4 )', - '( -2 x + 2 ) ( 4 x - 4 )', - '( -2 x + 2 ) ( -4 x - 2 )', - '( -2 x + 2 ) \\times ( -2 )', - '( -2 x + 2 ) ( 2 x - 2 )', - '( -2 x + 2 ) ( 4 x - 2 )', - '( -2 x + 2 ) \\times ( -4 x )', - '( -2 x + 2 ) \\times ( -2 x )', - '( -2 x + 2 ) \\times 2 x', - '( -2 x + 2 ) \\times 4 x', - '( -2 x + 2 ) ( -4 x + 2 )', - '( -2 x + 2 ) ( -2 x + 2 )', - '( -2 x + 2 ) \\times 2', - '( -2 x + 2 ) ( 4 x + 2 )', - '( -2 x + 2 ) ( -2 x + 4 )', - '( -2 x + 2 ) \\times 4', - '( -2 x + 2 ) ( 2 x + 4 )', - '( - x + 2 ) ( -2 x - 4 )', - '( - x + 2 ) \\times ( -4 )', - '( - x + 2 ) ( 2 x - 4 )', - '( - x + 2 ) ( 4 x - 4 )', - '( - x + 2 ) ( -4 x - 2 )', - '( - x + 2 ) \\times ( -2 )', - '( - x + 2 ) ( 2 x - 2 )', - '( - x + 2 ) ( 4 x - 2 )', - '( - x + 2 ) \\times ( -4 x )', - '( - x + 2 ) \\times ( -2 x )', - '( - x + 2 ) \\times 2 x', - '( - x + 2 ) \\times 4 x', - '( - x + 2 ) ( -4 x + 2 )', - '( - x + 2 ) ( -2 x + 2 )', - '( - x + 2 ) \\times 2', - '( - x + 2 ) ( 4 x + 2 )', - '( - x + 2 ) ( -4 x + 4 )', - '( - x + 2 ) \\times 4', - '( - x + 2 ) ( 2 x + 4 )', - '2 ( -2 x - 4 )', - '2 \\times ( -4 )', - '2 ( 2 x - 4 )', - '2 ( 4 x - 4 )', - '2 ( -4 x - 2 )', - '2 \\times ( -2 )', - '2 ( 2 x - 2 )', - '2 ( 4 x - 2 )', - '2 \\times ( -4 x )', - '2 \\times ( -2 x )', - '2 \\times 2 x', - '2 \\times 4 x', - '2 ( -4 x + 2 )', - '2 ( -2 x + 2 )', - '2 \\times 2', - '2 ( 4 x + 2 )', - '2 ( -4 x + 4 )', - '2 ( -2 x + 4 )', - '2 ( 2 x + 4 )', - '( x + 2 ) ( -2 x - 4 )', - '( x + 2 ) \\times ( -4 )', - '( x + 2 ) ( 2 x - 4 )', - '( x + 2 ) ( 4 x - 4 )', - '( x + 2 ) ( -4 x - 2 )', - '( x + 2 ) \\times ( -2 )', - '( x + 2 ) ( 2 x - 2 )', - '( x + 2 ) ( 4 x - 2 )', - '( x + 2 ) \\times ( -4 x )', - '( x + 2 ) \\times ( -2 x )', - '( x + 2 ) \\times 2 x', - '( x + 2 ) \\times 4 x', - '( x + 2 ) ( -4 x + 2 )', - '( x + 2 ) ( -2 x + 2 )', - '( x + 2 ) \\times 2', - '( x + 2 ) ( 4 x + 2 )', - '( x + 2 ) ( -4 x + 4 )', - '( x + 2 ) ( -2 x + 4 )', - '( x + 2 ) \\times 4'] -TXT_POLY_MUL_VALID_RESULTS = [ - '( - x - 2 ) * ( -4 )', - '( - x - 2 ) ( 2 x - 4 )', - '( - x - 2 ) ( 4 x - 4 )', - '( - x - 2 ) ( -4 x - 2 )', - '( - x - 2 ) * ( -2 )', - '( - x - 2 ) ( 2 x - 2 )', - '( - x - 2 ) ( 4 x - 2 )', - '( - x - 2 ) * ( -4 x )', - '( - x - 2 ) * ( -2 x )', - '( - x - 2 ) * 2 x', - '( - x - 2 ) * 4 x', - '( - x - 2 ) ( -4 x + 2 )', - '( - x - 2 ) ( -2 x + 2 )', - '( - x - 2 ) * 2', - '( - x - 2 ) ( 4 x + 2 )', - '( - x - 2 ) ( -4 x + 4 )', - '( - x - 2 ) ( -2 x + 4 )', - '( - x - 2 ) * 4', - '( - x - 2 ) ( 2 x + 4 )', - '-2 ( -2 x - 4 )', - '-2 ( 2 x - 4 )', - '-2 ( 4 x - 4 )', - '-2 ( -4 x - 2 )', - '-2 * ( -2 )', - '-2 ( 2 x - 2 )', - '-2 ( 4 x - 2 )', - '-2 * ( -4 x )', - '-2 * ( -2 x )', - '-2 * 2 x', - '-2 * 4 x', - '-2 ( -4 x + 2 )', - '-2 ( -2 x + 2 )', - '-2 * 2', - '-2 ( 4 x + 2 )', - '-2 ( -4 x + 4 )', - '-2 ( -2 x + 4 )', - '-2 * 4', - '-2 ( 2 x + 4 )', - '( x - 2 ) ( -2 x - 4 )', - '( x - 2 ) * ( -4 )', - '( x - 2 ) ( 4 x - 4 )', - '( x - 2 ) ( -4 x - 2 )', - '( x - 2 ) * ( -2 )', - '( x - 2 ) ( 2 x - 2 )', - '( x - 2 ) ( 4 x - 2 )', - '( x - 2 ) * ( -4 x )', - '( x - 2 ) * ( -2 x )', - '( x - 2 ) * 2 x', - '( x - 2 ) * 4 x', - '( x - 2 ) ( -4 x + 2 )', - '( x - 2 ) ( -2 x + 2 )', - '( x - 2 ) * 2', - '( x - 2 ) ( 4 x + 2 )', - '( x - 2 ) ( -4 x + 4 )', - '( x - 2 ) ( -2 x + 4 )', - '( x - 2 ) * 4', - '( x - 2 ) ( 2 x + 4 )', - '( 2 x - 2 ) ( -2 x - 4 )', - '( 2 x - 2 ) * ( -4 )', - '( 2 x - 2 ) ( 2 x - 4 )', - '( 2 x - 2 ) ( -4 x - 2 )', - '( 2 x - 2 ) * ( -2 )', - '( 2 x - 2 ) ( 2 x - 2 )', - '( 2 x - 2 ) ( 4 x - 2 )', - '( 2 x - 2 ) * ( -4 x )', - '( 2 x - 2 ) * ( -2 x )', - '( 2 x - 2 ) * 2 x', - '( 2 x - 2 ) * 4 x', - '( 2 x - 2 ) ( -4 x + 2 )', - '( 2 x - 2 ) ( -2 x + 2 )', - '( 2 x - 2 ) * 2', - '( 2 x - 2 ) ( 4 x + 2 )', - '( 2 x - 2 ) ( -4 x + 4 )', - '( 2 x - 2 ) ( -2 x + 4 )', - '( 2 x - 2 ) * 4', - '( 2 x - 2 ) ( 2 x + 4 )', - '( -2 x - 1 ) ( -2 x - 4 )', - '( -2 x - 1 ) * ( -4 )', - '( -2 x - 1 ) ( 2 x - 4 )', - '( -2 x - 1 ) ( 4 x - 4 )', - '( -2 x - 1 ) * ( -2 )', - '( -2 x - 1 ) ( 2 x - 2 )', - '( -2 x - 1 ) ( 4 x - 2 )', - '( -2 x - 1 ) * ( -4 x )', - '( -2 x - 1 ) * ( -2 x )', - '( -2 x - 1 ) * 2 x', - '( -2 x - 1 ) * 4 x', - '( -2 x - 1 ) ( -4 x + 2 )', - '( -2 x - 1 ) ( -2 x + 2 )', - '( -2 x - 1 ) * 2', - '( -2 x - 1 ) ( 4 x + 2 )', - '( -2 x - 1 ) ( -4 x + 4 )', - '( -2 x - 1 ) ( -2 x + 4 )', - '( -2 x - 1 ) * 4', - '( -2 x - 1 ) ( 2 x + 4 )', - '-1 ( -2 x - 4 )', - '-1 * ( -4 )', - '-1 ( 2 x - 4 )', - '-1 ( 4 x - 4 )', - '-1 ( -4 x - 2 )', - '-1 ( 2 x - 2 )', - '-1 ( 4 x - 2 )', - '-1 * ( -4 x )', - '-1 * ( -2 x )', - '-1 * 2 x', - '-1 * 4 x', - '-1 ( -4 x + 2 )', - '-1 ( -2 x + 2 )', - '-1 * 2', - '-1 ( 4 x + 2 )', - '-1 ( -4 x + 4 )', - '-1 ( -2 x + 4 )', - '-1 * 4', - '-1 ( 2 x + 4 )', - '( x - 1 ) ( -2 x - 4 )', - '( x - 1 ) * ( -4 )', - '( x - 1 ) ( 2 x - 4 )', - '( x - 1 ) ( 4 x - 4 )', - '( x - 1 ) ( -4 x - 2 )', - '( x - 1 ) * ( -2 )', - '( x - 1 ) ( 4 x - 2 )', - '( x - 1 ) * ( -4 x )', - '( x - 1 ) * ( -2 x )', - '( x - 1 ) * 2 x', - '( x - 1 ) * 4 x', - '( x - 1 ) ( -4 x + 2 )', - '( x - 1 ) ( -2 x + 2 )', - '( x - 1 ) * 2', - '( x - 1 ) ( 4 x + 2 )', - '( x - 1 ) ( -4 x + 4 )', - '( x - 1 ) ( -2 x + 4 )', - '( x - 1 ) * 4', - '( x - 1 ) ( 2 x + 4 )', - '( 2 x - 1 ) ( -2 x - 4 )', - '( 2 x - 1 ) * ( -4 )', - '( 2 x - 1 ) ( 2 x - 4 )', - '( 2 x - 1 ) ( 4 x - 4 )', - '( 2 x - 1 ) ( -4 x - 2 )', - '( 2 x - 1 ) * ( -2 )', - '( 2 x - 1 ) ( 2 x - 2 )', - '( 2 x - 1 ) * ( -4 x )', - '( 2 x - 1 ) * ( -2 x )', - '( 2 x - 1 ) * 2 x', - '( 2 x - 1 ) * 4 x', - '( 2 x - 1 ) ( -4 x + 2 )', - '( 2 x - 1 ) ( -2 x + 2 )', - '( 2 x - 1 ) * 2', - '( 2 x - 1 ) ( 4 x + 2 )', - '( 2 x - 1 ) ( -4 x + 4 )', - '( 2 x - 1 ) ( -2 x + 4 )', - '( 2 x - 1 ) * 4', - '( 2 x - 1 ) ( 2 x + 4 )', - '-2 x ( -2 x - 4 )', - '-2 x * ( -4 )', - '-2 x ( 2 x - 4 )', - '-2 x ( 4 x - 4 )', - '-2 x ( -4 x - 2 )', - '-2 x * ( -2 )', - '-2 x ( 2 x - 2 )', - '-2 x ( 4 x - 2 )', - '-2 x * ( -2 x )', - '-2 x * 2 x', - '-2 x * 4 x', - '-2 x ( -4 x + 2 )', - '-2 x ( -2 x + 2 )', - '-2 x * 2', - '-2 x ( 4 x + 2 )', - '-2 x ( -4 x + 4 )', - '-2 x ( -2 x + 4 )', - '-2 x * 4', - '-2 x ( 2 x + 4 )', - '- x ( -2 x - 4 )', - '- x * ( -4 )', - '- x ( 2 x - 4 )', - '- x ( 4 x - 4 )', - '- x ( -4 x - 2 )', - '- x * ( -2 )', - '- x ( 2 x - 2 )', - '- x ( 4 x - 2 )', - '- x * ( -4 x )', - '- x * 2 x', - '- x * 4 x', - '- x ( -4 x + 2 )', - '- x ( -2 x + 2 )', - '- x * 2', - '- x ( 4 x + 2 )', - '- x ( -4 x + 4 )', - '- x ( -2 x + 4 )', - '- x * 4', - '- x ( 2 x + 4 )', - 'x ( -2 x - 4 )', - 'x * ( -4 )', - 'x ( 2 x - 4 )', - 'x ( 4 x - 4 )', - 'x ( -4 x - 2 )', - 'x * ( -2 )', - 'x ( 2 x - 2 )', - 'x ( 4 x - 2 )', - 'x * ( -4 x )', - 'x * ( -2 x )', - 'x * 4 x', - 'x ( -4 x + 2 )', - 'x ( -2 x + 2 )', - 'x * 2', - 'x ( 4 x + 2 )', - 'x ( -4 x + 4 )', - 'x ( -2 x + 4 )', - 'x * 4', - 'x ( 2 x + 4 )', - '2 x ( -2 x - 4 )', - '2 x * ( -4 )', - '2 x ( 2 x - 4 )', - '2 x ( 4 x - 4 )', - '2 x ( -4 x - 2 )', - '2 x * ( -2 )', - '2 x ( 2 x - 2 )', - '2 x ( 4 x - 2 )', - '2 x * ( -4 x )', - '2 x * ( -2 x )', - '2 x * 2 x', - '2 x ( -4 x + 2 )', - '2 x ( -2 x + 2 )', - '2 x * 2', - '2 x ( 4 x + 2 )', - '2 x ( -4 x + 4 )', - '2 x ( -2 x + 4 )', - '2 x * 4', - '2 x ( 2 x + 4 )', - '( -2 x + 1 ) ( -2 x - 4 )', - '( -2 x + 1 ) * ( -4 )', - '( -2 x + 1 ) ( 2 x - 4 )', - '( -2 x + 1 ) ( 4 x - 4 )', - '( -2 x + 1 ) ( -4 x - 2 )', - '( -2 x + 1 ) * ( -2 )', - '( -2 x + 1 ) ( 2 x - 2 )', - '( -2 x + 1 ) ( 4 x - 2 )', - '( -2 x + 1 ) * ( -4 x )', - '( -2 x + 1 ) * ( -2 x )', - '( -2 x + 1 ) * 2 x', - '( -2 x + 1 ) * 4 x', - '( -2 x + 1 ) ( -2 x + 2 )', - '( -2 x + 1 ) * 2', - '( -2 x + 1 ) ( 4 x + 2 )', - '( -2 x + 1 ) ( -4 x + 4 )', - '( -2 x + 1 ) ( -2 x + 4 )', - '( -2 x + 1 ) * 4', - '( -2 x + 1 ) ( 2 x + 4 )', - '( - x + 1 ) ( -2 x - 4 )', - '( - x + 1 ) * ( -4 )', - '( - x + 1 ) ( 2 x - 4 )', - '( - x + 1 ) ( 4 x - 4 )', - '( - x + 1 ) ( -4 x - 2 )', - '( - x + 1 ) * ( -2 )', - '( - x + 1 ) ( 2 x - 2 )', - '( - x + 1 ) ( 4 x - 2 )', - '( - x + 1 ) * ( -4 x )', - '( - x + 1 ) * ( -2 x )', - '( - x + 1 ) * 2 x', - '( - x + 1 ) * 4 x', - '( - x + 1 ) ( -4 x + 2 )', - '( - x + 1 ) * 2', - '( - x + 1 ) ( 4 x + 2 )', - '( - x + 1 ) ( -4 x + 4 )', - '( - x + 1 ) ( -2 x + 4 )', - '( - x + 1 ) * 4', - '( - x + 1 ) ( 2 x + 4 )', - '1 ( -2 x - 4 )', - '1 * ( -4 )', - '1 ( 2 x - 4 )', - '1 ( 4 x - 4 )', - '1 ( -4 x - 2 )', - '1 * ( -2 )', - '1 ( 2 x - 2 )', - '1 ( 4 x - 2 )', - '1 * ( -4 x )', - '1 * ( -2 x )', - '1 * 2 x', - '1 * 4 x', - '1 ( -4 x + 2 )', - '1 ( -2 x + 2 )', - '1 ( 4 x + 2 )', - '1 ( -4 x + 4 )', - '1 ( -2 x + 4 )', - '1 * 4', - '1 ( 2 x + 4 )', - '( 2 x + 1 ) ( -2 x - 4 )', - '( 2 x + 1 ) * ( -4 )', - '( 2 x + 1 ) ( 2 x - 4 )', - '( 2 x + 1 ) ( 4 x - 4 )', - '( 2 x + 1 ) ( -4 x - 2 )', - '( 2 x + 1 ) * ( -2 )', - '( 2 x + 1 ) ( 2 x - 2 )', - '( 2 x + 1 ) ( 4 x - 2 )', - '( 2 x + 1 ) * ( -4 x )', - '( 2 x + 1 ) * ( -2 x )', - '( 2 x + 1 ) * 2 x', - '( 2 x + 1 ) * 4 x', - '( 2 x + 1 ) ( -4 x + 2 )', - '( 2 x + 1 ) ( -2 x + 2 )', - '( 2 x + 1 ) * 2', - '( 2 x + 1 ) ( -4 x + 4 )', - '( 2 x + 1 ) ( -2 x + 4 )', - '( 2 x + 1 ) * 4', - '( 2 x + 1 ) ( 2 x + 4 )', - '( -2 x + 2 ) ( -2 x - 4 )', - '( -2 x + 2 ) * ( -4 )', - '( -2 x + 2 ) ( 2 x - 4 )', - '( -2 x + 2 ) ( 4 x - 4 )', - '( -2 x + 2 ) ( -4 x - 2 )', - '( -2 x + 2 ) * ( -2 )', - '( -2 x + 2 ) ( 2 x - 2 )', - '( -2 x + 2 ) ( 4 x - 2 )', - '( -2 x + 2 ) * ( -4 x )', - '( -2 x + 2 ) * ( -2 x )', - '( -2 x + 2 ) * 2 x', - '( -2 x + 2 ) * 4 x', - '( -2 x + 2 ) ( -4 x + 2 )', - '( -2 x + 2 ) ( -2 x + 2 )', - '( -2 x + 2 ) * 2', - '( -2 x + 2 ) ( 4 x + 2 )', - '( -2 x + 2 ) ( -2 x + 4 )', - '( -2 x + 2 ) * 4', - '( -2 x + 2 ) ( 2 x + 4 )', - '( - x + 2 ) ( -2 x - 4 )', - '( - x + 2 ) * ( -4 )', - '( - x + 2 ) ( 2 x - 4 )', - '( - x + 2 ) ( 4 x - 4 )', - '( - x + 2 ) ( -4 x - 2 )', - '( - x + 2 ) * ( -2 )', - '( - x + 2 ) ( 2 x - 2 )', - '( - x + 2 ) ( 4 x - 2 )', - '( - x + 2 ) * ( -4 x )', - '( - x + 2 ) * ( -2 x )', - '( - x + 2 ) * 2 x', - '( - x + 2 ) * 4 x', - '( - x + 2 ) ( -4 x + 2 )', - '( - x + 2 ) ( -2 x + 2 )', - '( - x + 2 ) * 2', - '( - x + 2 ) ( 4 x + 2 )', - '( - x + 2 ) ( -4 x + 4 )', - '( - x + 2 ) * 4', - '( - x + 2 ) ( 2 x + 4 )', - '2 ( -2 x - 4 )', - '2 * ( -4 )', - '2 ( 2 x - 4 )', - '2 ( 4 x - 4 )', - '2 ( -4 x - 2 )', - '2 * ( -2 )', - '2 ( 2 x - 2 )', - '2 ( 4 x - 2 )', - '2 * ( -4 x )', - '2 * ( -2 x )', - '2 * 2 x', - '2 * 4 x', - '2 ( -4 x + 2 )', - '2 ( -2 x + 2 )', - '2 * 2', - '2 ( 4 x + 2 )', - '2 ( -4 x + 4 )', - '2 ( -2 x + 4 )', - '2 ( 2 x + 4 )', - '( x + 2 ) ( -2 x - 4 )', - '( x + 2 ) * ( -4 )', - '( x + 2 ) ( 2 x - 4 )', - '( x + 2 ) ( 4 x - 4 )', - '( x + 2 ) ( -4 x - 2 )', - '( x + 2 ) * ( -2 )', - '( x + 2 ) ( 2 x - 2 )', - '( x + 2 ) ( 4 x - 2 )', - '( x + 2 ) * ( -4 x )', - '( x + 2 ) * ( -2 x )', - '( x + 2 ) * 2 x', - '( x + 2 ) * 4 x', - '( x + 2 ) ( -4 x + 2 )', - '( x + 2 ) ( -2 x + 2 )', - '( x + 2 ) * 2', - '( x + 2 ) ( 4 x + 2 )', - '( x + 2 ) ( -4 x + 4 )', - '( x + 2 ) ( -2 x + 4 )', - '( x + 2 ) * 4'] diff --git a/mapytex/calculus/test/test_arithmetic.py b/mapytex/calculus/test/test_arithmetic.py deleted file mode 100644 index e1a0410..0000000 --- a/mapytex/calculus/test/test_arithmetic.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -from mapytex.calculus import arithmetic - - -def test_gcd_commu(): - assert arithmetic.gcd(3, 15) == arithmetic.gcd(15, 3) - - -def test_gcd1(): - assert arithmetic.gcd(3, 15) == 3 - - -def test_gcd2(): - assert arithmetic.gcd(14, 21) == 7 - - -def test_gcd_prem(): - assert arithmetic.gcd(14, 19) == 1 - - -def test_gcd_neg(): - assert arithmetic.gcd(3, -15) == 3 - assert arithmetic.gcd(-3, -15) == -3 - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/test/test_expression.py b/mapytex/calculus/test/test_expression.py deleted file mode 100644 index dd1dbc4..0000000 --- a/mapytex/calculus/test/test_expression.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -""" Testing Expression """ - - -from mapytex.calculus.expression import Expression -from mapytex.calculus.operator import op - - -def test_init_from_str(): - exp = Expression("2 + 3") - assert exp.postfix_tokens == [2, 3, op.add] - - -def test_init_from_exp(): - pass - - -def test_init_list(): - exp = Expression([2, 3, "+"]) - assert exp.postfix_tokens == [2, 3, op.add] - - -def test_init_one_element_int_from_str(): - exp = Expression("1") - - -def test_init_one_element_int_from_list(): - exp = Expression([1]) - -# def test_init_one_element_str_from_str(): -# exp = Expression("x") -# -# def test_init_one_element_str_from_list(): -# exp = Expression(["x"]) - - -def test_simplify_exp(): - exp = Expression("1 + 2 * 3") - simplified = exp.simplify() - ans = Expression("7") - assert ans == simplified - -# def test_simplify_frac(): -# exp = Expression("1/2 - 4") -# simplified = exp.simplify() -# ans = Expression("-7/2") -# assert simplified == ans -# -# def test_explain_frac(): -# exp = Expression("1/2 - 4") -# simplified = exp.simplify() -# -# steps = ['\\frac{ 1 }{ 2 } - 4', \ -# '\\frac{ 1 \\times 1 }{ 2 \\times 1 } - \\frac{ 4 \\times 2 }{ 1 \\times 2 }',\ -# '\\frac{ 1 }{ 2 } - \\frac{ 8 }{ 2 }',\ -# '\\frac{ 1 - 8 }{ 2 }',\ -# '\\frac{ -7 }{ 2 }'] -# assert simplified.steps == list(exp.simplify()) - - -def test_add_exp(): - e = Expression("12- 4") - f = Expression("4 + 1") - g = e + f - assert g.postfix_tokens == [12, 4, op.sub, 4, 1, op.add, op.add] - - -def test_mul_exp(): - e = Expression("12- 4") - f = Expression("4 + 1") - g = e * f - assert g.postfix_tokens == [12, 4, op.sub, 4, 1, op.add, op.mul] - - -def test_neg_exp(): - e = Expression("12- 4") - g = -e - assert g.postfix_tokens == [12, 4, op.sub, op.sub1] - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/test/test_fraction.py b/mapytex/calculus/test/test_fraction.py deleted file mode 100644 index 2547440..0000000 --- a/mapytex/calculus/test/test_fraction.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - -import unittest - -from mapytex.calculus.fraction import Fraction - - -class TestFraction(unittest.TestCase): - """Testing functions from mapytex.calculus.Fraction""" - - def setUp(self): - self.listFrom = [Fraction(1, 3), 1] - self.listAgainst = [Fraction(1, 3), - Fraction(2, 3), - Fraction(4, 5), - Fraction(-1, 3), - Fraction(1, -3), - 1, - ] - - def test_add(self): - ans = [ - [ - Fraction( - 2, 3), 1, Fraction( - 17, 15), 0, 0, Fraction( - 4, 3)], [ - Fraction( - 4, 3), Fraction( - 5, 3), Fraction( - 9, 5), Fraction( - 2, 3), Fraction( - 2, 3), 2]] - - for (i, f1) in enumerate(self.listFrom): - for (j, f2) in enumerate(self.listAgainst): - res = f1 + f2 - self.assertEqual(res, ans[i][j]) - - def test_sub(self): - ans = [[0, Fraction(-1, 3), Fraction(-7, 15), Fraction(2, 3), Fraction(2, 3), Fraction(-2, 3)], - [Fraction(2, 3), Fraction(1, 3), Fraction(1, 5), Fraction(4, 3), Fraction(4, 3), 0] - ] - - for (i, f1) in enumerate(self.listFrom): - for (j, f2) in enumerate(self.listAgainst): - res = f1 - f2 - self.assertEqual(res, ans[i][j]) - - def test_neg(self): - ans = [Fraction(-1, 3), - Fraction(-2, 3), - Fraction(-4, 5), - Fraction(1, 3), - Fraction(1, 3), - -1 - ] - for (j, f) in enumerate(self.listAgainst): - res = -f - self.assertEqual(res, ans[j]) - - def test_mul(self): - ans = [[Fraction(1, 9), Fraction(2, 9), Fraction(4, 15), Fraction(-1, 9), Fraction(-1, 9), Fraction( - 1, 3)], [Fraction(1, 3), Fraction(2, 3), Fraction(4, 5), Fraction(-1, 3), Fraction(1, -3), 1]] - - for (i, f1) in enumerate(self.listFrom): - for (j, f2) in enumerate(self.listAgainst): - res = f1 * f2 - self.assertEqual(res, ans[i][j]) - - def test_truediv(self): - ans = [[1, Fraction(1, 2), Fraction(5, 12), -1, -1, Fraction(1, 3)], - [3, Fraction(3, 2), Fraction(5, 4), -3, -3, 1] - ] - - for (i, f1) in enumerate(self.listFrom): - for (j, f2) in enumerate(self.listAgainst): - res = f1 / f2 - self.assertEqual(res, ans[i][j]) - - def test_lt(self): - pass - - def test_le(self): - pass - - def test_tex(self): - f = Fraction(2, 3) - ans = "\\frac{ 2 }{ 3 }" - self.assertEqual(f.__tex__(), ans) - - def test_txt(self): - f = Fraction(2, 3) - ans = "2 / 3" - self.assertEqual(f.__txt__(), ans) - -if __name__ == '__main__': - unittest.main() - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/test/test_generic.py b/mapytex/calculus/test/test_generic.py deleted file mode 100644 index ec1d982..0000000 --- a/mapytex/calculus/test/test_generic.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -import unittest - -from mapytex.calculus import generic - - -class TestGeneric(unittest.TestCase): - """Testing functions from mapytex.calculus.generic""" - - def test_flatten_list1(self): - l = [1, [2, 3], [[4, 5], 6], 7] - flat_l = generic.flatten_list(l) - - true_flat = list(range(1, 8)) - - self.assertEqual(flat_l, true_flat) - - def test_flatten_list2(self): - l = list(range(10)) - flat_l = generic.flatten_list(l) - - true_flat = list(range(10)) - - self.assertEqual(flat_l, true_flat) - - def test_first_elem_simple_iter(self): - """ For simple iterable """ - l = range(10) - first = generic.first_elem(l) - - self.assertAlmostEqual(0, first) - - s = "plopplop" - first = generic.first_elem(s) - self.assertAlmostEqual("p", first) - - def test_first_elem_iter_in_iter(self): - """ Interable in iterable """ - l = [[1, 2], [4, 5, [6, 7, 8]], 9] - first = generic.first_elem(l) - - self.assertAlmostEqual(first, 1) - - l = [[[1]]] - first = generic.first_elem(l) - - self.assertAlmostEqual(first, 1) - - l = ["abc"] - first = generic.first_elem(l) - - self.assertAlmostEqual(first, "a") - - l = ["abc", [4, 5, [6, 7, 8]], 9] - first = generic.first_elem(l) - - self.assertAlmostEqual(first, "a") - - l = [["abc", 1], [4, 5, [6, 7, 8]], 9] - first = generic.first_elem(l) - - self.assertAlmostEqual(first, "a") - -if __name__ == '__main__': - unittest.main() - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/test/test_polynom.py b/mapytex/calculus/test/test_polynom.py deleted file mode 100644 index cf4f8e9..0000000 --- a/mapytex/calculus/test/test_polynom.py +++ /dev/null @@ -1,190 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -import unittest - -from mapytex.calculus.polynom import Polynom -from mapytex.calculus.fraction import Fraction -from mapytex.calculus.expression import Expression -from mapytex.calculus.render import txt -from mapytex.calculus.operator import op - - -class TestPolynom(unittest.TestCase): - """Testing functions from mapytex.calculus.polynom""" - - def setup(self): - Expression.set_render(txt) - - def test_init(self): - p = Polynom([1, 2, 3], "x") - - def test_init_multi(self): - p = Polynom([1, [2, 3], 4], "x") - - # def test_init_arith(self): - # p = Polynom([1, [2, 3, "+"], 4], "x") - - # def test_init_arith_2(self): - # p = Polynom([1, [[2, 3, "*"],3], 4], "x") - - def test_deg(self): - pass - - def test_eval_base(self): - p = Polynom([1, 2]) - self.assertEqual(p(3), 7) - - def test_eval_const(self): - p = Polynom([1]) - self.assertEqual(p(3), 1) - - def test_eval_const_neg(self): - p = Polynom([-1]) - self.assertEqual(p(3), -1) - - def test_eval_poly(self): - p = Polynom([1, 2]) - self.assertEqual(p("h+1"), Polynom([3, 2], "h")) - - def test_postfix(self): - p = Polynom([1, 2, 3]) - ans = [3, 'x', 2, op.pw, op.mul, 2, 'x', op.mul, op.add, 1, op.add] - self.assertEqual(ans, p.postfix_tokens) - - def test_postfix_monom(self): - p = Polynom([0, 2]) - ans = [2, "x", op.mul] - self.assertEqual(ans, p.postfix_tokens) - - def test_postfix_0_coef(self): - p = Polynom([0, 2, 0, 4]) - ans = [4, 'x', 3, op.pw, op.mul, 2, 'x', op.mul, op.add] - self.assertEqual(ans, p.postfix_tokens) - - def test_postfix_1_coef(self): - p = Polynom([0, 1, 1]) - ans = ["x", 2, op.pw, "x", op.add] - self.assertEqual(ans, p.postfix_tokens) - - def test_postfix_neg_coef(self): - p = Polynom([-1, -2, -3]) - ans = [-3, 'x', 2, op.pw, op.mul, -2, 'x', op.mul, op.add, -1, op.add] - self.assertEqual(ans, p.postfix_tokens) - - def test_postfix_multi_coef(self): - p = Polynom([1, [2, 3], 4]) - ans = [4, 'x', 2, op.pw, op.mul, 2, 'x', op.mul, op.add, 3, 'x', op.mul, op.add, 1, op.add] - self.assertEqual(ans, p.postfix_tokens) - - def test_postfix_exp_coef(self): - p = Polynom([1, Expression([2, 3, "+"]), 4]) - ans = [4, 'x', 2, op.pw, op.mul, 2, 3, op.add, 'x', op.mul, op.add, 1, op.add] - self.assertEqual(ans, p.postfix_tokens) - - def test_str(self): - p = Polynom([1, 2, 3]) - ans = '3 x^{ 2 } + 2 x + 1' - self.assertEqual(ans, str(p)) - - def test_str_monom(self): - p = Polynom([0, 2]) - ans = '2 x' - self.assertEqual(ans, str(p)) - - def test_str_0_coef(self): - p = Polynom([0, 2, 0, 4]) - ans = '4 x^{ 3 } + 2 x' - self.assertEqual(ans, str(p)) - - def test_str_1_coef(self): - p = Polynom([0, 1, 1]) - ans = 'x^{ 2 } + x' - self.assertEqual(ans, str(p)) - - def test_str_neg_coef(self): - p = Polynom([-1, -2, -3]) - ans = '-3 x^{ 2 } - 2 x - 1' - self.assertEqual(ans, str(p)) - - def test_str_multi_coef(self): - p = Polynom([1, [2, 3], 4]) - ans = '4 x^{ 2 } + 2 x + 3 x + 1' - self.assertEqual(ans, str(p)) - - def test_str_exp_coef(self): - p = Polynom([1, Expression([2, 3, "+"]), 4]) - ans = '4 x^{ 2 } + ( 2 + 3 ) x + 1' - self.assertEqual(ans, str(p)) - - def test_reduce_nilpo(self): - p = Polynom([1, 2, 3]) - self.assertEqual(p, p.reduce()) - - def test_reduce(self): - p = Polynom([1, [2, 3], 4]) - ans = '4 x^{ 2 } + 5 x + 1' - self.assertEqual(str(p.reduce()), ans) - - def test_add_int(self): - p = Polynom([1, 2, 3]) - q = p + 2 - ans = '3 x^{ 2 } + 2 x + 3' - self.assertEqual(str(q), ans) - - def test_add_frac(self): - p = Polynom([1, 2, 3]) - f = Fraction(1, 2) - q = p + f - ans = '3 x^{ 2 } + 2 x + \\frac{ 3 }{ 2 }' - self.assertEqual(str(q), ans) - - def test_add_poly(self): - p = Polynom([1, 0, 3]) - q = Polynom([0, 2, 3]) - r = p + q - ans = '6 x^{ 2 } + 2 x + 1' - self.assertEqual(str(r), ans) - - def test_sub_int(self): - p = Polynom([1, 2, 3]) - q = p - 2 - ans = '3 x^{ 2 } + 2 x - 1' - self.assertEqual(str(q), ans) - - def test_sub_frac(self): - p = Polynom([1, 2, 3]) - f = Fraction(1, 2) - q = p - f - ans = '3 x^{ 2 } + 2 x + \\frac{ 1 }{ 2 }' - self.assertEqual(str(q), ans) - - def test_sub_poly(self): - p = Polynom([1, 0, 2]) - q = Polynom([0, 2, 3]) - r = p - q - ans = '- x^{ 2 } - 2 x + 1' - self.assertEqual(str(r), ans) - - def test_pow_monome(self): - p = Polynom([0, -2]) - r = p**3 - ans = '-8 x^{ 3 }' - self.assertEqual(str(r), ans) - - def test_pow2_monome(self): - p = Polynom([0, -2]) - r = p ^ 3 - ans = '-8 x^{ 3 }' - self.assertEqual(str(r), ans) - - -if __name__ == '__main__': - unittest.main() - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/test/test_polynomDeg2.py b/mapytex/calculus/test/test_polynomDeg2.py deleted file mode 100644 index 7784770..0000000 --- a/mapytex/calculus/test/test_polynomDeg2.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -import unittest - -from mapytex.calculus.polynomDeg2 import Polynom_deg2 - - -class TestPolynomDeg2(unittest.TestCase): - """Testing functions from mapytex.calculus.polynomDeg2""" - - pass - - -if __name__ == '__main__': - unittest.main() - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/test/test_random_expression.py b/mapytex/calculus/test/test_random_expression.py deleted file mode 100644 index f383a97..0000000 --- a/mapytex/calculus/test/test_random_expression.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -from mapytex.calculus.random_expression import RdExpression - - -def test_only_form(): - form = "{a} + 2" - rdExp = RdExpression(form) - - assert rdExp._letters == {'a'} - assert rdExp._2replaced == {'a'} - - rdExp() - assert set(rdExp._gene_varia.keys()) == {'a'} - assert set(rdExp._gene_2replaced.keys()) == {'a'} - - -def test_form_with_underscores(): - form = "_ + 2*_" - rdExp = RdExpression(form) - - assert rdExp._letters == {'A', 'B'} - assert rdExp._2replaced == {'A', 'B'} - - rdExp() - assert set(rdExp._gene_varia.keys()) == {'A', 'B'} - assert set(rdExp._gene_2replaced.keys()) == {'A', 'B'} - - -def test_only_form_calc(): - form = "{a+b} + 2" - rdExp = RdExpression(form) - - assert rdExp._letters, {'a' == 'b'} - assert rdExp._2replaced == {'a+b'} - - rdExp() - assert set(rdExp._gene_varia.keys()), {'a' == 'b'} - assert set(rdExp._gene_2replaced.keys()) == {'a+b'} - - -def test_only_form_cond(): - form = "{a} + 2" - cond = ["{a} == 3"] - rdExp = RdExpression(form, cond) - - assert rdExp._letters == {'a'} - assert rdExp._2replaced == {'a'} - - rdExp() - assert set(rdExp._gene_varia.keys()) == {'a'} - assert set(rdExp._gene_2replaced.keys()) == {'a'} - - assert rdExp._gene_varia['a'] == 3 - - -def test_only_form_conds(): - form = "{a} + 2" - cond = ["{a} in list(range(5))", "{a} % 2 == 1"] - rdExp = RdExpression(form, cond) - - assert rdExp._letters == {'a'} - assert rdExp._2replaced == {'a'} - - rdExp() - assert set(rdExp._gene_varia.keys()) == {'a'} - assert set(rdExp._gene_2replaced.keys()) == {'a'} - - assert rdExp._gene_varia['a'] in list(range(5)) - assert rdExp._gene_varia['a'] % 2 == 1 - - -def test_only_form_calc_cond(): - form = "{a*3} * {b}" - cond = ["{a} == 3"] - rdExp = RdExpression(form, cond) - - assert rdExp._letters, {'a' == 'b'} - assert rdExp._2replaced, {'a', 'b' == 'a*3'} - - rdExp() - assert set(rdExp._gene_varia.keys()), {'a' == 'b'} - assert set(rdExp._gene_2replaced.keys()), {'a', 'b' == 'a*3'} - - assert rdExp._gene_varia['a'] == 3 - - -def test_only_form_calc_cond_calc(): - form = "{a*3} * {b}" - cond = ["{a+b} == 3"] - rdExp = RdExpression(form, cond) - - assert rdExp._letters, {'a' == 'b'} - assert rdExp._2replaced, {'b', 'a*3' == 'a+b'} - - rdExp() - assert set(rdExp._gene_varia.keys()), {'a' == 'b'} - assert set(rdExp._gene_2replaced.keys()), {'b', 'a*3' == 'a+b'} - - assert (rdExp._gene_varia['a'] + rdExp._gene_varia['b']) == 3 - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/test/test_render.py b/mapytex/calculus/test/test_render.py deleted file mode 100644 index 51ba472..0000000 --- a/mapytex/calculus/test/test_render.py +++ /dev/null @@ -1,310 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -import unittest - -from mapytex.calculus.render import tex, txt -from mapytex.calculus.fraction import Fraction -from mapytex.calculus.polynom import Polynom -from mapytex.calculus.operator import op -from mapytex.calculus.expression import Expression - -from itertools import permutations - - -def mass_poly_test(operation, rg=5): - """ @todo - - :op: the operation - :rg: number of potential values for coefs - :returns: @todo - """ - coefs_p = [[(i - 2), (j - 2)] for i, j in permutations(range(rg), 2)] - coefs_q = [[2 * (i - 2), 2 * (j - 2)] - for i, j in permutations(range(rg), 2)] - l_p = [Polynom(i) for i in coefs_p] - l_q = [Polynom(i) for i in coefs_q] - return [Expression([l_p[i], l_q[j], op.get_op(operation)]) - for i, j in permutations(range(len(coefs_p)), 2)] - - -class TestTexRender(unittest.TestCase): - """Testing functions from mapytex.calculus.renders.tex""" - - def test_type_render_int(self): - self.assertEqual(tex([2]), "2") - - def test_type_render_str(self): - self.assertEqual(tex(["a"]), "a") - - def test_type_render_float(self): - self.assertEqual(tex([12.345]), "12.345") - - def test_type_render_fraction(self): - self.assertEqual(tex([Fraction(1, 2)]), "\\frac{ 1 }{ 2 }") - - def test_type_render_poly(self): - P = Polynom([1, 2, 3]) - self.assertEqual(tex([P]), "3 x^{ 2 } + 2 x + 1") - - def test_add_interger(self): - exps = [[2, 3, op.add], - [2, -3, op.add], - [-2, 3, op.add], - ] - wanted_render = ["2 + 3", - "2 - 3", - "-2 + 3", - ] - for (i, e) in enumerate(exps): - rend = tex(e) - self.assertEqual(rend, wanted_render[i]) - - def test_mass_add(self): - permu = mass_poly_test("+", 5) - from .mass_test import POLY_ADD_VALID_RESULTS - for (i, v) in enumerate(permu): - self.assertEqual(tex(v), POLY_ADD_VALID_RESULTS[i]) - - def test_mass_sub(self): - permu = mass_poly_test("-", 5) - from .mass_test import POLY_SUB_VALID_RESULTS - for (i, v) in enumerate(permu): - self.assertEqual(tex(v), POLY_SUB_VALID_RESULTS[i]) - - def test_mass_mul(self): - permu = mass_poly_test("*", 5) - from .mass_test import TEX_POLY_MUL_VALID_RESULTS - for (i, v) in enumerate(permu): - self.assertEqual(tex(v), TEX_POLY_MUL_VALID_RESULTS[i]) - - def test_add_letter(self): - exps = [[2, "a", op.add], - ["a", 3, op.add], - [-2, "a", op.add], - ["a", -2, op.add], - ] - wanted_render = ["2 + a", - "a + 3", - "-2 + a", - "a - 2", - ] - for (i, e) in enumerate(exps): - rend = tex(e) - self.assertEqual(rend, wanted_render[i]) - - def test_add_fraction(self): - exps = [[2, Fraction(1, 2), op.add], - [Fraction(1, 2), 3, op.add], - ] - wanted_render = ["2 + \\frac{ 1 }{ 2 }", - "\\frac{ 1 }{ 2 } + 3", - ] - for (i, e) in enumerate(exps): - rend = tex(e) - self.assertEqual(rend, wanted_render[i]) - - def test_add_poly(self): - exps = [[2, Polynom([1, 2, 3]), op.mul], - [Polynom([1, 2, 3]), 2, op.mul], - [Polynom([1, 2, 3]), Polynom([4, 5, 6]), op.mul], - ] - wanted_render = ["2 ( 3 x^{ 2 } + 2 x + 1 )", - "( 3 x^{ 2 } + 2 x + 1 ) \\times 2", - "( 3 x^{ 2 } + 2 x + 1 ) ( 6 x^{ 2 } + 5 x + 4 )", - ] - for (i, e) in enumerate(exps): - rend = tex(e) - self.assertEqual(rend, wanted_render[i]) - - def test_mult_interger(self): - exps = [[2, 3, op.mul], - [2, -3, op.mul], - [-2, 3, op.mul], - ] - wanted_render = ["2 \\times 3", - "2 \\times ( -3 )", - "-2 \\times 3", - ] - for (i, e) in enumerate(exps): - rend = tex(e) - self.assertEqual(rend, wanted_render[i]) - - def test_mult_letter(self): - exps = [[2, "a", op.mul], - ["a", 3, op.mul], - [-2, "a", op.mul], - ["a", -2, op.mul], - ] - wanted_render = ["2 a", "a \\times 3", "-2 a", "a \\times ( -2 )"] - for (i, e) in enumerate(exps): - rend = tex(e) - self.assertEqual(rend, wanted_render[i]) - - def test_mult_fraction(self): - exps = [[2, Fraction(1, 2), op.mul], [Fraction(1, 2), 3, op.mul]] - wanted_render = [ - "2 \\times \\frac{ 1 }{ 2 }", - "\\frac{ 1 }{ 2 } \\times 3"] - for (i, e) in enumerate(exps): - rend = tex(e) - self.assertEqual(rend, wanted_render[i]) - - def test_mult_poly(self): - exps = [[2, Polynom([1, 2, 3]), op.mul], - [Polynom([1, 2, 3]), 2, op.mul], - [Polynom([1, 2, 3]), Polynom([4, 5, 6]), op.mul], - ] - wanted_render = ["2 ( 3 x^{ 2 } + 2 x + 1 )", - "( 3 x^{ 2 } + 2 x + 1 ) \\times 2", - "( 3 x^{ 2 } + 2 x + 1 ) ( 6 x^{ 2 } + 5 x + 4 )", - ] - for (i, e) in enumerate(exps): - rend = tex(e) - self.assertEqual(rend, wanted_render[i]) - - def test_parentheses_int(self): - exps = [ - [2, 3, op.add, 4, op.mul], - [2, 3, op.mul, 4, op.add], - [2, 3, 4, op.mul, op.add], - [2, 3, 4, op.add, op.add], - [2, 3, 4, op.add, op.sub], - ] - wanted_render = [ - '( 2 + 3 ) \\times 4', - '2 \\times 3 + 4', - '2 + 3 \\times 4', - '2 + 3 + 4', - '2 - ( 3 + 4 )', - ] - for (i, e) in enumerate(exps): - rend = tex(e) - self.assertEqual(rend, wanted_render[i]) - - def test_parentheses_poly(self): - P = Polynom([1, 2, 3]) - Q = Polynom([4, 5, 6]) - exps = [ - [2, P, op.add], - [2, P, op.sub], - [2, P, P, op.mul, op.sub], - [Q, P, op.add], - [Q, P, op.sub], - ] - wanted_render = [ - '2 + 3 x^{ 2 } + 2 x + 1', - '2 - ( 3 x^{ 2 } + 2 x + 1 )', - '2 - ( 3 x^{ 2 } + 2 x + 1 ) ( 3 x^{ 2 } + 2 x + 1 )', - '6 x^{ 2 } + 5 x + 4 + 3 x^{ 2 } + 2 x + 1', - '6 x^{ 2 } + 5 x + 4 - ( 3 x^{ 2 } + 2 x + 1 )', - ] - for (i, e) in enumerate(exps): - rend = tex(e) - self.assertEqual(rend, wanted_render[i]) - - def test_slash(self): - pass - - -class TesttxtRender(unittest.TestCase): - """Testing functions from mapytex.calculus.renders.txt""" - - def test_type_render_int(self): - self.assertEqual(txt([2]), "2") - - def test_type_render_str(self): - self.assertEqual(txt(["a"]), "a") - - def test_type_render_float(self): - self.assertEqual(txt([12.345]), "12.345") - - def test_type_render_fraction(self): - self.assertEqual(txt([Fraction(1, 2)]), "1 / 2") - - def test_mult_interger(self): - exps = [[2, 3, op.mul], - [2, -3, op.mul], - [-2, 3, op.mul]] - wanted_render = ["2 * 3", "2 * ( -3 )", "-2 * 3"] - for (i, e) in enumerate(exps): - rend = txt(e) - self.assertEqual(rend, wanted_render[i]) - - def test_mult_letter(self): - exps = [[2, "a", op.mul], - ["a", 3, op.mul], - [-2, "a", op.mul], - ["a", -2, op.mul], - ["a", -2, op.mul, -2, op.mul], - ["a", -2, op.mul, "a", op.mul], - ] - wanted_render = ["2 a", - "a * 3", - "-2 a", - "a * ( -2 )", - "a * ( -2 ) * ( -2 )", - "a * ( -2 ) a", - ] - for (i, e) in enumerate(exps): - rend = txt(e) - self.assertEqual(rend, wanted_render[i]) - - def test_mult_fraction(self): - exps = [[2, Fraction(1, 2), op.mul], - [Fraction(1, 2), 3, op.mul]] - wanted_render = ["2 * 1 / 2", "1 / 2 * 3"] - for (i, e) in enumerate(exps): - rend = txt(e) - self.assertEqual(rend, wanted_render[i]) - - def test_parentheses(self): - mul = op.get_op("*", 2) - add = op.get_op("+", 2) - exps = [ - [2, 3, add, 4, mul], - [2, 3, mul, 4, add], - [2, 3, 4, mul, add], - [2, 3, 4, add, add], - ] - wanted_render = [ - '( 2 + 3 ) * 4', - '2 * 3 + 4', - '2 + 3 * 4', - '2 + 3 + 4', - ] - for (i, e) in enumerate(exps): - rend = txt(e) - self.assertEqual(rend, wanted_render[i]) - - def test_slash(self): - pass - - def test_mass_add(self): - permu = mass_poly_test("+", 5) - from .mass_test import POLY_ADD_VALID_RESULTS - for (i, v) in enumerate(permu): - self.assertEqual(txt(v), POLY_ADD_VALID_RESULTS[i]) - - def test_mass_sub(self): - permu = mass_poly_test("-", 5) - from .mass_test import POLY_SUB_VALID_RESULTS - for (i, v) in enumerate(permu): - self.assertEqual(txt(v), POLY_SUB_VALID_RESULTS[i]) - - def test_mass_mul(self): - permu = mass_poly_test("*", 5) - from .mass_test import TXT_POLY_MUL_VALID_RESULTS - for (i, v) in enumerate(permu): - self.assertEqual(txt(v), TXT_POLY_MUL_VALID_RESULTS[i]) - - -if __name__ == '__main__': - unittest.main() - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del diff --git a/mapytex/calculus/test/test_str2tokens.py b/mapytex/calculus/test/test_str2tokens.py deleted file mode 100644 index 66a7d22..0000000 --- a/mapytex/calculus/test/test_str2tokens.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python -# encoding: utf-8 - - -import unittest - -from mapytex.calculus.str2tokens import str2tokens, str2in_tokens, in2post_fix -from mapytex.calculus.polynom import Polynom -from mapytex.calculus.operator import op - - -class TestStr2tokens(unittest.TestCase): - """Testing functions from mapytex.calculus.str2tokens""" - - def test_str2in_tokens(self): - ans = str2in_tokens("2+3*4") - self.assertEqual(ans, [2, "+", 3, "*", 4]) - - ans = str2in_tokens("2*3+4") - self.assertEqual(ans, [2, "*", 3, "+", 4]) - - from decimal import Decimal - ans = str2in_tokens("2.34") - self.assertEqual(ans, [Decimal('2.34')]) - - def test_in2post_fix(self): - in_tokens = str2in_tokens("2+3*4") - ans = in2post_fix(in_tokens) - self.assertEqual(ans, [2, 3, 4, op.mul, op.add]) - - in_tokens = str2in_tokens("2*3+4") - ans = in2post_fix(in_tokens) - self.assertEqual(ans, [2, 3, op.mul, 4, op.add]) - - def test_str2in_tokens_big_num(self): - exp = "123 + 3" - tok = str2in_tokens(exp) - self.assertEqual(tok, [123, "+", 3]) - - def test_str2in_tokens_beg_minus(self): - exp = "-123 + 3" - tok = str2in_tokens(exp) - self.assertEqual(tok, [-123, "+", 3]) - - def test_str2in_tokens_time_lack(self): - exp = "(-3)(2)" - tok = str2in_tokens(exp) - self.assertEqual(tok, ["(", -3, ")", "*", "(", 2, ")"]) - - def test_str2tokens_poly(self): - exp = "2x + 4" - post = str2in_tokens(exp) - self.assertEqual(post, [2, "*", Polynom([0, 1]), '+', 4]) - - def test_str2tokens_poly_double_x(self): - exp = "xx + 4" - post = str2in_tokens(exp) - self.assertEqual(post, [Polynom([0, 1]), "*", Polynom([0, 1]), '+', 4]) - - def test_str2tokens_poly_par(self): - exp = "x(2+1) + 4" - post = str2in_tokens(exp) - self.assertEqual(post, [Polynom([0, 1]), "*", - "(", 2, "+", 1, ')', '+', 4]) - - def test_str2in_tokens_time_lack2(self): - exp = "-3(2)" - tok = str2in_tokens(exp) - self.assertEqual(tok, [-3, "*", "(", 2, ")"]) - - def test_str2tokens_error(self): - exp = "1 + $" - self.assertRaises(ValueError, str2tokens, exp) - - -if __name__ == '__main__': - unittest.main() - - -# ----------------------------- -# Reglages pour 'vim' -# vim:set autoindent expandtab tabstop=4 shiftwidth=4: -# cursor: 16 del