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
|
import Data.List
import Data.Maybe
type Coo = (Int, Int)
type Region = (Plot, [Coo])
type Plot = Char
type Grid = [[Plot]]
(!?) :: Grid -> Coo -> Maybe Plot
grid !? (row, col)
| row < 0 = Nothing
| row >= length grid = Nothing
| col < 0 = Nothing
| col >= (length $ head grid) = Nothing
| otherwise = Just (grid !! row !! col)
neighCoos :: Coo -> [Coo]
neighCoos (r,c) =
[(r-1, c), (r, c-1), (r, c+1), (r+1, c)]
neighs :: Grid -> Plot -> Coo -> [Coo]
neighs grid p c =
mapMaybe match $ neighCoos c
where
match coo = if grid !? coo == Just p then Just coo else Nothing
region :: Grid -> [Coo] -> [Coo] -> Region
region grid res@(h:_) [] =
(fromJust $ grid !? h, res)
region grid res (h:t) =
region grid (h:res) (t ++ filter f ns)
where
Just p = grid !? h
ns = neighs grid p h
f c = (not $ c `elem` res) && (not $ c `elem` t)
consume1 :: Grid -> [Region] -> [Coo] -> [Region]
consume1 _ acc [] =
acc
consume1 grid acc (h:t) =
consume1 grid (r:acc) (t \\ cs)
where
r@(_,cs) = region grid [] [h]
consume :: String -> [Region]
consume s =
consume1 grid [] allcoos
where
grid = lines s
allcoos = [(r, c) | r <- [0..((length grid) - 1)], c <- [0..((length $ head grid) - 1)]]
area :: Region -> Int
area (_, cs) =
length cs
perimeter1 :: Region -> Int -> [Coo] -> Int
perimeter1 _ s [] =
s
perimeter1 r@(_, cs) s (h:t) =
perimeter1 r (s + e) t
where
ncs = filter ((flip elem) cs) $ neighCoos h
e = 4 - (length ncs)
perimeter :: Region -> Int
perimeter r@(_, cs) =
perimeter1 r 0 cs
fenceCost :: Region -> Int
fenceCost r =
area r * perimeter r
part1 :: [Region] -> Int
part1 =
sum . map fenceCost
main = do
file <- readFile "day12.input"
let regions = consume file
putStrLn ("Part 1: " ++ (show $ part1 regions))
--putStrLn ("Part 2: " ++ (show $ part2 regions))
|