import itertools class Poly: def __init__(self, int_mod, elements): self.elements = {} self.int_mod = int_mod i = len(elements) - 1 for e in reversed(elements): self.elements[f"x{i}"] = e % self.int_mod i -= 1 def __str__(self): str_form = "" deg = len(self.elements) - 1 for e in self.elements: if self.elements[e] >= 0: if e != f"x{deg}": str_form += "+ " else: str_form += "- " str_form += str(abs(self.elements[e])) if e != "x0": str_form += e[0] + "^" + e[1:] + " " return str_form def __mul__(self, other): assert self.int_mod == other.int_mod elements = {} for e in self.elements: for f in other.elements: coefficient = self.elements[e] * other.elements[f] degree = f"x{int(e[1:])+int(f[1:])}" if elements.get(f"{degree}") is None: elements[degree] = coefficient % self.int_mod else: elements[degree] += coefficient % self.int_mod els = {} for i in reversed(range(len(elements))): els[f"x{i}"] = elements[f"x{i}"] return Poly(self.int_mod, list(reversed(list(els.values())))) def __mod__(self, other): elements = {} def __pow__(self, power, modulo=None): poly = Poly(self.int_mod, list(reversed(list(self.elements.values())))) for i in range(power - 1): poly *= poly return poly def __add__(self, other): assert self.int_mod == other.int_mod elements = self.elements.copy() for f in other.elements: if f in elements: elements[f] += other.elements[f] else: elements[f] = other.elements[f] els = {} for i in reversed(range(len(elements))): els[f"x{i}"] = elements[f"x{i}"] return Poly(self.int_mod, list(reversed(list(els.values())))) def __sub__(self, other): assert self.int_mod == other.int_mod elements = self.elements.copy() for e in other.elements: if e in elements: elements[e] -= other.elements[e] else: elements[e] = -other.elements[e] els = {} for i in reversed(range(len(elements))): els[f"x{i}"] = elements[f"x{i}"] return Poly(self.int_mod, list(reversed(list(els.values())))) def __truediv__(self, other): assert self.int_mod == other.int_mod if other.is_empty(): raise ZeroDivisionError("Polynomial is empty") poly = Poly(self.int_mod, list(reversed(list(self.elements.values())))) fdeg = len(poly.elements) - 1 sdeg = len(other.elements) - 1 while fdeg >= sdeg: coefficient = poly.elements[f"x{fdeg}"] / other.elements[f"x{sdeg}"] coefficient %= poly.int_mod degree = fdeg - sdeg divpoly = [0 for x in range(degree + 1)] divpoly[degree] = coefficient divpoly = Poly(poly.int_mod, divpoly) mulpoly = divpoly * other poly -= mulpoly for i in poly.elements.keys(): if poly.elements[f"{i}"] != 0: fdeg = int(i[1:]) break return poly def is_empty(self): for e in self.elements: if self.elements[e] != 0: return False return True class PolyIntField: def __init__(self, int_mod, poly_mod): self.int_modulo = int_mod self.poly_modulo = Poly(int_mod, poly_mod) product = list(itertools.product([x for x in range(0, int_mod)], repeat=len(poly_mod) - 1)) self.elements = [] for p in product: p = list(p) p = [x % int_mod for x in p] self.elements.append(Poly(int_mod, p)) def get_nilpotents(self): nilpotents = [] # for element in self.elements: if __name__ == "__main__": a = Poly(10, [-4, 0, -2, 1]) b = Poly(10, [-3, 1]) c = a/b print(c) # print(a - Poly(10, [0, 0, -3, 1])) # p = Poly(5, [-4, 0, -2, 1]) # print(p) # c = p * p # print(c.elements) # print(c) # print(p ** 2) # print(p) # print(d) # print(p) # print(p + d) # d = Poly(5, [-3, 1]) # g = Poly(5, [1, 2, 1]) # print(d) # print(g) # print() # # # print(g) # print(g - d) # print(d - g) # # print() # print(d + g) # print(g + d) # # print() # print(d * g) # print(g * d) # print(d) # print(g) # print(g - d) # print(p / d) # print(p.elements[0]) # a = PolyIntField(3, [1, 1, 2, 2]) # for e in a.elements: # print(e.elements) # print() # print(a.elements[4]) # print(a.elements[8]) # print(a.elements[4] * a.elements[8]) # a.elements[3] / a.elements[1]