#! /usr/bin/env python # -*- coding: utf-8 -*- # vim:fenc=utf-8 # # Copyright © 2017 lafrite # # Distributed under terms of the MIT license. """ Expression """ from ..core import AssocialTree, Tree, compute, typing from .renders import renders class Expression(object): """ Expression class :example: >>> e = Expression.from_str("2+3*4") >>> e2 = e.simplify() >>> print(e2) 14 >>> for s in e2.explain(): ... print(s) 2 + 3 * 4 2 + 12 14 """ RENDER = 'txt' def __init__(self, tree, ancestor=None): """ """ self._tree = tree self._ancestor = ancestor @classmethod def from_str(cls, string): """ Initiate the expression from a string :param string: String to parse to generate the Expression :returns: the expression """ t = Tree.from_str(string) return cls(t) @classmethod def random(self, template, conditions = [], shuffle = False): """ Initiate randomly the expression :param template: the template of the expression :param conditions: conditions on randomly generate variable :param shuffle: allowing to shuffle the tree :returns: TODO """ pass @classmethod def set_render(cls, render): """ Define default render function :param render: render function Tree -> str :example: >>> Expression.RENDER 'txt' >>> e = Expression.from_str("2+3*4") >>> print(e) 2 + 3 * 4 >>> Expression.set_render('tex') >>> Expression.RENDER 'tex' >>> print(e) 2 + 3 \\times 4 """ cls.RENDER = render def __str__(self): return renders[self.RENDER](self._tree) def __repr__(self): return f"" def simplify(self, optimize=True): """ Compute as much as possible the expression :param optimize: bool to optimize tree when it's possible :return: an expression :example: >>> e = Expression.from_str("2+3*4") >>> e >>> f = e.simplify() >>> f >>> f._ancestor """ if optimize: try: self._tree = self._tree.balance() except AttributeError: pass try: t = self._tree.apply_on_last_level(compute, typing) except AttributeError: return self except NotImplementedError: return self else: e = Expression(t, ancestor=self) return e.simplify(optimize=optimize) def explain(self): """ Yield every calculus step which have lead to self :example: >>> e = Expression.from_str("2+3*4") >>> f = e.simplify() >>> for s in f.explain(): ... print(s) 2 + 3 * 4 2 + 12 14 >>> e = Expression.from_str("1+2+3+4+5+6+7+8+9") >>> f = e.simplify() >>> for s in f.explain(): ... print(s) 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 3 + 3 + 9 + 6 + 7 + 17 6 + 9 + 6 + 24 15 + 30 45 >>> e = Expression.from_str("1+2+3+4+5+6+7+8+9") >>> f_no_balance = e.simplify(optimize=False) >>> for s in f_no_balance.explain(): ... print(s) 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 3 + 3 + 4 + 5 + 6 + 7 + 8 + 9 6 + 4 + 5 + 6 + 7 + 8 + 9 10 + 5 + 6 + 7 + 8 + 9 15 + 6 + 7 + 8 + 9 21 + 7 + 8 + 9 28 + 8 + 9 36 + 9 45 >>> e = Expression.from_str("1+2+3+4+5*6*7*8*9") >>> f = e.simplify() >>> for s in f.explain(): ... print(s) 1 + 2 + 3 + 4 + 5 * 6 * 7 * 8 * 9 3 + 3 + 4 + 30 * 7 * 72 6 + 4 + 210 * 72 10 + 15120 15130 >>> e = Expression.from_str("1+2+3+4+5*6*7*8*9") >>> f_no_balance = e.simplify(optimize=False) >>> for s in f_no_balance.explain(): ... print(s) 1 + 2 + 3 + 4 + 5 * 6 * 7 * 8 * 9 3 + 3 + 4 + 30 * 7 * 8 * 9 6 + 4 + 210 * 8 * 9 10 + 1680 * 9 10 + 15120 15130 """ try: yield from self._ancestor.explain() except AttributeError: yield self else: yield self # ----------------------------- # Reglages pour 'vim' # vim:set autoindent expandtab tabstop=4 shiftwidth=4: # cursor: 16 del