-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun.hs
63 lines (48 loc) · 1.54 KB
/
run.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
{-# LANGUAGE BlockArguments #-}
import Data.List (transpose)
import Data.List.Split (chunksOf, splitWhen)
import Data.Maybe (fromJust)
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
type Move = (Int, Int, Int)
type Crate = Char
type Stacks = Map Int [Crate]
parseStacks :: [String] -> Stacks
parseStacks =
Map.fromList
. zip [1..]
. map (filter (/= ' '))
. transpose
. map (map (!! 1) . chunksOf 4)
parseMoves :: [String] -> [Move]
parseMoves = map f . filter (not . null)
where f move =
let [_, count, _, from, _, to] = map read $ words move
in
(count, from, to)
parseAll :: String -> (Stacks, [Move])
parseAll input =
let [stacks, moves] = splitWhen ((== " 1") . take 2) $ lines input
in (parseStacks stacks, parseMoves moves)
exec :: ([Crate] -> [Crate]) -> Stacks -> Move -> Stacks
exec lift stacks (c, from, to) = fromJust do
fs <- stacks Map.!? from
ts <- stacks Map.!? to
let (move, fs') = splitAt c fs
ts' = lift move ++ ts
pure $ Map.insert from fs' $ Map.insert to ts' $ stacks
tops :: Stacks -> [Crate]
tops = map (head . snd) . Map.toAscList
part1 :: (Stacks, [Move]) -> String
part1 (stacks, moves) = tops $ foldl (exec reverse) stacks moves
part2 :: (Stacks, [Move]) -> String
part2 (stacks, moves) = tops $ foldl (exec id) stacks moves
main :: IO ()
main = main' "input.txt"
exampleMain :: IO ()
exampleMain = main' "example.txt"
main' :: FilePath -> IO ()
main' file = do
input <- parseAll <$> readFile file
putStrLn (part1 input)
putStrLn (part2 input)