1+ {-# OPTIONS_GHC -Wno-orphans #-}
12{-# OPTIONS_GHC -Wno-unused-imports #-}
23{-# OPTIONS_GHC -Wno-unused-top-binds #-}
34
2021-- types @_ :~> _@ with the actual types of inputs and outputs of the
2122-- solution. You can delete the type signatures completely and GHC
2223-- will recommend what should go in place of the underscores.
23- module AOC2024.Day17 (
24- day17a ,
25- day17b ,
26- )
24+ module AOC2024.Day17
2725where
2826
29- import AOC.Prelude
27+ -- (
28+ -- day17a,
29+ -- day17b,
30+ -- )
31+
32+ import AOC.Prelude hiding (Finite , modulo , packFinite )
33+ import Control.Monad.Primitive
34+ import Control.Monad.ST
3035import Data.Bits
36+ import qualified Data.Conduino as C
37+ import qualified Data.Conduino.Combinators as C
38+ import Data.Finite.Integral hiding (shift )
3139import qualified Data.Graph.Inductive as G
3240import qualified Data.IntMap as IM
3341import qualified Data.IntMap.NonEmpty as IM
@@ -39,37 +47,110 @@ import qualified Data.List.PointedList.Circular as PLC
3947import qualified Data.Map as M
4048import qualified Data.Map.NonEmpty as NEM
4149import qualified Data.OrdPSQ as PSQ
50+ import Data.Primitive.MutVar
51+ import Data.STRef
4252import qualified Data.Sequence as Seq
4353import qualified Data.Sequence.NonEmpty as NESeq
4454import qualified Data.Set as S
4555import qualified Data.Set.NonEmpty as NES
4656import qualified Data.Text as T
4757import qualified Data.Vector as V
58+ import qualified Data.Vector.Mutable.Sized as SMV
59+ import qualified Data.Vector.Sized as SV
60+ import qualified Data.Vector.Storable.Mutable.Sized as SMVS
61+ import qualified Data.Vector.Storable.Sized as SVS
4862import qualified Linear as L
4963import qualified Numeric.Lens as L
5064import qualified Text.Megaparsec as P
5165import qualified Text.Megaparsec.Char as P
5266import qualified Text.Megaparsec.Char.Lexer as PP
5367
54- day17a :: _ :~> _
68+ day17a :: _ :~> [ Int ]
5569day17a =
5670 MkSol
5771 { sParse = parseMaybe' do
58- a <- " Register A: " *> pDecimal
59- P. newline
60- b <- " Register B: " *> pDecimal
61- P. newline
62- c <- " Register C: " *> pDecimal
63- P. newline
72+ a <- " Register A: " *> pDecimal <* P. newline
73+ b <- " Register B: " *> pDecimal <* P. newline
74+ c <- " Register C: " *> pDecimal <* P. newline
6475 P. newline
6576 d <- " Program: " *> (pDecimal `sepBy'` " ," )
66- pure (a, b, c, d)
77+ p <- case parseProgram d of
78+ Nothing -> fail " Bad program"
79+ Just p -> pure p
80+ pure (a, b, c, p)
6781 , sShow = intercalate " ," . map show
68- , sSolve =
69- noFail $ \ (a, b, c, p :: [Int ]) ->
70- go 0 (V3 a b c) (Seq. fromList p)
82+ , sSolve = \ (a, b, c, instrs) -> do
83+ pure . map fromIntegral $ stepProg instrs (V3 a b c)
7184 }
7285
86+ data Combo
87+ = CLiteral (Finite Word 4 )
88+ | CReg (Finite Word 3 )
89+ deriving stock (Show , Eq , Ord )
90+
91+ data Instr
92+ = ADV Combo
93+ | BXL (Finite Word 8 )
94+ | BST Combo
95+ | JNZ (Finite Word 4 )
96+ | BXC
97+ | OUT Combo
98+ | BDV Combo
99+ | CDV Combo
100+ deriving stock (Show , Eq , Ord )
101+
102+ comboParser :: Finite Word 7 -> Combo
103+ comboParser = either CLiteral CReg . separateSum
104+
105+ instrParser :: Finite Word 8 -> Finite Word 8 -> Maybe Instr
106+ instrParser i =
107+ SV. fromTuple @ _ @ 8
108+ ( fmap (ADV . comboParser) . strengthen
109+ , Just . BXL
110+ , fmap (BST . comboParser) . strengthen
111+ , Just . JNZ . snd . separateProduct @ 2 @ 4
112+ , const $ Just BXC
113+ , fmap (OUT . comboParser) . strengthen
114+ , fmap (BDV . comboParser) . strengthen
115+ , fmap (CDV . comboParser) . strengthen
116+ )
117+ `SV.index` fromIntegral i
118+
119+ parseProgram :: [Int ] -> Maybe (SV. Vector 8 Instr )
120+ parseProgram xs = do
121+ xsVec <- SV. fromList @ 16 =<< traverse (packFinite . fromIntegral ) xs
122+ SV. generateM \ i ->
123+ instrParser (xsVec `SV.index` combineProduct (0 , i)) (xsVec `SV.index` combineProduct (1 , i))
124+
125+ readComboV3 :: Combo -> V3 Word -> Word
126+ readComboV3 = \ case
127+ CLiteral l -> \ _ -> fromIntegral l
128+ CReg 0 -> \ (V3 a _ _) -> a
129+ CReg 1 -> \ (V3 _ b _) -> b
130+ CReg 2 -> \ (V3 _ _ c) -> c
131+ _ -> undefined
132+
133+ stepProg :: SV. Vector 8 Instr -> V3 Word -> [Finite Word 8 ]
134+ stepProg tp = go' 0
135+ where
136+ go' :: Finite Word 8 -> V3 Word -> [Finite Word 8 ]
137+ go' i v@ (V3 a b c) = case tp `SV.index` fromIntegral i of
138+ ADV r -> withStep $ V3 (a `div` (2 ^ combo r)) b c
139+ BXL l -> withStep $ V3 a (b `xor` fromIntegral l) c
140+ BST r -> withStep $ V3 a (combo r `mod` 8 ) c
141+ JNZ l
142+ | a == 0 -> withStep v
143+ | otherwise -> go' (weakenN l) v
144+ BXC -> withStep $ V3 a (b `xor` c) c
145+ OUT r -> modulo (combo r) : withStep v
146+ BDV r -> withStep $ V3 a (a `div` (2 ^ combo r)) c
147+ CDV r -> withStep $ V3 a b (a `div` (2 ^ combo r))
148+ where
149+ combo = flip readComboV3 v
150+ withStep
151+ | i == maxBound = const []
152+ | otherwise = go' (succ i)
153+
73154go :: Int -> V3 Int -> Seq Int -> [Int ]
74155-- go i (V3 a b c) tp = case (,) <$> Seq.lookup i tp <*> Seq.lookup (i + 1) tp of
75156go i (V3 a b c) tp = case (,) <$> Seq. lookup i tp <*> Seq. lookup (i + 1 ) tp of
@@ -158,10 +239,18 @@ go i (V3 a b c) tp = case (,) <$> Seq.lookup i tp <*> Seq.lookup (i + 1) tp of
158239day17b :: _ :~> _
159240day17b =
160241 MkSol
161- { sParse = sParse day17a
242+ { sParse = parseMaybe' do
243+ _ <- " Register A: " *> pDecimal @ Int
244+ P. newline
245+ _ <- " Register B: " *> pDecimal @ Int
246+ P. newline
247+ _ <- " Register C: " *> pDecimal @ Int
248+ P. newline
249+ P. newline
250+ " Program: " *> (pDecimal `sepBy'` " ," )
162251 , sShow = show
163252 , sSolve =
164- \ (_, _, _, p :: [ Int ]) -> listToMaybe do
253+ \ p -> listToMaybe do
165254 option <- stepBackwards (reverse p)
166255 guard $ go 0 (V3 option 0 0 ) (Seq. fromList p) == p
167256 pure option
0 commit comments