数字 1...N 的所有排列使用列表理解(没有 itertools)
All permutations of numbers 1...N using list comprehension (without itertools)
我目前正在使用 Python 3.7.7,我给自己提出了一个编码挑战。
我想使用 一行代码 (也许是列表理解)列出从 1 到 N 的所有整数排列。我不能使用 itertools(或其他用一个功能解决这个问题的包)。
对于 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)])])
示例:
Out: [['1', '2', '3'], ['1', '3', '2'], ['2', '1', '3'], ['2', '3', '1'], ['3', '1', '2'], ['3', '2', '1']]
在 N = 3 的情况下,这将按顺序遍历从 0 到 999 的所有整数,并选择正好有一个 1、正好有一个 2 和正好有一个 3 的整数。(这些是 123、132 , 213, 231, 312, 321;从这里开始,将它们转换为列表就足够简单了。)
然而,对于 N >= 10,这显然失败了。
我考虑过先将数字转换为更高的基数,但事实证明,当我限制自己只使用列表理解时,这变得更加困难。
谁能想出办法让 N >= 10 做到这一点?
我尝试在这里使用递归,它显然有效:
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]]
打印(烫发(4))
输出:
[[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]]
A not-so-simple 函数 one-liner 除了 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)
输出
[[3, 2, 1], [2, 3, 1], [2, 1, 3], [3, 1, 2], [1, 3, 2], [1, 2, 3]]
无缘无故,这是您的方法在 base 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])])
我目前正在使用 Python 3.7.7,我给自己提出了一个编码挑战。
我想使用 一行代码 (也许是列表理解)列出从 1 到 N 的所有整数排列。我不能使用 itertools(或其他用一个功能解决这个问题的包)。
对于 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)])])
示例:
Out: [['1', '2', '3'], ['1', '3', '2'], ['2', '1', '3'], ['2', '3', '1'], ['3', '1', '2'], ['3', '2', '1']]
在 N = 3 的情况下,这将按顺序遍历从 0 到 999 的所有整数,并选择正好有一个 1、正好有一个 2 和正好有一个 3 的整数。(这些是 123、132 , 213, 231, 312, 321;从这里开始,将它们转换为列表就足够简单了。)
然而,对于 N >= 10,这显然失败了。
我考虑过先将数字转换为更高的基数,但事实证明,当我限制自己只使用列表理解时,这变得更加困难。
谁能想出办法让 N >= 10 做到这一点?
我尝试在这里使用递归,它显然有效:
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]]
打印(烫发(4))
输出:
[[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]]
A not-so-simple 函数 one-liner 除了 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)
输出
[[3, 2, 1], [2, 3, 1], [2, 1, 3], [3, 1, 2], [1, 3, 2], [1, 2, 3]]
无缘无故,这是您的方法在 base 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])])