找到最大的操作


12

挑战在于使用基本算术运算符(加法,减法,乘法,一元负数)从整数列表中找到最大数目

输入值

整数列表

输出量

使用 intput中的每个整数的最大结果。

输入顺序无关紧要,结果应该相同。

您不需要输出完整的操作,只需输出结果即可。

例子

Input : 3 0 1
Output : 4 (3 + 1 + 0)

Input : 3 1 1 2 2
Output : 27 ((2+1)*(2+1)*3))

Input : -1 5 0 6
Output : 36 (6 * (5 - (-1)) +0)

Input : -10 -10 -10
Output : 1000 -((-10) * (-10) * (-10))

Input : 1 1 1 1 1
Output : 6 ((1+1+1)*(1+1))

规则

  • 最短代码胜出

  • 适用标准“漏洞”

  • 您只能使用+ *-运算符(加,乘,减,一元求反)

  • 只要结果可以存储在32位整数中,代码就应该起作用。

  • 任何溢出行为都取决于您。

我希望这很清楚,这是我对Code Golf提出的第一个挑战建议。


您的示例之一就是使用了不允许的操作:如果一元否定要出现在白名单中,那么减法就没有必要了。
彼得·泰勒

编辑并添加一元否定。减法将保留在白名单中。
CNicolas 2014年

1
它必须是完整的程序还是足够的功能?
ThreeFx

完整程序。如果可以在线运行,甚至更好,但显然不是强制性的
CNicolas 2014年

@INSeed我应该添加一种在线运行方式吗?
骄傲的haskeller 2014年

Answers:


9

C-224字节-运行时间O(n)

o=0,w=0,n[55],t,*m=n,*p=n;main(r){for(;scanf("%d",++p);t<3?--p,w+=t/2,o+=t&1:t<*m|m==n?m=p:9)t=*p=abs(*p);t=o<w?o:w;o-=t;w-=t;t+=o/3;for(o%3?o%3-2?t?t--,w+=2:++*m:w++:9;t--;)r*=3;for(r<<=w;--p>n;)r*=*p;printf("%d",r>1?r:o);}

看到线性时间问题的指数时间解很有趣,但我认为这是一种逻辑上的解决方法,因为实际上没有算法可以得到加分,这是对数的字谜。

在将负数转换为正数并丢弃零之后,显然,我们对乘法最感兴趣。我们想要最大化最终数字的对数。

log(a + b)<log(a)+ log(b)除外,当a = 1或b = 1时除外,因此只有在我们有兴趣将任何东西加在一起的情况下,这种情况才会出现。通常,最好将1加到一个较小的数字上,因为与对一个大数字加1相比,这会导致对数增加更大,即百分比增加幅度更大。有四种可能的场景,以从高到低的顺序排列,以进行利用:

  1. 将1加到2得到+ log .405 [log(3)-log(2)]
  2. 将它们组合成三,则每1个+ log .366 [log(3)/ 3]
  3. 每2个中的2个给出+ log .347,每1个[log(2)/ 2]
  4. 将1加到3或更高的数字上可得到+ log .288或更小的值[log(4)-log(3)]

该程序会跟踪1的数量,2的数量以及最小数量大于2的情况,并列出了使用1的最不推荐方法。最后,它将所有剩余的数字相乘。


6

Haskell,126个字符

这只是蛮力,只是忽略了输入的符号而忽略了减法和一元否定。

import Data.List
f[x]=abs x::Int
f l=maximum$subsequences l\\[[],l]>>= \p->[f p+f(l\\p),f p*f(l\\p)]
main=interact$show.f.read

这段代码非常慢。代码对输入的每个子序列进行四次 递归计算f ([]和输入本身除外)。但嘿,这是代码高尔夫球。


5

SWI-序言-250

哦,男孩,我花了太长时间。

o(A,B,A+B).
o(A,B,A-B).
o(A,B,A*B).
t([],0).
t([A,B|T],D):-t(T,Q),o(A,B,C),o(C,Q,D).
t([A|T],C):-t(T,Q),o(A,Q,C).
a(A):-t(A,B),n(C),B>C,retract(n(C)),assert(n(B)).
m(A):-assert(n(0)),\+p(A),n(R),R2 is R,write(R2).
p(A):-permutation([0|A],B),a(B),0=1.

从命令行调用(例如):

> swipl -s filename.pl -g "m([1, 1, 1, 1, 1])" -t halt
6

(没有特别的原因,我发现我的高尔夫球功能名称拼写为“ tomato pot”,真是棒极了。)

非高尔夫版本:

% Possible operations
operation(Left, Right, Left + Right).
operation(Left, Right, Left - Right).
operation(Left, Right, Left * Right).

% Possible ways to transform
transform([], 0).
transform([A, B|T], D) :- transform(T, Q), operation(A, B, C), operation(C, Q, D).
transform([A|T], C) :- transform(T, Q), operation(A, Q, C).

% Throw the given array through every possible transformation and update the max
all_transforms(A) :- transform(A, B), n(C), B>C, retract(n(C)), assert(n(B)).

