Trouver le maximum de chemins

12

Étant donné un carré de nombres positifs, écrire un programme trouver un chemin horizontal et vertical avec la somme des nombres le long d'eux étant maximale. Un chemin horizontal va de la première colonne à la dernière et doit augmenter sa position de colonne d'une unité à chaque étape. Un chemin vertical va de la première ligne à la dernière et doit augmenter sa position d'une ligne à chaque étape. De plus, la position des rangées dans un chemin horizontal peut rester la même ou changer d'une unité dans les deux sens, de même pour les chemins verticaux.

Pour illustrer, ce qui suit pourrait être un chemin valide:

Illustration d'un chemin valide

Le chemin suivant ne serait pas valide, car il recule (et reste sur la même ligne à certains endroits):

Illustration d'un chemin non valide

Le chemin suivant serait également invalide, car il modifie la position de la ligne de plusieurs en une seule étape:

Une autre illustration d'un chemin non valide

Remarque: La solution doit s'exécuter dans un délai acceptable.

Contribution

n lignes d'entrée avec n entiers positifs séparés par des espaces chacune sont données sur l'entrée standard. 2 ≤ n ≤ 40. Chaque ligne se termine par un saut de ligne. Les nombres sont suffisamment petits pour que la somme maximale tienne dans un entier signé 32 bits.

Production

Somme maximale des trajets horizontal et vertical (dans cet ordre) séparés par un seul espace.

Exemple d'entrée 1

1 2
1 2

Exemple de sortie 1

3 4

Exemple d'entrée 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

Exemple de sortie 2

37 35

Exemple d'entrée 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

Exemple de sortie 3

4650 4799

Pour votre commodité, nous avons préparé quelques cas de test en bash (grâce à Ventero ) et PowerShell à travers lesquels vous pouvez exécuter votre programme. L'invocation est:, <test> <command line>donc quelque chose comme ./test python paths.pyou ./test.ps1 paths.exe. S'amuser :-)

Joey
la source
@Joey: Tâche légèrement modifiée par rapport à celle que nous avons utilisée l'année dernière dans notre concours :)
Joey
+10 pour le bashscript de test! Je souhaite que tout le golf de code soit livré avec un tel.
MtnViewMark
@MtnViewMark: Nous essayons :-) Personnellement, je déteste les tâches qui nécessitent trop d'éclaircissements après avoir été publiées et j'écris généralement mes propres scripts de test de toute façon car j'ai besoin de savoir quand une tentative de golf introduit une régression. J'ai également observé que certaines personnes ont tendance à publier des réponses manifestement erronées. Les cas de test aident à mettre tout le monde sur la même ligne. Avoir une installation qui fonctionne pour chaque tâche au lieu de simples hackjobs ponctuels pour chaque tâche serait clairement mieux, mais nous ne sommes pas encore là ;-)
Joey

Réponses:

6

GolfScript - 49 caractères améliorés Nabb

51 caractères
50 caractères strictement et absolument nécessaires + 3 slackers qui n'ont fait que le travail de 1
56 caractères pour la plupart redondants

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

51 solution:

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

53 solution:

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

La méthode fonctionne sur deux lignes à la fois, l'une contenant les sommes maximales atteintes à chaque point et l'autre contenant la ligne suivante.

a / 14: Répétez deux fois, une fois pour chaque résultat.
8: Prenez la première ligne de l'entrée et passez-la derrière le tableau d'entrée, ceci est maintenant le premier ensemble de sommes maximales.
b / 13: Itère sur chaque ligne restante du tableau.
9: Mettez 0 au début des sommes maximales.
c / 12: Itérer sur chaque élément de la ligne.
10: Faites une copie des sommes maximales avec le premier élément supprimé.
11: Prenez les 3 premiers éléments des sommes maximales, triez-les et ajoutez le plus grand à l'élément courant de la ligne.

56 solution:

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

1: De l'entrée au tableau de tableaux en 9 caractères, cela aurait pu être fait avec seulement 1, mais j'ai cassé cette clé donc cela devra faire.
2: 4 caractères juste pour faire une copie transposée.
3: Tableau de 99 0 en 5 caractères, cela pourrait probablement être fait de manière plus intelligente, mais je fume trop de weed pour comprendre comment.
4: Double boucle trop compliquée qui itère sur chaque élément de l'entrée et fait une logique floue ou quelque chose comme ça pour produire le résultat. Nabb fera probablement quelque chose d'équivalent en 3½ caractères environ.
5: Le résultat est maintenant là, à l'intérieur d'un tableau qui est, ce morceau de code idiot est juste là pour le sortir (et jonque un morceau de restes (et mettez le résultat en place)).
6: Il s'agit d'une commande si simple que son nombre de caractères serait probablement négatif dans une solution optimale. 7: À ce stade, le programme est vraiment terminé, mais en raison de la négligence du code précédent, la sortie est dans le mauvais ordre et manque d'espace, alors voici quelques bits de plus.

