Encontrar caminos máximos

12

Dado un cuadrado positivo, los números naturales escriben un programa para encontrar una ruta horizontal y una vertical con la suma de números a lo largo de ellos siendo máxima. Una ruta horizontal va de la primera columna a la última y tiene que aumentar su posición de columna en uno en cada paso. Una ruta vertical va de la primera fila a la última y tiene que aumentar su posición de fila en uno en cada paso. Además, la posición de la fila en un camino horizontal puede permanecer igual o cambiar en uno en cualquier dirección, del mismo modo para los caminos verticales.

Para ilustrar, lo siguiente podría ser una ruta válida:

Ilustración de una ruta válida

La siguiente ruta sería inválida, ya que retrocede (y permanece en la misma fila en algunos lugares):

Ilustración de una ruta inválida

La siguiente ruta sería igualmente inválida, ya que cambia la posición de la fila en más de uno en un solo paso:

Otra ilustración de una ruta inválida

Nota: La solución debe ejecutarse en un período de tiempo aceptable.

Entrada

n líneas de entrada con n enteros positivos separados por espacios, cada una se da en la entrada estándar. 2 ≤ n ≤ 40. Cada línea termina con un salto de línea. Los números son lo suficientemente pequeños como para que la suma máxima encaje en un entero con signo de 32 bits.

Salida

Las sumas máximas de las rutas horizontales y verticales (en ese orden) separadas por un solo espacio.

Entrada de muestra 1

1 2
1 2

Salida de muestra 1

3 4

Entrada de muestra 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

Salida de muestra 2

37 35

Entrada de muestra 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

Salida de muestra 3

4650 4799

Para su comodidad, hemos preparado algunos casos de prueba en bash (gracias a Ventero ) y PowerShell a través de los cuales puede ejecutar su programa. La invocación es:, <test> <command line>entonces algo así como ./test python paths.pyo ./test.ps1 paths.exe. Que te diviertas :-)

Joey
fuente
@Joey: Tarea ligeramente alterada de la que usamos el año pasado en nuestro concurso :)
Joey
¡+10 para el bashscript de prueba! Ojalá todo el código de golf viniera con tal.
MtnViewMark
@MtnViewMark: Intentamos :-) Personalmente, odio las tareas que requieren demasiada aclaración después de ser publicadas y, por lo general, escribo mis propios scripts de prueba, ya que necesito saber cuándo un intento de golf introduce una regresión. También he observado que algunas personas tienden a publicar respuestas claramente incorrectas. Los casos de prueba ayudan a que todos estén en la misma línea. Tener una instalación que funcione para cada tarea en lugar de solo hackjobs únicos para cada tarea claramente sería mejor, pero todavía no estamos allí ;-)
Joey

Respuestas:

6

GolfScript - 49 caracteres mejorados de Nabb

51 caracteres
50 caracteres estrictamente necesarios absolutamente + 3 holgazanes que solo hicieron el trabajo de 1
56 caracteres en su mayoría redundantes

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

51 solución:

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

53 solución:

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

El método funciona en dos líneas a la vez, una que contiene las sumas máximas alcanzadas en cada punto y otra que contiene la siguiente línea.

a / 14: Repite dos veces, una para cada resultado.
8: Tome la primera línea de la entrada y cámbiela detrás de la matriz de entrada, esta ahora es el primer conjunto de sumas máximas.
b / 13: Iterar sobre cada línea restante en la matriz.
9: Ponga 0 al comienzo de las sumas máximas.
c / 12: Iterar sobre cada elemento de la línea.
10: Haga una copia de las sumas máximas con el primer elemento eliminado.
11: Tome los primeros 3 elementos de las sumas máximas, ordénelos y agregue el más grande al elemento actual de la línea.

56 solución:

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

1: desde la entrada hasta la matriz de matrices en 9 caracteres, en realidad podría haberse hecho con solo 1, pero rompí esa clave, así que esto tendrá que hacer.
2: 4 caracteres solo para hacer una copia transpuesta.
3: Matriz de 99 0s en 5 caracteres, probablemente podría hacerse de una manera más inteligente, pero fumo demasiada hierba para entender cómo.
4: Doble bucle demasiado complicado que itera sobre cada elemento de la entrada y hace una lógica difusa o algo así para producir el resultado. Nabb probablemente hará algo equivalente en alrededor de 3½ caracteres.
5: Por ahora el resultado está ahí, dentro de una matriz que es, este código tonto está ahí para sacarlo (y desechar un pedazo de sobras (y cambiar el resultado a su lugar)).
6: Este es un comando tan simple que su recuento de caracteres probablemente sería negativo en una solución óptima. 7: En este punto, el programa realmente está terminado, pero debido a la descuido en el código anterior, la salida está en el orden incorrecto y carece de espacio, por lo que aquí van algunos bits más por el desagüe.

