63
src/Day4.hs
Normal file
63
src/Day4.hs
Normal file
@@ -0,0 +1,63 @@
|
||||
module Main where
|
||||
|
||||
import qualified AoC as A (diagonals, findSubstrings)
|
||||
import Data.List (intersect, transpose)
|
||||
|
||||
-- |
|
||||
-- A.diagonals gives the diagonals of a matrix
|
||||
-- A.findSubstrings provides the indices of a substring in a string
|
||||
-- We get the number of substrings XMAS and SAMX in all possible ways and add
|
||||
part1 :: [[Char]] -> Int
|
||||
part1 grid =
|
||||
(sum . concat)
|
||||
[ map countXmas grid,
|
||||
map countXmas $ transpose grid,
|
||||
map countXmas $ A.diagonals grid,
|
||||
map countXmas $ A.diagonals $ map reverse grid
|
||||
]
|
||||
where
|
||||
countXmas :: [Char] -> Int
|
||||
countXmas =
|
||||
(+)
|
||||
<$> length . A.findSubstrings "XMAS"
|
||||
<*> length . A.findSubstrings "SAMX"
|
||||
|
||||
-- |
|
||||
-- We get indices of substrings MAS and SAM across only the diagonals
|
||||
-- Then we calculate the coordinates of the letter 'A' in those
|
||||
-- Then we intersect the lists to find common As
|
||||
part2 :: [[Char]] -> Int
|
||||
part2 grid =
|
||||
let m = length grid
|
||||
n = length $ head grid
|
||||
-- diagonals = left -> right, top -> bottom
|
||||
diags1 = findMas $ A.diagonals grid
|
||||
-- diagonals = right -> left, top -> bottom
|
||||
diags2 = findMas $ A.diagonals $ map reverse grid
|
||||
in length $
|
||||
intersect
|
||||
-- coordinate calculation for A across diag1 and diag2
|
||||
[ if i < n
|
||||
then (n - i + diag, diag + 1)
|
||||
else (diag + 1, i - n + diag + 2)
|
||||
| (i, diags) <- zip [0 ..] diags1,
|
||||
diag <- diags
|
||||
]
|
||||
[ if i < m
|
||||
then (i - diag - 1, diag + 1)
|
||||
else (m - diag - 2, i - m + diag + 2)
|
||||
| (i, diags) <- zip [0 ..] diags2,
|
||||
diag <- diags
|
||||
]
|
||||
where
|
||||
-- find indices of MAS and SAM across diagonals
|
||||
findMas :: [[Char]] -> [[Int]]
|
||||
findMas = map ((++) <$> A.findSubstrings "MAS" <*> A.findSubstrings "SAM")
|
||||
|
||||
main :: IO ()
|
||||
main =
|
||||
do
|
||||
raw <- lines <$> readFile "./inputs/day4.in"
|
||||
|
||||
putStr "Part 1: " >> print (part1 raw)
|
||||
putStr "Part 2: " >> print (part2 raw)
|
||||
Reference in New Issue
Block a user