【问题标题】:Constrained Composition of Tuples元组的约束组合
【发布时间】:2018-12-03 20:47:46
【问题描述】:

我有这个组合数学问题: 令 m=(m1,...,mk) 为 k 个正整数的向量。如果对于所有 1≤i≤k,ai≤mi,则 n 的 k-组合 (a1,...,ak) 是 m 约束的。例如,(1,1,3) 和 (2,1,2) 是 5 的唯一 (2,1,4) 约束 3 分区。

编写一个函数 constrained_compositions,它接受一个自然数 n 和一个由 k 个正整数组成的向量 m,并打印 n 的所有 m-约束 k-compositions 的集合。请注意,可以从 m 推断出 k。

谷歌搜索发现了这个有用的功能:

def compositions(k, n):
# inputs: k and n are of type 'int'
# output: a set of tuples
assert n > k > 1
to_process = [[i] for i in range(1, n+1)]
while to_process:
    l = to_process.pop()
    s = sum(l)
    le = len(l)
    for i in range(1, n-s+1): 
        news = s + i
        if news <= n:
            newl = list(l)
            newl.append(i)
            if le == k-1 and news == n:
                yield tuple(newl)
            elif le < k-1 and news < n:
                to_process.append(newl)

并实现以获取匹配约束的元组,如下所示:

def constrained_compositions(n, m):
# inputs: n is of type 'int' and m is a list of integers
# output: a set of tuples
k = len(m)
max_num = max(m)
l = []
comp = list(compositions(k,n))
for i in comp:
    for j in i:
        if j <= max_num:
            l.append(i)
print(set(l))

但这是我的结果:

{(2, 3, 2), (2, 1, 4), (4, 2, 1), (5, 1, 1), (3, 3, 1), (3, 2, 2), (3, 1, 3), (1, 5, 1), (1, 4, 2), (2, 2, 3), (2, 4, 1), (1, 2, 4), (4, 1, 2), (1, 1, 5), (1, 3, 3)}

它应该是:

{(1, 1, 5), (1, 2, 4), (2, 1, 4), (2, 2, 3), (3, 1, 3), (3, 2, 2)}

提前感谢您的帮助?

【问题讨论】:

  • 您是否尝试将l 设为一个集合,而不是一个列表?
  • 不行,让我试试!

标签: python tuples combinatorics


【解决方案1】:

您的代码中有一点有点偏离,即您只考虑来自m 的最大值并对照它检查您的作品的所有元素,而不考虑它们的实际位置。

这是一个递归生成器,可直接生成受约束的组合:

def constrained_compositions(n, m):
    if n == 0 and not m:
        yield ()
    if n < 0 or not m:
        return
    for i in range(1, min(n, m[0])+1):
        for cc in constrained_compositions(n-i, m[1:]):
            yield (i,) + cc

>>> list(constrained_compositions(7, [3, 2, 5]))
[(1, 1, 5), (1, 2, 4), (2, 1, 4), (2, 2, 3), (3, 1, 3), (3, 2, 2)]

这定义了成功和失败的基本情况。否则,它确保组合 i 的第一个元素在给定的限制 &lt;= m[0] 内,并与 nm 的余数递归:n-im[1:]

【讨论】:

  • 有趣的例子让我看看!!
【解决方案2】:

这对我来说很好:

def constrained_compositions(n, m):
    C = set()

    
    def help_comp(k, l):
        D = set()
        if k == 1:
            for i in range(m[0]):
                D.add((i+1,))
        else:
            for j in help_comp(k=k-1, l=l):
                for i in range(m[(len(list(j)))]):
                    i=i+1
                    if i <= m[(len(list(j)))]:
                        D.add((j)+(i,))
        return D

    if len(m) == 1 & m[0] != n:
        return C

    if n == 0 and m[0] !=n:
        return C

    if len(m) == 1 and m[0] == n:
        C.add((n,))

    else:
        for i in range(m[-1]):
            i=i+1
            for j in help_comp(k=len(m)-1, l=n):
                if sum(list((i,)+(j))) == n:
                    if i <= m[-1]:
                        C.add((j)+(i,))
    return C

【讨论】:

  • 你能解释一下它是如何解决问题的,而不仅仅是给出代码吗?
  • 对不起,我已经更正并清理了代码。首先它创建了一个辅助函数来创建一组元组。它首先创建单元素元组,每个元组小于或等于 m 的第一个元素。然后它在每次递归中添加一个元素,其中新元素小于等于 m 的相应元素。在主函数中,创建空集 C 并为 len(m)-1 个元组调用辅助函数。在 m 的最后一个元素的范围的 for 循环中,如果辅助函数的元组和 m 的最后一项之和等于 n,则将一个新元组添加到 C。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多