summaryrefslogtreecommitdiff
path: root/day10/day10.hs
blob: 5c970e50a40671ab3bed6dcc72dd64b3c79a7fdf (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
import Data.Char
import Data.List
import Data.Maybe

type Height = Int
type Coo = (Int, Int)
type Map = [[Height]]

data Trail = Point Coo Height Trail | Nowhere deriving Show

(!?) :: [[a]] -> Coo -> Maybe a
mp !? (row, col)
  | row < 0                   = Nothing
  | row >= length mp          = Nothing
  | col < 0                   = Nothing
  | col >= (length $ head mp) = Nothing
  | otherwise                 = Just (mp !! row !! col)

consume :: [Char] -> Map
consume file =
  map (map (digitToInt)) $ lines file

trailheads2 :: [Coo] -> Int -> Int -> [Height] -> [Coo]
trailheads2 acc _ _ [] =
  reverse acc
trailheads2 acc r c (h:rest)
  | h == 0 = trailheads2 ((r, c):acc) r (c + 1) rest
  | otherwise = trailheads2 acc r (c + 1) rest

trailheads1 :: [Coo] -> Int -> Map -> [Coo]
trailheads1 acc _ [] =
  acc
trailheads1 acc r (row:rest) =
  trailheads1 (acc ++ heads) (r + 1) rest
  where heads = trailheads2 [] r 0 row

trailheads :: Map -> [Coo]
trailheads = trailheads1 [] 0

trails2 :: Map -> Trail -> [Trail]
trails2 mp p@(Point (r,c) h _) =
  map pointify $
    catMaybes $
    map oneup
    [nxt (-1, 0), nxt (0, -1), nxt (0, 1), nxt (1, 0)]
  where
    pointify c = Point c (h+1) p
    oneup (nr, nc, Just nh) = if nh == h + 1 then Just (nr, nc) else Nothing
    oneup (_, _, Nothing) = Nothing
    nxt (dr, dc) = (r+dr, c+dc, mp !? (r+dr, c+dc))

trails1 :: Map -> [Trail] -> [Trail] -> [Trail]
trails1 _ acc@((Point _ 9 _):_) [] =
  acc
trails1 mp acc [] =
  trails1 mp [] acc
trails1 mp acc (th@(Point _ 9 _):rest) =
  trails1 mp (th:acc) rest
trails1 mp acc (th:rest) =
  trails1 mp (acc ++ trails2 mp th) rest

trails :: Map -> Coo -> [Trail]
trails mp th =
  trails1 mp [] [Point th 0 Nowhere]

score :: [Trail] -> Int
score th =
  length $ nub $ map untrail th
  where
    untrail (Point c _ _) = c

part1 :: Map -> Int
part1 mp =
  sum $ map (score . (trails mp)) $ trailheads mp

main = do
  file <- readFile "day10.input"
  let mp = consume file
  putStrLn ("Part 1: " ++ (show $ part1 mp))
  --putStrLn ("Part 2: " ++ (show $ part2 mp))