41 lines
1.1 KiB
Haskell
41 lines
1.1 KiB
Haskell
import Data.List (transpose, delete)
|
|
import Data.List.Split (chunksOf, splitOn)
|
|
import Data.Char (isSpace)
|
|
|
|
data Command = Move Int Int Int
|
|
|
|
type State = [[Char]]
|
|
|
|
parseInit :: [String] -> State
|
|
parseInit s = map (dropWhile isSpace . init . (!!1)) (chunksOf 4 $ transpose s)
|
|
|
|
parseCmds :: [String] -> [Command]
|
|
parseCmds s = map readCmd s where
|
|
readCmd s = let w = words s in Move (read (w !! 1)) (read (w !! 3) - 1) (read (w !! 5) - 1)
|
|
|
|
listApp :: Int -> (a -> a) -> [a] -> [a]
|
|
listApp 0 f (x:xs) = f x : xs
|
|
listApp n f (x:xs) = x : listApp (n-1) f xs
|
|
|
|
moveN :: Command -> State -> State
|
|
moveN (Move 0 _ _) = id
|
|
moveN (Move n f t) = moveN (Move (n-1) f t) . move (Move 1 f t)
|
|
|
|
move :: Command -> State -> State
|
|
move (Move n f t) state = addTo $ popFrom state where
|
|
popFrom = listApp f (drop n)
|
|
elems = take n (state !! f)
|
|
addTo = listApp t (elems ++ )
|
|
|
|
main :: IO ()
|
|
main = do
|
|
[init', cmds'] <- splitOn [""] . lines <$> getContents
|
|
let init = parseInit init'
|
|
let cmds = parseCmds cmds'
|
|
|
|
putStr "part 1: "
|
|
print $ map head $ foldl (flip moveN) init cmds
|
|
|
|
putStr "part 2: "
|
|
print $ map head $ foldl (flip move) init cmds
|