|
1 |
| -{-# OPTIONS_GHC -Wno-unused-imports #-} |
2 |
| -{-# OPTIONS_GHC -Wno-unused-top-binds #-} |
3 |
| - |
4 | 1 | -- |
|
5 | 2 | -- Module : AOC.Challenge.Day15
|
6 | 3 | -- License : BSD3
|
|
9 | 6 | -- Portability : non-portable
|
10 | 7 | --
|
11 | 8 | -- Day 15. See "AOC.Solver" for the types used in this module!
|
12 |
| --- |
13 |
| --- After completing the challenge, it is recommended to: |
14 |
| --- |
15 |
| --- * Replace "AOC.Prelude" imports to specific modules (with explicit |
16 |
| --- imports) for readability. |
17 |
| --- * Remove the @-Wno-unused-imports@ and @-Wno-unused-top-binds@ |
18 |
| --- pragmas. |
19 |
| --- * Replace the partial type signatures underscores in the solution |
20 |
| --- types @_ :~> _@ with the actual types of inputs and outputs of the |
21 |
| --- solution. You can delete the type signatures completely and GHC |
22 |
| --- will recommend what should go in place of the underscores. |
23 | 9 |
|
24 | 10 | module AOC.Challenge.Day15 (
|
25 | 11 | day15a
|
26 | 12 | , day15b
|
27 | 13 | ) where
|
28 | 14 |
|
29 |
| -import AOC.Prelude |
| 15 | +import AOC.Common (digitToIntSafe) |
| 16 | +import AOC.Common.Point (Point, V2(..), parseAsciiMap, mannDist, cardinalNeighbsSet) |
| 17 | +import AOC.Common.Search (aStar) |
| 18 | +import AOC.Solver ((:~>)(..)) |
| 19 | +import Control.Monad ((<=<)) |
| 20 | +import Data.Finite (Finite, packFinite) |
| 21 | +import Data.Map (Map) |
| 22 | +import qualified Data.Map as M |
| 23 | +import qualified Data.Set as S |
30 | 24 |
|
31 |
| -import qualified Data.Graph.Inductive as G |
32 |
| -import qualified Data.IntMap as IM |
33 |
| -import qualified Data.IntSet as IS |
34 |
| -import qualified Data.List.NonEmpty as NE |
35 |
| -import qualified Data.List.PointedList as PL |
36 |
| -import qualified Data.List.PointedList.Circular as PLC |
37 |
| -import qualified Data.Map as M |
38 |
| -import qualified Data.OrdPSQ as PSQ |
39 |
| -import qualified Data.Sequence as Seq |
40 |
| -import qualified Data.Set as S |
41 |
| -import qualified Data.Text as T |
42 |
| -import qualified Data.Vector as V |
43 |
| -import qualified Linear as L |
44 |
| -import qualified Text.Megaparsec as P |
45 |
| -import qualified Text.Megaparsec.Char as P |
46 |
| -import qualified Text.Megaparsec.Char.Lexer as PP |
47 |
| -import AOC.Common.Search |
| 25 | +type Risk = Finite 9 |
48 | 26 |
|
49 |
| -day15a :: _ :~> _ |
50 |
| -day15a = MkSol |
51 |
| - { sParse = Just . parseAsciiMap digitToIntSafe |
| 27 | +day15 :: (Map Point Risk -> Map Point Risk) -> Map Point Risk :~> Int |
| 28 | +day15 reMap = MkSol |
| 29 | + { sParse = Just . parseAsciiMap (packFinite . subtract 1 . fromIntegral <=< digitToIntSafe) |
52 | 30 | , sShow = show
|
53 |
| - , sSolve = \mp -> |
54 |
| - let targ = fst $ M.findMax mp |
| 31 | + , sSolve = \mp0 -> |
| 32 | + let mp = reMap mp0 |
| 33 | + (targ, _) = M.findMax mp |
| 34 | + cost p = fromIntegral (mp M.! p) + 1 |
55 | 35 | in fst <$> aStar
|
56 | 36 | (mannDist targ)
|
57 |
| - (M.fromSet (\x -> mp M.! x) . (`S.intersection` M.keysSet mp) . cardinalNeighbsSet) |
| 37 | + (M.fromSet cost . S.intersection (M.keysSet mp) . cardinalNeighbsSet) |
58 | 38 | 0
|
59 | 39 | (== targ)
|
60 | 40 | }
|
61 | 41 |
|
62 |
| --- aStar |
63 |
| --- :: forall n p. (Ord n, Ord p, Num p) |
64 |
| --- => (n -> p) -- ^ heuristic |
65 |
| --- -> (n -> Map n p) -- ^ neighborhood |
66 |
| --- -> n -- ^ start |
67 |
| --- -> (n -> Bool) -- ^ target |
68 |
| --- -> Maybe (p, [n]) -- ^ the shortest path, if it exists, and its cost |
69 | 42 |
|
70 |
| -day15b :: _ :~> _ |
71 |
| -day15b = MkSol |
72 |
| - { sParse = sParse day15a |
73 |
| - , sShow = show |
74 |
| - , sSolve = \mp0 -> |
75 |
| - let mp = M.fromList |
76 |
| - [ (k', v') |
77 |
| - | (k, v) <- M.toList mp0 |
78 |
| - , dx <- [0,1,2,3,4] |
79 |
| - , dy <- [0,1,2,3,4] |
80 |
| - , let k' = k + V2 (shifter * dx) (shifter * dy) |
81 |
| - , let v' = ((v - 1 + dx+dy) `mod` 9) + 1 |
82 |
| - ] |
83 |
| - corner = fst $ M.findMax mp0 |
84 |
| - V2 shifter _ = corner + 1 |
85 |
| - targ = fst $ M.findMax mp |
86 |
| - in fst <$> aStar |
87 |
| - (mannDist targ) |
88 |
| - (M.fromSet (\x -> mp M.! x) . (`S.intersection` M.keysSet mp) . cardinalNeighbsSet) |
89 |
| - 0 |
90 |
| - (== targ) |
91 |
| - } |
| 43 | +day15a :: Map Point Risk :~> Int |
| 44 | +day15a = day15 id |
| 45 | + |
| 46 | +day15b :: Map Point Risk :~> Int |
| 47 | +day15b = day15 \mp0 -> |
| 48 | + let (corner, _) = M.findMax mp0 |
| 49 | + shifter = corner + 1 |
| 50 | + in M.fromList |
| 51 | + [ (k', v + dx + dy) |
| 52 | + | (k, v) <- M.toList mp0 |
| 53 | + , dx <- [0,1,2,3,4] |
| 54 | + , dy <- [0,1,2,3,4] |
| 55 | + , let k' = k + (shifter * (fromIntegral <$> V2 dx dy)) |
| 56 | + ] |
0 commit comments