forked from kalmar/DALGLI0
Prześlij pliki do ''
This commit is contained in:
parent
16f4649ea6
commit
d100a1f9b1
121
hw2.py
Normal file
121
hw2.py
Normal file
@ -0,0 +1,121 @@
|
||||
import sys
|
||||
import ast
|
||||
import operator
|
||||
from fractions import gcd
|
||||
|
||||
class Polynomial():
|
||||
def __init__(self, lst, mod):
|
||||
super().__init__()
|
||||
self.poly = list(map(lambda x: x % mod, lst))
|
||||
self.mod = mod
|
||||
self.normalize()
|
||||
def normalize(self):
|
||||
while self.poly and self.poly[-1] == 0:
|
||||
self.poly.pop()
|
||||
|
||||
def arithm(self, p1, p2, op):
|
||||
len_p1, len_p2= len(p1.poly), len(p2.poly)
|
||||
res = [0] * max(len_p1, len_p2)
|
||||
if len_p1 > len_p2:
|
||||
for _ in range(len_p1-len_p2):
|
||||
p2.poly.append(0)
|
||||
else:
|
||||
for _ in range(len_p2-len_p1):
|
||||
p1.poly.append(0)
|
||||
|
||||
for i in range(len(res)):
|
||||
res[i] = op(p1.poly[i], p2.poly[i]) % self.mod
|
||||
return Polynomial(res, self.mod)
|
||||
|
||||
def __add__(self, p2):
|
||||
return self.arithm(self, p2, operator.add)
|
||||
|
||||
def __sub__(self, p2):
|
||||
return self.arithm(self, p2, operator.sub)
|
||||
|
||||
def __mul__(self, p2):
|
||||
res = [0]*(len(self.poly)+len(p2.poly)-1)
|
||||
for i, x1 in enumerate(self.poly):
|
||||
for j, x2 in enumerate(p2.poly):
|
||||
res[i+j] += x1 * x2 % self.mod
|
||||
return Polynomial(res, self.mod)
|
||||
|
||||
def __truediv__(self, p2):
|
||||
p1 = self
|
||||
m = self.mod
|
||||
|
||||
if len(p1.poly) < len(p2.poly):
|
||||
return p1
|
||||
|
||||
if len(p2.poly) == 0:
|
||||
raise ZeroDivisionError
|
||||
|
||||
divisor_coeff = p2.poly[-1]
|
||||
divisor_exp = len(p2.poly) - 1
|
||||
while len(p1.poly) >= len(p2.poly):
|
||||
max_coeff_p1 = p1.poly[-1] #wspolczynnik przy najwyzszej potedze
|
||||
try:
|
||||
tmp_coeff = modDiv(max_coeff_p1, divisor_coeff, m)
|
||||
except ZeroDivisionError as e:
|
||||
raise e
|
||||
|
||||
tmp_exp = len(p1.poly)-1 - divisor_exp
|
||||
'''tmp to pomocniczy wielomian o reprezentacji [0, 0, .., c^n], gdzie c^n to
|
||||
mnożnik w danym kroku algorytmu dzielenia w słupku.
|
||||
Następnie mnożymy go z wielomianem-dzielnikiem (p2) i
|
||||
odejmujemy (sub) od wielomianu-dzielnej (p1)'''
|
||||
tmp = []
|
||||
for i in range(tmp_exp):
|
||||
tmp.append(0)
|
||||
tmp.append(tmp_coeff)
|
||||
sub = Polynomial(tmp, m) * p2
|
||||
p1 = p1 - sub
|
||||
p1.normalize() #obcinamy zbędne zera dopisane do wielomianu podczas odejmowania
|
||||
return Polynomial(p1.poly, m)
|
||||
|
||||
def poly_gcd(self, p2):
|
||||
p1 = self
|
||||
try:
|
||||
divisible = p2
|
||||
except ZeroDivisionError as e:
|
||||
raise e
|
||||
if p2.poly == []:
|
||||
return p1
|
||||
return p2.poly_gcd(p1 / p2)
|
||||
|
||||
def modDiv(a, b, m): # a*b^-1 (mod m)
|
||||
if gcd(b, m) != 1:
|
||||
raise ZeroDivisionError
|
||||
else:
|
||||
return (a * modinv(b, m)) % m
|
||||
|
||||
#rozszerzony algorytm euklidesa
|
||||
def egcd(a, b):
|
||||
if a == 0:
|
||||
return (b, 0, 1)
|
||||
else:
|
||||
g, y, x = egcd(b % a, a)
|
||||
return (g, x - (b // a) * y, y)
|
||||
|
||||
def modinv(a, m):
|
||||
g, x, y = egcd(a, m)
|
||||
return x % m
|
||||
|
||||
def main():
|
||||
n, p1, p2 = int(sys.argv[1]), ast.literal_eval(sys.argv[2]), ast.literal_eval(sys.argv[3])
|
||||
P1 = Polynomial(p1, n)
|
||||
P2 = Polynomial(p2, n)
|
||||
mul = (P1 * P2).poly
|
||||
try:
|
||||
div = (P1 / P2).poly
|
||||
except ZeroDivisionError as e:
|
||||
div = e
|
||||
try:
|
||||
gcd = P1.poly_gcd(P2).poly
|
||||
except ZeroDivisionError as e:
|
||||
gcd = e
|
||||
print([mul, div, gcd])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue
Block a user