-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day10.hs
157 lines (129 loc) · 4.32 KB
/
Day10.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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ViewPatterns #-}
module Day10 where
import Control.Arrow ((&&&))
import Control.Monad
import Data.Array (Array)
import Data.Bifunctor
import Data.Char
import Data.Either
import Data.Foldable
import Data.Function (on)
import Data.Functor
import Data.Map (Map)
import Data.Maybe
import Data.MultiSet (MultiSet)
import Data.Set (Set)
import Text.ParserCombinators.ReadP
import Harness
import ParseHelper
import Data.Array qualified as A
import Data.List qualified as L
import Data.Map qualified as M
import Data.MultiSet qualified as MS
import Data.Set qualified as S
import Debug.Trace
main :: IO ()
main = getInputAndSolve (parseInputRaw parseGrid) findMidPoint (const "Implement Part 2")
-- SOLVE
findMidPoint :: Grid -> Int
findMidPoint g =
let start = findStart g
in length (followPipe g [] start) `div` 2
enclosedTiles :: Grid -> Int
enclosedTiles g =
let start@(startIx, _) = findStart g
pipeIxs = startIx : followPipe g [] start
groundIxs = map fst . filter ((== Ground) . snd) $ A.assocs g.fromGrid
in 0
-- HELPERS
findStart :: Grid -> ((Int, Int), Direction)
findStart g =
let startIx = fst . fromJust . L.find ((== Start) . snd) $ A.assocs g.fromGrid
in {- TODO: calculate first direction to move from start
validDirs =
[ ((East, (+ 1), (+ 0)), [NorthWest, SouthWest, EastWest])
, ((West, \x -> x - 1, (+ 0)), [NorthEast, SouthEast, EastWest])
, ((North, (+ 0), (+ 1)), [NorthSouth, SouthWest, SouthEast])
, ((South, (+ 0), \y -> y - 1), [NorthSouth, NorthEast, NorthWest])
]
neighbors = A.getGridNeighborsCardinal g.fromGrid startIx
nextDir = L.find ...
-}
(startIx, South)
followPipe :: Grid -> [(Int, Int)] -> ((Int, Int), Direction) -> [(Int, Int)]
followPipe g seen (nextIx, fromDir) =
let moveNorth = (second (\y -> y - 1) nextIx, South)
moveSouth = (second (+ 1) nextIx, North)
moveEast = (first (+ 1) nextIx, West)
moveWest = (first (\x -> x - 1) nextIx, East)
keepMoving = followPipe g (nextIx : seen)
in case (g.fromGrid A.! nextIx, fromDir) of
(Start, _) ->
if
| not (null seen) -> seen
| fromDir == South -> keepMoving moveSouth
| fromDir == North -> keepMoving moveNorth
| fromDir == East -> keepMoving moveEast
| fromDir == West -> keepMoving moveWest
| otherwise -> error "unexpected"
(Ground, _) -> error "got to ground?"
(NorthSouth, South) -> keepMoving moveNorth
(NorthSouth, North) -> keepMoving moveSouth
(EastWest, East) -> keepMoving moveWest
(EastWest, West) -> keepMoving moveEast
(NorthEast, North) -> keepMoving moveEast
(NorthEast, East) -> keepMoving moveNorth
(NorthWest, North) -> keepMoving moveWest
(NorthWest, West) -> keepMoving moveNorth
(SouthEast, South) -> keepMoving moveEast
(SouthEast, East) -> keepMoving moveSouth
(SouthWest, South) -> keepMoving moveWest
(SouthWest, West) -> keepMoving moveSouth
other -> error $ "Unexpected: " <> show other <> " via " <> show seen
data Direction
= North
| South
| East
| West
deriving (Show, Eq)
-- PARSE
newtype Grid = Grid
{ fromGrid :: Array (Int, Int) Tile
}
deriving (Show)
parseGrid :: ReadP Grid
parseGrid =
Grid <$> parseValueGrid parseTile <* newline
data Tile
= Ground
| NorthSouth
| EastWest
| NorthEast
| NorthWest
| SouthWest
| SouthEast
| Start
deriving (Show, Eq)
parseTile :: ReadP Tile
parseTile =
choice $
map
(\(t, c) -> t <$ char c)
[ (NorthSouth, '|')
, (EastWest, '-')
, (NorthEast, 'L')
, (NorthWest, 'J')
, (SouthWest, '7')
, (SouthEast, 'F')
, (Ground, '.')
, (Start, 'S')
]