39 lines
1.6 KiB
Haskell
39 lines
1.6 KiB
Haskell
module Day11 (main) where
|
|
|
|
import Data.Char (digitToInt)
|
|
import Data.List (maximumBy)
|
|
import Data.Ord (comparing)
|
|
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)
|
|
|
|
-- 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
|
|
|
|
-- 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 = print part2 |