Нахождение максимальных путей

12

Учитывая квадрат положительных натуральных чисел, напишите программу, найдите горизонтальный и вертикальный путь с суммой чисел вдоль них, являющейся максимальной. Горизонтальный путь проходит от первого столбца до последнего и должен увеличить свою позицию столбца по одному в каждом шаге. Вертикальный путь проходит от первой строки до последнего и должен увеличить свою позицию строки по одному в каждом шаге. Кроме того, положение строки в горизонтальной траектории может оставаться неизменным или изменяться на единицу в любом направлении, аналогично для вертикальных траекторий.

Чтобы проиллюстрировать это, допустимым может быть следующее:

Иллюстрация действительного пути

Следующий путь будет недопустимым, поскольку он идет назад (и в некоторых местах остается в той же строке):

Иллюстрация неверного пути

Следующий путь будет в равной степени недействительным, так как он меняет положение строки более чем на один шаг:

Еще одна иллюстрация неверного пути

Примечание. Решение должно работать в течение приемлемого периода времени.

вход

n строк ввода с n разделенными пробелом положительными целыми числами каждая дана на стандартном вводе. 2 ≤ n ≤ 40. Каждая строка заканчивается разрывом строки. Числа достаточно малы, чтобы максимальная сумма помещалась в 32-разрядное целое число со знаком.

Выход

Максимальные суммы горизонтальных и вертикальных путей (в указанном порядке) разделены одним пробелом.

Пример ввода 1

1 2
1 2

Пример вывода 1

3 4

Пример ввода 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

Пример вывода 2

37 35

Пример ввода 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

Пример вывода 3

4650 4799

Для вашего удобства мы подготовили несколько тестовых примеров в bash (благодаря Ventero ) и PowerShell, через которые вы можете запустить свою программу. Invocation:, <test> <command line>так что-то вроде ./test python paths.pyили ./test.ps1 paths.exe. Веселиться :-)

детеныш
источник
@Joey: слегка измененное задание, которое мы использовали в прошлом году в нашем конкурсе :)
Joey
+10 за bashтестовый скрипт! Я хотел бы, чтобы весь код гольф пришел с таким.
MtnViewMark
@MtnViewMark: мы стараемся :-) Лично я ненавижу задачи, которые требуют слишком много разъяснений после публикации, и я обычно пишу свои собственные тестовые сценарии, так как мне нужно знать, когда попытка игры в гольф вводит регресс. Также я заметил, что некоторые люди склонны публиковать явно неправильные ответы. Тестовые случаи помогают привести всех на одну линию. Очевидно, было бы лучше иметь средство, которое работает для каждой задачи, а не только одноразовые хак-хобы для каждой задачи, но мы еще не совсем готовы ;-)
Joey

Ответы:

6

GolfScript - 49 улучшенных персонажей Nabb

51 символ
50 строго и крайне необходимых символов + 3 бездельника, которые выполнили работу только из 1
56 в основном избыточных символов

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

51 решение:

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

53 решение:

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

Этот метод работает с двумя строками одновременно, одна из которых содержит максимальные суммы, достигнутые в каждой точке, а другая содержит следующую строку.

a / 14: повторите дважды, один раз для каждого результата.
8: Возьмите первую строку из ввода и переключите ее за массив ввода, теперь это первый набор максимальных сумм.
b / 13: перебирать каждую оставшуюся строку в массиве.
9: Поставьте 0 в начале максимальной суммы.
c / 12: перебирать каждый элемент строки.
10: Сделайте копию максимальных сумм с удаленным первым элементом.
11: Возьмите первые 3 элемента максимальных сумм, отсортируйте их и добавьте наибольшее к текущему элементу строки.

56 решение:

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

1: От ввода до массива массивов в 9 символов, на самом деле это можно было сделать всего с 1, но я сломал этот ключ, так что это придется делать.
2: 4 символа, просто чтобы сделать транспонированную копию.
3: Массив 99 0 в 5 символах, вероятно, это можно сделать более умным способом, но я курю слишком много травки, чтобы понять, как это сделать.
4: Слишком сложный двойной цикл, который перебирает каждый элемент ввода и выполняет некоторую нечеткую логику или что-то подобное для получения результата. Набб, вероятно, сделает что-то эквивалентное в 3½ символа.
5: к настоящему моменту результат есть, внутри массива, то есть этот глупый кусок кода только для того, чтобы вытащить его (и отбросить кусок остатков (и переключить результат на место)).
6: эта команда настолько проста, что ее количество символов, вероятно, будет отрицательным в оптимальном решении. 7: на этом этапе программа действительно выполнена, но из-за неаккуратности в предыдущем коде вывод находится в неправильном порядке и ему не хватает пробела, так что здесь идет еще несколько битов.

