move postfix_op (or corr) and remove unneeded 1 in fractions

This commit is contained in:
Benjamin Bertrand 2016-02-14 18:34:32 +03:00
parent 29a25203c2
commit c6ee2f2140
3 changed files with 50 additions and 44 deletions

View File

@ -4,9 +4,8 @@
from .explicable import Explicable from .explicable import Explicable
from .expression import Expression from .expression import Expression
from .operator import op from .operator import op
from .generic import spe_zip, expand_list, isNumber, transpose_fill, flatten_list, isPolynom, isNumerand from .generic import spe_zip, expand_list, isNumber, transpose_fill, flatten_list, isPolynom, isNumerand, postfix_op
from .render import txt, tex from .render import txt, tex
from itertools import chain
from functools import wraps from functools import wraps
@ -340,7 +339,7 @@ class AbstractPolynom(Explicable):
coef_steps += s coef_steps += s
# Convert last element into postfix addition. # Convert last element into postfix addition.
postfix_add = self.postfix_add([i for i in last if i != 0]) postfix_add = postfix_op([i for i in last if i != 0], op.add)
# Convert it to an expression # Convert it to an expression
coef_exp = Expression(postfix_add) coef_exp = Expression(postfix_add)
@ -376,33 +375,6 @@ class AbstractPolynom(Explicable):
"""Same as reduce """ """Same as reduce """
return self.reduce() return self.reduce()
@staticmethod
def postfix_add(numbers):
"""Convert a list of numbers into a postfix addition
:numbers: list of numbers
:returns: Postfix list of succecive attition of number
>>> AbstractPolynom.postfix_add([1])
[1]
>>> AbstractPolynom.postfix_add([1, 2])
[1, 2, '+']
>>> AbstractPolynom.postfix_add([1, 2, 3])
[1, 2, '+', 3, '+']
>>> AbstractPolynom.postfix_add(1)
[1]
>>> AbstractPolynom.postfix_add([])
[0]
"""
if not isinstance(numbers, list):
return [numbers]
elif numbers == []:
return [0]
else:
ans = [[a, op.add] if i != 0 else [a]
for (i, a) in enumerate(numbers)]
return list(chain.from_iterable(ans))
def __eq__(self, other): def __eq__(self, other):
try: try:
o_poly = self.conv2poly(other) o_poly = self.conv2poly(other)

View File

