使用乘法获得唯一整数组合的算法

发布于 2024-10-02 13:09:11 字数 284 浏览 6 评论 0原文

我有一堆 2 和 3,我必须将它们相乘。现在我想生成这些数字的每个唯一组合,这样当这些组合相乘时不超过 10。

例如,我有这样的东西。

2*2*2*2*3*3*3

我可以从上面得到以下有效组合。

4*4*9*3
8*6*9
4*2*6*9

但下面的组合是错误的。 16*3*94*4*27

有人可以建议一种算法来做到这一点吗?

I got bunch of 2s and 3s that i have to multiply together. Now i want to generate every unique combination of these numbers such that when these combination are multiplied does not exceed 10.

For example, I have something like this.

2*2*2*2*3*3*3

I can have following valid combination from above.

4*4*9*3
8*6*9
4*2*6*9

But the following combination are wrong. 16*3*9 and 4*4*27.

Can somebody suggest an algorithm to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

波浪屿的海角声 2024-10-09 13:09:11

该解决方案可以递归地建立。将输入视为数字列表,例如 [2,2,2,2,3,3,3]。将列表分为前缀(例如 [2,2])和相应的后缀(本例中为 [2,2,3,3,3])。现在乘以前缀中的条目(在本例中我们得到 4),并递归地解决后缀中的相同问题。将重数中的值插入到后缀的每个解的开头,我们就得到了原始问题的答案。

在下面的Python代码中,递归逻辑在函数collapse中定义,该函数查找所有有效的前缀(其重数小于10)并将重数插入到折叠剩余数据返回的所有结果中删除前缀后 (collapse(d[prefix_len:]))。

a = [2,2,2,2,3,3,3]

def collapse(d):
    if len(d) > 0:
        for prefix_len in range(1, len(d) + 1):
            prefix = reduce(lambda x,y: x*y, d[:prefix_len], 1)
            if prefix > 10:
                break
            for suffix in collapse(d[prefix_len:]):
                yield [prefix] + suffix
    else:
        yield d

for i in collapse(a):
    print i

输出是

[2, 2, 2, 2, 3, 3, 3]
[2, 2, 2, 2, 3, 9]
[2, 2, 2, 2, 9, 3]
[2, 2, 2, 6, 3, 3]
[2, 2, 2, 6, 9]
[2, 2, 4, 3, 3, 3]
[2, 2, 4, 3, 9]
[2, 2, 4, 9, 3]
[2, 4, 2, 3, 3, 3]
[2, 4, 2, 3, 9]
[2, 4, 2, 9, 3]
[2, 4, 6, 3, 3]
[2, 4, 6, 9]
[2, 8, 3, 3, 3]
[2, 8, 3, 9]
[2, 8, 9, 3]
[4, 2, 2, 3, 3, 3]
[4, 2, 2, 3, 9]
[4, 2, 2, 9, 3]
[4, 2, 6, 3, 3]
[4, 2, 6, 9]
[4, 4, 3, 3, 3]
[4, 4, 3, 9]
[4, 4, 9, 3]
[8, 2, 3, 3, 3]
[8, 2, 3, 9]
[8, 2, 9, 3]
[8, 6, 3, 3]
[8, 6, 9]

The solution can be built up recursively. Consider the input as a list of numbers such as [2,2,2,2,3,3,3]. Divide the list into a prefix (such as [2,2]) and the corresponding suffix ([2,2,3,3,3] in this case). Now multiple the entries in the prefix (and we get 4 in this example), and recursively solve the same problem for the suffix. Inserting the value from the multiplicity to the beginning of each of the solution for the suffix, we get the answer for the original problem.

In the following Python code, the recursive logic is defined in the function collapse, which finds all valid prefix (whose multiplicity is less than 10) and insert the multiplicity to all the results returned in collapsing the remaining data after cutting out the prefix (collapse(d[prefix_len:])).

a = [2,2,2,2,3,3,3]

def collapse(d):
    if len(d) > 0:
        for prefix_len in range(1, len(d) + 1):
            prefix = reduce(lambda x,y: x*y, d[:prefix_len], 1)
            if prefix > 10:
                break
            for suffix in collapse(d[prefix_len:]):
                yield [prefix] + suffix
    else:
        yield d

for i in collapse(a):
    print i

Output is

[2, 2, 2, 2, 3, 3, 3]
[2, 2, 2, 2, 3, 9]
[2, 2, 2, 2, 9, 3]
[2, 2, 2, 6, 3, 3]
[2, 2, 2, 6, 9]
[2, 2, 4, 3, 3, 3]
[2, 2, 4, 3, 9]
[2, 2, 4, 9, 3]
[2, 4, 2, 3, 3, 3]
[2, 4, 2, 3, 9]
[2, 4, 2, 9, 3]
[2, 4, 6, 3, 3]
[2, 4, 6, 9]
[2, 8, 3, 3, 3]
[2, 8, 3, 9]
[2, 8, 9, 3]
[4, 2, 2, 3, 3, 3]
[4, 2, 2, 3, 9]
[4, 2, 2, 9, 3]
[4, 2, 6, 3, 3]
[4, 2, 6, 9]
[4, 4, 3, 3, 3]
[4, 4, 3, 9]
[4, 4, 9, 3]
[8, 2, 3, 3, 3]
[8, 2, 3, 9]
[8, 2, 9, 3]
[8, 6, 3, 3]
[8, 6, 9]
心是晴朗的。 2024-10-09 13:09:11

如果顺序很重要(即 2*4*2 与 2*2*4 不同)并且您必须列出它们(即“生成”),那么您应该递归地执行所有操作。 In Scala:

def combine(who: List[Int], limit: Int=10): List[List[Int]] = who match {
  case x :: y :: more =>
    combine(y :: more, limit).map(x :: _) :::
    (if (x*y<limit) combine((x*y) :: more, limit) else Nil)
  case x :: Nil => List(who)
  case Nil => List()
}

您可能不了解 Scala,因此以下是这三种情况的工作原理。第一种情况:列表至少还剩下两个元素。挑选第一个元素并将其添加到所有可能的后续组合中。然后,如果您可以合并第一个和第二个元素,那么就这样做,并找到以此开头的列表的所有组合。第二种情况:只有一个元素的简单列表;将其作为列表中唯一的内容返回。第三种情况:简并输入(没有给出值);返回一个空列表。

(在 Scala 中,::: 将两个列表连接在一起,而 x :: listx 粘贴在 listx和其余元素,则使用case x :: stuff。 ,stuffNil 是空列表。)

这是实际操作:

scala> combine( List(2,2,2,2,3,3,3) )

res18: List[List[Int]] = List(List(2, 2, 2, 2, 3, 3, 3), List(2, 2, 2, 2, 3, 9),
  List(2, 2, 2, 2, 9, 3), List(2, 2, 2, 6, 3, 3), List(2, 2, 2, 6, 9),
  List(2, 2, 4, 3, 3, 3), List(2, 2, 4, 3, 9), List(2, 2, 4, 9, 3),
  List(2, 4, 2, 3, 3, 3), List(2, 4, 2, 3, 9), List(2, 4, 2, 9, 3), List(2, 4, 6, 3, 3),
  List(2, 4, 6, 9), List(2, 8, 3, 3, 3), List(2, 8, 3, 9), List(2, 8, 9, 3),
  List(4, 2, 2, 3, 3, 3), List(4, 2, 2, 3, 9), List(4, 2, 2, 9, 3), List(4, 2, 6, 3, 3),
  List(4, 2, 6, 9), List(4, 4, 3, 3, 3), List(4, 4, 3, 9), List(4, 4, 9, 3),
  List(8, 2, 3, 3, 3), List(8, 2, 3, 9), List(8, 2, 9, 3), List(8, 6, 3, 3), List(8, 6, 9))

编辑:如果您只是想对它们进行计数,则可以使用不同类型的重复。令 S(n) 为从第 n 开始的组合数,令 L(n)L(n) 的值列表中的第 n 项。然后

S(i) = S(i+1) +
       if (L(i)+L(i+1)<10) S(i+2) +
       if (L(i)+...+L(i+2)<10) S(i+3) +
       ....

,您从最后一项开始(只有一种可能性),然后使用此公式按顺序倒退。 (如果这就是您想要的,我将编写执行此操作的代码,但希望该算法足够清晰。)

If order matters (i.e. 2*4*2 is not the same as 2*2*4) and you have to list them (i.e. "generate") then you should just do it all recursively. In Scala:

def combine(who: List[Int], limit: Int=10): List[List[Int]] = who match {
  case x :: y :: more =>
    combine(y :: more, limit).map(x :: _) :::
    (if (x*y<limit) combine((x*y) :: more, limit) else Nil)
  case x :: Nil => List(who)
  case Nil => List()
}

You may not know Scala, so here's how the three cases work. First case: list has at least two elements remaining. Pick off the first element and add it to all possible later combinations. Then, if you can merge the first and second elements, do so, and find all combinations of the list that starts with that. Second case: trivial list with only one element; return that as the only thing in the list. Third case: degenerate input (no values given); return an empty list.

(In Scala, ::: concatenates two lists together, while x :: list sticks x on the front of list. When you're matching, it goes the other way around: case x :: stuff is used if the list can be broken into an element x and the rest, stuff. Nil is the empty list.)

Here it is in action:

scala> combine( List(2,2,2,2,3,3,3) )

res18: List[List[Int]] = List(List(2, 2, 2, 2, 3, 3, 3), List(2, 2, 2, 2, 3, 9),
  List(2, 2, 2, 2, 9, 3), List(2, 2, 2, 6, 3, 3), List(2, 2, 2, 6, 9),
  List(2, 2, 4, 3, 3, 3), List(2, 2, 4, 3, 9), List(2, 2, 4, 9, 3),
  List(2, 4, 2, 3, 3, 3), List(2, 4, 2, 3, 9), List(2, 4, 2, 9, 3), List(2, 4, 6, 3, 3),
  List(2, 4, 6, 9), List(2, 8, 3, 3, 3), List(2, 8, 3, 9), List(2, 8, 9, 3),
  List(4, 2, 2, 3, 3, 3), List(4, 2, 2, 3, 9), List(4, 2, 2, 9, 3), List(4, 2, 6, 3, 3),
  List(4, 2, 6, 9), List(4, 4, 3, 3, 3), List(4, 4, 3, 9), List(4, 4, 9, 3),
  List(8, 2, 3, 3, 3), List(8, 2, 3, 9), List(8, 2, 9, 3), List(8, 6, 3, 3), List(8, 6, 9))

Edit: if you just wanted to count them, you'd use a different type of recurrence. Let S(n) be the number of combinations taken from the nth onwards, and let L(n) be the value of the nth item in your list. Then

S(i) = S(i+1) +
       if (L(i)+L(i+1)<10) S(i+2) +
       if (L(i)+...+L(i+2)<10) S(i+3) +
       ....

So you start with the last item--only one possibility there--and work your way backwards in order using this formula. (If this is what you're after, I'll write code that does it, but hopefully the algorithm is clear enough as is.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文