Trovare i massimi percorsi


12

Dato un quadrato di numeri naturali positivi, scrivere un programma trova un percorso orizzontale e uno verticale con la somma dei numeri lungo di essi massima. Un percorso orizzontale va dalla prima colonna all'ultima e deve aumentare la posizione della colonna di una in ogni passaggio. Un percorso verticale va dalla prima all'ultima riga e deve aumentare la posizione della riga di una in ogni passaggio. Inoltre, la posizione della fila in un percorso orizzontale può rimanere la stessa o cambiare di una in entrambe le direzioni, allo stesso modo per i percorsi verticali.

Per illustrare, potrebbe essere un percorso valido quanto segue:

Illustrazione di un percorso valido

Il seguente percorso non sarebbe valido, poiché fa un passo indietro (e rimane sulla stessa riga in alcuni punti):

Illustrazione di un percorso non valido

Il seguente percorso sarebbe ugualmente non valido, poiché modifica la posizione della riga di più di una in un singolo passaggio:

Un'altra illustrazione di un percorso non valido

Nota: la soluzione dovrebbe essere eseguita in un periodo di tempo accettabile.

Ingresso

N righe di input con n numeri interi positivi separati da spazi sono fornite ciascuna su input standard. 2 ≤ n ≤ 40. Ogni linea è terminata da un'interruzione di linea. I numeri sono abbastanza piccoli da contenere la somma massima in un intero con segno a 32 bit.

Produzione

Le somme massime dei percorsi orizzontale e verticale (in quell'ordine) separate da un singolo spazio.

Esempio di input 1

1 2
1 2

Uscita campione 1

3 4

Esempio di input 2

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 1 1 1 1 1 1 1 1 1 1 1 1
2 1 4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 4 1 3 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 4 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 5 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 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 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 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 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Uscita campione 2

37 35

Esempio di input 3

683 671 420 311 800 936
815 816 123 142 19 831
715 588 622 491 95 166
885 126 262 900 393 898
701 618 956 865 199 537
226 116 313 822 661 214

Uscita campione 3

4650 4799

Per tua comodità, abbiamo preparato alcuni casi di test in bash (grazie a Ventero ) e PowerShell su cui puoi eseguire il tuo programma. L'invocazione è:, <test> <command line>quindi qualcosa di simile ./test python paths.pyo ./test.ps1 paths.exe. Divertiti :-)


@Joey: compito leggermente modificato rispetto a quello che abbiamo usato l'anno scorso nel nostro concorso :)
Joey

+10 per lo bashscript di prova! Vorrei che tutto il codice golf venisse con questo.
MtnViewMark

@MtnViewMark: proviamo :-) Personalmente odio le attività che richiedono troppi chiarimenti dopo essere stato pubblicato e di solito scrivo i miei script di test in quanto devo sapere quando un tentativo di golf introduce ulteriormente una regressione. Inoltre ho osservato che alcune persone tendono a pubblicare risposte chiaramente sbagliate. I casi di test aiutano a mettere tutti sulla stessa linea. Avere una struttura che funziona per ogni attività invece che solo hackjobs una tantum per ogni attività sarebbe chiaramente migliore, ma non siamo ancora del tutto lì ;-)
Joey

Risposte:


6

GolfScript - 49 personaggi migliorati di Nabb

51 caratteri
50 caratteri strettamente necessari e 3 fannulloni che hanno fatto solo il lavoro di 1
56 personaggi per lo più ridondanti

n%{~]}%.zip{{0@+\{\.1>\3<$-1=@+}%\;}*$-1=\}2*' '@

51 soluzione:

n%{~]}%.zip{(\{0@+\{\.1>\3<$-1=@+}%\}%;$-1=\}2*' '@

53 soluzione:

n/{~]}%);.zip{(\{0@+\{\.1>\3<$-1=@+}%\}%;$-1=\}2*' '@
             a8_b9___c10___11______12 13      14_

Il metodo funziona su due righe alla volta, una contenente le somme massime raggiunte in ciascun punto e una contenente la riga successiva.

a / 14: ripetere due volte, una volta per ogni risultato.
8: Prendi la prima riga dall'input e commutala dietro l'array di input, questo ora è il primo set di somme massime.
b / 13: Iterate su ogni riga rimanente nell'array.
9: Metti 0 all'inizio delle somme massime.
c / 12: Iterate su ogni elemento della linea.
10: crea una copia delle somme massime rimuovendo il primo elemento.
11: Prendi i primi 3 elementi delle somme massime, ordinali e aggiungi il più grande all'elemento corrente della linea.

56 soluzione:

n/{~]}%);.zip{1,99*\{{\.1>\3<$-1=@+}%0\+\}%;$-1=\}2*' '@
1________2___ 3____ 4______________________5_____ 6_7___

