-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day3.idr
80 lines (69 loc) · 2.2 KB
/
Day3.idr
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
68
69
70
71
72
73
74
75
76
77
78
79
module Advent.Day3
import Data.Either
import Data.List
import Data.SortedMap
import Text.Lexer
import Text.Parser
public export
record Claim where
constructor ElfClaim
ident: Int
left: Int
top: Int
width: Int
height: Int
public export
Show Claim where
show c =
"#" ++ show (ident c) ++
" @ " ++ show (left c) ++ "," ++ show (top c) ++
": " ++ show (width c) ++ "x" ++ show (height c)
export
(.positions): Claim -> List(Int,Int)
(.positions) claim = [ (x,y) |
x <- [ claim.left .. claim.left + claim.width - 1 ],
y <- [ claim.top .. claim.top + claim.height - 1 ]]
namespace SortedMap
export
(.positions): Claim -> SortedMap(Int,Int) Int
(.positions) = fromList . map (,1) . (.positions)
||| Note: punctuation are indistinguishable from one another in this simple token representation.
data ClaimTokens = I | Punct
TokenKind ClaimTokens where
TokType I = Int
TokType Punct = String
tokValue = \case
I => cast
Punct => id
ClaimToken: Type
ClaimToken = Token ClaimTokens
lexFully: TokenMap t -> String -> Maybe (List t)
lexFully tokenMap str = case lex tokenMap str of
(tokens, (_, (_, ""))) => Just (map tok tokens)
_ => Nothing
lexClaims: List String -> List (List ClaimToken)
lexClaims strs = let
claimTokenMap = toTokenMap [
(spaces, Punct),
(is '#', Punct),
(is '@', Punct),
(is ',', Punct),
(is ':', Punct),
(is 'x', Punct),
(intLit, I)]
in mapMaybe (lexFully claimTokenMap) strs
claimGrammar: Grammar ClaimToken True Claim
claimGrammar = let
punct = \label => terminal label (\t => case kind t of { Punct => Just (); _ => Nothing })
num = \label => terminal label (\t => case kind t of { I => Just (tokValue I (text t)); _ => Nothing })
in ElfClaim
<$> (punct "#" *> num "claim ID")
<*> (punct "space" *> punct "@" *> punct "space" *> num "left-inches")
<*> (punct "," *> num "right-inches")
<*> (punct ":" *> punct "space" *> num "width-inches")
<*> (punct "x" *> num "height-inches")
export
parseClaims: List String -> List Claim
parseClaims strs = mapMaybe
(\tokens => map fst (eitherToMaybe (parse claimGrammar tokens)))
(lexClaims strs)