AAAAAAAAAAAA
источник
Ааа, я просто предположил, что ввод не заканчивается переводом строки. Я удивлен, что это на самом деле работает частично, такого рода вещи обычно полностью портят программу GolfScript.
аааааааааааа
1
Выглядит хорошо, хотя вы должны использовать {}*вместо (\{}%.
Набб
Да, это имеет смысл, спасибо.
аааааааааааа
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)

Я отказываюсь делать IO, резко снижая свой счет. Пройдены все тесты в тестовом жгуте (хотя он работает только в том случае, если ввод заканчивается на конце строки, как в тестовом жгуте).

Я удалил обработку для концов строк Windows, так как Крис предположил, что в этом нет необходимости. Мультиплатформенная версия будет иметь a=:".;._2 toJ(1!:1)3в качестве первой строки.

Объяснение:

  • fдает пару решений, вызывая p нормально и с помощью input transposed ( |:).
  • pпринимает максимум ( >./) итоговых сумм от применения cмежду каждой строкой ( c/)
  • cзанимает две строки (х и у). Он добавляет x к каждому из y, y сдвигается на 1 ячейку ( 1|.!.0 y), а y сдвигается на 1 ячейку ( _1|.!.0 y). Затем он берет максимумы трех альтернатив для каждого ряда. ( >./). Остальное - звание [sic] - я не уверен, правильно ли я это делаю.
Джесси Милликен
источник
4
Точно, понижение вашего счета. -1
аааааааааааа
@eBusiness: Вы уверены, что отрицательное голосование является правильным ответом на неполное решение?
Джесси Милликен
1
@Joey: не upvoting другой вариант. Я был слишком устал, чтобы делать IO в то время, но мое решение настолько отличается от другого решения J, что я действительно хотел опубликовать его в любом случае. Если бы был явный способ пометить ответ как «не участвующий», или что-то подобное, я бы сделал.
Джесси Милликен
@Joey: Другая причина в том, что отрицательные голоса вряд ли будут отменены, даже если решение является фиксированным; первоначальный пользователь должен вернуться и изменить свой голос. (Удалено, понято, что замкнуло дискуссию, и восстановлено. Думаю, вместо этого я буду стрелять по значку «Дисциплинировано».)
Джесси Милликен,
@ Джесси Милликен: Мы делаем это. Никаких гарантий, но если вы решите проблему в разумные сроки, большинство downvoters должны отозвать свои голоса.
аааааааааааа
3

Haskell: 314 необходимых символов

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

Примечание: для этого требуется модуль Data.Vector . Я не уверен, включен ли он в платформу Haskell или нет.

Безголовая версия:

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

Это решение использует лень в тандеме с Data.Vector для запоминания . Для каждой точки вычисляется решение для максимального пути от нее до конца, затем сохраняется в ячейке Vector mи повторно используется при необходимости.

Джои Адамс
источник
Я полагаю, вы можете убрать фигурные скобки после оператора where, если сложите все определения в одну строку.
FUZxxl
2

Ruby 1.9, 155 символов

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

Простое решение, которое проходит все тестовые случаи.

Ventero
источник
2

Хаскель, 154 персонажа

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

  • Редактировать: (155 -> 154) встроенная функция
MtnViewMark
источник
Будет ли использование zipWith3сокращать код?
гордый haskeller
Я думаю, что вы могли бы заменить максимум на foldl1 max, который добавляет символы, но позволяет вам разложить foldl1 и max, что должно сохранять символы.
гордый haskeller
maximum.foldl1, maxИ max--vs-- f=foldl1;m=max;, f m.f, m, и m. - или 20 против 22. Так что нет, это не спасает.
MtnViewMark
Правильно. И я просто вспомнил, что ограничение мономорфизма перестало бы писать m=max. Что насчет zipWith3?
гордый haskeller
1

J 109 + 10 = 119 символов

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

Запустить с tr:

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

Как обычно в J, большая часть кода предназначена для ввода / вывода. «Фактический» код состоит из 65 символов:

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

Проходит все тесты

Eelvex
источник
Итак, нам снова нужен JB с решением, которое сокращает разбор до 10 символов? ;-)
Джои
@ Джой, я в отпуске, у меня почти нет доступа в интернет; не так много времени для игры в гольф ;-)
JB
Не могли бы вы рассказать мне, как вы напрямую запускаете maxpath.ijs?
Джесси Милликен
@Jesse: В * nix поместите некоторые #!/usr/bin/env jconsoleповерх файла и установите флаг исполняемого файла.
Eelvex
1

Питон, 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)

Если бы я рассчитывал только кратчайший путь по вертикали или по горизонтали,
это можно было бы сделать на месте, сэкономив около трети байтов.

hallvabo
источник
1

Python, 204 символа

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)
Кит Рэндалл
источник