在 PHP 中,如何找到所有 N 个个位数、非重复数字的总和达到给定总和的集合?
假设我想找到所有 5 个个位数的非重复数字,加起来等于 30...我最终会得到 [9,8,7,5,1], [9,8,7 ,4,2]、[9,8,6,4,3]、[9,8,6,5,2]、[9,7,6,5,3] 和 [8,7,6, 5,4]。每组都包含 5 个不重复的数字,加起来等于 30,即给定的总和。
任何帮助将不胜感激。即使只是我使用的一个起点也会很棒。
我想出了一种方法,这似乎是一个很长的方法:获取所有唯一的 5 位数字(12345、12346、12347 等),将数字相加,然后看看它是否等于给定的总和(例如30)。如果是,则将其添加到可能的匹配集列表中。
我这样做是为了一个个人项目,这将帮助我解决数谜题,而不是一次真正解决整个问题。是的,这可能是作弊,但它......它并没有那么糟糕......:P
Let's say I want to find all sets of 5 single-digit, non-repeating numbers that add up to 30... I'd end up with [9,8,7,5,1], [9,8,7,4,2], [9,8,6,4,3], [9,8,6,5,2], [9,7,6,5,3], and [8,7,6,5,4]. Each of those sets contains 5 non-repeating digits that add up to 30, the given sum.
Any help would be greatly appreciated. Even just a starting point for me to use would be awesome.
I came up with one method, which seems like a long way of going about it: get all unique 5-digit numbers (12345, 12346, 12347, etc.), add up the digits, and see if it equals the given sum (e.g. 30). If it does, add it to the list of possible matching sets.
I'm doing this for a personal project, which will help me in solving Kakuro puzzles without actually solving the whole thing at once. Yeah, it may be cheating, but it's... it's not THAT bad... :P
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
一种简单的方法是将变量从
12345
增加到98765
,并且仅当它具有唯一数字且数字总和为30
时才选择它:工作示例
A naive approach would be to increment a variable from
12345
till98765
and to select it only if it has unique digits and sum of digits is30
:Working example
这可能足够快:
This is probably sufficiently fast:
使用此处中的组合代码
结果
是不是很可爱?
Using Combinations code from here
result
isn't it cute?
我知道有一些算法可以实现这一点,并且它们可能会由其他人提供,但是您可以进行一个快速简化:查找所有 4 个个位数加起来为 21-29 的集合(我假设您是不把 0 算作一个数字),只消除 30-(总和)是其中一个数字的那些。
如果我想更快地尝试一些东西,我会考虑从 45678 开始,通过在一个数字上加 1 并从另一个数字上减去 1 来逐步改变它。但不确定最终效果如何。
I know there are algorithms for this, and they will probably be provided by other people, but here's one quick simplification you can make: look for all sets of 4 single digits that add up to 21-29 (I'm assuming you're not counting 0 as a digit) and just eliminate the ones for which 30-(the sum) is one of the digits.
If I wanted to try something even quicker, I'd think about starting with 45678 and incrementally changing that by adding 1 to a digit and subtracting 1 from another digit. Not sure how well it'd work in the end, though.
我相信这被称为子集和问题:
http://mathworld.wolfram.com/SubsetSumProblem.html
I believe this is known as the Subset Sum problem:
http://mathworld.wolfram.com/SubsetSumProblem.html
让我们写 f(30,5,1) 作为问题的答案。 30 表示所需的总和,5 表示应添加到所需总和的位数,1 表示可接受的最小位数。在这种形式下,您可以递归地解决问题。例如,
f(30,5,b) = sum(i = 1..9) f(30-i,4,i+1)
我们正在有效地穷尽出现的最低值 i在您寻求的组合中。
如果您更仔细地考虑 i 的最大可能值(它不能太大,因为它是数字中的最小值),并添加一些适当的纾困条件,那么您将获得一个非常快速的解决方案。
Let's write f(30,5,1) for the answer to your problem. The 30 indicates the desired sum, the 5 indicates the number of digits which should add to the desired sum, and the 1 indicates the minimal acceptable digit. In this form, you can solve the problem recursively. For example,
f(30,5,b) = sum(i = 1..9) f(30-i,4,i+1)
We are effectively exhausting over the lowest value i occurring in the combination you seek.
If you think more carefully about the maximum possible value of i (it can't be too large since it's the minimum of the digits), and add some appropriate bail-out conditions, then you'll have a very fast solution.
打印数字之和形成一个包含 n 个数字的数组,其中没有重复的数字。例如
输入:[100, 213, 414, 555, 62, 321]
输出:596(即 213+62+321 )
Print sum of numbers form an array of n numbers having no duplicate digit in it. For example
Input: [100, 213, 414, 555, 62, 321]
Output: 596 ( i.e. 213+62+321 )