-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path11a.hs
93 lines (70 loc) · 2.13 KB
/
11a.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
import Data.List.Index
import qualified Data.Map as M
import Data.Maybe
import Prelude
data Space = Empty | Occupied | Floor deriving (Show, Eq)
type Coordinate = (Int, Int)
type RowId = Int
type ColId = Int
type Row = M.Map ColId Space
type Grid = M.Map RowId Row
main = do
input <- getContents
putStr $ show $ fn $ lines input
--putStr $ show $ fn $ lines $ input
toSpace :: Char -> Space
toSpace 'L' = Empty
toSpace '#' = Occupied
toSpace '.' = Floor
makeIndexedMap :: [a] -> M.Map Int a
makeIndexedMap xs = M.fromList $ indexed xs
toRow :: String -> Row
toRow = makeIndexedMap . map toSpace
flatten :: Maybe (Maybe a) -> Maybe a
flatten (Just x) = x
flatten _ = Nothing
safeGridLookup :: (Int, Int) -> Grid -> Maybe Space
safeGridLookup (x, y) grid = flatten $ M.lookup x <$> M.lookup y grid
generateCombinations :: Coordinate -> [Coordinate]
generateCombinations (y, x) =
[ (left, above),
(x, above),
(right, above),
(left, y),
(right, y),
(left, below),
(x, below),
(right, below)
]
where
above = y -1
below = y + 1
left = x - 1
right = x + 1
countAdjacent :: Coordinate -> Grid -> Int
countAdjacent c grid = length $ filter (Occupied ==) $ mapMaybe (`safeGridLookup` grid) $ generateCombinations c
next :: Coordinate -> Space -> Grid -> Space
next (x, y) z grid
| z == Occupied && adjacents >= 4 = Empty
| z == Empty && adjacents == 0 = Occupied
| otherwise = z
where
adjacents = countAdjacent (x, y) grid
getNextRow :: Grid -> Int -> Row -> Row
getNextRow grid colId = M.mapWithKey (\rowId x -> next (colId, rowId) x grid)
getNextGrid :: Grid -> Grid
getNextGrid grid = M.mapWithKey (getNextRow grid) grid
incr :: Int -> Int
incr = (+ 1)
countSeatsRow :: Row -> Int
countSeatsRow row = length $ filter (Occupied ==) $ map snd $ M.toList row
countSeatsGrid :: Grid -> Int
countSeatsGrid grid = sum $ map (countSeatsRow . snd) $ M.toList grid
countGrids :: Int -> Grid -> Int
countGrids x grid
| next == grid = countSeatsGrid grid
| otherwise = countGrids (incr x) next
where
next = getNextGrid grid
fn :: [String] -> Int
fn xs = countGrids 0 $ makeIndexedMap $ map toRow xs