3
在尽可能短的时间内找到该数字难题的所有解决方案
历史 我的公司每周向公司内的每个人发送时事通讯。这些新闻通讯中包括一个谜语,并向公司中第一个向上一周的谜语发送电子邮件/提供解决方案的人大喊大叫。对于科技公司来说,这些谜语大多数都不是小事,而且平淡无奇,但是几个月前,有一个引起了我的注意。 原始谜语: 鉴于以下形状: 您具有从1到16的自然数。将它们全部适合此形状,以使所有连续的行和连续的列总计为29。 例如,以下是该难题的一种解决方案(这是我提交给时事通讯的“规范”解决方案): 但是,在解决此问题的过程中,我发现了一些相当有趣的信息: 解决方案远远不止一种。实际上,有9,368解决方案。 如果将规则集扩展为仅要求行和列彼此相等,而不必等于29,则会得到33,608个解决方案: 4,440个解决方案,总计27个。 7,400个解决方案,总计28个。 9,368个解决方案,总计29个。 6,096个解决方案,总计30个。 5,104个解决方案,总计31个。 1,200个解决方案,总计32个。 因此,我和我的同事们(尽管大多数情况下只是我的经理,因为他是我之外唯一拥有“通用”编程技能的人)开始了一个挑战,这个挑战持续了一个月的大部分时间-我们还有其他实际工作,我们必须承担的相关义务—尝试编写一个程序,以最快的方式找到每个解决方案。 原始统计 我编写的用于解决该问题的第一个程序只是反复检查随机解,并在找到解时停止运行。如果您已经对这个问题进行了数学分析,那么您可能已经知道这不应该起作用。但是以某种方式我很幸运,该程序只花了一分钟时间就找到了一个解决方案(我在上面发布了一个解决方案)。重复运行该程序通常要花费10到20分钟,因此显然这不是严格解决问题的方法。 我切换到了“递归解决方案”,该解决方案遍历了难题的每个可能排列,并通过消除未加总和而一次丢弃了很多解决方案。IE,如果我正在比较的第一行/列已经不相等,那么我可以立即停止检查该分支,因为知道拼图中没有其他排列会改变这一点。 使用这种算法,我获得了第一个“正确”的成功:该程序可以在大约5分钟内生成并吐出所有33,608个解决方案。 我的经理采用了另一种方法:根据我的工作,得知唯一可能的解决方案的总和为27、28、29、30、31或32,他编写了一个多线程解决方案,仅检查那些特定值的可能总和。他设法使程序仅在2分钟内运行。所以我又重复了一次。我对所有可能的3/4位和进行了哈希处理(在程序开始时;在总运行时中进行了计数),并使用行的“部分和”来基于先前完成的行查找剩余值,而不是测试所有剩余值,并将时间减少到72秒。然后,使用一些多线程逻辑,我将其缩短到40秒。我的经理将程序带回家,对程序的运行方式进行了一些优化,并将其降低到12秒。我对行和列的评估重新排序, 一个月后,我们中每个人获得程序最快的是我的经理0.15秒,我的0.33秒。最后,我声称我的程序更快,因为我经理的程序虽然找到了所有解决方案,但并未将它们打印到文本文件中。如果他在代码中添加了该逻辑,则通常需要花费0.4-0.5秒以上的时间。 我们既然允许我们内部的个人挑战生存,当然,问题依然存在:可这一计划进行得更快? 这就是我要对你们提出的挑战。 您的挑战 我们根据“ 29之和”规则放宽的参数改为“所有行/列的总和相等”,我也将为你们设置该规则。因此,面临的挑战是:编写一个程序,以在尽可能短的时间内找到(并打印)此难题的所有解决方案。我将为提交的解决方案设置一个上限:如果该程序在相对不错的计算机(小于8岁)上花费10秒钟以上,则可能太慢而无法计算。 另外,我还有一些难题的奖励: 您能否概括该解决方案,使其适用于任何16个数字集,而不仅是int[1,16]?时间分数将根据原始提示号集进行评估,但会通过此代码路径传递。(-10%) 您是否可以用能很好地处理和解决重复编号的方式编写代码?这并不像看起来那样简单!“视觉上相同”的解决方案在结果集中应该是唯一的。(-5%) 你能处理负数吗?(-5%) 您也可以尝试生成处理浮点数的解决方案,但是,如果完全失败,请不要感到震惊。如果您确实找到了一个可靠的解决方案,那可能值得大笔奖励! 出于所有目的和目的,“轮换”被视为唯一的解决方案。因此,只是一个不同解决方案的轮换解决方案将被视为自己的解决方案。 我在计算机上使用的IDE是Java和C ++。我可以接受其他语言的答案,但您可能还需要提供一个链接,以获取可以为您的代码轻松设置运行时环境的位置。