是时候做数学了


14

介绍

这是我最喜欢的数学难题之一。

给定一个数字(例如3)和使用该数字的次数(例如5),请生成10个表达式,仅使用+即可得出1、2、3、4、5、6、7、8、9和10 -,×,÷,^和√(根)(允许使用括号将操作分组)。

例如:

(3^3 + 3)/(3 + 3) = (33 - 3)/(3 + 3) = 3 + 3/3 + 3/3 = 5

请注意,以上所有方法均使用5个3和数学运算并将结果求和为5。您也可以在√之前使用3表示立方根。对于在√之前使用4表示第四个根,也是如此。

另请注意,可以使用两个3来形成33,或者可以使用三个3来形成333,依此类推。

挑战

  • 您将获得两个数字(范围从1到5)作为函数参数,STDIN或命令行参数。
  • 第一个数字表示要使用哪个数字,第二个数字表示要在表达式中使用该数字的次数。
  • 您的程序应输出大小为10(或10个以空格分隔的数字)的数组,其中每个元素表示是否(index + 1)可以使用真/假值来计算(仅使用允许的运算符)得出该数字的数学表达式。

例如,如果输入是

1 3

然后输出应该是

[1, 1, 1, 0, 0, 0, 0, 0, 0, 1]

因为只能使用三个1来表示1、2、3和10。

得分了

奖金

全部列印[−50]

如果输出数组元素等于合理组合的总数,则从您的分数中减去50以获取该(index + 1)值,而不是真实值或虚假值。

例如,如果只有3个可能的组合,即5个3的结果为5,则输出数组的 4 条目应为3。

极限数学[−100]

如果输出数组元素包含至少一个导致该(index + 1)值的实际表达式,则从您的分数中减去100 。

例如,如果使用五个3的,输出阵列的4 条目可以是(3^3 + 3)/(3 + 3)(33 - 3)/(3 + 3)3 + 3/3 + 3/3

过度杀伤力[−200]

如果输出数组元素包含所有可能的组合(用分隔|),则从您的分数中减去200 。该奖金被添加到Extreme Maths奖金的顶部,因此您总共获得−300。

例如,如果使用五个3,则输出数组的 4 元素应为(3^3 + 3)/(3 + 3)|(33 - 3)/(3 + 3)|3 + 3/3 + 3/3

注意:要获得相同结果的任何两个表达式在逻辑上都应该采用不同的方法来区别。

例如,使用五个3来获得5 3 + 3/3 + 3/3等于3/3 + 3 + 3/33/3 + 3/3 + 3因为它们每个都采用相同的方法。(3^3 + 3)/(3 + 3)(33 - 3)/(3 + 3)有所不同,因为分子中的30是通过不同的方法实现的。

更新:经过所有答案后,发现由于一元-和√ 的极端情况,所有答案都有缺陷。因此,就涉及答案的完整性而言,认为遗漏那些极端情况是可以的。

这是一个棘手的问题,但很有趣。

打高尔夫球快乐!


1
抱歉,这可能是愚蠢的,但是如何仅用3 1s 就得到10 ?
FryAmTheEggman 2014年

3
@FryAmTheEggman 11-1
Optimizer

1
啊,所以我
很傻

4
这是一个非常模糊的规则。我可能会认为1的平方根,1的平方根的等等都是不同的方法,并且我有无限多个答案。a + b与b + a不同吗?(-a)*(-b)与b * a是否不同?
feersum

2
我知道这一点,但是我不能以任何常规数字格式表示4 ^(4 ^(4 ^(4 ^ 4)))–存储4 ^(4 ^(4 ^ 4))因为整数已经需要更多位比宇宙中有原子)。因此,除非我使用能够处理此类数字(如果根本存在)的计算机代数系统,否则需要将它们视为特殊情况。但是,这几乎可以肯定需要比我被过分杀人的角色更多的角色因此,除非您在某种程度上排除了多个平方根,否则这些奖项毫无意义。
Wrzlprmft

Answers:


1

Python 3(不完美),449-300 = 149

遭受与KSab解决方案相同的缺点:没有一元运算符,全括号括起来,没有包含等价的表达式,例如(1+1)+11+(1+1)。通过将结果传递给,我消除了重复项set()。为了节省一些字节,输出可能有点难看,但是我喜欢这种方式。我也没有扎根,因为在这个问题上似乎他们没有买很多东西。

R=range
E=lambda z:eval(z.replace("^","**"))
def m(d,n):_=R(1,11);s={i:[]for i in _};r=R(1,n);n<2 and s[d].append(str(d));d=str(d);t=[[(d*i,i)for i in r]]+[[]]*n;h=[];[(h.append("("+A+o+B+")"),t[l].append((h[0],a+b))if a+b<n else E(*h)in _ and s[E(*h)].append(h[0]),h.pop())for l in r for j in R(l)for A,a in t[j]for k in R(l)for B,b in t[k]if a+b<=n for o in"+-*/^"if(o=="^"and-~-(0<E(B)<9)or 0==E(B)and"/"==o)-1];[print(i,set(s[i])or'')for i in _]

