我需要生成数字排列,数字可能大于数字计数。出于我目前的目的,我需要生成这些数字0, 1, 2
的排列,以获得长达20位的数字。例如,我的前几个排列将是0, 1, 2, 10, 11, 12, ... 1122, 1211
。
在Python here或here中使用Iterator存在现有答案,这些答案直接提供了完整的排列。
但是我需要对每个排列执行一些测试,如果我将整个排列列表保留在内存中它会变得太大,特别是对于20个数字,它会达到3 20 排列。
所以我的问题是可以在没有递归的情况下完成,这样我就可以对每个排列执行测试。
修改:
我正在重复查看排列。因此,对于多个说20个数字,每个数字可以从[0, 1, 2]
获取值。这就是为什么在这种情况下排列的数量将达到3 20 。
答案 0 :(得分:2)
是的,你的程序可能是这样的:
import itertools
def perform_test(permutation):
pass
# permutations() does not construct entire list, but yields
# results one by on.
for permutation in itertools.permutations([1, 2, 3, 4, 5], 2):
perform_test(permutation)
答案 1 :(得分:2)
您所看到的被称为笛卡尔积,而不是置换。 Python itertools有一个方法itertools.product()
来产生所需的结果:
import itertools
for p in itertools.product(range(3), repeat=4):
print p
输出为3 ^ 4行:
(0, 0, 0, 0)
(0, 0, 0, 1)
(0, 0, 0, 2)
(0, 0, 1, 0)
(0, 0, 1, 1)
...
(2, 2, 2, 1)
(2, 2, 2, 2)
要生成长度为1到4的输出元组,请使用额外的迭代:
for l in range(1, 5):
for p in itertools.product(range(3), repeat=l):
print p
最后,这也适用于字符串元素:
for i in range(5):
for p in itertools.product(('0', '1', '2'), repeat=i):
print ''.join(p),
print
输出:
0 1 2 00 01 02 10 11 12 20 21 22 000 001 002 010 [...] 2220 2221 2222
答案 2 :(得分:1)
虽然有很多方法可以使用itertools等来实现这一点,但这里的方法与您通常采用的方式略有不同。
如果您要按顺序列出这些排列,那么您实际拥有的是表示它们在列表中的位置的三元数。例如list [4]是11,其中三元组为4(3 * 1 + 1 * 1)。因此,您可以将要测试的索引值转换为三元,这将产生正确的值。
虽然python可以在整数中转换为整数到其形式(例如int(“11”,3)输出4),但反过来并未隐式实现。虽然有很多实现。 Here是一个很好的(根据您的情况进行了修改):
def digit_to_char(digit):
if digit < 10:
return str(digit)
return chr(ord('a') + digit - 10)
def perm(number):
(d, m) = divmod(number, 3)
if d > 0:
return perm(d) + digit_to_char(m)
return digit_to_char(m)
因此,如果你想找到第20个排列,你可以做烫发(20),它会给你202.所以现在你可以只做一个你想要的索引值的常规循环。没有在内存中存储大的列表。
permutation = 0
i = 0
while len(str(permutation)) < 20:
permutation = perm(i)
do_test(permutation)
i += 1