Maksimum işlemi bulun


12

Zorluk, temel aritmetik işleçleri (toplama, çıkarma, çarpma, tek taraflı olumsuzlama) kullanarak bir tamsayı listesinden alabileceğiniz maksimum sayıyı bulmaktır.

Giriş

Tamsayıların listesi

Çıktı

Intput'taki her tamsayıyı kullanan maksimum sonuç .

Giriş sırası önemli değil, sonuç aynı olmalıdır.

Tam sonucu çıkarmanız gerekmez, sadece sonuç.

Örnekler

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))

kurallar

  • En kısa kod kazanır

  • Standart "boşluklar" geçerlidir

  • Yalnızca + * - operatörlerini kullanabilirsiniz (toplama, çarpma, çıkarma, tekli olumsuzlama)

  • Sonuç 32 bitlik bir Tamsayıda saklanabildiği sürece kodun çalışması gerekir.

  • Herhangi bir taşma davranışı size kalmış.

Umarım bu yeterince açıktır, bu benim ilk Code Golf meydan okuma önerim.


Örneklerinizden biri izin verilmeyen bir işlem kullanıyor: eğer olağan olmayan olumsuzlama beyaz listenizde ise, çıkarma gerçekten gerekli değildir.
Peter Taylor

Düzenlenmiş ve tek taraflı olumsuzlama eklenmiştir. Çıkarma beyaz listede tutulur.
CNicolas

1
Tam bir program mı olmalı yoksa yeterli bir işlev mi?
ThreeFx

Tam program. Çevrimiçi olarak çalıştırılabiliyorsa, ancak açıkça zorunlu değilse bile daha iyi
CNicolas

@INSeed Çevrimiçi çalışmanın bir yolunu eklemem gerekir mi?
gururlu haskeller

Yanıtlar:


9

C - 224 bayt - Çalışma süresi 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);}

Doğrusal zaman problemi için sadece üstel zaman çözümlerini görmek eğlenceliydi, ama sanırım, logaritmanın bir anagramı olan bir algoritmaya sahip olmanın bonus noktaları olmadığı için devam etmek mantıklı bir yoldu.

Negatif sayıları pozitif ve sıfırları atadıktan sonra, çoğunlukla çarpma ile ilgileniyoruz. Nihai sayının logaritmasını en üst düzeye çıkarmak istiyoruz.

log (a + b) <log (a) + log (b), a = 1 veya b = 1 hariç, bu nedenle, birlikte bir şey eklemek istediğimiz tek durum bunlardır. Genel olarak, daha küçük bir sayıya 1 eklemek daha iyidir, çünkü bu, logaritmada daha büyük bir artışa, yani daha büyük bir yüzde artışına, büyük bir sayıya 1 eklemekten daha fazla neden olur. Bunları kullanmak için en çok en az tercih edilen şekilde sıralanan dört olası senaryo vardır:

  1. Birine 2 eklemek + log .405 verir [log (3) - log (2)]
  2. Bunları üçlülerle birleştirmek, birer birer + log .366 verir [log (3) / 3]
  3. Bunlardan 2'sinin yapılması, bir kerede + log .347 verir [log (2) / 2]
  4. 3 veya daha yüksek bir sayıya bir tane eklemek + log .288 veya daha azını verir [log (4) - log (3)]

Program, sayı, ikişer sayı ve 2'den büyük minimum sayıları takip eder ve bunları kullanmanın en çok ve en az tercih edilen yollarının listesine gider. Son olarak, kalan tüm sayıları çarpar.


6

Haskell, 126 karakter

bu sadece girişin işaretini görmezden gelmek ve çıkarma ve tek taraflı olumsuzlamayı görmezden gelmek dışında kaba-zorlamadır.

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

bu kod son derece yavaş. kod, girişin dört ardışıkında f'yi tekrar tekrar hesaplar ([] ve girişin kendisi hariç) . ama hey, bu kod golf.


5

SWI-Prolog - 250

Oh oğlum, bunun için çok uzun zaman harcadım.

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.

Komut satırından çağırılır (örn.):

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

(Parçasız bir sebepten dolayı, golf fonksiyonumun isimlerinin "domates saksısı" hecelediğini harika buldum.)

