1
0
Fork 0

Day 11 - part 2 using a modification of Kadane's algorithm.

This commit is contained in:
Jonathan Chan 2018-12-13 12:08:04 -08:00
parent c53606ebfa
commit 0244211290
3 changed files with 30 additions and 13 deletions

View File

@ -17,8 +17,8 @@ To arrive at [⟨ortho|normal⟩](https://hilb.ert.space) as December comes.
| 07 | ~ 1 | | 07 | ~ 1 |
| 08 | ~ 6.5 | | 08 | ~ 6.5 |
| 09 | ~ 7 | | 09 | ~ 7 |
| 10 | | | 10 | ~ 6.5 |
| 11 | | | 11 | ~ 7 |
| 12 | | | 12 | |
| 13 | | | 13 | |
| 14 | | | 14 | |

View File

@ -25,6 +25,7 @@ dependencies:
- text - text
- extra - extra
- matrix - matrix
- vector
library: library:
source-dirs: src source-dirs: src

View File

@ -3,21 +3,37 @@ module Day11 (main) where
import Data.Char (digitToInt) import Data.Char (digitToInt)
import Data.List (maximumBy) import Data.List (maximumBy)
import Data.Ord (comparing) import Data.Ord (comparing)
import Data.Tuple (swap)
indexToCoord :: Int -> (Int, Int) import Data.Matrix (Matrix, matrix, toLists, fromLists, getCol)
indexToCoord i = (1 + i `div` 300, 1 + i `mod` 300) import Data.Vector (Vector, (!))
import qualified Data.Vector as V (scanl1, zipWith3)
powerLevel :: (Int, Int) -> Int powerLevel :: (Int, Int) -> Int
powerLevel (x, y) = (subtract 5) . digitToInt . (!! 2) . reverse . show $ ((x + 10) * y + 7672) * (x + 10) powerLevel (x, y) = (subtract 5) . digitToInt . (!! 2) . reverse . show $ ((x + 10) * y + 7672) * (x + 10)
powerSquare :: Int -> (Int, Int) -> Int -- maxSubvectorSum :: size -> vector -> (value, y-coord)
powerSquare size (x, y) = maxSubvectorSum :: Int -> Vector Int -> (Int, Int)
if x > 300 - size + 1 || y > 300 - size + 1 then -5 maxSubvectorSum size v =
else sum [powerLevel (x', y') | x' <- [x .. x + size - 1], y' <- [y .. y + size - 1]] 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) -- maxSubsquareSum :: grid -> grid with scanl'd rows -> (left, right) -> (subsquare sum, (x, y, size))
part1 = indexToCoord . fst . maximumBy (comparing snd) . zip [0..] . map (powerSquare 3 . indexToCoord) $ [0 .. 300 * 300] 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 :: IO ()
main = do main = print part2
print part1