- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
import Control.Monad
import Control.Arrow
import Data.List
solve' :: [String] -> [[String]]
solve' = nub . filter (
and . uncurry (
zipWith (
(.head) . (==) . last
)
) . (id &&& tail)
) . uncurry ($) . (
last . (((
map (
last . fst &&& uncurry (++) . (init . fst &&& snd)
) . tail . uncurry (zipWith (,)) . (inits &&& tails)
) >=> (uncurry map) .
((:) *** solve')
):
) . (uncurry takeWhile) . (
const . null &&& const [const [[]]]
) &&& id
)
main = print $ solve' ["123","321","123"]
Кресты тоже эзотерика, до тех пор пока значки не выучишь. Тут та же проблема - аинтуитивность обозначений.
Кстати я заметил что тут многие любители С++ изучили и хацкиль. Повторюсь: тут очень кошерно отформатирован код, даже местами прослеживается следование заветам тарасоформатирования.
> nub . filter
Очень даже неплохой. Меня отфильтровал, т.к. я не знаю, что делают >=> , &&& и ***. А читать про них что-то влом.
http://rchan.ws/pr/src/1361391985569.png
Стареешь, бор. Какой уж десяток разменял?
Блок 13-22 прогоняет аргумент через композицию last, 14-19, uncurry takeWhile и 21, и возвращает результат в виде тупла, наряду с исходным аргументом.
uncurry (zipWith (,)) . (inits &&& tails) - функция, возвращающая все варианты разбиения списка на два, tail отбросит случай с пустым первым списком, а map преобразует каждый тупл: \(x, y) -> (last x, init x ++ y). В результате получаем функцию, которая возвращает все варианты выборки одного элемента - для [1,2,3] она вернет [(1, [2, 3]), (2, [1, 3]), (3, [1, 2])].
(uncurry map) . ((:) *** solve') это \(x, y) -> map (x:) $ solve' y. Объединив этот блок с предыдущим с помощью >=> получим функцию, которая вынимает каждый элемент списка, выполняет solve' над оставшимися, и к каждому результату приклеивает в начало вынутый элемент.
const . null это \x -> \_ -> null x, а const [const [[]]] это \_ -> [\_ -> [[]]] поэтому строка 21 переписывается как \x -> (\_ -> null x, [\_ -> [[]]]). Композиция этой фигни с uncurry takeWhile даст нам \x -> takeWhile (\_ -> null x) [\_ -> [[]]]. Если x пуст, мы получим список из одной функции: [\_ -> [[]]], иначе - пустой список.
В итоге строки 12-23 возвращают [[]] для пустого списка, а для непустого вынимает каждый элемент списка, выполняет solve' над оставшимися, и к каждому результату приклеивает в начало вынутый элемент. Перепишем эти строки как to be continued...
В результате получаем вот такой код: А задача была примерно такой - "найти все перестановки исходных строк, при которых они будут правильно сцеплены (последний символ предыдущей равен первому символу следующей)".
Что это и где это?
P.S. Но юзать лямбдабота не спортивно ;)
...
Троллить вечно