Change names and pass tests

This commit is contained in:
Benjamin Bertrand
2017-04-17 16:48:52 +03:00
parent 30a6402e40
commit 500426bf82
54 changed files with 103 additions and 87 deletions

View File

@@ -0,0 +1,12 @@
#!/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

View File

@@ -0,0 +1,70 @@
#!/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

View File

@@ -0,0 +1,61 @@
#!/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

View File

@@ -0,0 +1,121 @@
#!/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

View File

@@ -0,0 +1,234 @@
#!/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

View File

@@ -0,0 +1,129 @@
#!/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 <class 'str'>
"""
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

View File

@@ -0,0 +1,26 @@
#!/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

View File

@@ -0,0 +1,87 @@
#!/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

View File

@@ -0,0 +1,69 @@
#!/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

View File

@@ -0,0 +1,64 @@
#!/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