From c8b06176bf6a661e406a908f053646657081bd26 Mon Sep 17 00:00:00 2001 From: Crizomb <62544756+Crizomb@users.noreply.github.com> Date: Mon, 31 Jul 2023 04:39:20 +0200 Subject: [PATCH] Init --- python_symb/__pycache__/tools.cpython-311.pyc | Bin 0 -> 550 bytes python_symb/__pycache__/tree.cpython-311.pyc | Bin 0 -> 5224 bytes python_symb/expr.py | 13 ++ python_symb/fractions.py | 131 ++++++++++++++++++ python_symb/integers.py | 3 + python_symb/operator.py | 56 ++++++++ python_symb/symbols.py | 8 ++ python_symb/tools.py | 14 ++ python_symb/tree.py | 80 +++++++++++ 9 files changed, 305 insertions(+) create mode 100644 python_symb/__pycache__/tools.cpython-311.pyc create mode 100644 python_symb/__pycache__/tree.cpython-311.pyc create mode 100644 python_symb/expr.py create mode 100644 python_symb/fractions.py create mode 100644 python_symb/integers.py create mode 100644 python_symb/operator.py create mode 100644 python_symb/symbols.py create mode 100644 python_symb/tools.py create mode 100644 python_symb/tree.py diff --git a/python_symb/__pycache__/tools.cpython-311.pyc b/python_symb/__pycache__/tools.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c4ba3f815ff93d4e58f13075ce1d2b5ac2df411 GIT binary patch literal 550 zcmZWmze~eF6n-yhYphg79O_mDhd3A<1r^+-6zXD^aOP60Cb@dK2$2p&94a`}sk4hB z;=keCu>=G`9NY@sI(gStL4CaY-uvFY?|weya#@geckn`=WqeoU+q7|lgMv&tK!KtM zK2{J_u6f!%Q2h!jI!%?qOn<6&6O$Pd1WXWd%z{u-TyrK1sd-4tp#$K6%A^AgY`|$s zP4IbvDvnLn@1^ePM_ZP?6i-K-YYiyF-~I+(WZ<95)QVh*gPMYdN0lyMeGuu~Q@5FL8F_IwG{{v8b_NLM=)Ju|vTlM_3N=9J|W6?|PPC%nR4+ zF_-(p2-G#hO$kkSn=)D(mr*l%om*&cw8?dR6L*cgD(_yNH_v->^DX0JX0~?QSYRkYXsBsU&OL)ks9#wQVk64w8(B>&L;-XrD*m>I3<-grTwJGa7mB4xg1& fy=J&2p|2xi4_3Ory$6fkZ|`ReT>?JG|7uI15v?a?Dma^Ic!mPB=O70?S;<+Ja?XmaH zcuQPI;sLd3#e+dvh22sWwTKeY2OjossQT!v@?ecr38`ACyt$$eRbJY2?zJbL#8B-@ zt<*c?bHC5M=bYa;_m2M%iS!akmp=cK`QtDlf5l2WX|kZa_#qTlh)GN(PYOy}QLr4y z2MTIhEof;?)YZIR2&RJy36S@Qsof%`{wP4m6ZpxL?lFTOkVMaOtR@t<&#r2@ zWhVk|=$ym2F`H*@_&sJp(J68mrJL;IGRwAjh)k6g<;90kSRst06_ca`rjk~#!M=W{ zq&0KU95O?<^t5gcn|-&mbkH0z`yuavJOX*h95thmharza-V6Co$on84fV|&~!(PW+ z?J{S~_z;BXrI4=V9d6KTxW8PMUS_sKvw6d|lk^9MMQ0f;+svd+k#bhz%x0ED4QoLT zv>jf~I%Uq1y@J;#M!wAGG?jUAjym&(yUkQ zP^xELRwy|OQmBOL>H-FCs6EBq*`Y|eFh^J7=&u_)+Rh>by2|^Y(N%MnlWjRI)CqVZ zA>b^^iz852AyuVHGT1IsRfU@3)dEoST-78WkX0p>P&vc|BDjln6Pl~pEI%ikaVMhB z#zoORHZDxf7Yl4EEAcS({z7)%;Dz^j@jA;o_Ec#B@L;v7Q>Nh<8R->MStFm#fNcvb zKjnbAlBESVl*#0*oRi5^B512*yE+7`+2cTNlE%=kCGB=^WAAsCwDr(LW0XQQvINfy z=qGNFGw?XeRbiQ|CoJ^n@Dr*z2nC33pqlGYlIhnFMWF7Dhr0S39pZtOs^|hXmB3-T zp(GN4O--ySJOR<`2mg=m4?w)N^FxTM2{gQN+$EC|n>4 z;)h%vT~w;d18CWv{A>M)tSAb(J%&i)Q5X%OJUGvC*XEtofE!32adm-o8!<#dR?LHQM=cmP1i1MqGTk&E-vjkZU<U!9D~8?H2p=sAT{2>=zfIv^H{P zedNra->Jt_Yw^@N&}gb2O1;8{XMqz!@9Ws`5$x}YXY-c*)D+(hy#Cwv)9hS@aiRJS ztMR?CbY)zq2?uns7LMq&*6>Vyc;>NQE3Z`UR_;`nt5DtY3bmni>~f*Ibq?UNVQ*QA zYhYX3HiG5T!7ugz=e6OPb)fN?_4v$MbfzAf5&Soz-c3WsQJ)4iV73oE;2{*G2XtDh zO0Fq>YoKrNx4=I<`@lpm`Tb)tPz_x7;_X>-b!1V6ndo)fQdRY@1AaAH4M-2GDo;?wD>BQOVYY7z zl>wnv@tlga`EoPJC~L(Exp?qo47yG zBueCUL27yoTHlAlFBEC7 zC1p-Am0O`-DFO0J2=RVBz6)CWnF@Lg{9IgNArb~s+aMr<;4@(QX^W{J1e>RXpE-b` z;{>s_Dv<_r@Z@Qw&Jq6E0Eqo~>0Ar|EbuJyfbo$44fptgVA@uI_yxOtpmV;dv^WIY zJ8HuRgn#}oNN~ujd1guAgc)2U@$$*UNuSVN&4IJnRV-J@3FNq{QNCfLRB!>HHwAw9 z_n=zYFHqBYjcG;Q%@6@o@or-O9>_l>lKv8l*Um0qT#HSv$0nEFX~ajC-$umjZVd0L z_2To@`2Gjx!@}D5vGws|O`=5(2y!P>Q)@xgoA`e^dYc(NW(Hg-+a&g1iJ_r$%U z_sXA5-=D6>_IG`sMdRzy{f`H}j2@~-4|%KMicOWo4nw1W-6~lP2saW^$^-1Qbenh= zVJo9ARRcT&D)}U1; zKyiE#T`y4G5-PVKbkGZ5aEt1N$*U?q2AKeuR5Ln&A70g{h7?iWh39}>B(fwViuainT(w;IyQXt3?T0@BzR@! zcrD{eB-2P{kf2ve?}=jxzn6HZP4EU|H-Oyqo@Ss=4>bvrQL^)`dJN+D^v!diEPXF1 zYdh&x^zVXS`$$mHFDcl#g+lvj(Y}QS!}@5G_{nfghoIpnulHb^pA7h`{$7b8lsApTS_|Fii4w3E#orO})y2kMe%JFD*`?AG+9=@UR&oXhrlgbj|$5Y@&=%h5#DUPVe tYpA^l1cH{LG{|J#|2D{hdbhVh_SF4vGk9K6K*H|y@1p%5FX Fractions(2, 1) + For one simplification step put rec=False + + return None""" + + def aux(fract): + match fract: + case Fractions(Fractions(a, b), Fractions(c, d)): + fract.num = a * d + fract.den = b * c + case Fractions(num, Fractions(a, b)): + fract.num = num * b + fract.den = a + case Fractions(Fractions(a, b), den): + fract.num = a + fract.den = b * den + + if rec: + num, den = self.num, self.den + if isinstance(num, Fractions) or isinstance(den, Fractions): + aux(fract) + + aux(self) + + def simplify_all_(self): + self.simplify_gcd() + self.simplify_nested() + res = self.simplify_to_num() + if res: + return res + + return self + + def __add__(self, other): + match other: + case int(x): + return Fractions(self.num + self.den*x, self.den) + case Fractions(num, den): + result = Fractions(self.num*den + num*self.den, self.den*den) + return result + return ValueError + + def __radd__(self, other): + return other + self + + def __neg__(self): + return Fractions(-self.num, self.den) + + def __mul__(self, other): + match other: + case int(x): + return Fractions(self.num*x, self.den) + case Fractions(num, den): + result = Fractions(self.num*num, self.den*den) + return result + return ValueError + + def __rmul__(self, other): + return self*other + + def __truediv__(self, other): + match other: + case int(x): + return Fractions(self.num, self.den*x) + case Fractions(num, den): + return Fractions(self.num*den, self.den*num) + + def __rtruediv__(self, other): + res = self/other + return Fractions(res.den, res.num) + + +if __name__ == "__main__": + a = Fractions(1, 2) + a += 1 + print(a) + + + + + + + + + + + + diff --git a/python_symb/integers.py b/python_symb/integers.py new file mode 100644 index 0000000..cc56d3b --- /dev/null +++ b/python_symb/integers.py @@ -0,0 +1,3 @@ +""" +Python int is already an arbitrary precision integer, so we don't need to implement it. +""" diff --git a/python_symb/operator.py b/python_symb/operator.py new file mode 100644 index 0000000..038fd7e --- /dev/null +++ b/python_symb/operator.py @@ -0,0 +1,56 @@ +from __future__ import annotations +from typing import Dict, Callable + + +class Operator: + __slots__ = 'name', 'precedence', 'call' + + def __init__(self, name: str, precedence: int, call: Callable): + self.name = name + self.precedence = precedence + self.call = call + + +class UnaryOperator(Operator): + __slots__ = 'name', 'precedence' + + def __init__(self, name: str, precedence: int, call: Callable): + super().__init__(name, precedence, call) + + def __call__(self, expr): + return self.call(expr) + + +class BinProperties: + __slots__ = 'associativity', 'commutativity', 'left_distributivity', 'right_distributivity' + + def __init__(self, associativity: bool, commutativity: True, + left_distributivity: Dict[str, bool], right_distributivity: Dict[str, bool]): + + self.associativity = associativity + self.commutativity = commutativity + self.left_distributivity = left_distributivity + self.right_distributivity = right_distributivity + + +class BinOperator(Operator): + __slots__ = 'name', 'precedence', 'properties' + + def __init__(self, name: str, precedence: int, properties: BinProperties, call: Callable): + super().__init__(name, precedence, call) + self.properties = properties + + def __call__(self, left, right): + return self.call(left, right) + + +AddProperties = BinProperties(True, True, {'*': True}, {'*': True}) +Add = BinOperator('+', 1, AddProperties, lambda x, y: x + y) + + +MulProperties = BinProperties(True, True, {'+': True}, {'+': True}) +Mul = BinOperator('*', 2, MulProperties, lambda x, y: x * y) + +Neg = UnaryOperator('-', -1, lambda x: -x) +Parenthesis = UnaryOperator('()', 0, lambda x: x) + diff --git a/python_symb/symbols.py b/python_symb/symbols.py new file mode 100644 index 0000000..1ec2079 --- /dev/null +++ b/python_symb/symbols.py @@ -0,0 +1,8 @@ +from __future__ import annotations + + +class Symbols: + __slots__ = 'name' + + def __init__(self, name): + self.name = name diff --git a/python_symb/tools.py b/python_symb/tools.py new file mode 100644 index 0000000..3d3b00a --- /dev/null +++ b/python_symb/tools.py @@ -0,0 +1,14 @@ +from __future__ import annotations +from typing import * + + +def gcd(a, b): + + if b > a: + return gcd(b, a) + + if b == 0: + return a + + return gcd(b, a % b) + diff --git a/python_symb/tree.py b/python_symb/tree.py new file mode 100644 index 0000000..758339b --- /dev/null +++ b/python_symb/tree.py @@ -0,0 +1,80 @@ +from __future__ import annotations +from typing import Iterable, Generator +from collections import deque + + +class Tree: + """ + Ultra generic Test class. Can be used to represent any Test structure. + + value : value of the node. Can be a binary operator like "+", a ternary operator like "if", a number etc... + + depth_first_order : the default order of the node in the depth first traversal. Used to implement the depth_first method. + 0 is pre-order, 1 is in-order (for binary Test), -1 is post-order. + for instance to write "a ? b : c" you need to write Tree("?", [Tree("a"), Tree("b"), Tree("c")]) + and set the depth_first_order of the "?" node to 1. + + children : the children of the node. Can be empty. + """ + __slots__ = ['value', 'children', 'depth_first_order'] + + def __init__(self, value, children: Iterable[Tree] = None, depth_first_order: int = 0): + self.value = value + self.depth_first_order = depth_first_order + self.children = children if children else [] + + def __repr__(self) -> str: + return f'Tree({self.value}, {self.children})' + + def height(self) -> int: + return 1 + max((child.height() for child in self.children), default=0) + + def size(self) -> int: + return 1 + sum(child.size() for child in self.children) + + def breadth_first(self) -> Generator[Tree]: + + queue = deque([self]) + + while queue: + poped = queue.popleft() + for child in poped.children: + queue.append(child) + + yield poped + + def depth_first_default(self) -> Generator[Tree]: + + def aux(tree): + n = len(tree.children) + if not tree.children: + yield tree + + for i, child in enumerate(tree.children): + if i == tree.depth_first_order: + yield tree + + yield from aux(child) + + if tree.depth_first_order == -1: + yield tree + + yield from aux(self) + + def depth_first_pre_order(self) -> Generator[Tree]: + + def aux(tree): + yield tree + for child in tree.children: + yield from aux(child) + + yield from aux(self) + + def depth_first_post_order(self) -> Generator[Tree]: + + def aux(tree): + for child in tree.children: + yield from aux(child) + yield tree + + yield from aux(self) \ No newline at end of file