如何找到一系列数字(可能包含相似项目)的方式可以重新排列,以便数字不会放置在相同的位置或放置相似的数字。
例如,[0,0,0,1,1,1]
只能以一种方式重新排列,即[1,1,1,0,0,0]
。
[0,0,0,1,1,1,1]
无法以任何方式安排。
[1,2,2,14]
可以通过两种方式排列,即[2,1,14,2], [2,14,1,2]
。
[1,1,2,2,14]
可以通过4种方式排列,[14,2,1,1,2], [2,2,14,1,1], [2,2,1,14,1], [2,14,1,1,2]
。
数学解决方案可用但我正在考虑使用编程概念的一些简单方法。数学代码有点像这样..(对不起,我无法以正确的格式发布)
∫∞0 Ln1(x)..Lnr(x)e−xdx
其中r是项目数,ni是项目i的出现次数,Lk是第k个Laguerre多项式。例如,对于1,1,2,2,14,我们有r = 3,n1 = 2,n2 = 2,n3 = 1,所以重新排列的数字是
∫∞0 L2(x)L2(x)L1(x)e−xdx
= ∫∞0 12(x2−4x+2)12(x2−4x+2)(1−x)e−xdx
= ∫∞0(−14x5+94x4−7x3+9x2−5x+1)e−xdx
= −4
但我在想是否有任何python库可以根据我们的需要生成所有排列。
答案 0 :(得分:3)
你试过itertools.permutations吗?
http://docs.python.org/library/itertools.html#itertools.permutations
import itertools
def my_combos(val):
results = []
l = itertools.permutations(val, len(val))
for c in l:
if all([x != y for (x,y) in zip(c,val)]):
results.append(c)
return list(set(results))
print my_combos([0,0,0,1,1,1])
print my_combos([1,1,2,2,14])
收率:
[(1, 1, 1, 0, 0, 0)]
[(2, 14, 1, 1, 2), (2, 2, 1, 14, 1), (14, 2, 1, 1, 2), (2, 2, 14, 1, 1)]
答案 1 :(得分:3)
更多参与,但在长输入序列上应该快一点:
from collections import Counter
def _rearrange(orig, rem):
if len(orig)==1:
v = rem[0][0]
if v != orig[0]:
yield [v]
else:
o, orig = orig[0], orig[1:]
for i,(v,c) in enumerate(rem):
if v != o:
for r in _rearrange(orig, rem[:i]+([(v,c-1)] if c>1 else [])+rem[i+1:]):
yield [v]+r
def rearrange(orig):
if len(orig) > 1:
return list(_rearrange(orig, Counter(orig).items()))
else:
return []
def main():
print rearrange([0,0,0,1,1,1])
print rearrange([1,1,2,2,14])
if __name__=="__main__":
main()
结果
[[1, 1, 1, 0, 0, 0]]
[[2, 2, 1, 14, 1], [2, 2, 14, 1, 1], [2, 14, 1, 1, 2], [14, 2, 1, 1, 2]]
编辑:比较函数的运行时,我得到:
(蒂姆的蓝色,我的绿色;点是数据,线条最适合(数据记录的最小平方); x轴是序列长度,y轴是运行时间,以秒为单位(对数刻度)。数据点是对于每个序列长度,在20个随机序列的每一个中运行10个中的最佳值。)
结论:
Tim的fn运行时增长为7.44 * * n;我的成长为3.69 * * n。
在一个十项目的序列中,他的fn平均为53.9s,而我的平均为0.93s;对于序列中的每个额外项目,差异略大于双倍。
他的fn具有更加一致的运行时间;我的变量很大,取决于序列中重复项目的数量。
直线拟合看起来不是最好的预测因子;运行时应该是n!的函数,而不是k * * n。不过,我不知道如何对此进行建模。建议?
答案 2 :(得分:1)
使用itertools
:
import itertools
def arrangements(arr):
p = itertools.permutations(arr)
return set(item for item in p if all(x!=y for x,y in zip(item,arr)))
结果:
>>> arrangements([0,0,0,1,1,1])
{(1, 1, 1, 0, 0, 0)}
>>> arrangements([0,0,0,1,1,1,1])
set()
>>> arrangements([1,2,2,14])
{(2, 14, 1, 2), (2, 1, 14, 2)}
>>> arrangements([1,1,2,2,14])
{(2, 14, 1, 1, 2), (2, 2, 1, 14, 1), (14, 2, 1, 1, 2), (2, 2, 14, 1, 1)}