使用用户指定的数字生成有效方程


10

这是基于我的一位数学老师在中学时期玩的一款游戏。他将在板上写下5个随机的一位数字,然后再写入一个随机的两位数字。我们将尝试创建一个方程,该方程使用所有5个一位数字来产生两位数。以下是一些带有解决方案的示例,可以更好地说明这一点:

Input:           Solution:
7 5 4 8 4 34     5*8-7+4/4 = 34
3 1 5 7 6 54     (7+3)*6-5-1 = 54
3 9 2 1 6 87     9*(2+1)*3+6 = 87
2 1 6 9 7 16     (9-7+6*1)*2 = 16
2 4 5 8 6 96     8*(5+6)+2*4 = 96
3 8 4 5 4 49     8*(4+4)-3*5 = 49

面临的挑战是编写一个可以为给定输入生成此类方程式的程序。可以通过命令行或提示符来提供输入。始终将首先输入5个数字(无特定顺序),然​​后再输入两个数字。然后,程序将打印出找到的解决方案方程式;您不必处理没有解决方案的情况。该函数必须能够在方程式中使用以下运算:加法,减法,乘法和除法。如果您希望允许进行其他基本操作,那么只要它们仍然符合挑战的精神就可以了(否定,求幂和模数是不错的补充)。操作顺序遵循标准的数学规则,因此分组需​​要括号。

程序将根据代码长度(包括所需的空格)进行评分。注意:除法必须精确,不得四舍五入或截断为最接近的整数。



这是非常相似的任务,但是我认为附加术语以及对表达式分组方式的限制都不会扩展问题,以使它有趣地有所不同。此外,这是一场高尔夫挑战赛,而不是代码挑战赛,这将需要不同的解决方案。
Sir_Lagsalot 2012年

串联呢?例如,如果给定7 5 4 8 4 34,将允许输出7 + 54/8 * 4?
Patrick Roberts

Answers:


7

Python 2.7(284),Python 3.x(253)

from __future__ import division #(Remove for Python 3.x)
from itertools import *
a=raw_input().split()
for i in permutations(a[:-1],5):
 for j in product('+-*/',repeat=5):
  for k,l in combinations(range(1,12,2),2):
   d=''.join(sum(zip(i,j),()))[:-1];d='('+d[:l]+')'+d[l:]
   if eval(d)==int(a[-1]):print d;b

b在解决方案上给出错误(调用未知函数)。

基本上,这是巨大的暴力。它接受输入,将其按空格(1 2 -> [1,2])分割,然后在该列表中进行排列。对于每个排列,它将使用字符遍历长度为5的所有可能字符串+-*/。对于每个迭代,它将生成列表长度2的组合[1,3,5,7,9,11],将排列和字符串交织在一起(12345 *-/+- -> 1*2-3/4+5-),并放在括号中。最后,它将对其进行评估,如果答案和方程式为真,则将打印方程式并停止。

这大约是效率极低的,O(n!/(n-5)!)=O(n^5)但是对于测试输入来说,它在合理的时间内运行。


1
使用除法时,整数数学会导致错误的输出。例如,输入“ 3 6 8 7 1 29”将产生“(3 + 8/6)* 7 + 1”,等于31 1/3,而不是29。我将更新描述以使其明确。
Sir_Lagsalot 2012年

它给(3/6)*8*7+1我。
beary605

好的,我将其归结为我使用的口译员的问题。
Sir_Lagsalot 2012年

3

Scala 368:

第二个g = -Line更容易测试,第一个g = -Line可以灵活地接受命令参数,并且它们的长度相等,因此我仅从第二个开始计数-将其删除以进行args传递:

val g=(args.map(_.toDouble))
val g=Array(3,9,2, 1, 6, 87)
val k="+*/-DQ"
val i=(0 to 5)
val f:Seq[(Double,Double)=>Double]=Seq(_+_,_*_,_/_,_-_,(a,b)=>b-a,(a,b)=>b/a)
val h=g.init.permutations;
for(j<-h;o<-i;p<-i;q<-i;r<-i;z=try{f(r)(f(q)(f(p)(f(o)(j(0),j(1)),j(2)),j(3)),j(4))}catch{case _ => 0}
if(z==g(5)))printf("(((%d%c%d)%c%d)%c%d)%c%d=%d\n",j(0),k(o),j(1),k(p),j(2),k(q),j(3),k(r),j(4),g(5))

示例输出(您可能现在有一个问题-稍后):

(((5+7)/1)+6)*3=54
(((5-7)D1)*6)*3=54
(((5D7)+1)*6)*3=54
(((5+7)+6)Q1)Q3=54

那5D7呢?D1?是十六进制吗?有Q1,Q3-那是什么。

Sir_Lagsalot本着挑战的精神允许进行新的基本操作,是的,这些是基本操作,即Delta和Quotient。

它们与a / b和ab的不同之处在于aQb表示b / a,而aDb表示ba。我们称其为乌克兰记号。

所以

(((5-7)D1)*6)*3=54

手段

((1-(5-7))*6)*3=54
 (1-(-2))*6*3
   3*6*3 = 18*3=54

关于如何以及为什么这样一个更有趣的问题:一开始,我对放置括号的可能性以及(a + b)-c = a + bc =(a + bc)=((a + b) )-c)=(b + a)-c等。您可能会为这个问题感到生气,但是如果写下​​可能的括号组合,则有时会丢掉便条纸而面对这样一个事实:您始终在5个值之间执行4个运算,并且始终从其中之一开始。如果模式始终是(((_x_)x_)x_)x_ ?= _(x是4个运算符之一)并且允许相反的方向(xb)和(bxa),则说明了所有可能性。

现在,对于a + b和a * b,我们不需要相反的方向,它们是可交换的。因此,我发明了D和Q运算符,它只是切换方向。现在,我还有2个操作员,但不需要切换方向。好吧-这是在功能Sequence中完成的:

 (a,b)=>b-a,(a,b)=>b/a

我的理解力是从Array g中获取值,并将其分布在a到e上,然后选择4个索引来选择函数,然后选择(仅按索引)关联的运算符。我必须捕捉div / 0错误,因为减法可能导致零,而样本输入数据不包含0。


Delta和Quotient运算符很好。如果您计划打高尔夫球,则需要在输出中添加括号。
Sir_Lagsalot

现在,输出显示括号。
用户未知
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.