zad 3 #29
2
README.md
Normal file
2
README.md
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Program przyjmuje input z konsoli (argv) i korzysta z funkcji eval niedziałającej poprawnie w obecności spacji między elementami listy.
|
||||||
|
Przykładowe uruchomienie: python hw2.py 2 [1,1,1,0,1] [0,1,1]
|
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()
|
177
hw3.py
Normal file
177
hw3.py
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
from sys import argv
|
||||||
|
from fractions import gcd
|
||||||
|
from ast import literal_eval
|
||||||
|
|
||||||
|
class Polynomial():
|
||||||
|
def __init__(self, lst, mod):
|
||||||
|
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()
|
||||||
|
|
||||||
|
#zwraca jednomian stopnia n
|
||||||
|
@staticmethod
|
||||||
|
def Monomial(n, c, mod):
|
||||||
|
zeros = [0]*n
|
||||||
|
zeros.append(c)
|
||||||
|
return Polynomial(zeros, mod)
|
||||||
|
|
||||||
|
def __add__(self, p2):
|
||||||
|
p1 = self
|
||||||
|
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] = (p1.poly[i] + p2.poly[i]) % self.mod
|
||||||
|
return Polynomial(res, self.mod)
|
||||||
|
|
||||||
|
def __sub__(self, p2):
|
||||||
|
p1 = self
|
||||||
|
res = []
|
||||||
|
len_p2 = len(p2.poly)
|
||||||
|
for i in range(len(p1.poly)):
|
||||||
|
if i < len_p2:
|
||||||
|
res.append(p1.poly[i] - p2.poly[i] % self.mod)
|
||||||
|
else:
|
||||||
|
res.append(p1.poly[i])
|
||||||
|
return Polynomial(res, self.mod)
|
||||||
|
|
||||||
|
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 = [0] * tmp_exp
|
||||||
|
tmp.append(tmp_coeff)
|
||||||
|
sub = Polynomial(tmp, m) * p2
|
||||||
|
p1 = p1 - sub
|
||||||
|
p1.normalize()
|
||||||
|
return Polynomial(p1.poly, m)
|
||||||
|
|
||||||
|
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
|
||||||
|
#lista stringow binarnych -> lista intow 0/1
|
||||||
|
def bin_str_to_list(lst):
|
||||||
|
res = []
|
||||||
|
for elem in lst:
|
||||||
|
for ch in elem:
|
||||||
|
res.append(int(ch))
|
||||||
|
return res
|
||||||
|
|
||||||
|
def mod8format(lst):
|
||||||
|
while len(lst) % 8 != 0:
|
||||||
|
lst.append(0)
|
||||||
|
return lst
|
||||||
|
|
||||||
|
def to_bin(x):
|
||||||
|
data = bin(ord(x)).replace('b', '')
|
||||||
|
while len(data) != 8:
|
||||||
|
if len(data) < 8:
|
||||||
|
data = str(0) + data
|
||||||
|
else:
|
||||||
|
data = data[1:]
|
||||||
|
return data
|
||||||
|
|
||||||
|
def to_ascii_val(lst):
|
||||||
|
sum = 0
|
||||||
|
for i in range(len(lst)):
|
||||||
|
if lst[i] == 1:
|
||||||
|
sum += 2**(7-i)
|
||||||
|
|
||||||
|
return chr(sum)
|
||||||
|
|
||||||
|
def data():
|
||||||
|
p = bin_str_to_list(list(map(lambda x: to_bin(x), m)))
|
||||||
|
p.reverse()
|
||||||
|
Lx = Polynomial([1] * 16, 2) #L(x)
|
||||||
|
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)
|
||||||
|
return (p, Lx, X16, Gx)
|
||||||
|
|
||||||
|
def fcs(m):
|
||||||
|
p, Lx, X16, Gx = data()
|
||||||
|
Mx = Polynomial(p, 2) #M(x) #X^16
|
||||||
|
Xnsub16 = Polynomial.Monomial(len(m)*8, 1, 2) #X^(n-16)
|
||||||
|
rhs = Xnsub16 * Lx
|
||||||
|
lhs = X16 * Mx
|
||||||
|
xor = lhs + rhs
|
||||||
|
fcs = xor/Gx
|
||||||
|
#algorytm dzielenia ucina zera, trzeba dopelnic do 16 bitow
|
||||||
|
for i in range(16 - len(fcs.poly)):
|
||||||
|
fcs.poly.append(0)
|
||||||
|
fcs.poly.reverse()
|
||||||
|
return fcs.poly
|
||||||
|
|
||||||
|
def check(m):
|
||||||
|
p, Lx, X16, Gx = data()
|
||||||
|
Xn = Polynomial.Monomial(len(p), 1, 2) #X^n
|
||||||
|
Cx = Polynomial(p, 2)
|
||||||
|
Cx = X16 * Cx
|
||||||
|
Cx.poly = mod8format(Cx.poly)
|
||||||
|
Sx = (Cx + Xn * Lx) / Gx
|
||||||
|
if Sx.poly == []:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global m
|
||||||
|
m = list(argv[2])
|
||||||
|
mode = argv[1] # flagi -e -d (encode, decode)
|
||||||
|
if mode == '-e':
|
||||||
|
res = fcs(m)
|
||||||
|
fcs_ch1 = to_ascii_val(res[:8])
|
||||||
|
fcs_ch2 = to_ascii_val(res[8:])
|
||||||
|
m.append(fcs_ch1)
|
||||||
|
m.append(fcs_ch2)
|
||||||
|
print(m)
|
||||||
|
elif mode == '-d':
|
||||||
|
to_check = literal_eval(argv[3])
|
||||||
|
m += to_check
|
||||||
|
print(check(m))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user