这将需要几分钟的时间运行,如果第二个参数是5,测试通过调用m(digit, number)

>>> m(1,3)
1 {'((1*1)^1)', '(1^(1+1))', '((1-1)+1)', '((1/1)/1)', '((1*1)*1)', '((1^1)/1)', '(1*(1*1))', '(1^(1*1))', '(1+(1-1))', '(1^(1^1))', '((1^1)*1)', '(1^(1/1))', '((1/1)*1)', '(1-(1-1))', '(1/(1^1))', '(1/(1*1))', '(1/(1/1))', '(1*(1^1))', '((1+1)-1)', '((1*1)/1)', '((1^1)^1)', '(1*(1/1))', '((1/1)^1)'}
2 {'(1*(1+1))', '((1^1)+1)', '((1+1)/1)', '((1*1)+1)', '((1+1)^1)', '(1+(1*1))', '((1/1)+1)', '(1+(1^1))', '(1+(1/1))', '((1+1)*1)'}
3 {'((1+1)+1)', '(1+(1+1))'}
4 
5 
6 
7 
8 
9 
10 {'(11-1)'}
>>> m(3,3)
1 {'((3/3)^3)'}
2 {'(3-(3/3))', '((3+3)/3)'}
3 {'(3-(3-3))', '((3-3)+3)', '((3/3)*3)', '(3*(3/3))', '(3/(3/3))', '((3+3)-3)', '(3^(3/3))', '(3+(3-3))', '((3*3)/3)'}
4 {'((3/3)+3)', '(3+(3/3))'}
5 
6 {'((3*3)-3)'}
7 
8 
9 {'(3+(3+3))', '((3+3)+3)', '((3^3)/3)'}
10 

4

Python(不完美)493474-300 = 174

该解决方案存在很多问题,首先,它会忽略任何太大的指数(任何指数大于100的指数)。我实际上不认为这会消除输入小于或等于5的任何可能性,但我不确定100%。

另一件事是,它不考虑任何一元平方根,因为它会变得复杂(任何项等于0或1的任何解都将产生无数个解)。出于相同的原因,它也不会考虑任何一元否定(“-”符号),而且我实际上不确定是否要问这个问题。

我还考虑了什么条件可以决定两个表达式是否相等,但是我找不到一种以直观的方式严格定义它的方法,因此(至少到目前为止)我没有实现任何类似的方法。这确实意味着它输出了很多结果,并且还以相当幼稚的方式使用了括号。

附带一提,我认为这可能包括我编写的最长的单行代码,尤其是在完全编写之前。

R=range
F=lambda s:lambda a,b:eval(s)
L=lambda D,N:[(int(str(D)*N),str(D)*N)]+[(o(u,v),"(%s%s%s)"%(s,c,t))for p in R(1,N)for u,s in L(D,p)for v,t in L(D,N-p)for c,o in[('+',F('a+b')),('-',F('a-b')),('*',F('a*b')),('/',F("1.*a/b if b else''")),('^',F("''if(a<0 and int(b)!=b)|(a and b<0)|(b>99)else a**b")),('v',F("b**(1./a)if a and(a>=0 or b)and(b>=0 or int(1./a)==1./a)&(1./a<99)else''"))]if o(u,v)!='']
A=L(*input())
for i in R(11):
 for v,s in A:
    if v==i:print i,s[1:-1]

示例:(“ v”代表“√”)

2,3

0 2*(2-2)
0 2v(2-2)
0 (2-2)*2
0 (2-2)/2
0 (2-2)^2
1 2^(2-2)
1 2-(2/2)
1 2v(2/2)
1 (2/2)^2
2 2v(2+2)
2 2+(2-2)
2 2-(2-2)
2 2v(2*2)
2 2*(2/2)
2 2/(2/2)
2 2^(2/2)
2 2v(2^2)
2 (2+2)-2
2 (2+2)/2
2 (2-2)+2
2 (2*2)-2
2 (2*2)/2
2 (2/2)*2
2 (2/2)v2
2 (2^2)-2
2 (2^2)/2
3 2+(2/2)
3 (2/2)+2
6 2+(2+2)
6 2+(2*2)
6 2+(2^2)
6 (2+2)+2
6 (2*2)+2
6 (2^2)+2
8 2*(2+2)
8 2*(2*2)
8 2*(2^2)
8 (2+2)*2
8 (2*2)*2
8 (2^2)*2

我发现有几件事情可以缩短LL=lambda D,N:[(int(str(D)*N),str(D)*N)]+[(o(u,v),"(%s%s%s)"%(s,c,t))for p in R(1,N)for u,s in L(D,p)for v,t in L(D,N-p)for c,o in[('+',F('a+b')),('-',F('a-b')),('*',F('a*b')),('/',F("1.*a/b if b else''")),('^',F("''if(a<0 and int(b)!=b)|(a and b<0)or b>100 else a**b")),('v',F("''if a==0 or(b<0 and int(1./a)!=(1./a))or(b or a<0)or(1./a)>100 else b**(1./a)"))]if o(u,v)!='']
FryAmTheEggman 2014年

