【问题标题】:In Python, how do I generate all permutations of a string of 0s and 1s in order?在 Python 中,如何按顺序生成 0 和 1 字符串的所有排列?
【发布时间】:2017-03-16 00:31:39
【问题描述】:

我正在尝试排列任意长度的 0 和 1 字符串。我已经看到了很多关于这个主题的答案,因此长度为 n 的字符串的结果就像n=3 的结果一样。

000
001
010
011
100
101
110
111

但这不是我需要的!

我需要它在长度为 3 时是这样的:

000
100
010
001
110
101
011
111

对于长度 4,这将是:

0000
1000
0100
0010
0001
1100
1010
1001
0110
0101
0011
1110
1101
1011
0111
1111

对于长度 5,它将是:

00000
10000
01000
00100
00010
00001
11000
10100
10010
10001
01100
01010
01001
00110
00101
00011
11100
11010
11001
10110
10101
10011
01110
01101
01011
00111
11110
11101
11011
10111
01111
11111

等等。

我就是想不出这个算法,谁能帮帮我?

编辑:我弹出提示我可以在本网站的其他地方找到答案。我是新来的,所以我可能理解不正确,但我在这两个问题中看到的唯一重叠是排列这个词。

【问题讨论】:

    标签: numpy permutation bits


    【解决方案1】:

    这对我有用。但是,它不会按顺序生成元素,而是先生成元素,然后对它们进行排序。

    n = 5
    i = np.array(np.indices(n * (2,))).reshape(n, -1)
    i[:, np.argsort(i.sum(0)[::-1], kind='mergesort')].T[::-1]
    

    它使用稳定的排序方式按数字的总和对二进制单词进行排序,即在出现平局的情况下保留原始顺序。

    可以使用itertools构造按顺序生成单词的解决方案

    itertools.chain((n*(0,),), (l[0] * (0,) + sum(((1,) + (i-j-1) * (0,) for i, j in zip(l[1:], l[:-1])), ()) + (1,) + (n-l[-1]-1)*(0,) for k in range(1,n+1) for l in itertools.combinations(range(n), k)))
    

    这会循环 k 的数量(k = 0 是特殊情况并使用 itertools.chain 前置)。对于每个 k,它使用itertools.combinations 创建集合`{0, 1, ..., n-1} 并将每个子集转换为二进制字。这种翻译的工作原理是为 l 的每个元素放置一个 1,并计算中间必须有多少个零。前导零和尾随零必须是特殊情况。

    示例输出:numpy:

    # array([[0, 0, 0, 0, 0], [1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0],
             [0, 0, 0, 1, 0], [0, 0, 0, 0, 1], [1, 1, 0, 0, 0], [1, 0, 1, 0, 0],
             [1, 0, 0, 1, 0], [1, 0, 0, 0, 1], [0, 1, 1, 0, 0], [0, 1, 0, 1, 0],
             [0, 1, 0, 0, 1], [0, 0, 1, 1, 0], [0, 0, 1, 0, 1], [0, 0, 0, 1, 1],
             [1, 1, 1, 0, 0], [1, 1, 0, 1, 0], [1, 1, 0, 0, 1], [1, 0, 1, 1, 0],
             [1, 0, 1, 0, 1], [1, 0, 0, 1, 1], [0, 1, 1, 1, 0], [0, 1, 1, 0, 1],
             [0, 1, 0, 1, 1], [0, 0, 1, 1, 1], [1, 1, 1, 1, 0], [1, 1, 1, 0, 1],
             [1, 1, 0, 1, 1], [1, 0, 1, 1, 1], [0, 1, 1, 1, 1], [1, 1, 1, 1, 1]])
    

    itertools:

    list(_)
    # [(0, 0, 0, 0, 0), (1, 0, 0, 0, 0), (0, 1, 0, 0, 0), (0, 0, 1, 0, 0), (0, 0, 0, 1, 0), (0, 0, 0, 0, 1),
       (1, 1, 0, 0, 0), (1, 0, 1, 0, 0), (1, 0, 0, 1, 0), (1, 0, 0, 0, 1), (0, 1, 1, 0, 0), (0, 1, 0, 1, 0),
       (0, 1, 0, 0, 1), (0, 0, 1, 1, 0), (0, 0, 1, 0, 1), (0, 0, 0, 1, 1), (1, 1, 1, 0, 0), (1, 1, 0, 1, 0),
       (1, 1, 0, 0, 1), (1, 0, 1, 1, 0), (1, 0, 1, 0, 1), (1, 0, 0, 1, 1), (0, 1, 1, 1, 0), (0, 1, 1, 0, 1),
       (0, 1, 0, 1, 1), (0, 0, 1, 1, 1), (1, 1, 1, 1, 0), (1, 1, 1, 0, 1), (1, 1, 0, 1, 1), (1, 0, 1, 1, 1),
       (0, 1, 1, 1, 1), (1, 1, 1, 1, 1)]
    

    【讨论】:

    • 非常感谢!明天当我再次有电脑时,我将首先尝试这个:)我现在正在使用手机。
    • 你能解释一下你的 itertools 代码吗?我正在尝试 n=40 和 k in range(1,2) 这应该只给出 41 个非常基本的向量,但由于某种原因它需要永远。你能帮我优化一下吗?
    • @Perm.Questiin 我刚刚用n=40, k in range(1, 2) 试了一下,在我的笔记本电脑上眨了眨眼。您是否将列表应用于结果?我会看看如何更好地解释代码。
    • 你是对的!我犯了一个错误,这减慢了速度。无论如何谢谢:)
    猜你喜欢
    • 2013-04-22
    • 1970-01-01
    • 2013-06-28
    • 2021-12-27
    • 2023-04-07
    • 2011-02-06
    • 2012-02-29
    • 2023-03-04
    相关资源
    最近更新 更多