from poly import Polynomial from sys import argv from ast import literal_eval from fractions import gcd class QuotientRing(): def __init__(self, f, m): self.f = Polynomial(f, m) self.m = m self.remainders = self.remainders() self.reversibles = self.reversibles() self.zero_divisors = self.zero_divisors() self.idempotent = self.idempotent() self.nilpotent = self.nilpotent() def remainders(self): #n - exponent rems = [] #lista reszt m = self.m t = [0] i = 0 while len(t) < len(self.f.poly): rems.append(Polynomial(t, m)) i = (i + 1) % m t[0] = i if i == 0: if len(t) == 1: t.append(1) else: t[1] += 1 for j in range(1, len(t)): if t[j] == 0 or t[j] % m != 0: break temp = t[j] % m t[j] = 0 if temp == 0: if (j + 1) < len(t): t[j+1] += 1 else: t.append(1) return rems def reversibles(self): return [ rem for rem in self.remainders if len(rem.poly_gcd(self.f).poly) == 1 ] #dopelnienie elementow odwracalnych def zero_divisors(self): return [ rem for rem in self.remainders if rem not in self.reversibles ] def idempotent(self): idems = [] for rem in self.remainders: if (rem * rem % self.f) == (rem % self.f): idems.append(rem) try: if idems[0].poly == []: #implementacja wielomianow ucina zera idems[0].poly = [0] except IndexError: return idems return idems def nilpotent(self): nils = [] phi = len([ i for i in range(1, self.m) if gcd(i, self.m) == 1 ]) for zero_div in self.zero_divisors: for i in range(phi+1): if len((zero_div ** i % self.f).poly) == 0: nils.append(zero_div) break return nils def main(): m = int(argv[1]) f = literal_eval(argv[2]) qr = QuotientRing(f, m) out = [ [ rev.poly for rev in qr.reversibles ], [ zero_div.poly for zero_div in qr.zero_divisors ], [ nil.poly for nil in qr.nilpotent ], [ idem.poly for idem in qr.idempotent ] ] print(*out, sep='\n') if __name__ == '__main__': main()