Python 重新排列字符串/列表的所有方法的列表

Python 重新排列字符串/列表的所有方法的列表,python,cryptography,combinations,permutation,product,Python,Cryptography,Combinations,Permutation,Product,我正试图找到一种方法,列出所有可能的方法来重新排列字符串,以获得所需的字符串(最终帮助破解列转置密码) 例如,要将“abaca”重新排列为“cabaa”,可以将原始字符串的索引3、0、1、2、4处的字符放入一个新字符串(按该顺序)。但是3,0,1,4,2和3,2,1,0,4等等。。。也行 print get_rearrangement_indices("abaca", "cabaa") >>> [(3, 0, 1, 2, 4), (3, 0, 1, 4, 2), (3, 2,

我正试图找到一种方法,列出所有可能的方法来重新排列字符串,以获得所需的字符串(最终帮助破解列转置密码)

例如,要将“abaca”重新排列为“cabaa”,可以将原始字符串的索引3、0、1、2、4处的字符放入一个新字符串(按该顺序)。但是3,0,1,4,2和3,2,1,0,4等等。。。也行

print get_rearrangement_indices("abaca", "cabaa")
>>> [(3, 0, 1, 2, 4), (3, 0, 1, 4, 2), (3, 2, 1, 0, 4), (3, 2, 1, 4, 0), (3, 4, 1, 0, 2), (3, 4, 1, 2, 0)]
我想避免暴力强迫所有可能的排列,因为当你有一个由“abcdef”组成的字符串,你想把它变成“fedcba”时,一定有一个更聪明的方法,但我有一个思维障碍试图解决它。以下是我目前掌握的情况:

def get_rearrangement_indices(in_string, out_string):
    old_indices_to_new = {}
    for i, char in enumerate(in_string):
        old_indices_to_new[i] = get_indices_of_element(out_string, char) # where get_indices_of_element("abaca", "a") gives you all the indices where there is an "a" i.e. 0,2,4
    unique_tuples = set([v for k,v in old_indices_to_new.items()])
    new_indices_to_old = defaultdict(tuple)
    for unique_tuple in unique_tuples:
        for k,v in old_indices_to_new.items():
            if not k in new_indices_to_old[v]:
                new_indices_to_old[v] += (k,)
    print old_indices_to_new                   # {0: (1, 3, 4), 1: (2,), 2: (1, 3, 4), 3: (0,), 4: (1, 3, 4)}
    old_indices_to_new = {v:k for k,v in new_indices_to_old.items()} # Can't decide if this or the old one is easier to work with
    print old_indices_to_new                   # {(3,): (0,), (0, 2, 4): (1, 3, 4), (1,): (2,)}
    # itertools
    # ???
    return profit

您可以分别排列每个字母的索引

from itertools import permutations, product
from collections import defaultdict

def get_rearrangement_indices(in_string, out_string):
    indices = defaultdict(list)
    for i, c in enumerate(in_string):
        indices[c].append(i)
    for perms in product(*map(permutations, indices.values())):
        inds = {c: iter(p) for c, p in zip(indices, perms)}
        yield tuple(next(inds[c]) for c in out_string)
演示:

>>> list(get_rearrangement_indices("abaca", "cabaa"))
[(3, 0, 1, 2, 4), (3, 0, 1, 4, 2), (3, 2, 1, 0, 4), (3, 2, 1, 4, 0), (3, 4, 1, 0, 2), (3, 4, 1, 2, 0)]

>>> list(get_rearrangement_indices("aabb", "abab"))
[(0, 2, 1, 3), (0, 3, 1, 2), (1, 2, 0, 3), (1, 3, 0, 2)]

可能是这样的:

  • 为源和输出构建位置字典。位置字典将每个字符映射到在字符串中找到该字符的索引列表

  • 构建所有允许的转换。允许的字符转换为:

    a) 如果该字符在字符串中是唯一的(其位置计数为1),则其源索引将明确映射到输出索引

    b) 如果不止一次地找到这个字符,那么构建其输出dict位置的所有排列,并根据源dict将它们放在列表中

  • 因此,生成的列表是几个子空间的直积

    例如,字符串“ann”可以转换为“nan”,如下所示:

    源dict是{'a':[0],'n':[1,2]} 输出dict为{'a':[1],'n':[0,2]}

    Then for each character in the source keys for each permutation of its output value list create a list with this permutation spread across the indices from the source value 然后针对源密钥中的每个字符 对于其输出值列表的每个排列 创建一个列表,将此排列分布在源值的索引中 排列是 ‘a’->[1] 'n'->[0,2],[2,0]

    由此产生的产品是

    [1] 放置在位置[0];[0,2]放置在[1,2]-->[1,0,2]
    [1] 放置在位置[0];[2,0]放在[1,2]-->[1,2,0]

    不知道,但请记住,为了简单起见,您可以使用列表理解
    [i for i,x in enumerate(out_string),如果x==element]
    而不是
    获取_元素的索引()