Вы, в некотором смысле, уже написали де-скремблер.Все, что вам нужно сделать, это кормить scrambler
обратная перестановка .Ниже обратная перестановка задается как argsort(P)
, где P
- это перестановка.
def scramble(S, P): #Scramble string S with permutation P
pn = len(P) # length of permutation array
E = (len(S) + pn - (len(S)%pn)) * [' '] # array of chars, padded
for i in range(len(S)):
seg,j = divmod(i,pn)
E[ seg*pn + P[j] ] = S[i]
return ''.join(E).rstrip()
def argsort(seq):
# http://stackoverflow.com/questions/3382352/3382369#3382369
'''
>>> seq=[1,3,0,4,2]
>>> index=argsort(seq)
[2, 0, 4, 1, 3]
Given seq and the index, you can construct the sorted seq:
>>> sorted_seq=[seq[x] for x in index]
>>> assert sorted_seq == sorted(seq)
Given the sorted seq and the index, you can reconstruct seq:
>>> assert [sorted_seq[x] for x in argsort(index)] == seq
'''
return sorted(range(len(seq)), key=seq.__getitem__)
P=[9, 14, 11, 19, 16, 18, 12, 6, 7, 15, 0, 5, 17, 4, 3, 10, 2, 1, 8, 13]
text="0123456789abcdefghij"
print scramble(text,P)
# ahgedb78i0f26j194c53
print(scramble(scramble(text,P),argsort(P)))
# 0123456789abcdefghij
Кстати, вместо того, чтобы предварительно выделять достаточно места для E
с помощью
E = (len(S) + pn - (len(S)%pn)) * [' ']
, вы можете генерировать элементы в E
взаказ с помощью argsort
:
def scramble(S, P):
pn = len(P)
E = []
idx = argsort(P)
for i in range(len(S)):
seg,j = divmod(i,pn)
E.append(S[idx[j]+seg*pn])
return ''.join(E)