summaryrefslogtreecommitdiff
path: root/day04/day04.hs
blob: 83ba82924743b2b4fd316edbb9f357e9e07b18be (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
import Data.List

type Pr = (Int, Int)

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

findChs1 :: Char -> String -> Int -> Int -> [Pr] -> [Pr]
findChs1 _  []    _ _ acc = acc
findChs1 ch (h:t) j i acc
  | ch == h   = findChs1 ch t j (i + 1) (acc ++ [(j,i)])
  | otherwise = findChs1 ch t j (i + 1) acc

findChs :: Char -> [String] -> Int -> [Pr] -> [Pr]
findChs _  []    _ acc = acc
findChs ch (h:t) j acc = findChs ch t (j + 1) (acc ++ findChs1 ch h j 0 [])

checkCh :: Char -> [String] -> Pr -> Pr -> [(Pr, Pr)]
checkCh ch grid coo@(row, col) dir@(dr, dc)
  | grid !? (row + dr, col + dc) == Just ch = [(coo, dir)]
  | otherwise = []

findMCorners :: [String] -> Pr -> [(Pr, Pr)]
findMCorners grid coo =
  let checkM = checkCh 'M' grid coo in
    checkM (-1, -1) ++
    checkM (-1,  1) ++
    checkM ( 1, -1) ++
    checkM ( 1,  1)

findMNeighs :: [String] -> Pr -> [(Pr, Pr)]
findMNeighs grid coo =
  let checkM = checkCh 'M' grid coo in
    findMCorners grid coo ++
    checkM (-1,  0) ++
    checkM ( 0, -1) ++
    checkM ( 0,  1) ++
    checkM ( 1,  0)

testXmas :: [String] -> (Pr, Pr) -> Bool
testXmas grid ((row, col), (dr, dc)) =
  grid !? (row + 2 * dr, col + 2 * dc) == Just 'A' &&
  grid !? (row + 3 * dr, col + 3 * dc) == Just 'S'

testMas :: [String] -> (Pr, Pr) -> Bool
testMas grid ((row, col), (dr, dc)) =
  grid !? (row - dr, col - dc) == Just 'S'

car :: (a, a) -> a
car (a, _) = a

findReps :: [Pr] -> [Pr] -> [Pr]
findReps acc [] = acc
findReps acc (h:t)
  | h `elem` t = findReps (h:acc) t
  | otherwise = findReps acc t

part1 grid = 
  length $ filter (testXmas grid) $
    concat $ map (findMNeighs grid) $
    findChs 'X' grid 0 []

part2 grid =
  length $ findReps [] $
    map (car) $ filter (testMas grid) $
    concat $ map (findMCorners grid) $
    findChs 'A' grid 0 []

main = do
  file <- readFile "day04.input"
  let lns = lines file
  putStrLn ("Part 1: " ++ (show $ part1 lns))
  putStrLn ("Part 2: " ++ (show $ part2 lns))