AoC2018/Day6/Part1.hs

42 lines
1.5 KiB
Haskell
Executable File

#! /usr/bin/env stack
-- stack --resolver lts-12.20 --install-ghc script
{-# LANGUAGE ViewPatterns, TupleSections #-}
module Main where
import Control.Arrow ((***), (&&&))
import Data.Bifunctor (Bifunctor, bimap)
import Data.Function (on)
import Data.Maybe (catMaybes)
import qualified Data.Array as A
import qualified Data.List as L
import qualified Data.Set as S
import Debug.Trace
main :: IO ()
main = interact $ (. (map parseLine . lines)) $ \points ->
let limits = (both minimum &&& both maximum) $ (map fst &&& map snd) points
((minX,minY),(maxX,maxY)) = limits
closest = A.array limits $ map (\p -> (p, findClosest p)) (A.range limits)
dist (x0,y0) (x1,y1) = abs (x0-x1) + abs (y0-y1)
findClosest pt
| ((d0,pt0):(d1,_):_) <- L.sortBy (compare `on` fst) (map (dist pt &&& id) points)
, d0 < d1 = Just pt0
| otherwise = Nothing
infinite = S.fromList $ catMaybes $
[ closest A.! ix
| ix <- map (,minY) [minX..maxX-1]
++ map (maxX,) [minY..maxY-1]
++ map (,maxY) [minX+1..maxX]
++ map (minX,) [minY+1..maxY]
]
finite = S.fromList points `S.difference` infinite
areas = [ (p, length $ filter (== Just p) (A.elems closest)) | p <- S.toList finite ]
in traceShow closest $ unlines $ map show $ L.sortBy (compare `on` snd) areas
parseLine :: String -> (Int, Int)
parseLine (break (==',') -> (read -> x, ',':' ':(read -> y))) = (x, y)
both :: Bifunctor p => (a -> b) -> p a a -> p b b
both f = bimap f f