summaryrefslogtreecommitdiff
path: root/day08/day08.hs
blob: 728dd71f636ee44ca8e472f6d5efaddc85f61f7b (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
82
83
import Data.List

type Vec = (Int, Int)
type Ant = (Int, Int, Char)
type Map = (Vec, [Ant])

consume2 :: [Ant] -> Int -> Int -> [Char] -> [Ant]
consume2 acc _ _ [] = acc
consume2 acc r c ('.':t) = consume2 acc r (c+1) t
consume2 acc r c (h:t) = consume2 ((r, c, h):acc) r (c+1) t

consume1 :: [Ant] -> Int -> [[Char]] -> [Ant]
consume1 acc _ [] = acc
consume1 acc r (h:t) = consume1 (acc ++ (consume2 [] r 0 h)) (r+1) t

consume :: [Char] -> Map
consume file =
  ((length grid, length $ head grid), consume1 [] 0 grid)
  where grid = lines file

neg :: Vec -> Vec
neg (r, c) = (-r, -c)
add :: Vec -> Vec -> Vec
add (fr, fc) (dr, dc) = (fr + dr, fc + dc)
scale :: Int -> Vec -> Vec
scale m (r, c) = (r * m, c * m)
path :: (Vec, Vec) -> Vec
path (f, t) = add t $ neg f

inside :: Vec -> Vec -> Bool
inside (mr, mc) (r, c) =
  r >= 0 && r < mr && c >= 0 && c < mc

simplify :: Vec -> Vec
simplify (r, c) =
  (r `div` d, c `div` d)
  where d = gcd r c

antiNodes :: Map -> Char -> [Vec]
antiNodes (size, ants) freq =
  filter (inside size) $ map (\p@(f, _) -> add f $ scale 2 $ path p) pairs
  where
    fants = filter (\(_, _, f) -> f == freq) ants
    coos = map (\(r, c, _) -> (r, c)) fants
    pairs = [(a1, a2) | a1 <- coos, a2 <- coos, a1 /= a2]

antiNodes22 :: [Vec] -> Vec -> Vec -> Vec -> [Vec]
antiNodes22 acc size from del
  | inside size nxt = antiNodes22 (nxt:acc) size nxt del
  | otherwise = acc
  where nxt = add from del

antiNodes21 :: Vec -> (Vec, Vec) -> [Vec]
antiNodes21 s p@(f, t) =
  antiNodes22 [] s f d ++
    [f] ++
    antiNodes22 [] s f (neg d)
  where
    d = simplify $ path p

antiNodes2 :: Map -> Char -> [Vec]
antiNodes2 (size, ants) freq =
  nub $ concat $ map (antiNodes21 size) pairs
  where
    fants = filter (\(_, _, f) -> f == freq) ants
    coos = map (\(r, c, _) -> (r, c)) fants
    pairs = [(a1, a2) | a1 <- coos, a2 <- coos, a1 /= a2]

part1 mp@(_, ants) =
  length $ nub $ concat $ map (antiNodes mp) freqs
  where
    freqs = nub $ map (\(_, _, f) -> f) ants

part2 mp@(_, ants) =
  length $ nub $ concat $ map (antiNodes2 mp) freqs
  where
    freqs = nub $ map (\(_, _, f) -> f) ants

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