import Data.List.Split import Data.List main :: IO () main = do input <- map lines <$> splitOn "\n\n" <$> readFile "input" let field = parseField $ head input let moves = parseMoves $ last input print $ map last $ doMoves reverse moves field print $ map last $ doMoves id moves field parseField :: [String] -> [String] parseField = filter (not.null) . map (takeWhile (/=' ') . reverse) . filter (null . intersect "[]") . transpose . init parseMoves :: [String] -> [[Int]] parseMoves = map (map (subtract 1 . read) . filter (not.null . intersect ['0'..'9']) . words) move :: (String -> String) -> [Int] -> [String] -> [String] move f (p:a:b:[]) field = newFieldA ++ [new] ++ newFieldB where line = field !! a (rmn,splt) = splitAt (length line - 1 - p) line new = field !! b ++ (f splt) (fieldA,_) = splitAt a field (_,fieldB) = splitAt (a+1) field removedField = fieldA ++ [rmn] ++ fieldB (newFieldA,_) = splitAt b removedField (_,newFieldB) = splitAt (b+1) removedField doMoves :: (String -> String) -> [[Int]] -> [String] -> [String] doMoves f [] field = field doMoves f (m:ms) field = doMoves f ms (move f m field)