1: Dall'input alla matrice di array in 9 caratteri, in realtà avrebbe potuto essere fatto con solo 1, ma ho rotto quella chiave quindi questo dovrà fare.
2: 4 caratteri solo per fare una copia trasposta.
3: Matrice di 99 0 in 5 caratteri, probabilmente potrebbe essere fatta in un modo più intelligente, ma fumo troppa erba per capire come.
4: Doppio loop eccessivamente complicato che scorre su ogni singolo elemento dell'input e fa una logica fuzzy o qualcosa del genere per produrre il risultato. Nabb probabilmente realizzerà qualcosa di equivalente in circa 3½ caratteri.
5: Ormai il risultato è lì, all'interno di un array che è, questo stupido pezzo di codice è proprio lì per tirarlo fuori (e spazzare un pezzo di avanzi (e cambiare il risultato in posizione)).
6: Questo è un comando così semplice che il suo conteggio dei caratteri sarebbe probabilmente negativo in una soluzione ottimale. 7: A questo punto il programma è veramente fatto, ma a causa della sciattezza nel codice precedente l'output è nell'ordine sbagliato e manca uno spazio, quindi qui ci sono alcuni bit in più nello scarico.


Ah, ho solo casualmente supposto che l'input non finisse con una nuova riga. Sono sorpreso che in realtà abbia funzionato parzialmente, quel genere di cose di solito rovina completamente un programma GolfScript.
aaaaaaaaaaaa

