这个post提供了一些很好的python代码来查找一个总和到某个数字S的集合中的所有排列。我想消除输出中的不连续性,以便输出行中没有一个元素与任何相邻行的差异超过1。
以下是生成我想要订购/排序的输出的代码:
def f(n,s):
if n == 1:
yield (s,)
else:
for i in xrange(s + 1):
for j in f(n - 1,s - i):
yield (i,) + j
L = list(f(3,5))
for i in L:
print i
输出:
(0, 0, 5)
(0, 1, 4)
(0, 2, 3)
(0, 3, 2)
(0, 4, 1)
(0, 5, 0)
(1, 0, 4) <-Bad, 0 transitioned to 4 from one row to the next
(1, 1, 3)
(1, 2, 2)
(1, 3, 1)
(1, 4, 0)
(2, 0, 3) <-Bad, 4 transitioned to 0 from one row to the next
(2, 1, 2)
(2, 2, 1)
(2, 3, 0)
(3, 0, 2)
(3, 1, 1)
(3, 2, 0)
(4, 0, 1) <-Bad, 2 transitioned to 0 from one row to the next
(4, 1, 0)
(5, 0, 0)
Desired Output:
(0, 0, 5)
(0, 1, 4)
(0, 2, 3)
(0, 3, 2)
(0, 4, 1)
(0, 5, 0)
(1, 4, 0)
(1, 3, 1)
(1, 2, 2)
(1, 1, 3)
(1, 0, 4)
(2, 0, 3)
(2, 1, 2)
(2, 2, 1)
(2, 3, 0)
(3, 2, 0)
(3, 1, 1)
(3, 0, 2)
(4, 0, 1)
(4, 1, 0)
(5, 0, 0)
有人能提出一些能以这种方式订购输出的代码吗?
答案 0 :(得分:1)
这是我能提出的最简单的天真(“词法排序”)解决方案,它保留了转换平滑性并生成所有排列:
def g(n, s, direction=1):
if n == 1:
yield (s,)
else:
if direction > 0:
r = xrange(s + 1)
else:
r = xrange(s, -1, -1)
if s % 2:
direction = -direction
for i in r:
for j in g(n - 1, s - i, direction):
yield (i,) + j
direction = -direction
不幸的是,对于s
的奇数值,它不是根据需要以(0,) * (n - 1) + (s,)
开头,而是(0, s) + (0,) * (n - 2)
。 (所以g(5, 7)
不是以(0, 0, 0, 0, 7)
开头,而是以(0, 7, 0, 0, 0)
开头。)我假设必须有一些相对简单的调整才能解决这个问题,但目前我还在逃避。如果我正确地阅读了这个问题,那么平滑性和完整性是唯一真正关键的要求。
如果您只限于n <= 3
,那么您可以通过摆脱
if s % 2:
direction = -direction
但不知何故,这似乎是一个严酷的限制。
答案 1 :(得分:0)
虽然可能不是最优雅的解决方案,但这可行:
def f(n, s):
def g(n,s):
if n == 1:
yield (s,)
else:
for i in xrange(s + 1):
for j in g(n - 1,s - i):
yield (i,) + j
L = list(g(3, 5))
D = []
i = 1
while i != len(L):
for j in xrange(len(L[i])):
if abs(L[i][j] - L[i-1][j]) > 1:
D.append(L.pop(i))
i -= 1
break
for d in D:
ins = True
for j in xrange(len(L[-1])):
if abs(L[-1][j] - d[j]) > 1:
ins = False
break
if ins:
L.append(d)
D.remove(d)
i += 1
return L
for i in f(3, 5):
print i
打印:
(0, 0, 5)
(0, 1, 4)
(0, 2, 3)
(0, 3, 2)
(0, 4, 1)
(0, 5, 0)
(1, 4, 0)
(2, 3, 0)
(3, 2, 0)
(4, 1, 0)
(5, 0, 0)
(4, 0, 1)
(3, 0, 2)
(2, 0, 3)
(1, 0, 4)
(1, 1, 3)
(2, 1, 2)
(3, 1, 1)
(2, 2, 1)
(1, 2, 2)
(1, 3, 1)
它基本上定义g
内的f
,作为创建permations的生成器。然后它通过它的列表并检查每个元素,如果一个子列表中的元素与之前的元素之间的差异(abs
部分)(未解释得很好,我知道......但是你得到它)大于1,如果删除该列表,则将其附加到D
并将索引减少1(这就是我使用while
而不是for
)的原因。
修改强>
每次检查一个元素后,它会经过D
并查看是否有任何内容适合L
,如果适合,请附加它。
然后返回已过滤的列表。