-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay3.hs
67 lines (56 loc) · 1.9 KB
/
Day3.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
64
65
66
67
module Day3
( part1
, part2
) where
import Control.Monad.State (State, evalState, get, put)
import Data.Bifunctor (first)
import Data.ByteString (ByteString)
import Data.Either (fromRight)
import Data.Set (Set, empty, insert, size, union)
import Data.Tuple (swap)
import Data.Void (Void)
import Data.Word8 (_circum, _greater, _less, _v)
import Helpers.Graph (Pos, east, north, origin, south, west)
import Text.Megaparsec (ParsecT, Token, eof, runParserT, token,
(<|>))
import Text.Megaparsec.Char (char, eol)
type Parser = ParsecT Void ByteString (State Pos) Houses
type RobotParser = ParsecT Void ByteString (State (Pos, Pos)) (Houses, Houses)
type Houses = Set Pos
directions :: Token ByteString -> Maybe Pos
directions d
| d == _circum = Just north
| d == _v = Just south
| d == _less = Just west
| d == _greater = Just east
parseDir :: Parser
parseDir = do
pos <- get
dir <- token directions empty
put (pos + dir)
insert (pos + dir) <$> parseInput
robotParseDir :: RobotParser
robotParseDir = do
(curPos, otherPos) <- get
dir <- token directions empty
put (otherPos, curPos + dir)
swap . first (insert (curPos + dir)) <$> robotParseInput
parseInput :: Parser
parseInput = parseDir <|> (eof >> return empty)
robotParseInput :: RobotParser
robotParseInput = robotParseDir <|> (eof >> return (empty, empty))
part1 :: Bool -> ByteString -> String
part1 _ =
show
. size
. fromRight (error "parser failed")
. flip evalState origin
. runParserT parseInput "Day 3"
part2 :: Bool -> ByteString -> String
part2 _ =
show
. size
. uncurry union
. fromRight (error "parser failed")
. flip evalState (origin, origin)
. runParserT robotParseDir "Day 3"