% Find all the permutations and transformations, then fail and continue execution.
prog(A) :- assert(n(0)), !, permutation([0|A], B), all_transforms(B), fail.

% End the program
finished :- n(R), write(R), nl, R2 is R, write(R2), nl.

% Run the program
main(A) :- ignore(prog(A)), finished.

说明:

  1. 接受数组作为参数。
  2. 获取数组的所有排列。
  3. 找到一些要添加到数组中的运算符。(这是通过动态编程完成的,看看是否可以将前两个元素组合在一起会更好。)
  4. 对照我们当前的最大值进行检查。如果更好,请更换它。
  5. 告诉程序我们失败了,以便它继续检查,但随后取反(使用ignore\+)以使谓词整体返回true并继续。
  6. 我们给了一个谓词字符串,而不是一个数字字符串,因此请先使用它进行分配is,然后再编写它。

4

斯卡拉(Scala),134

print(args.map(Math abs _.toInt)./:(Seq(Array(0)))((l,a)=>l.map(a+:_)++l.flatMap(_.permutations.map{r=>r(0)+=a;r}))map(_.product)max)

取消评论:

print(
  args
    .map(Math abs _.toInt)                     // to int, ignoring -
    .foldLeft(Seq(Array(0))){ (list,num) =>    // build up a list of sums of numbers
      list.map(num+:_) ++                      // either add the new number to the list
      list.flatMap(_.permutations.map{ copy =>
        copy(0)+=num                           // or add it to one of the elements
        copy
      })
    }
    .map(_.product) // take the maximum of the the products-of-sums
    .max
)

与意识到最大的答案始终可以表示为总和的结果的方法略有不同。

如此接近,但是一堆库的愚蠢(排列返回一个Iterator而不是一个Seq,对空序列的可怕类型推断,Array.update返回Unit)使我陷入了困境。


3

Python 278(O(n!))

from itertools import*
def f(n):
 f,n,m=lambda n:[(n,)]+[(x,)+y for x in range(1,n)for y in f(n-x)],map(abs,map(int,n.split())),0
 for p,j in product(permutations(n),f(len(n))):
  i=iter(p)
  m=max(m,reduce(lambda e,p:e*p,(sum(zip(*zip([0]*e,i))[1])for e in j)))
 return m

说明

  1. 一元求和应该明智地用于将所有负数转换为正数
  2. 查找数字的所有可能排列
  3. 使用整数分区查找给定排列的所有幂集
  4. 求和
  5. 返回总和的乘积的最大值

3

Haskell- 295290265246203189189182字节


终于可以了!而且现在它是一种蛮力,而不是动态的解决方案。


感谢自豪的哈萨克勒提供一些高尔夫技巧。

这可能不是一个完整的解决方案,因为我实际上很喜欢打高尔夫球,但这是我能想到的最好的方法(而且看起来很复杂,所以我就可以了):

import Data.List
main=interact$show.g.read
g x=maximum[product$a#b|a<-sequence$replicate(length x-1)[0,1],b<-permutations x]
(a:b)#(c:d:e)|a>0=b#(c+d:e)|0<1=c:b#(d:e)
_#x=x

新的测试用例:

[1,1,1,2,2]
12

[1,1,3,3,3]
54

[1,1,1,1,1,1,1,1,5,3]
270

解决方案说明:

main函数仅获取输入并g与之一起运行。

g 接受输入并返回总和和列表顺序的所有可能组合的最大值。

# 是用于计算清单中的总和的函数,如下所示:

a = [1,0,0,1]
b = [1,1,1,2,2]
a#b = [2,1,4]

这似乎是一个性能驱动的解决方案。
骄傲的haskeller 2014年

您可以写换行符;吗?它不会改变字节数,但会极大地提高可读性
骄傲的haskeller 2014年

@proudhaskeller我不知道该如何进行暴力破解,所以我不得不提出其他建议:D
ThreeFx

我对打高尔夫球的建议-1)内联仅使用一次的每个功能(除非使用模式匹配或保护)。2)您可以将d实施为d n=[0,2,1]!!nd n=mod(3-n)3。3)生成og获取列表的长度,而不是获取列表本身,因为它们仅取决于长度(很明显,只要不内联,此长度即成立)。4)替换otherwise0<1。5)使r的最后定义为r$o x:y。6)移除a@并替换为x:y。打高尔夫球祝你好运!
骄傲的haskeller 2014年

您的算法为[3,3,3,2,2,2,2,1,1,1]给出了错误的答案。我运行了您的代码,它返回216(我能想到的最大结果是729)。
Brilliand 2014年

1

GolfScript(52个字符)

~]0-{abs}%.1-.1,or@,@,-,-1%{!\$.0=3<@+{()}1if+}/{*}*

在线演示

feersum的分析相当出色,但如果目标是打高尔夫球而不是效率,则可以做得更进一步。用伪代码:

filter zeros from input and replace negatives with their absolute value
filter ones to get A[]
count the ones removed to get C
while (C > 0) {
    sort A
    if (A[0] < 3 || C == 1) A[0]++
    else A.append(1)
    C--
}
fold a multiply over A
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.