#! /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