Mapytex/pymath/calculus/explicable.py

226 lines
6.5 KiB
Python
Raw Normal View History

#!/usr/bin/env python
# encoding: utf-8
2016-02-13 08:24:31 +00:00
from .render import Renderable
2016-02-15 12:20:24 +00:00
from decimal import Decimal
from .generic import transpose_fill
2015-04-21 16:10:14 +00:00
2016-02-13 03:29:26 +00:00
2015-02-27 16:46:16 +00:00
class Explicable(Renderable):
""" An Explicable object is an object which can be explicable!
2016-02-13 03:29:26 +00:00
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
2016-02-13 03:29:26 +00:00
"""
2016-02-13 04:04:08 +00:00
def __init__(self, *args, **kwargs):
2016-02-13 08:24:31 +00:00
super(Explicable, self).__init__()
self.steps = []
2016-03-07 08:01:57 +00:00
self.explainator = 0
2016-03-07 08:01:57 +00:00
def explain(self):
r""" Generate and render steps which leed to itself
2016-02-13 03:29:26 +00:00
2016-03-07 08:01:57 +00:00
After beening explained, the Explicable become amnesiac.
See 'history_generator' to explain it once again.
>>> action = Explicable()
>>> from .expression import Expression
>>> action.postfix_tokens = Expression('42')
>>> 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
2016-03-07 08:01:57 +00:00
>>> # Now action is amnesiac
>>> for i in action.explain():
... print(i)
"""
if not self.explainator:
self.explainator = self.history_generator()
return self.explainator
2016-03-06 15:18:01 +00:00
2016-03-07 08:01:57 +00:00
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()
>>> from .expression import Expression
>>> action.postfix_tokens = Expression('42')
>>> for i in action.history_generator():
... print(i)
42
2016-03-07 08:01:57 +00:00
>>> 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
"""
old_s = ''
try:
for s in self.steps:
2016-02-13 08:24:31 +00:00
try:
2015-02-27 17:02:27 +00:00
new_s = self.STR_RENDER(s.postfix_tokens)
2016-02-13 08:24:31 +00:00
except AttributeError:
2015-02-27 17:02:27 +00:00
new_s = self.STR_RENDER(s)
2016-02-13 08:24:31 +00:00
if not self.is_same_step(new_s, old_s):
old_s = new_s
yield new_s
2016-02-13 08:24:31 +00:00
except AttributeError:
pass
2016-03-07 08:01:57 +00:00
# if noself:
new_s = self.STR_RENDER(self.postfix_tokens)
if not self.is_same_step(new_s, old_s):
yield new_s
def is_same_step(self, new, old):
"""Return whether the new step is the same than old step
"""
try:
if new.replace(" ", "") == old.replace(" ", ""):
return True
else:
return False
except AttributeError:
if new == old:
return True
else:
return False
def this_append_before(self, steps):
""" Add steps at the beginning of self.steps
:param steps: list of steps that append before
>>> e = Explicable()
>>> 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 = steps + self.steps
@staticmethod
def merge_history(expl1, expl2, operation):
2016-03-07 07:00:41 +00:00
r""" Take two Explicable objects, explain where they are from and merge their history
This method try to use 'explain' method from expl1 and expl2. This means that after using this method, those two objects will become amnesiac.
:param expl1: fist explicable
:param expl2: second explicable
:param operation: the operation that link them
:returns: the list of steps
>>> from .expression import Expression
>>> from .operator import op
>>> action1 = Explicable()
>>> action1.postfix_tokens = Expression('42')
>>> action1.this_append_before([Expression('2+10*4'), Expression('2+40')])
>>> action2 = Explicable()
>>> action2.postfix_tokens = Expression('24')
>>> action2.this_append_before([Expression('2*12')])
>>> m_history = Explicable().merge_history(action1, action2, op.add)
>>> m_history
<generator object transpose_fill ...>
>>> for i in m_history:
... print(i)
['2 + 10 \\times 4', '2 \\times 12', +]
['2 + 40', '24', +]
['42', '24', +]
>>> for i in action1.explain():
... print(i)
>>> action1 = Explicable()
>>> action1.postfix_tokens = Expression('42')
>>> action1.this_append_before([Expression('2+10*4'), Expression('2+40')])
>>> m_history = Explicable().merge_history(action1, 12, op.add)
>>> m_history
<generator object transpose_fill ...>
>>> for i in m_history:
... print(i)
['2 + 10 \\times 4', 12, +]
['2 + 40', 12, +]
['42', 12, +]
"""
try:
steps1 = list(expl1.explain())
except AttributeError:
steps1 = [expl1]
try:
steps2 = list(expl2.explain())
except AttributeError:
steps2 = [expl2]
return transpose_fill([steps1, steps2, [operation]])
2016-03-06 15:18:01 +00:00
2016-02-13 08:24:31 +00:00
class Explicable_int(int, Explicable):
2016-03-06 15:18:01 +00:00
""" An Explicable_int is an int which can be explain """
2016-03-06 15:18:01 +00:00
2016-02-13 08:24:31 +00:00
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)
2016-03-06 15:18:01 +00:00
2016-02-15 12:20:24 +00:00
class Explicable_Decimal(Decimal, Explicable):
2016-03-06 15:18:01 +00:00
2016-02-15 12:20:24 +00:00
""" An Explicable_Decimal is an decimal which can be explain """
2016-03-06 15:18:01 +00:00
isNumber = True
def __init__(self, val):
2016-02-15 12:20:24 +00:00
super(Explicable_Decimal, self).__init__(val)
self._val = val
self.postfix_tokens = [self]
self.steps = []
def simplify(self):
2016-02-15 12:20:24 +00:00
return Explicable_Decimal(self._val)
def __txt__(self):
return str(self._val)
def __tex__(self):
return str(self._val)
2016-02-13 08:24:31 +00:00
# -----------------------------
# Reglages pour 'vim'
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
2016-02-13 03:29:26 +00:00
# cursor: 16 del