From 6fa7a855ee48fceabdff31153065553b9b14937d Mon Sep 17 00:00:00 2001 From: Jonathan Chan Date: Mon, 3 Dec 2018 10:08:06 -0800 Subject: [PATCH] Day 03 - now with IntMap! --- README.md | 2 +- src/Day03.hs | 33 ++++++++++++--------------------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index f2b4b47..6d1d88b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ To arrive at [⟨ortho|normal⟩](https://hilb.ert.space) as December comes. |-----|-------------|------------| | 01 | < 0.1 | | 02 | < 0.1 | -| 03 | | +| 03 | ~ 2 | | 04 | | | 05 | | | 06 | | diff --git a/src/Day03.hs b/src/Day03.hs index 4d9c60e..344a612 100644 --- a/src/Day03.hs +++ b/src/Day03.hs @@ -1,33 +1,24 @@ module Day03 (main) where -import Data.Text (split, pack, unpack) +import Data.Text (empty, split, pack, unpack) +import Data.IntMap (IntMap, fromListWith, size, notMember) +import qualified Data.IntMap as M (filter) -type Claim = (Int, Int, Int, Int, Int) -- id, left, top, width, height -(%) = mod -(//) = div +type Claim = (Int, [Int]) parse :: String -> Claim parse str = - let i:l:t:w:h:[] = map (read . unpack) . tail . split (flip elem $ "#@,:x") . pack . filter (/= ' ') $ str - in (i, l, t, w, h) + let i:l:t:w:h:[] = map (read . unpack) . filter (/= empty) . split (flip elem $ " #@,:x") . pack $ str + in (i, [r * 1000 + c | r <- [t .. t + h - 1], c <- [l .. l + w - 1]]) -doesClaim :: Int -> Claim -> Bool -doesClaim cell (_, left, top, width, height) = - let row = cell // 1000 - col = cell % 1000 - in (row >= top) && (row < top + height) && (col >= left) && (col < left + width) - -claimCount :: [Claim] -> Int -> Int -claimCount claims cell = length . filter (doesClaim cell) $ claims +overlapMap :: [Claim] -> IntMap Int +overlapMap = M.filter (> 1) . fromListWith (+) . (flip zip) (repeat 1) . concat . map snd part1 :: [Claim] -> Int -part1 claims = length . filter id . map ((> 1) . claimCount claims) $ [0 .. 1000 * 1000 - 1] - -part2 :: [Claim] -> Claim -part2 claims = filterOverlaps 0 claims - where filterOverlaps cell acc = - let newAcc = if claimCount claims cell > 1 then filter (not . doesClaim cell) acc else acc - in if length newAcc == 1 then head newAcc else filterOverlaps (cell + 1) newAcc +part1 = size . overlapMap + +part2 :: [Claim] -> Int +part2 claims = fst . head . filter (all (flip notMember $ overlapMap claims) . snd) $ claims main :: IO () main = do