Ungolfed sürümü:

% 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.

Açıklama:

  1. Bir diziyi argüman olarak kabul edin.
  2. Dizinin tüm permütasyonlarını alın.
  3. Diziye eklenecek işleçlerin bazı düzenlemelerini bulun. (Bu, ilk iki öğeyi birleştirip birleştirmemenin daha iyi olup olmadığını görerek dinamik programlama yoluyla yapılır.)
  4. Mevcut maksimum değerimize göre bunu kontrol edin. Daha iyiyse değiştirin.
  5. Programa başarısız olduğumuzu söyleyin, böylece kontrol etmeye devam eder, ancak yüklemin genel olarak geri dönmesine izin vermek için ( ignoreveya kullanarak \+)true ve devam .
  6. Bize bir sayı yerine bir tahmin dizisi verilir, bu yüzden bunu kullanarak atayın isve yazın.

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)

Ungolfed ve yorumladı:

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
)

En büyük cevabın her zaman toplamların bir ürünü olarak ifade edilebileceğini fark etmekten biraz farklı bir yaklaşım.

Çok yakın, ama bir grup kütüphane aptallığı (permütasyonlar bir Seq yerine bir Iterator döndürür, boş dizilerde korkunç tip çıkarım, Array.update dönen Birim) beni içeri aldı.


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

açıklama

  1. Unary Negate, tüm negatif sayıları pozitif olarak dönüştürmek için akıllıca kullanılmalıdır
  2. Sayıların tüm olası permütasyonlarını bulun
  3. Belirli bir permütasyonun tüm güç setlerini bulmak için Tamsayı bölümünü kullanma
  4. Toplamların ürününü bulun
  5. Toplamların çarpımının maksimumu

3

Haskell - 295 290265246203189182 bayt


Sonunda çalışıyor! Ayrıca şimdi dinamik bir çözümden ziyade kaba bir güçtür.


Bazı golf ipuçları için proudhaskeller için teşekkürler.

Bu muhtemelen değil aslında golf sonrası emmek çünkü tam golfed çözüm, ancak ben ile çıkabilirler en iyisi (ve benim için gidiş var ki bu yüzden, karmaşık görünüyor):

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

Yeni test örnekleri:

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

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

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

Çözüm açıklaması:

mainFonksiyon sadece bir giriş alır ve çalıştırır gonunla.

g girdiyi alır ve olası toplamlar ve liste siparişleri kombinasyonlarının maksimumunu döndürür.

# aşağıdaki gibi bir listedeki toplamları hesaplayan işlevdir:

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

bu oldukça performans odaklı bir çözüm gibi görünüyor.
gururlu haskeller

;mümkünse satırsonu yazabilir misiniz ? bayt sayısını değiştirmez ancak okunabilirliğe büyük ölçüde yardımcı olur
gururlu haskeller

@proudhaskeller Bunu nasıl zorlayacağımı bilmiyordum, bu yüzden başka bir şey bulmak zorunda kaldım: D
ThreeFx

Bu golf için tavsiyem - 1) sadece bir kez kullanılan her işlevi satır içi (desen eşleştirme veya korumaları kullanmadığı sürece). 2) d'yi d n=[0,2,1]!!nveya olarak uygulayabilirsiniz d n=mod(3-n)3. 3) sadece uzunluğa bağlı oldukları için listenin kendisini almak yerine listenin uzunluğunu yapın ove galın (açıkçası bu sadece satır içi olmadıkları sürece geçerlidir). 4) yerine otherwiseile 0<1. 5) r be'nin son tanımını yapar r$o x:y. 6) a'yı çıkarın a@ve a ile değiştirin x:y. golf ile iyi şanslar!
gururlu haskeller

Algoritmanız [3,3,3,2,2,2,1,1,1] için yanlış cevap veriyor. Kodunuzu çalıştırdım ve 216 döndürdü (bulabildiğim en büyük sonuç 729 idi).
Brilliand

1

GolfScript (52 karakter)

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

Çevrimiçi demo

feersum'un analizi oldukça iyidir, ancak amaç verimlilikten ziyade golf oynamaksa daha ileri götürülebilir. Sözde kodda:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.