最大の操作を見つける


12

課題は、基本的な算術演算子(加算、減算、乗算、単項否定)を使用して整数のリストから取得できる最大数を見つけることです

入力

整数のリスト

出力

入力のすべての整数を使用した最大結果。

入力順序は関係なく、結果は同じである必要があります。

すべての操作を出力する必要はなく、結果だけを出力する必要があります。

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チャレンジ提案です。


あなたの例の1つは、許可されていない操作を使用しています。単項否定がホワイトリストに含まれることが意図されている場合、減算は実際には必要ありません。
ピーターテイラー14

単項否定を編集および追加しました。減算はホワイトリストに保持されます。
CNicolas 14

1
完全なプログラムである必要がありますか、それとも機能は十分ですか?
ThreeFx 14

完全なプログラム。さらに良いことに、それは明らかに必須ではありませんオンラインで実行することができますが、場合
CNicolas

@INSeedオンラインで実行する方法を追加する必要がありますか?
誇りに思ってhaskeller 14

回答:


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を追加することをお勧めします。シナリオを利用するために、最も望ましいシナリオから最も望ましくないシナリオの4つのシナリオがあります。

  1. 1を2に追加すると、+ log .405 [log(3)-log(2)]が得られます
  2. 1つを3つに結合すると、1つにつき+ log .366が得られます[log(3)/ 3]
  3. 1から2を作成すると、1つずつ+ log .347が得られます[log(2)/ 2]
  4. 3以上の数値に1を追加すると、+ 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を再帰的に4回 計算します([]および入力自体を除く)。しかし、ちょっと、それはコードゴルフです。


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

(特に理由もなく、ゴルフの機能名のスペルが「トマトポット」であることは素晴らしいと思いました。)

ゴルフされていないバージョン:

% 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. 配列に追加する演算子の配列を見つけます。(これは動的プログラミングを介して行われ、最初の2つの要素を組み合わせた方が良いかどうかを確認します。)
  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
)

最大の答えは常に合計の積として表現できることを認識することからの、わずかに異なるアプローチ。

非常に近いが、たくさんのライブラリの愚かさ(順列は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- 295290265246203189189バイト


最後に動作します!また、今では動的な解決策ではなく、総当たりです。


ゴルフのヒントの一部については、proudhaskellerに感謝します。

私は実際にゴルフを吸うので、これはおそらく完全にゴルフされたソリューションではありませが、それは私が思いつくことができる最高です(そして複雑に見えるので、私はそれを手に入れました):

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 14

可能な場合ではなく、改行を書いてください;。バイトカウントは変更しませんが、読みやすさを途方もなく助けます
誇りに思ってhaskeller 14

D:@proudhaskeller私は他の何かを思い付くしていた方法をブルートフォースにこのように、全く分からなかった
ThreeFx

これをゴルフするための私のアドバイス-1)一度だけ使用されるすべての関数をインライン化します(パターンマッチングまたはガードを使用しない限り)。2)d n=[0,2,1]!!nまたはとしてdを実装できますd n=mod(3-n)3。3)リスト自体を取得するのではなく、リストの長さだけを作成しog取得します(明らかに、インライン化されていない場合に限ります)。4)を交換otherwiseして0<1。5)rの最後の定義をbeにしますr$o x:y。6)を取り外し、a@aをに置き換えx:yます。あなたのゴルフで頑張ってください!
誇りに思ってhaskeller 14

アルゴリズムは[3,3,3,2,2,2,1,1,1,1]に対して間違った答えを与えます。コードを実行すると、216が返されます(思いついた最大の結果は729でした)。
ブリリアンド14

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.