50 lines
1.6 KiB
Haskell
50 lines
1.6 KiB
Haskell
module Day10 (main) where
|
|
|
|
import Data.List (sortBy, groupBy)
|
|
import Data.Ord (comparing)
|
|
import Data.Function (on)
|
|
import Data.Tuple.Extra ((***))
|
|
import Data.Matrix (matrix, toLists)
|
|
|
|
type Point = (Position, Velocity)
|
|
type Position = (Int, Int) -- ( x, y)
|
|
type Velocity = (Int, Int) -- (dx, dy)
|
|
|
|
stepPoint :: Point -> Point
|
|
stepPoint ((x, y), (dx, dy)) = ((x + dx, y + dy), (dx, dy))
|
|
|
|
parse :: String -> Point
|
|
parse str =
|
|
let position = "(" ++ (take 14 . drop 10 $ str) ++ ")"
|
|
velocity = "(" ++ (take 6 . drop 36 $ str) ++ ")"
|
|
in (read position, read velocity)
|
|
|
|
alignedX :: Int -> [Point] -> Bool
|
|
alignedX n =
|
|
any nearby . map (snd . unzip) . groupBy ((==) `on` fst) . sortBy (comparing fst) . fst . unzip
|
|
where nearby ys = length ys >= n && (maximum ys) - (minimum ys) < n
|
|
|
|
toGrid :: [Point] -> String
|
|
toGrid points =
|
|
let positions = fst . unzip $ points
|
|
minX = minimum . fst . unzip $ positions
|
|
minY = minimum . snd . unzip $ positions
|
|
maxX = maximum . fst . unzip $ positions
|
|
maxY = maximum . snd . unzip $ positions
|
|
isPoint (y, x) = if (x + minX - 1, y + minY - 1) `elem` positions then '#' else '.'
|
|
grid = matrix (maxY - minY + 1) (maxX - minX + 1) isPoint
|
|
in unlines . toLists $ grid
|
|
|
|
part1 :: Int -> [Point] -> (String, Int)
|
|
part1 sec points =
|
|
if alignedX 10 points
|
|
then (toGrid $ points, sec)
|
|
else part1 (sec + 1) $ map stepPoint points
|
|
|
|
main :: IO ()
|
|
main = do
|
|
input <- map parse . lines <$> readFile "input/10.txt"
|
|
let result = part1 0 input
|
|
putStrLn $ fst result
|
|
print $ snd result
|