Haskell、187バイト
l=length
f a@(b:c)=snd$maximum$(zip=<<map(sum.concat))$map(zipWith((uncurry((.drop 1).(++)).).flip splitAt)a)$iterate((\e@(f:_)->[f-1:e,f:e,min(f+1)(l b-1):e])=<<)[[y]|y<-[0..l b-1]]!!l c
使用例:
*Main> f [[1,4,3,5,2],[3,2,5,2,3],[5,2,4,2,1]]
[[4,3,5,2],[3,5,2,3],[5,4,2,1]]
*Main> f [[1],[2],[3]]
[[],[],[]]
*Main> f [[1,2,3,4,5]]
[[2,3,4,5]]
仕組み、ショートバージョン:すべてのパスのリストを作成し(1)、パスごとに:対応する要素を削除し(2)、残りのすべての要素を合計します(3)。最大合計(4)の長方形を取ります。
長いバージョン:
Input parameters, assigned via pattern matching:
a = whole input, e.g. [[1,2,4],[2,5,6],[3,1,6]]
b = first line, e.g. [1,2,4]
c = all lines, except first, e.g. [[2,5,6],[3,1,6]]
Step (1), build all paths:
iterate((\e@(f:_)->[f-1:e,f:e,min(f+1)(l b-1):e])=<<)[[y]|y<-[0..l b-1]]!!l c
[[y]|y<-[0..l b-1]] # build a list of single element lists
# for all numbers from 0 to length b - 1
# e.g. [[0],[1],[2]] for a 3 column input.
# These are all possible start points
\e@(f:_)->[f-1:e,f:e,min(f+1)(l b-1):e]
# expand a list of paths by replacing each
# path with 3 new paths (up-left, up, up-right)
(...)=<< # flatten the list of 3-new-path lists into
# a single list
iterate (...) [...] !! l c # repeatedly apply the expand function to
# the start list, all in all (length c) times.
Step (2), remove elements
map(zipWith((uncurry((.drop 1).(++)).).flip splitAt)a)
(uncurry((.drop 1).(++)).).flip splitAt
# point-free version of a function that removes
# an element at index i from a list by
# splitting it at index i, and joining the
# first part with the tail of the second part
map (zipWith (...) a) $ ... # per path: zip the input list and the path with
# the remove-at-index function. Now we have a list
# of rectangles, each with a path removed
Step (3), sum remaining elements
zip=<<map(sum.concat) # per rectangle: build a pair (s, rectangle)
# where s is the sum of all elements
Step (4), take maximum
snd$maximum # find maximum and remove the sum part from the
# pair, again.