zad 3 #29

Closed
s426285 wants to merge 5 commits from s426285/DALGLI0:zad3_426285 into master
Showing only changes of commit c93bc4b37e - Show all commits

348
hw3.py
View File

@ -1,173 +1,177 @@
from sys import argv from sys import argv
from fractions import gcd from fractions import gcd
from ast import literal_eval
class Polynomial():
def __init__(self, lst, mod): class Polynomial():
self.poly = list(map(lambda x: x % mod, lst)) def __init__(self, lst, mod):
self.mod = mod self.poly = list(map(lambda x: x % mod, lst))
self.normalize() self.mod = mod
def normalize(self): self.normalize()
while self.poly and self.poly[-1] == 0: def normalize(self):
self.poly.pop() while self.poly and self.poly[-1] == 0:
self.poly.pop()
#zwraca jednomian stopnia n
@staticmethod #zwraca jednomian stopnia n
def Monomial(n, c, mod): @staticmethod
zeros = [0]*n def Monomial(n, c, mod):
zeros.append(c) zeros = [0]*n
return Polynomial(zeros, mod) zeros.append(c)
return Polynomial(zeros, mod)
def __add__(self, p2):
p1 = self def __add__(self, p2):
len_p1, len_p2= len(p1.poly), len(p2.poly) p1 = self
res = [0] * max(len_p1, len_p2) len_p1, len_p2= len(p1.poly), len(p2.poly)
if len_p1 > len_p2: res = [0] * max(len_p1, len_p2)
for _ in range(len_p1-len_p2): if len_p1 > len_p2:
p2.poly.append(0) for _ in range(len_p1-len_p2):
else: p2.poly.append(0)
for _ in range(len_p2-len_p1): else:
p1.poly.append(0) for _ in range(len_p2-len_p1):
p1.poly.append(0)
for i in range(len(res)):
res[i] = (p1.poly[i] + p2.poly[i]) % self.mod for i in range(len(res)):
return Polynomial(res, self.mod) res[i] = (p1.poly[i] + p2.poly[i]) % self.mod
return Polynomial(res, self.mod)
def __sub__(self, p2):
p1 = self def __sub__(self, p2):
res = [] p1 = self
len_p2 = len(p2.poly) res = []
for i in range(len(p1.poly)): len_p2 = len(p2.poly)
if i < len_p2: for i in range(len(p1.poly)):
res.append(p1.poly[i] - p2.poly[i] % self.mod) if i < len_p2:
else: res.append(p1.poly[i] - p2.poly[i] % self.mod)
res.append(p1.poly[i]) else:
return Polynomial(res, self.mod) res.append(p1.poly[i])
return Polynomial(res, self.mod)
def __mul__(self, p2):
res = [0]*(len(self.poly)+len(p2.poly)-1) def __mul__(self, p2):
for i, x1 in enumerate(self.poly): res = [0]*(len(self.poly)+len(p2.poly)-1)
for j, x2 in enumerate(p2.poly): for i, x1 in enumerate(self.poly):
res[i+j] += x1 * x2 % self.mod for j, x2 in enumerate(p2.poly):
return Polynomial(res, self.mod) res[i+j] += x1 * x2 % self.mod
return Polynomial(res, self.mod)
def __truediv__(self, p2):
p1 = self def __truediv__(self, p2):
m = self.mod p1 = self
m = self.mod
if len(p1.poly) < len(p2.poly):
return p1 if len(p1.poly) < len(p2.poly):
return p1
if len(p2.poly) == 0:
raise ZeroDivisionError if len(p2.poly) == 0:
raise ZeroDivisionError
divisor_coeff = p2.poly[-1]
divisor_exp = len(p2.poly) - 1 divisor_coeff = p2.poly[-1]
while len(p1.poly) >= len(p2.poly): divisor_exp = len(p2.poly) - 1
max_coeff_p1 = p1.poly[-1] #wspolczynnik przy najwyzszej potedze while len(p1.poly) >= len(p2.poly):
try: max_coeff_p1 = p1.poly[-1] #wspolczynnik przy najwyzszej potedze
tmp_coeff = modDiv(max_coeff_p1, divisor_coeff, m) try:
except ZeroDivisionError as e: tmp_coeff = modDiv(max_coeff_p1, divisor_coeff, m)
raise e except ZeroDivisionError as e:
raise e
tmp_exp = len(p1.poly)-1 - divisor_exp
tmp = [0] * tmp_exp tmp_exp = len(p1.poly)-1 - divisor_exp
tmp.append(tmp_coeff) tmp = [0] * tmp_exp
sub = Polynomial(tmp, m) * p2 tmp.append(tmp_coeff)
p1 = p1 - sub sub = Polynomial(tmp, m) * p2
p1.normalize() p1 = p1 - sub
return Polynomial(p1.poly, m) p1.normalize()
return Polynomial(p1.poly, m)
def modDiv(a, b, m): # a*b^-1 (mod m)
if gcd(b, m) != 1: def modDiv(a, b, m): # a*b^-1 (mod m)
raise ZeroDivisionError if gcd(b, m) != 1:
else: raise ZeroDivisionError
return (a * modinv(b, m)) % m else:
#rozszerzony algorytm euklidesa return (a * modinv(b, m)) % m
def egcd(a, b): #rozszerzony algorytm euklidesa
if a == 0: def egcd(a, b):
return (b, 0, 1) if a == 0:
else: return (b, 0, 1)
g, y, x = egcd(b % a, a) else:
return (g, x - (b // a) * y, y) g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m) def modinv(a, m):
return x % m g, x, y = egcd(a, m)
#lista stringow binarnych -> lista intow 0/1 return x % m
def bin_str_to_list(lst): #lista stringow binarnych -> lista intow 0/1
res = [] def bin_str_to_list(lst):
for elem in lst: res = []
for ch in elem: for elem in lst:
res.append(int(ch)) for ch in elem:
return res res.append(int(ch))
return res
def mod8format(lst):
while len(lst) % 8 != 0: def mod8format(lst):
lst.append(0) while len(lst) % 8 != 0:
return lst lst.append(0)
return lst
def to_bin(x):
data = bin(ord(x)).replace('b', '') def to_bin(x):
while len(data) != 8: data = bin(ord(x)).replace('b', '')
if len(data) < 8: while len(data) != 8:
data = str(0) + data if len(data) < 8:
else: data = str(0) + data
data.replace(data[0], '') else:
return data data = data[1:]
return data
def to_ascii_val(lst):
sum = 0 def to_ascii_val(lst):
for i in range(len(lst)): sum = 0
if lst[i] == 1: for i in range(len(lst)):
sum += 2**(7-i) if lst[i] == 1:
return chr(sum) sum += 2**(7-i)
def data(): return chr(sum)
p = bin_str_to_list(list(map(lambda x: to_bin(x), m)))
p.reverse() def data():
Lx = Polynomial([1] * 16, 2) #L(x) p = bin_str_to_list(list(map(lambda x: to_bin(x), m)))
X16 = Polynomial.Monomial(16, 1, 2) #X^16 p.reverse()
Gx = Polynomial([1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1], 2) #G(x) Lx = Polynomial([1] * 16, 2) #L(x)
return (p, Lx, X16, Gx) X16 = Polynomial.Monomial(16, 1, 2) #X^16
Gx = Polynomial([1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1], 2) #G(x)
def fcs(m): return (p, Lx, X16, Gx)
p, Lx, X16, Gx = data()
Mx = Polynomial(p, 2) #M(x) #X^16 def fcs(m):
Xnsub16 = Polynomial.Monomial(len(m)*8, 1, 2) #X^(n-16) p, Lx, X16, Gx = data()
rhs = Xnsub16 * Lx Mx = Polynomial(p, 2) #M(x) #X^16
lhs = X16 * Mx Xnsub16 = Polynomial.Monomial(len(m)*8, 1, 2) #X^(n-16)
xor = lhs + rhs rhs = Xnsub16 * Lx
fcs = xor/Gx lhs = X16 * Mx
#algorytm dzielenia ucina zera, trzeba dopelnic do 16 bitow xor = lhs + rhs
for i in range(16 - len(fcs.poly)): fcs = xor/Gx
fcs.poly.append(0) #algorytm dzielenia ucina zera, trzeba dopelnic do 16 bitow
fcs.poly.reverse() for i in range(16 - len(fcs.poly)):
return fcs.poly fcs.poly.append(0)
fcs.poly.reverse()
def check(m): return fcs.poly
p, Lx, X16, Gx = data()
Xn = Polynomial.Monomial(len(p), 1, 2) #X^n def check(m):
Cx = Polynomial(p, 2) p, Lx, X16, Gx = data()
Cx = X16 * Cx Xn = Polynomial.Monomial(len(p), 1, 2) #X^n
Cx.poly = mod8format(Cx.poly) Cx = Polynomial(p, 2)
Sx = (Cx + Xn * Lx) / Gx Cx = X16 * Cx
if Sx.poly == []: Cx.poly = mod8format(Cx.poly)
return True Sx = (Cx + Xn * Lx) / Gx
return False if Sx.poly == []:
return True
def main(): return False
global m
m = list(argv[1]) def main():
mode = argv[2] # flagi -e -d (encode, decode) global m
if mode == '-e': m = list(argv[2])
res = fcs(m) mode = argv[1] # flagi -e -d (encode, decode)
fcs_ch1 = to_ascii_val(res[:8]) if mode == '-e':
fcs_ch2 = to_ascii_val(res[8:]) res = fcs(m)
m.append(fcs_ch1) fcs_ch1 = to_ascii_val(res[:8])
m.append(fcs_ch2) fcs_ch2 = to_ascii_val(res[8:])
print(''.join(m)) m.append(fcs_ch1)
elif mode == '-d': m.append(fcs_ch2)
print(check(m)) print(m)
elif mode == '-d':
if __name__ == '__main__': to_check = literal_eval(argv[3])
m += to_check
print(check(m))
if __name__ == '__main__':
main() main()