Trova l'operazione massima


12

La sfida è trovare il numero massimo che puoi ottenere da un elenco di numeri interi usando operatori aritmetici di base (addizione, sottrazione, moltiplicazione, negazione unaria)

Ingresso

Un elenco di numeri interi

Produzione

Il massimo risultato usando ogni numero intero nell'intput.

L'ordine di input non ha importanza, il risultato dovrebbe essere lo stesso.

Non è necessario eseguire l'output dell'intera operazione, ma solo il risultato.

Esempi

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

Regole

  • Il codice più corto vince

  • Si applicano "scappatoie" standard

  • È possibile utilizzare solo + * - operatori (addizione, moltiplicazione, sottrazione, negazione unaria)

  • Il codice dovrebbe funzionare fino a quando il risultato può essere memorizzato su un numero intero a 32 bit.

  • Qualsiasi comportamento di overflow dipende da te.

Spero che sia abbastanza chiaro, questo è il mio primo suggerimento per la sfida di Code Golf.


Uno dei tuoi esempi sta usando un'operazione che non è consentita: se la negazione unaria è prevista nella tua lista bianca, la sottrazione non è davvero necessaria.
Peter Taylor,

Negazione unaria modificata e aggiunta. La sottrazione viene mantenuta nella lista bianca.
CNicolas,

1
Deve essere un programma completo o è una funzione sufficiente?
ThreeFx,

Programma completo. Ancora meglio se può essere eseguito online, ma ovviamente non obbligatorio
CNicolas

@INSeed Devo aggiungere un modo per correre online?
orgoglioso haskeller il

Risposte:


9

C - 224 byte - Tempo di esecuzione 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);}

È stato divertente vedere solo soluzioni di tempo esponenziale per un problema di tempo lineare, ma suppongo che fosse il modo logico di procedere poiché non c'erano punti bonus per avere effettivamente un algoritmo, che è un anagramma di logaritmo.

Dopo aver convertito i numeri negativi in ​​zero positivi e scartando, chiaramente ci interessa soprattutto la moltiplicazione. Vogliamo massimizzare il logaritmo del numero finale.

log (a + b) <log (a) + log (b) tranne quando a = 1 o b = 1, quindi quelli sono gli unici casi in cui siamo interessati ad aggiungere qualcosa insieme. In generale è meglio aggiungere un 1 a un numero più piccolo, perché ciò provoca un aumento maggiore del logaritmo, ovvero un aumento percentuale maggiore, rispetto all'aggiunta di 1 a un numero elevato. Esistono quattro possibili scenari, ordinati dal più preferibilmente meno preferibile, per l'utilizzo di quelli:

  1. Aggiungendo uno a 2 si ottiene + log .405 [log (3) - log (2)]
  2. La combinazione di quelli in tre dà + log .366 per uno [log (3) / 3]
  3. Fare un 2 su uno dà + log .347 per uno [log (2) / 2]
  4. Aggiungendo uno a un numero 3 o superiore si ottiene + log .288 o meno [log (4) - log (3)]

Il programma tiene traccia del numero di quelli, il numero di due e il numero minimo maggiore di 2 e scende l'elenco dei modi più preferibili per usarli. Infine, moltiplica tutti i numeri rimanenti.


6

Haskell, 126 caratteri

questo è solo bruto, con l'eccezione di ignorare il segno dell'input e ignorare la sottrazione e la negazione unaria.

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

questo codice è estremamente lento. il codice calcola ricorsivamente f su ciascuna sottosequenza dell'input quattro volte (tranne per [] e l'input stesso) . ma hey, è il golf del codice.


5

SWI-Prolog - 250

Oh ragazzo, ci ho passato troppo tempo.

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.

Chiamato dalla riga di comando (ad es.):

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

(Per nessun motivo particolare, ho trovato fantastico che i nomi delle mie funzioni giocate a golf dicessero "pot di pomodoro").

Versione non golfata:

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

Spiegazione:

  1. Accettare un array come argomento.
  2. Ottieni tutte le permutazioni dell'array.
  3. Trova una disposizione degli operatori da aggiungere all'array. (Ciò avviene tramite la programmazione dinamica, verificando se è meglio combinare i primi due elementi o meno).
  4. Controlla questo con il nostro valore massimo attuale. Se è meglio, sostituiscilo.
  5. Informa il programma che abbiamo fallito in modo che continui a controllare, ma poi negalo (usando ignoreo \+) per consentire al predicato di ritornare truee continuare.
  6. Ci viene data una stringa di predicati, anziché un numero, quindi assegnalo usando ise poi scrivilo.

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)

Ungolf e commentato:

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
)

Un approccio leggermente diverso, dal rendersi conto che la risposta più grande può sempre essere espressa come un prodotto di somme.

Così vicino, ma un sacco di stupidità da biblioteca (permutazioni restituisce un Iteratore invece di un Seq, inferenza di tipo orribile su sequenze vuote, Array. Aggiornamento unità di ritorno) mi ha fatto entrare.


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

Spiegazione

  1. Unary Negate dovrebbe essere usato con giudizio per convertire tutti i numeri negativi in ​​positivi
  2. Trova tutte le possibili permutazioni dei numeri
  3. Utilizzo della partizione Integer per trovare tutti i gruppi di potenza di una determinata permutazione
  4. Trova il prodotto delle somme
  5. Restituisce il massimo del prodotto delle somme

3

Haskell - 295 290 265 246 203 189 182 byte


Finalmente funziona! Inoltre ora è una forza bruta piuttosto che una soluzione dinamica.


Grazie a proudhaskeller per alcuni dei consigli sul golf.

Probabilmente questa non è una soluzione completamente giocata a golf perché in realtà faccio schifo al golf, ma è la migliore che posso inventare (e sembra complicata, quindi ho capito che va bene per me):

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

Nuovi casi di test:

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

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

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

Spiegazione della soluzione:

La mainfunzione ottiene solo un input e viene eseguita gcon esso.

g accetta l'input e restituisce il massimo di tutte le possibili combinazioni di somme e ordini di elenco.

# è la funzione che calcola le somme in un elenco come questo:

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

questa sembra una soluzione piuttosto orientata alle prestazioni.
orgoglioso haskeller il

puoi per favore scrivere newline invece che ;quando possibile? non cambia il conteggio dei byte ma aiuta la leggibilità in modo trionfale
haskeller orgoglioso

@proudhaskeller Non avevo idea di come forzare questa forza, quindi ho dovuto
inventarmi

il mio consiglio per giocare a golf con questo - 1) incorpora tutte le funzioni che vengono usate una sola volta (a meno che non utilizzi il pattern matching o le protezioni). 2) è possibile implementare d come d n=[0,2,1]!!no d n=mod(3-n)3. 3) crea oe gprendi la lunghezza della lista invece di prendere la lista stessa, poiché dipendono solo dalla lunghezza (ovviamente questo vale solo fino a quando non sono allineati). 4) sostituire otherwisecon 0<1. 5) rendere l'ultima definizione di r essere r$o x:y. 6) rimuovere a@e sostituire un con x:y. buona fortuna con il tuo golf!
orgoglioso haskeller il

Il tuo algoritmo fornisce la risposta errata per [3,3,3,2,2,2,1,1,1]. Ho eseguito il tuo codice e restituisce 216 (il risultato più grande che sono riuscito a trovare è stato 729).
Brilliand,

1

GolfScript (52 caratteri)

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

Demo online

L'analisi di feersum è piuttosto buona, ma può essere ulteriormente approfondita se l'obiettivo è giocare a golf anziché a efficienza. In pseudo-codice:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.