From 02442112904f211a9131f7160e9dbf3556bbaf6c Mon Sep 17 00:00:00 2001 From: Jonathan Chan Date: Thu, 13 Dec 2018 12:08:04 -0800 Subject: [PATCH] Day 11 - part 2 using a modification of Kadane's algorithm. --- README.md | 4 ++-- package.yaml | 1 + src/Day11.hs | 38 +++++++++++++++++++++++++++----------- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index f3331f5..ab81969 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ To arrive at [⟨ortho|normal⟩](https://hilb.ert.space) as December comes. | 07 | ~ 1 | | 08 | ~ 6.5 | | 09 | ~ 7 | -| 10 | | -| 11 | | +| 10 | ~ 6.5 | +| 11 | ~ 7 | | 12 | | | 13 | | | 14 | | diff --git a/package.yaml b/package.yaml index 2267f2e..c33663a 100644 --- a/package.yaml +++ b/package.yaml @@ -25,6 +25,7 @@ dependencies: - text - extra - matrix +- vector library: source-dirs: src diff --git a/src/Day11.hs b/src/Day11.hs index dc49209..27d5a38 100644 --- a/src/Day11.hs +++ b/src/Day11.hs @@ -3,21 +3,37 @@ module Day11 (main) where import Data.Char (digitToInt) import Data.List (maximumBy) import Data.Ord (comparing) - -indexToCoord :: Int -> (Int, Int) -indexToCoord i = (1 + i `div` 300, 1 + i `mod` 300) +import Data.Tuple (swap) +import Data.Matrix (Matrix, matrix, toLists, fromLists, getCol) +import Data.Vector (Vector, (!)) +import qualified Data.Vector as V (scanl1, zipWith3) powerLevel :: (Int, Int) -> Int powerLevel (x, y) = (subtract 5) . digitToInt . (!! 2) . reverse . show $ ((x + 10) * y + 7672) * (x + 10) -powerSquare :: Int -> (Int, Int) -> Int -powerSquare size (x, y) = - if x > 300 - size + 1 || y > 300 - size + 1 then -5 - else sum [powerLevel (x', y') | x' <- [x .. x + size - 1], y' <- [y .. y + size - 1]] +-- maxSubvectorSum :: size -> vector -> (value, y-coord) +maxSubvectorSum :: Int -> Vector Int -> (Int, Int) +maxSubvectorSum size v = + let accuml = V.scanl1 (+) v + summed = map (\i -> accuml ! (i + size - 1) - accuml ! i + v ! i) [0 .. 300 - size] + zipped = zip summed [1..] + in maximumBy (comparing fst) zipped -part1 :: (Int, Int) -part1 = indexToCoord . fst . maximumBy (comparing snd) . zip [0..] . map (powerSquare 3 . indexToCoord) $ [0 .. 300 * 300] +-- maxSubsquareSum :: grid -> grid with scanl'd rows -> (left, right) -> (subsquare sum, (x, y, size)) +maxSubsquareSum :: Matrix Int -> Matrix Int -> (Int, Int) -> (Int, (Int, Int, Int)) +maxSubsquareSum grid accRow (left, right) = + let vec = V.zipWith3 (\accR accL gridL -> accR - accL + gridL) (getCol right accRow) (getCol left accRow) (getCol left grid) + size = right - left + 1 + (v, y) = maxSubvectorSum size vec + in (v, (left, y, size)) + +-- part2 :: (x, y, size) +part2 :: (Int, Int, Int) +part2 = + let grid = matrix 300 300 (powerLevel . swap) + accRow = fromLists . map (scanl1 (+)) . toLists $ grid + colRange = [(left, right) | left <- [1..300], right <- [left..300]] -- part1: [(left, left + 2) | left <- [1..298]] + in snd . maximumBy (comparing fst) . map (maxSubsquareSum grid accRow) $ colRange main :: IO () -main = do - print part1 \ No newline at end of file +main = print part2 \ No newline at end of file