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): if self.int_mod != other.int_mod: raise Exception("Different modulo") 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 return Poly(self.int_mod, list(reversed(list(elements.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): if self.int_mod != other.int_mod: raise Exception("Different modulo") elements = self.elements.copy() for f in other.elements: if f in elements: elements[f] += other.elements[f] else: elements[f] = other.elements[f] return Poly(self.int_mod, list(reversed(list(sorted(elements.values()))))) def __truediv__(self, other): if self.int_mod != other.int_mod: raise Exception("Different modulo") if other.is_empty(): raise ZeroDivisionError("Polynomial is empty") fdeg = len(self.elements) - 1 sdeg = len(other.elements) - 1 while not other.is_empty(): coefficient = self.elements[f"x{fdeg}"] / other.elements[f"x{sdeg}"] coefficient %= self.int_mod degree = fdeg - sdeg # print(self.elements["x2"]) # break 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__": p = Poly(5, [-4, 0, -2, 1]) # print(p) # c = p * p # print(c.elements) # print(c) # print(p ** 2) d = Poly(5, [-3, 1]) # print(p) # print(d) # print(p) # print(p + d) g = Poly(5, [1, 2, 1]) # print() # print(g ** 2) print(d) print(g) # c = d * g print(g * d) print(d * g) print(g + d) print(d + g) 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]