@ -2,7 +2,7 @@
# encoding: utf-8 # encoding: utf-8
from .arithmetic import gcd from .arithmetic import gcd
from .generic import isNumber from .generic import isNumber, postfix_op
from .operator import op from .operator import op
from .expression import Expression from .expression import Expression
from .explicable import Explicable from .explicable import Explicable
@ -309,22 +309,23 @@ class Fraction(Explicable):
< Fraction 1 / 3> < Fraction 1 / 3>
>>> print("\\n".join([repr(i) for i in (f*g).steps])) >>> print("\\n".join([repr(i) for i in (f*g).steps]))
< <class 'pymath.calculus.expression.Expression'> [< Fraction 1 / 2>, < Fraction 2 / 3>, '*'] > < <class 'pymath.calculus.expression.Expression'> [< Fraction 1 / 2>, < Fraction 2 / 3>, '*'] >
< <class 'pymath.calculus.expression.Expression'> [1, 2, '*', 2, 3, '*', '/'] > < <class 'pymath.calculus.expression.Expression'> [1, 2, '*', 2, 3, '*', '/'] >
< <class 'pymath.calculus.expression.Expression'> [1, 3, '/'] > < <class 'pymath.calculus.expression.Expression'> [1, 3, '/'] >
>>> f * 0 >>> f * 0
0 0
>>> (f*0).steps >>> (f*0).steps
[] [< <class 'pymath.calculus.expression.Expression'> [< Fraction 1 / 2>, 0, '*'] >]
>>> f*1 >>> f*1
< Fraction 1 / 2> < Fraction 1 / 2>
>>> (f*1).steps >>> (f*1).steps
[] [< <class 'pymath.calculus.expression.Expression'> [< Fraction 1 / 2>, 1, '*'] >]
>>> f*4 >>> f*4
2 2
>>> print("\\n".join([repr(i) for i in (f*4).steps])) >>> print("\\n".join([repr(i) for i in (f*4).steps]))
< <class 'pymath.calculus.expression.Expression'> [1, 2, '/', 4, '*'] > < <class 'pymath.calculus.expression.Expression'> [< Fraction 1 / 2>, 4, '*'] >
< <class 'pymath.calculus.expression.Expression'> [1, 2, '*', 2, '*', 1, 2, '*', '/'] > < <class 'pymath.calculus.expression.Expression'> [1, 2, '*', 2, '*', 1, 2, '*', '/'] >
< <class 'pymath.calculus.expression.Expression'> [2, 2, '*', 2, '/'] > < <class 'pymath.calculus.expression.Expression'> [1, 2, '*', 1, '/'] >
< <class 'pymath.calculus.expression.Expression'> [2, 1, '/'] >
""" """
steps = [Expression([self, other, op.mul])] steps = [Expression([self, other, op.mul])]
@ -359,8 +360,8 @@ class Fraction(Explicable):
num1_s = [gcd1] + [int(self._num / gcd1), op.mul] * (int(self._num / 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) denom2_s = [gcd1] + [int(number._denom / gcd1), op.mul] * (int(number._denom / gcd1) != 1)
num1 = [int(self._num / gcd1)] num1 = [int(self._num / gcd1)] * (int(self._num / gcd1) != 1)
denom2 = [int(number._denom / gcd1)] denom2 = [int(number._denom / gcd1)] * (int(self._denom / gcd1) != 1)
else: else:
num1_s = [self._num] num1_s = [self._num]
denom2_s = [number._denom] denom2_s = [number._denom]
@ -373,8 +374,8 @@ class Fraction(Explicable):
num2_s = [gcd2] + [int(number._num / gcd2), op.mul] * (int(number._num / 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) denom1_s = [gcd2] + [int(self._denom / gcd2), op.mul] * (int(self._denom / gcd2) != 1)
num2 = [int(number._num / gcd2)] num2 = [int(number._num / gcd2)] * (int(number._num / gcd2) != 1)
denom1 = [int(self._denom / gcd2)] denom1 = [int(self._denom / gcd2)] * (int(number._denom / gcd2) != 1)
else: else:
num2_s = [number._num] num2_s = [number._num]
denom1_s = [self._denom] denom1_s = [self._denom]
@ -382,12 +383,12 @@ class Fraction(Explicable):
num2 = [number._num] num2 = [number._num]
denom1 = [self._denom] denom1 = [self._denom]
# TODO: Pour enlever encore des *1, il faudrait réutililser postfix_add de Abstract_polynom et le mettre dans générique en postfix_op. Et mettre une liste vide quand num ou denom est égal à 1 |dim. févr. 14 17:51:41 EAT 2016
steps.append(Expression(num1_s + num2_s + [op.mul] + \ steps.append(Expression(num1_s + num2_s + [op.mul] + \
denom1_s + denom2_s + [op.mul, op.div])) denom1_s + denom2_s + [op.mul, op.div]))
exp = Expression(num1 + num2 + [op.mul] + exp = Expression(postfix_op(num1 + num2, op.mul, 1) +
denom1 + denom2 + [op.mul, op.div]) postfix_op(denom1 + denom2, op.mul, 1) +
[op.div])
ans = exp.simplify() ans = exp.simplify()
ans.steps = steps + ans.steps ans.steps = steps + ans.steps

View File

@ -2,7 +2,7 @@
# encoding: utf-8 # encoding: utf-8
from itertools import zip_longest from itertools import zip_longest, chain
class Stack(object): class Stack(object):
@ -287,6 +287,39 @@ def transpose_fill(list_lists):
yield col 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): def isOperator(exp):
"""Check if the expression is an opération in "+-*/:^" """Check if the expression is an opération in "+-*/:^"