【问题标题】:Descramble a message string using a permutation as a key使用排列作为键解扰消息字符串
【发布时间】:2011-11-11 01:11:26
【问题描述】:

帮助我正在尝试使用排列作为密钥对文件进行解扰,我知道如何对其进行加扰,但我需要创建一个函数来将其解扰回使用相同排列密钥的内容,这是代码:

def stringtoarray(S):
    A = []
    i = 0
    while i<len(S):
        A.append(S[i])
        i += 1
    return A

def arraytostring(A):
    S = ""
    for c in A:  # "for each element/value c in array A"
        S = S+c
    return S
#arraytostring
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 
    i = 0
    while i< len(S):
        seg = i/pn   # segment number
        j = i % pn   # segment offset
        E[ seg*pn + P[j] ] = S[i]
        i += 1
    # while
    return arraytostring(E)
# scramble
print scramble("0123456789abcdefghij",[9, 14, 11, 19, 16, 18, 12, 6,
               7, 15, 0, 5, 17, 4, 3, 10, 2, 1, 8, 13])

# prints ahgedb78i0f26j194c53

我想再次将其设置回字符串“0123456789abcdefghij”

【问题讨论】:

  • 您不应该使用它来保护任何东西。我敢肯定这是一个有趣的编程挑战或什么的,在这种情况下你会更有力量。
  • 你确定扰码器是正确的吗? E 的长度应该怎么计算?提示:检查len(E) 看看是否正确。你认为seg 是什么? (提示:对于您的示例,它始终为零)

标签: python string permutation


【解决方案1】:

从某种意义上说,您已经编写了解扰器。你所要做的就是喂scramblerinverse permutation。下面,逆排列由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)) * [' ']

您可以使用argsort按顺序生成E中的项目:

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)

【讨论】:

    【解决方案2】:

    简单。计算排列的倒数并应用它。有一个众所周知的算法。你可以发现它被引用为 Donald Knuth 的“计算机编程艺术”中的算法 J。

    这里似乎有源代码:http://binetacm.wikidot.com/algo:perminv

    void inversePermutation(int perm[], int n, int inv[]) {
       for (int i=0; i<n; i++)
          inv[perm[i]]=i;
    }
    

    【讨论】:

    • 是的,这是我需要做的,但我很难将其输入到我的代码中
    【解决方案3】:

    首先在您的代码中添加一些 cmets。

    以下是完全没有必要的:

    def stringtoarray(S):
        A = []
        i = 0
        while i<len(S):
            A.append(S[i])
            i += 1
        return A
    

    只要做list(your_string)就可以实现

    另外,如果你想迭代一些东西,你可以使用for .. in .. 例如。

    for char in some_string:
        # do something with character
    

    您的arraytostring 函数也是不必要的。将列表连接成字符串的正确方法是使用string.join()[docs]。例如,''.join(['a', 'b', 'c']) 会给你'abc'


    这就是我将如何执行加扰/解扰功能:

    def scramble(s, p):
        chars = list(s)
        scrambled = ['']*len(chars)
        for char, i in zip(chars, p):
            scrambled[i] = char
        return ''.join(scrambled)
    
    def unscramble(s, p):
        reverse_p = sorted(range(len(p)), key=p.__getitem__)
        return scramble(s, reverse_p)
    
    s = "abcdefg"
    
    p_key = [6, 1, 3, 0, 5, 2, 4]
    
    print "original:", s
    
    scrambled = scramble(s, p_key)
    
    print "scrambled:", scrambled
    
    print "unscrambled:", unscramble(scrambled, p_key)
    

    结果:

    原文:0123456789abcdefghij 加扰:ahgedb78i0f26j194c53 解读:0123456789abcdefghij

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-12
      • 2021-09-13
      • 1970-01-01
      • 1970-01-01
      • 2017-06-22
      相关资源
      最近更新 更多