|
| 1 | +import qualified Data.Attoparsec.Text as At |
| 2 | +import qualified Data.Map.Strict as M |
| 3 | +import qualified Data.Set as S |
| 4 | +import Control.Monad |
| 5 | +import Control.Applicative |
| 6 | +import Data.List (sort) |
| 7 | +import Debug.Trace |
| 8 | + |
| 9 | +import Commons |
| 10 | +import Algorithms |
| 11 | + |
| 12 | +dirs :: [V2i] |
| 13 | +dirs = [V2 1 0, V2 0 1, V2 (-1) 0, V2 0 (-1)] |
| 14 | + |
| 15 | +pathFromWeights :: M.Map V2i Dist -> V2i -> S.Set V2i |
| 16 | +pathFromWeights w cur |
| 17 | + | w M.! cur == Dist 0 = S.singleton cur |
| 18 | + | otherwise = let neighbors = filter (`M.member` w) $ map (cur +) dirs |
| 19 | + lowestCost = minimum $ map (w M.!) neighbors |
| 20 | + next = head $ filter ((== lowestCost) . (w M.!)) neighbors |
| 21 | + in S.insert cur (pathFromWeights w next) |
| 22 | + |
| 23 | +matchWindow :: M.Map V2i Dist -> Int -> V2i -> [Int] |
| 24 | +matchWindow w len p = let wrange = [-len,-len+1..len] |
| 25 | + del (Dist a) (Dist b) = a - b |
| 26 | + in [del (w M.! (p + V2 i j)) (w M.! p) - (abs i + abs j) | i <- wrange, j <- wrange, |
| 27 | + abs i + abs j <= len, M.member (p + V2 i j) w, |
| 28 | + del (w M.! (p + V2 i j)) (w M.! p) > (abs i + abs j)] |
| 29 | + |
| 30 | +main :: IO () |
| 31 | +main = do |
| 32 | + inputGrid <- inp (parseGrid id) |
| 33 | + let findPos c = head $ M.keys $ M.filter (== c) inputGrid |
| 34 | + (begin, end) = (findPos 'S', findPos 'E') |
| 35 | + g = M.union (M.fromList [(begin, '.'), (end, '.')]) inputGrid |
| 36 | + getNeighbor v = map (,Dist 1) $ filter (\i -> M.member i g && g M.! i == '.') $ map (v +) dirs |
| 37 | + weights = shortestPath getNeighbor begin |
| 38 | + path = pathFromWeights weights end |
| 39 | + solve n = sum $ map snd $ filter ((>= 100) . fst) $ M.assocs $ counter $ concatMap (matchWindow weights n) path |
| 40 | + print $ solve 2 |
| 41 | + print $ solve 20 |
| 42 | + return () |
0 commit comments