{-# LANGUAGE OverloadedStrings #-} import qualified Data.Text as T import GHC.Utils.Misc (chunkList) import Data.Char (isSpace, isNumber) import Data.List (transpose) parseState :: String -> [[Char]] parseState = map (dropWhile isSpace) . transpose . map (map (!! 1) . chunkList 4) . init . lines parseInstructions :: String -> [(Int, Int, Int)] parseInstructions = map ((\[n, a, b] -> (n, a, b)) . map read . filter (isNumber . head) . words) . lines evaluateState :: [[Char]] -> (Int, Int, Int) -> [[Char]] evaluateState state (n, a, b) = newState where extracted = zipWith (\i l -> (if i == a then drop n l else l)) [1..] state movedChars = take n $ state !! (a - 1) newState = zipWith (\i l -> (if i == b then movedChars ++ l else l)) [1..] extracted executeInstructions :: [[Char]] -> [(Int, Int, Int)] -> [[Char]] executeInstructions state (instruction:xs) = executeInstructions newState xs where newState = evaluateState state instruction executeInstructions state [] = state main = interact $ map head . (\[state, instructions] -> executeInstructions (parseState state) (parseInstructions instructions)) . map T.unpack . T.splitOn "\n\n" . T.pack