1
Sembra a posto, anche se dovresti usare {}*invece di (\{}%.
Nabb,

Sì, ha senso, grazie.
aaaaaaaaaaaa

3

J, 91 95

a=:".;._2(1!:1)3
c=:4 :'>./x+"1|:y,.(1|.!.0 y),._1|.!.0 y'
p=:[:>./c/
(":(p|:a),p a)1!:2(4)

Mi rifiuto di fare IO, abbassando drasticamente il mio punteggio. Supera tutti i test nel cablaggio di prova (sebbene funzioni solo se l'ingresso termina con una linea che termina, come nel cablaggio di prova).

Ho rimosso la gestione per i finali di linea di Windows, poiché Chris ha suggerito che non era necessario. La versione multipiattaforma avrebbe a=:".;._2 toJ(1!:1)3come prima linea.

Spiegazione:

  • ffornisce la coppia di soluzioni chiamando p normalmente e con input trasposto ( |:).
  • pprende il massimo ( >./) dei totali di riga dall'applicazione ctra ogni riga ( c/)
  • cprende due file (xey). Aggiunge x a ciascuna di y, y spostata in alto di 1 cella ( 1|.!.0 y) e y spostata in basso di 1 cella ( _1|.!.0 y). Quindi prende il massimo delle tre alternative per ogni riga. ( >./). Il resto è rango [sic] - Non sono sicuro di farlo nel modo giusto.

4
Esatto, abbassando il tuo punteggio. -1
aaaaaaaaaaaa

@eBusiness: sei sicuro che il downvoting sia la risposta giusta a una soluzione incompleta?
Jesse Millikan,

1
@Joey: l'altra opzione non è la votazione. Ero troppo stanco per fare IO al momento, ma la mia soluzione è così diversa dall'altra soluzione J che volevo davvero pubblicarla comunque. Se ci fosse un modo esplicito di contrassegnare la risposta come "non partecipante", o qualcosa del genere, avrei.
Jesse Millikan,

@Joey: un altro motivo è che è improbabile che i voti negativi vengano invertiti anche se la soluzione è fissa; l'utente originale deve tornare e cambiare il proprio voto. (Eliminato, realizzato che ha messo in cortocircuito la discussione, e cancellato. Immagino che sparo invece per il badge "Disciplinato".)
Jesse Millikan

@Jesse Millikan: Lo facciamo. Nessuna garanzia, ma se risolvi il problema entro un termine ragionevole, la maggior parte dei votanti dovrebbe revocare il proprio voto.
aaaaaaaaaaaa,

3

Haskell: 314 caratteri necessari

import Data.Vector(fromList,generate,(!))
import List
l=fromList
x=maximum
g=generate
p a=show$x[m!i!0|i<-[0..h-1]]where{
w=length$head a;h=length$a;n=l$map l a;
m=g h$ \i->g w$ \j->n!i!j+x[k#(j+1)|k<-[i-1..i+1]];
i#j|i<0||i>=h||j>=w=0|1>0=m!i!j;}
q a=p a++' ':(p.transpose)a
main=interact$q.map(map read.words).lines

Nota: questo richiede il modulo Data.Vector . Non sono sicuro che sia incluso nella piattaforma Haskell o no.

Versione non golfata:

import Data.Vector(fromList,generate,(!))
import Data.List

-- horizontal; we use transpose for the vertical case
max_path :: [[Integer]] -> Integer
max_path numbers = maximum [m ! i ! 0 | i <- [0..h-1]] where
    w = length (head numbers)
    h = length numbers
    n = fromList $ map fromList numbers
    m = generate h $ \i -> generate w $ \j ->
        n ! i ! j + maximum [f i' (j+1) | i' <- [i-1..i+1]]
    f i j | i < 0 || i >= h || j >= w = 0
    f i j = m ! i ! j

max_paths :: [[Integer]] -> String
max_paths numbers = (show . max_path) numbers ++ " " ++
                    (show . max_path . transpose) numbers

main = interact $ max_paths . map (map read . words) . lines

Questa soluzione utilizza la pigrizia, insieme a Data.Vector , per la memorizzazione. Per ogni punto, viene calcolata la soluzione per il percorso massimo da essa fino alla fine, quindi memorizzata nella cella di Vector me riutilizzata quando necessario.


Immagino che tu possa rimuovere le parentesi graffe dopo la tua istruzione where, se comprimi tutte le definizioni in un'unica riga.
FUZxxl

2

Ruby 1.9, 155 caratteri

f=->t{(1...l=t.size).map{|a|l.times{|b|t[a][b]+=t[a-1][(b>0?b-1:0)..b+1].max}};t[-1].max};q=[*$<].map{|a|a.split.map &:to_i};puts [f[q.transpose],f[q]]*" ""

Soluzione semplice che supera tutti i test.


2

Haskell, 154 caratteri

import List
z=zipWith
f=show.maximum.foldl1(\a->z(+)$z max(tail a++[0])$z max(0:a)a)
q a=f(transpose a)++' ':f a
main=interact$q.map(map read.words).lines

  • Modifica: (155 -> 154) ha sottolineato la funzione ripiegata

Usando zipWith3accorciamo il codice?
orgoglioso haskeller il

Penso che potresti sostituire il massimo con foldl1 max, che aggiunge caratteri ma ti consente di fattorizzare foldl1 e max, che dovrebbe salvare i caratteri.
orgoglioso haskeller il

maximum.foldl1, maxE max--vs-- f=foldl1;m=max;, f m.f, m, e m. - o 20 contro 22. Quindi, no, non salva.
MtnViewMark,

Giusto. E ho appena ricordato che la limitazione del monomorfismo avrebbe smesso di scrivere m=max. Che dire di zipWith3?
orgoglioso haskeller il

1

J, 109 + 10 = 119 caratteri

y=:0".(1!:1)3
N=:%:#y
y=:y$~N,N
r=:(((1&{)(+(3>./\0,0,~]))(0&{)),2&}.)^:(<:N)
(":([:>./"1([:r|:),r)y)(1!:2)4

Esegui con tr:

cat << EOF | tr \\n ' ' | ./maxpath.ijs

Come al solito in J, la maggior parte del codice è per input / output. Il codice "effettivo" è di 65 caratteri:

r=:(((1&{)(+(3>./\0,0,~]))(0&{)),2&}.)^:(<:#y)
([:>./"1([:r|:),r)y

Passa tutti i casi di test


Quindi abbiamo di nuovo bisogno di JB con una soluzione che riduca l'analisi a 10 caratteri? ;-)
Joey,

@Joey sono in vacanza, ho a malapena accesso a Internet; non c'è molto tempo per giocare a golf ;-)
JB

Puoi darmi un'idea di come stai eseguendo direttamente maxpath.ijs?
Jesse Millikan,

@Jesse: In * nix mettine un po ' #!/usr/bin/env jconsolesopra il file e imposta il flag eseguibile.
Eelvex,

1

Python, 149

import sys
def f(g,t=[]):
 for r in g:t=[int(e)+max(t[i-1:i+2]+[0])for i,e in enumerate(r)]
 print max(t),
g=map(str.split,sys.stdin)
f(zip(*g)),f(g)

Se dovessi calcolare solo un percorso più breve verticale o orizzontale,
potrebbe invece essere eseguito sul posto, risparmiando circa un terzo dei byte.


1

Python, 204 caratteri

import sys
I=sys.stdin.read()
n=I.count('\n')
A=map(int,I.split())
R=range(n)
X=lambda h,a:[a[i]+max(([0]+h)[i:i+3])for i in R]
h=v=[0]*n
for i in R:h=X(h,A[i*n:i*n+n]);v=X(v,A[i::n])
print max(v),max(h)
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.