module Main where import Data.List (uncons) import Data.Map.Strict (Map) import Data.Map.Strict qualified as M import Data.Maybe (mapMaybe) import Data.Set (Set) import Data.Set qualified as S import System.Environment (getArgs) main :: IO () main = do input <- maybe (error "Missing argument to input file") (readFile . fst) =<< uncons <$> getArgs putStrLn $ unwords ["Part 1:", show $ part1 input] putStrLn $ unwords ["Part 2:", show $ part2 input] area :: (Int, Int) -> (Int, Int) -> Int area (x1, y1) (x2, y2) = x' * y' where x' = max x1 x2 - min x1 x2 + 1 y' = max y1 y2 - min y1 y2 + 1 parse :: String -> [(Int, Int)] parse = mapMaybe (fmap fst . uncons . go) . lines where go :: String -> [(Int, Int)] go s = do (x, ',' : s1) <- reads s (y, []) <- reads s1 pure (x, y) combine :: (Ord a) => [a] -> [(a, a)] combine as = S.toList $ foldl' (go as) S.empty as where go :: (Ord a) => [a] -> Set (a, a) -> a -> Set (a, a) go as' pairs b = foldl' (\pairs' a -> if a /= b then S.insert (a, b) pairs' else pairs') pairs as' -- | Idea: Generate pairs of all coordinates and calculate the area of -- them. Take the maximum. part1 :: String -> Int part1 = maximum . map (uncurry area) . combine . parse -- | Idea: The red tiles form corners in a shape where the green tiles -- are the walls. In order to be able to create a rectangle the -- opposite tiles needs to be "visible" to each other, i.e. there -- cannot be a wall tile in the way. -- -- Create the shape, for each red tile create a beam to every other -- red tile, if they are unobstructed store the area. Pick the -- greatest area. part2 :: String -> Int part2 = error "Not implemented" testInput :: String testInput = unlines [ "7,1", "11,1", "11,7", "9,7", "9,5", "2,5", "2,3", "7,3" ]