我很抱歉,这则留言看起来非常糟糕:(反正解释:对比较时0,我试图否定的声明,然后交换后果我也发现了几个地方使用。|&而不是orand这两个花样。可以用来缩短对F的最后一次通话,但是那将需要一些Demorgan通话,而我的喙时间
用光了

@FryAmTheEggman哦,这很不错,我已经用您发布的内容更新了答案,当我有时间的时候我将看看最后一个。那些条件来检查输入的有效性确实比我预期的要重:/
KSab 2014年

+10的嵌套lambda的亮度,而且eval-我花了好一会儿才知道第二行!不过,我认为您已经在“最长的单行”中胜出。;)我同意忽略大指数;实际上,我认为任何大于9的指数都将无用(除非基数为1时作为无操作)。
DLosc 2014年

@DLosc那么您可以遇到的一种情况是3 = 33 √ (3 ^ 33)。实际上,在撰写本文时,我意识到我的答案遗漏的两个(可能只有两个?)组合4 = (4^4) √ (4 ^ (4^4))以及与5s 等效的表达式。诚然,根似乎并没有增加太多的问题,因为它们的绝大多数要么在0或1上用作无操作,要么在根为1时用作无操作,或者只是用来抵消幂。
KSab 2014年

3

Python的3 - 349 346

r=range
l=lambda s:eval("lambda a"+s)
def T(u,f,X,Y):
    try:return u(f(X,Y))
    except:0
c=l(',x:{x}.union(*[{u(int("1"*a)*x)}|{T(u,f,X,Y)for j in r(1,a)for X in c(j,x)for Y in c(a-j,x)for f in[l(",b:a%sb"%o)for o in{"**"}|set("+-*/")]+[l(",b:a**b**-1")]}for u in[l(":-a")]+[l(":a**.5**%i"%k)for k in r(9)]])')
R=l(",i:[{n+1}<c(i,a)for n in r(10)]")

这是一个相当不实用的版本:

def R(x,i):
    # Unary Operations
    U = [lambda a:-a] + [eval("lambda a:a**(1/2.**%i)" % j) for j in range(9)]
    # Binary Operations
    F = [eval("lambda a,b:a%sb"%o) for o in ["+","-","*","/","**"]] + [lambda a,b:a**(1./b)]

    def combos(i):
        L = {x}
        for u in U:
            # 3, 33, 333, etc.
            L |= {u(int(str(x)*i))}

            for j in range(1,i):
                for X in combos(j):
                    for Y in combos(i-j):
                        for f in F:
                            # To avoid trouble with division by zero, overflows and similar:
                            try:
                                L |= {u(f(X,Y))}
                            except:
                                pass
        return L

    return [n in combos(i) for n in range(1,11)]

对于测试,我建议更改(9)为较小的值,因为这是考虑到的多个平方根的数量,这会对性能产生巨大影响。

最后,这使我想知道,在某些情况下是否真的需要一元减法…


1
我认为您对一元“-”可能不添加任何内容是正确的(至少对没有奖金的基本问题而言)。我能想到的唯一不平凡的场景是1 = 3^3 * 3^(-3),但是即使考虑到这些,我也怀疑在没有其他方法的情况下,有多少方法可以解决这个问题。
KSab 2014年

1
您可以使用a**.5**%i而不是a**(1/2**%i)计算多个平方根来节省3个字节。
DLosc

@DLosc:的确,谢谢。
Wrzlprmft

您可以通过将四个空格缩进一个空格来节省六个字节。
Beta Decay

@BetaDecay:我从不使用四空格缩进(颤抖),而是使用制表符。只要看看我的帖子的来源。Stack Exchange只是将它们呈现为四个空间。
Wrzlprmft

2

Mathematica-246个字符(无奖金要求)

f[x_,y_]:=x-y
g[x_,y_]:=x/y
h[x_,y_]:=x^(1/y)
j[x_,y_]:=FromDigits@Join[IntegerDigits@x,{y}]
z[{r_,n_,L_}]:=z[{L[[1]][r,n],n,Rest@L}]
z[{r_,n_,{}}]:=r
a[n_,t_]:=Union@Select[z[{n,n,#}]&/@Tuples[{Plus,f,Times,g,Power,h,j},t-1],IntegerQ@#&&0<#<11&]

说明

函数以j数字方式连接两个数字。

Function z接受结果r,number n和函数列表L,每个函数都对两个参数进行操作。然后,它[r,n]使用递归将函数列表顺序应用于argumnt ,直到该列表为空,然后返回结果。

函数a需要n多个副本t。它从函数列表中创建长度为(t-1)的所有元组,{Plus, f, Times, g, Power, h, j}并通过函数z发送每个元组,然后返回创建的所有数字1至10的列表。

a[2,3]返回执行示例{1, 2, 3, 6, 8}

局限性

由于功能列表是按顺序应用的,每次消耗一个数字的副本,因此它可能会错过某些组合。例如,当以四为二进行运算时,由于无法评估乱序的函数列表,它将错过22/22 = 1。当然,这种情况为2/2 * 2/2 = 1。

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.