aaaaaaaaaaaa
la source
Ahh, j'ai juste accidentellement supposé que l'entrée ne se terminait pas par une nouvelle ligne. Je suis surpris que cela ait fonctionné en partie, ce genre de choses gâche généralement complètement un programme GolfScript.
aaaaaaaaaaaa
1
Semble bien, bien que vous devriez utiliser à la {}*place de (\{}%.
Nabb
Oui, c'est logique, merci.
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)

Je refuse de faire des IO, ce qui réduit considérablement mon score. Réussit tous les tests dans le faisceau de tests (bien que cela ne fonctionne que si l'entrée se termine par une fin de ligne, comme dans le faisceau de tests).

J'ai supprimé la gestion des fins de ligne Windows, car Chris a suggéré que ce n'était pas nécessaire. La version multi-plateforme aurait a=:".;._2 toJ(1!:1)3comme première ligne.

Explication:

  • fdonne la paire de solutions en appelant p normalement et avec une entrée transposée ( |:).
  • pprend le maximum ( >./) des totaux de ligne à appliquer centre chaque ligne ( c/)
  • cprend deux lignes (x et y). Il ajoute x à chacun des y, y décalé d'une cellule ( 1|.!.0 y) et y décalé d'une cellule ( _1|.!.0 y). Ensuite, il prend le maximum des trois alternatives pour chaque ligne. ( >./). Le reste est de rang [sic] - je ne sais pas si je le fais bien.
Jesse Millikan
la source
4
Exactement, en abaissant votre score. -1
aaaaaaaaaaaa
@eBusiness: Êtes-vous sûr que le vote à la baisse est la bonne réponse à une solution incomplète?
Jesse Millikan
1
@Joey: Ne pas voter est l'autre option. J'étais trop fatigué pour faire des IO à l'époque, mais ma solution est tellement différente de l'autre solution J que je voulais vraiment la publier de toute façon. S'il y avait un moyen explicite de marquer la réponse comme "non participante", ou quelque chose comme ça, je l'aurais fait.
Jesse Millikan
@Joey: Une autre raison est qu'il est peu probable que les votes vers le bas soient inversés même si la solution est corrigée; l'utilisateur d'origine doit revenir et modifier son vote. (Supprimé, réalisé que court-circuité la discussion, et non supprimé. Je suppose que je vais plutôt tirer pour le badge "Discipliné".)
Jesse Millikan
@Jesse Millikan: C'est ce que nous faisons. Aucune garantie, mais si vous résolvez le problème dans un délai raisonnable, la plupart des votants devraient révoquer leur vote.
aaaaaaaaaaaa
3

Haskell: 314 caractères nécessaires

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

Remarque: cela nécessite le module Data.Vector . Je ne sais pas si c'est inclus dans la plate-forme Haskell ou non.

Version non golfée:

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

Cette solution utilise la paresse, en tandem avec Data.Vector , pour la mémorisation. Pour chaque point, la solution pour le chemin maximum de celui-ci à la fin est calculée, puis stockée dans la cellule de Vector met réutilisée en cas de besoin.

Joey Adams
la source
Je suppose que vous pouvez supprimer les accolades après votre instruction where, si vous réduisez toutes les définitions en une seule ligne.
FUZxxl
2

Ruby 1.9, 155 caractères

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

Solution simple qui passe tous les tests.

Ventero
la source
2

Haskell, 154 caractères

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

  • Modifier: (155 -> 154) a souligné la fonction repliée
MtnViewMark
la source
Est-ce que l'utilisation zipWith3raccourcira le code?
fier haskeller
Je pense que vous pourriez remplacer maximum par foldl1 max, qui ajoute des caractères mais vous permet de factoriser foldl1 et max, ce qui devrait sauver les caractères.
fier haskeller
maximum.foldl1, maxEt max--vs-- f=foldl1;m=max;, f m.f, met m. - ou 20 contre 22. Donc, non, ça ne sauve pas.
MtnViewMark
Droite. Et je viens de me rappeler que la restriction du monomorphisme arrêterait d'écrire m=max. Qu'en est-il de zipWith3?
fier haskeller
1

J, 109 + 10 = 119 caractères

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

Courir avec tr:

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

Comme d'habitude dans J, la majeure partie du code est destinée aux entrées / sorties. Le code "réel" est de 65 caractères:

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

Réussit tous les cas de test

Eelvex
la source
Nous avons donc besoin de JB à nouveau avec une solution qui réduit l'analyse à 10 caractères? ;-)
Joey
@Joey Je suis en vacances, j'ai à peine accès à Internet; pas beaucoup de temps pour le golf ;-)
JB
Pouvez-vous me dire comment vous exécutez directement maxpath.ijs?
Jesse Millikan
@Jesse: Dans * nix, mettez-en #!/usr/bin/env jconsolesur le fichier et définissez le drapeau exécutable.
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 je devais calculer uniquement un chemin le plus court vertical ou horizontal,
cela pourrait être fait sur place à la place, économisant environ un tiers des octets.

hallvabo
la source
1

Python, 204 caractères

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
la source