简体   繁体   English

使用列表理解的数字 1...N 的所有排列(没有 itertools)

[英]All permutations of numbers 1...N using list comprehension (without itertools)

I am currently using Python 3.7.7, and I posed a coding challenge for myself.我目前使用的是 Python 3.7.7,我对自己提出了编码挑战。

I would like to list all permutations of integers from 1 to N using a one-line code (perhaps a list comprehension).我想使用一行代码(可能是列表理解)列出从 1 到 N 的所有整数排列。 I cannot use itertools (or other packages which solve this with one function).我不能使用 itertools (或其他用一个功能解决这个问题的包)。

For N <= 9, I found "cheaty" method:对于 N <= 9,我发现“作弊”方法:

N = 3
print([list(str(i)) for i in range(10**N) if all([str(i).count(str(j)) == 1 for j in range(1,N+1)])])

Example:例子:

Out: [['1', '2', '3'], ['1', '3', '2'], ['2', '1', '3'], ['2', '3', '1'], ['3', '1', '2'], ['3', '2', '1']]

In the case of N = 3, this goes through all integers from 0 to 999 in order, and selects the ones that have exactly one 1, exactly one 2, and exactly one 3. (These are 123, 132, 213, 231, 312, 321; and from here, it's simple enough to convert them to a list.)在 N = 3 的情况下,这会依次遍历从 0 到 999 的所有整数,并选择恰好有一个 1、正好有一个 2 和正好有一个 3 的整数。(这些是 123、132、213、231、 312、321;从这里开始,将它们转换为列表很简单。)

However this obviously fails for N >= 10.然而,对于 N >= 10,这显然失败了。

I thought about converting the numbers to a higher base first, but that turned out to be even more difficult when restricting myself to only using list comprehension.我考虑过首先将数字转换为更高的基数,但是当将自己限制为仅使用列表理解时,这变得更加困难。

Can anyone think of a way to do this for N >= 10?谁能想到 N >= 10 的方法?

A not-so-simple functional one-liner without any "outside" variable assignment except N .一个不那么简单的功能单线,除了N没有任何“外部”变量赋值。

N = 3
(lambda n: (lambda f, n: f(f, n))(lambda f, n: [p[:i]+[n]+p[i:] for p in f(f, n-1) for i in range(len(p)+1)] if n > 1 else [[1]], n))(N)

Output输出

[[3, 2, 1], [2, 3, 1], [2, 1, 3], [3, 1, 2], [1, 3, 2], [1, 2, 3]]

I tried to use recursion here, and it apparently works:我尝试在这里使用递归,它显然有效:

def perm(n):
    return [p[:i] + [n] + p[i:]  for p in perm(n-1) for i in range(0,len(p)+1)] if n > 2 else [[2,1], [1,2]]

print(perm(4))打印(烫发(4))

output:输出:

[[4, 3, 2, 1], [3, 4, 2, 1], [3, 2, 4, 1], [3, 2, 1, 4], [4, 2, 3, 1], [2, 4, 3, 1], [2, 3, 4, 1], [2, 3, 1, 4], [4, 2, 1, 3], [2, 4, 1, 3], [2, 1, 4, 3], [2, 1, 3, 4], [4, 3, 1, 2], [3, 4, 1, 2], [3, 1, 4, 2], [3, 1, 2, 4], [4, 1, 3, 2], [1, 4, 3, 2], [1, 3, 4, 2], [1, 3, 2, 4], [4, 1, 2, 3], [1, 4, 2, 3], [1, 2, 4, 3], [1, 2, 3, 4]]

For no good reason, here is an implementation of your approach in base 16, which means that this method works for N<=15.没有充分的理由,这是您的方法在基数 16 中的实现,这意味着此方法适用于 N<=15。

N = 3
print([[
dict(zip([*map(str,range(10)),*'abcdef'],
         map(str,range(16))))[c] 
    for c in f'{i:x}'] 
    for i in range(16**N) 
    if set(f'{i:x}') == set('1234567890abcdef'[:N])])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM