summaryrefslogtreecommitdiff
path: root/day12/day12.hs
blob: cb35a0e45914a0b958ff04afc8010a680fb09d42 (plain)
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))