aaaaaaaaaaaa
fuente
Ahh, simplemente asumí accidentalmente que la entrada no terminaría con una nueva línea. Me sorprende que en realidad funcionó parcialmente, ese tipo de cosas generalmente estropea un programa de GolfScript por completo.
aaaaaaaaaaaa
1
Se ve bien, aunque debería usarlo en {}*lugar de (\{}%.
Nabb
Sí, eso tiene sentido, gracias.
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)

Me niego a hacer IO, bajando mi puntaje dramáticamente. Pasa todas las pruebas en el arnés de prueba (aunque solo funciona si la entrada termina con un final de línea, como en el arnés de prueba).

Eliminé el manejo de las terminaciones de línea de Windows, ya que Chris sugirió que no era necesario. La versión multiplataforma tendría a=:".;._2 toJ(1!:1)3como primera línea.

Explicación:

  • fda el par de solución llamando a p normalmente y con entrada transpuesta ( |:).
  • ptoma el máximo ( >./) de los totales de fila de la aplicación centre cada fila ( c/)
  • ctoma dos filas (x e y). Agrega x a cada uno de y, y desplazado hacia arriba 1 celda ( 1|.!.0 y), y y desplazado hacia abajo 1 celda ( _1|.!.0 y). Luego toma los máximos de las tres alternativas para cada fila. ( >./) El resto es rango [sic]: no estoy seguro de si lo estoy haciendo bien.
Jesse Millikan
fuente
44
Exactamente, bajando su puntaje. -1
aaaaaaaaaaaa
@eBusiness: ¿Está seguro de que el voto negativo es la respuesta correcta a una solución incompleta?
Jesse Millikan
1
@Joey: No votar es la otra opción. Estaba demasiado cansado para hacer IO en ese momento, pero mi solución es tan diferente de la otra solución J que realmente quería publicarla de todos modos. Si hubiera una forma explícita de marcar la respuesta como "no participante", o algo así, lo habría hecho.
Jesse Millikan
@Joey: Otra razón es que es poco probable que se revoquen los votos negativos, incluso si se soluciona la solución; el usuario original tiene que regresar y cambiar su voto. (Suprimido, me di cuenta de que eso provocó un corto circuito en la discusión, y se recuperó. Supongo que voy a disparar por la insignia "Disciplinado").
Jesse Millikan
@Jesse Millikan: Hacemos eso. No hay garantías, pero si soluciona el problema dentro de un tiempo razonable, la mayoría de los votantes deberán revocar sus votos.
aaaaaaaaaaaa
3

Haskell: 314 personajes necesarios

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: esto requiere el módulo Data.Vector . No estoy seguro de si está incluido en la plataforma Haskell o no.

Versión sin golf:

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

Esta solución utiliza la pereza, junto con Data.Vector , para la memorización. Para cada punto, se calcula la solución para la ruta máxima desde el mismo hasta el final, luego se almacena en la celda de Vector my se reutiliza cuando es necesario.

Joey Adams
fuente
Supongo que puede quitar las llaves después de su declaración where, si contrae todas las definiciones en una sola línea.
FUZxxl
2

Ruby 1.9, 155 caracteres

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]]*" ""

Solución sencilla que supera todas las pruebas.

Ventero
fuente
2

Haskell, 154 caracteres

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

  • Editar: (155 -> 154) alineó la función plegada
MtnViewMark
fuente
¿Usando zipWith3acortar el código?
orgulloso Haskeller
Creo que podría reemplazar el máximo con foldl1 max, que agrega caracteres pero le permite factorizar foldl1 y max, lo que debería guardar los caracteres.
orgulloso Haskeller
maximum.foldl1, maxY max--vs-- f=foldl1;m=max;, f m.f, m, y m. - o 20 vs. 22. Entonces, no, no se guarda.
MtnViewMark
Correcto. Y acabo de recordar que la restricción del monomorfismo dejaría de escribir m=max. ¿Qué pasa con zipWith3?
orgulloso Haskeller
1

J, 109 + 10 = 119 caracteres

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

Correr con tr:

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

Como es habitual en J, la mayor parte del código es para entrada / salida. El código "real" tiene 65 caracteres:

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

Pasa todos los casos de prueba

Eelvex
fuente
Entonces, ¿necesitamos JB nuevamente con una solución que reduzca el análisis a 10 caracteres? ;-)
Joey
@Joey Estoy de vacaciones, apenas tengo acceso a internet; no mucho tiempo para jugar al golf ;-)
JB
¿Me puede dar una idea de cómo está ejecutando directamente maxpath.ijs?
Jesse Millikan
@Jesse: en * nix, coloque algunos #!/usr/bin/env jconsoleencima del archivo y establezca el indicador ejecutable.
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)

Si
tuviera que calcular solo una ruta más corta vertical u horizontal, podría hacerse en su lugar, ahorrando aproximadamente un tercio de los bytes.

hallvabo
fuente
1

Python, 204 caracteres

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)
Keith Randall
fuente