From: Neil Smith Date: Wed, 15 Dec 2021 13:15:17 +0000 (+0000) Subject: Done day 15 X-Git-Url: https://git.njae.me.uk/?a=commitdiff_plain;h=ebd6d5f3f72d7fc7b5b0d7e17054373058cdf103;p=advent-of-code-21.git Done day 15 --- diff --git a/advent-of-code21.cabal b/advent-of-code21.cabal index 90d342a..050473f 100644 --- a/advent-of-code21.cabal +++ b/advent-of-code21.cabal @@ -149,3 +149,13 @@ executable advent13 import: common-extensions, build-directives main-is: advent13/Main.hs build-depends: text, attoparsec, containers, linear + +executable advent14 + import: common-extensions, build-directives + main-is: advent14/Main.hs + build-depends: text, attoparsec, containers, multiset + +executable advent15 + import: common-extensions, build-directives + main-is: advent15/Main.hs + build-depends: text, containers, linear, array, pqueue, mtl, lens diff --git a/advent14/Main.hs b/advent14/Main.hs new file mode 100644 index 0000000..c6ade97 --- /dev/null +++ b/advent14/Main.hs @@ -0,0 +1,92 @@ +-- Writeup at https://work.njae.me.uk/2021/12/13/advent-of-code-2021-day-13/ + +import Data.Text () +import qualified Data.Text.IO as TIO + +import Data.Attoparsec.Text +import Control.Applicative + +import Data.List +import qualified Data.Map as M +import Data.Map ((!)) +import qualified Data.MultiSet as MS +import qualified Data.Set as S + +type RuleSet = M.Map String String +type PolyPairs = MS.MultiSet String + + +main :: IO () +main = + do text <- TIO.readFile "data/advent14.txt" + let (template, rules) = successfulParse text + print $ part1 rules template + print $ part2 rules template + +part1 :: RuleSet -> String -> Int +part1 rules template = (last counts) - (head counts) + where result = (simulateNaive rules template) !! 10 + counts = sort $ map snd $ MS.toOccurList $ MS.fromList result + +simulateNaive :: RuleSet -> String -> [String] +simulateNaive rules polymer = iterate (stepNaive rules) polymer + +stepNaive :: RuleSet -> String -> String +stepNaive rules polymer = merge polymer $ concatMap (rules !) $ mkPairs polymer + +part2 :: RuleSet -> String -> Int +part2 rules template = (last counts) - (head counts) + where pairs = MS.fromList $ mkPairs template + result = (simulate rules pairs) !! 40 + elementCounts = countElements result + -- counts = sort $ map snd $ MS.toOccurList elementCounts + counts = sort $ M.elems elementCounts + +simulate :: RuleSet -> PolyPairs -> [PolyPairs] +simulate rules polymer = iterate (step rules) polymer + +step :: RuleSet -> PolyPairs -> PolyPairs +step rules polymer = MS.union firsts seconds + where firsts = MS.map (addFirst rules) polymer + seconds = MS.map (addSecond rules) polymer + +addFirst :: RuleSet -> String -> String +addFirst rules pair = a : c + where a = pair!!0 + c = rules ! pair + +addSecond :: RuleSet -> String -> String +addSecond rules pair = c ++ [a] + where a = pair!!1 + c = rules ! pair + +-- countElements :: PolyPairs -> MS.MultiSet Char +countElements :: PolyPairs -> M.Map Char Int +countElements pairs = counts + where firsts = MS.map (!!0) pairs + seconds = MS.map (!!1) pairs + elems = S.union (MS.toSet firsts) (MS.toSet seconds) + -- counts = MS.fromMap $ M.map ((`div` 2) . (+ 1)) $ MS.toMap $ MS.union firsts seconds + counts = M.map ((`div` 2) . (+ 1)) $ MS.toMap $ MS.union firsts seconds + + +mkPairs :: String -> [String] +mkPairs polymer = map stringify $ zip polymer $ tail polymer +stringify (a, b) = [a, b] + +merge :: [a] -> [a] -> [a] +merge [] ys = ys +merge (x:xs) ys = x : (merge ys xs) + +-- Parse the input file + +inputP = (,) <$> (many1 letter) <* many1 endOfLine <*> rulesP + +rulesP = M.fromList <$> ruleP `sepBy` endOfLine +ruleP = (,) <$> many1 letter <* " -> " <*> many1 letter + +-- successfulParse :: Text -> (Integer, [Maybe Integer]) +successfulParse input = + case parseOnly inputP input of + Left _err -> ("", M.empty) -- TIO.putStr $ T.pack $ parseErrorPretty err + Right indata -> indata diff --git a/advent15/Main.hs b/advent15/Main.hs new file mode 100644 index 0000000..1186a52 --- /dev/null +++ b/advent15/Main.hs @@ -0,0 +1,229 @@ +-- Writeup at https://work.njae.me.uk/2021/12/13/advent-of-code-2021-day-13/ + + +import Debug.Trace + +-- import qualified Data.Text.IO as TIO + +-- import qualified Data.Map.Strict as M +-- import Data.Map.Strict ((!)) +import qualified Data.PQueue.Prio.Min as P +import qualified Data.Set as S +import qualified Data.Sequence as Q +import Data.Sequence ((<|), (|>), (><)) --, ViewR( (:>) ), ViewL( (:<) )) +import Data.Foldable (foldl', sum) -- (toList, foldr', foldl', all) +import Data.Char +import Control.Monad.Reader +import Control.Lens hiding ((<|), (|>), (:>), (:<)) +import Data.Maybe (fromMaybe) +import Linear (V2(..), (^+^), (^-^), (*^), (^*)) +import Data.Array.IArray + + +pattern Empty <- (Q.viewl -> Q.EmptyL) where Empty = Q.empty +pattern x :< xs <- (Q.viewl -> x Q.:< xs) where (:<) = (Q.<|) +pattern xs :> x <- (Q.viewr -> xs Q.:> x) where (:>) = (Q.|>) + +type BasePosition = V2 Int -- r, c +newtype Position = Position BasePosition -- r, c + deriving (Eq, Ord, Show) +newtype TiledPosition = TiledPosition BasePosition -- r, c + deriving (Eq, Ord, Show) +type Grid = Array BasePosition Int + +data Cave = Cave + { _grid :: Grid + , _goal :: BasePosition + } deriving (Eq, Ord, Show) +makeLenses ''Cave + +type CaveContext = Reader Cave + + +data Agendum s = + Agendum { _current :: s + , _trail :: Q.Seq s + , _cost :: Int + } deriving (Show, Eq) +makeLenses ''Agendum + +type Agenda s = P.MinPQueue Int (Agendum s) + +type ExploredStates s = S.Set s + +class (Eq s, Ord s, Show s) => SearchState s where + unwrapPos :: s -> BasePosition + successors :: s -> CaveContext (Q.Seq s) + estimateCost :: s -> CaveContext Int + emptySearchState :: s + isGoal :: s -> CaveContext Bool + entryCost :: s -> CaveContext Int + + +instance SearchState Position where + + unwrapPos (Position p) = p + + emptySearchState = Position (V2 0 0) + + -- successors :: Position -> CaveContext (Q.Seq Position) + successors here = + do grid <- asks _grid + let neighbours = + filter (inRange (bounds grid)) + [ (unwrapPos here) ^+^ delta + | delta <- [V2 -1 0, V2 1 0, V2 0 -1, V2 0 1] + ] + let succs = Q.fromList $ map Position neighbours + return succs + + -- estimateCost :: Position -> CaveContext Int + estimateCost here = + do goal <- asks _goal + let (V2 dr dc) = (unwrapPos here) ^-^ goal + return $ (abs dr) + (abs dc) + + -- isGoal :: here -> CaveContext Bool + isGoal here = + do goal <- asks _goal + return $ (unwrapPos here) == goal + + entryCost here = + do grid <- asks _grid + return $ grid ! (unwrapPos here) + +instance SearchState TiledPosition where + + emptySearchState = TiledPosition (V2 0 0) + + unwrapPos (TiledPosition p) = p + + -- successors :: Position -> CaveContext (Q.Seq Position) + successors (TiledPosition here) = + do grid <- asks _grid + let (lowBound, highBound) = bounds grid + let extendedBounds = ( lowBound + , tileScale highBound + ) + let neighbours = + filter (inRange extendedBounds) + [ here ^+^ delta + | delta <- [V2 -1 0, V2 1 0, V2 0 -1, V2 0 1] + ] + let succs = Q.fromList $ map TiledPosition neighbours + return succs + + -- estimateCost :: Position -> CaveContext Int + estimateCost (TiledPosition here) = + do goal <- asks _goal + let (V2 dr dc) = here ^-^ (tileScale goal) + return $ (abs dr) + (abs dc) + + -- isGoal :: here -> CaveContext Bool + isGoal (TiledPosition here) = + do goal <- asks _goal + return $ here == (tileScale goal) + + entryCost (TiledPosition (V2 r c)) = + do grid <- asks _grid + let (_, V2 maxR maxC) = bounds grid + let (tileR, gridR) = r `divMod` (maxR + 1) + let (tileC, gridC) = c `divMod` (maxC + 1) + let gridCost = grid ! (V2 gridR gridC) + let cost = (gridCost - 1 + tileR + tileC) `mod` 9 + 1 + return cost + +tileScale :: BasePosition -> BasePosition +tileScale (V2 r c) = V2 (ts r) (ts c) + where ts n = (n + 1) * 5 - 1 + +-- enTilePosition :: Position -> TiledPosition +-- enTilePosition (V2 a b) = V2 a b + +------------------------------ + +main :: IO () +main = + do text <- readFile "data/advent15.txt" + let cave = mkCave text + print $ part1 cave + print $ part2 cave + -- print $ part2 grid + +mkCave :: String -> Cave +mkCave text = Cave { _grid = grid, _goal = V2 r c } + where rows = lines text + r = length rows - 1 + c = (length $ head rows) - 1 + grid = listArray ((V2 0 0), (V2 r c)) $ map mkCell $ concat rows + mkCell e = digitToInt e + + +part1 :: Cave -> Int +-- part1 :: Maze -> Maybe (Agendum Portal) +part1 cave = maybe 0 _cost result + where result = runReader searchCave cave :: Maybe (Agendum Position) + +part2 :: Cave -> Int +-- part1 :: Maze -> Maybe (Agendum Portal) +part2 cave = maybe 0 _cost result + where result = runReader searchCave cave :: Maybe (Agendum TiledPosition) + +-- part2 :: Maze -> Int +-- -- part2 :: Maze -> Maybe (Agendum LevelledSearchState) +-- part2 maze = maybe 0 _cost result +-- where result = runReader searchMaze maze :: Maybe (Agendum LevelledSearchState) + + +searchCave :: SearchState s => CaveContext (Maybe (Agendum s)) +searchCave = + do agenda <- initAgenda + aStar agenda S.empty + +initAgenda :: SearchState s => CaveContext (Agenda s) +initAgenda = + do let ss = emptySearchState + c <- estimateCost ss + return $ P.singleton c Agendum { _current = ss, _trail = Q.empty, _cost = c} + + +aStar :: SearchState s => Agenda s -> ExploredStates s -> CaveContext (Maybe (Agendum s)) +aStar agenda closed + -- | trace ("Peeping " ++ (show $ fst $ P.findMin agenda) ++ ": " ++ (show reached) ++ " <- " ++ (show $ toList $ Q.take 1 $ _trail $ currentAgendum) ++ " :: " ++ (show newAgenda)) False = undefined + -- | trace ("Peeping " ++ (show $ _current $ snd $ P.findMin agenda) ) False = undefined + | P.null agenda = return Nothing + | otherwise = + do let (_, currentAgendum) = P.findMin agenda + let reached = currentAgendum ^. current + nexts <- candidates currentAgendum closed + let newAgenda = foldl' (\q a -> P.insert (_cost a) a q) (P.deleteMin agenda) nexts + reachedGoal <- isGoal reached + if reachedGoal + then return (Just currentAgendum) + else if reached `S.member` closed + then aStar (P.deleteMin agenda) closed + else aStar newAgenda (S.insert reached closed) + + +candidates :: SearchState s => Agendum s -> ExploredStates s -> CaveContext (Q.Seq (Agendum s)) +candidates agendum closed = + do let candidate = agendum ^. current + let previous = agendum ^. trail + -- let prevCost = agendum ^. cost + succs <- successors candidate + let nonloops = Q.filter (\s -> s `S.notMember` closed) succs + mapM (makeAgendum previous) nonloops + +makeAgendum :: SearchState s => (Q.Seq s) -> s -> CaveContext (Agendum s) +makeAgendum previous newPosition = + do predicted <- estimateCost newPosition + grid <- asks _grid + let newTrail = previous |> newPosition + let _ :< entered = newTrail + -- let incurred = foldr (+) 0 $ mapM entryCost entered + incurredQ <- mapM entryCost newTrail + let incurred = foldr (+) 0 incurredQ + return Agendum { _current = newPosition + , _trail = newTrail + , _cost = incurred + predicted + } diff --git a/data/advent14.txt b/data/advent14.txt new file mode 100644 index 0000000..7ce2054 --- /dev/null +++ b/data/advent14.txt @@ -0,0 +1,102 @@ +SCVHKHVSHPVCNBKBPVHV + +SB -> B +HH -> P +VF -> N +BS -> S +NC -> C +BF -> H +BN -> H +SP -> H +BK -> H +FF -> N +VN -> B +FN -> C +FS -> S +PP -> F +ON -> H +FV -> F +KO -> F +PK -> H +VB -> S +HS -> B +NV -> O +PN -> S +VH -> B +OS -> P +BP -> H +OV -> B +HK -> S +NN -> K +SV -> C +PB -> F +SK -> F +FB -> S +NB -> K +HF -> P +FK -> K +KV -> P +PV -> F +BC -> S +FO -> N +HC -> F +CP -> B +KK -> F +PC -> S +HN -> O +SH -> H +CK -> P +CO -> F +HP -> K +PS -> C +KP -> F +OF -> K +KS -> F +NO -> V +CB -> K +NF -> N +SF -> F +SC -> P +FC -> V +BV -> B +SS -> O +KC -> K +FH -> C +OP -> C +CF -> K +VO -> V +VK -> H +KH -> O +NP -> V +NH -> O +NS -> V +BH -> C +CH -> S +CC -> F +CS -> P +SN -> F +BO -> S +NK -> S +OO -> P +VV -> F +FP -> V +OK -> C +SO -> H +KN -> P +HO -> O +PO -> H +VS -> N +PF -> N +CV -> F +BB -> H +VC -> H +HV -> B +CN -> S +OH -> K +KF -> K +HB -> S +OC -> H +KB -> P +OB -> C +VP -> C +PH -> K \ No newline at end of file diff --git a/data/advent14a.txt b/data/advent14a.txt new file mode 100644 index 0000000..6c1c3a1 --- /dev/null +++ b/data/advent14a.txt @@ -0,0 +1,18 @@ +NNCB + +CH -> B +HH -> N +CB -> H +NH -> C +HB -> C +HC -> B +HN -> C +NN -> C +BH -> H +NC -> B +NB -> B +BN -> B +BB -> N +BC -> B +CC -> N +CN -> C \ No newline at end of file diff --git a/data/advent15.txt b/data/advent15.txt new file mode 100644 index 0000000..2fdd133 --- /dev/null +++ b/data/advent15.txt @@ -0,0 +1,100 @@ +7123177913871491389589264788547148381988811673752241637816163827448692499239515115894381588375396471 +9738878597866183278612514475755598861117949965829826949819696599841511616198177483157219211238226665 +2728314738118818417596585299898141515484167717378811771172771455459817575879182681543225671796579564 +3698237941798921857499612323641798179312519816114669628793538557419995793394792976116175183983211218 +8931299558895122919849817111991912299694619511272212888417418196496976619283339474157935296969177921 +4876399196561616888211818411392552865916811686918294139639998168582233818894993882378164973177419292 +1292826913925292993394627812472966298114458928424398988196171891981314199973375171711499591999295722 +2612819791685974812429441111697818261281422279834379563115293558312533728942295586148171358952659947 +6638822314594315236886818282759119972499915998333742951291758918511191291981139924297194471198819992 +3212921351399439782291441141194213794861268171719226573929478185198972881798292879922296597111267985 +9694955531925421216621667171387812673256762869119116982546712788121611188865459428311479913923252812 +8993899649958218893492947198596622311414594129991613199694121881963973616778199437361417251114898896 +2932137594986313811563891831516429822264187117794718732832322275923584989344938612756788851319215445 +9923942842169247311971329991517267154685897333913756132933889376946781927392178755261819729642288132 +9142173591893199149829423314381331583328694313941266171113924219211681916313986812131311533142191693 +5848192685188599944816146242793127138949121256118119414186816441591293151999119971396296221276131241 +3495527991317138191168853316591298662515462388318695459314259431427199827112814475291998894533661719 +6815167261798913879534189564249399392672145779914816489949341922439166128967131283857229364832939232 +9715263568753956232885237118388651333374435831664275153715817339997179993814287431396622272616271133 +1812949719568129216833815893498895318898151127318887918774267731151122617626267391916721894187735879 +6194936292994131619884424828772115321296933111248146743138951133525259921388132674296978191595215421 +8977231295463954488743917723843199269161928319992799113233196719627994185231913636481128347191888993 +7191387136716153811135921391495919122211583111131242512186177359857642411281598176173477158148461742 +8748994183994891161849125494181651122719172611112829351936539911981374881952184859949776981967135889 +4818995199799799317796797181385776752888232638392141897612916871898458673919399565456391616359619722 +2324149221529527952295121615332529396955513926313268682677391936267663467637119911666968839741927288 +9387191819291784198317392415819191724129835871495311699431299514299912942877459422153796598154195936 +3187152295157488239629224167299278792979374188163598271919325679669943944631641114319613632913941867 +4187553758199893917166292177621116363872642297713977519579918916911132498628192671316693138923217738 +7896983716218397299912126791897926852272193176651193815853749813676172192991933991241531915358592943 +2348247919145847514999915288812971366894736367322416127123839211819819893938238144595466824813581688 +6911579174885666196116496835334513924129158549472491355911727571419193999691849595418142654987162596 +8233311258291312123922594216362361184417111671134933993719988681111993994811784424145912713728546148 +1162139841389997711783335749151324349829189455223249558153435151167312198161429992286971283355217762 +9499631991542729216797153991489111797686945155575494822971821485199834897292889255296899325832659372 +9919722366494721121916812991347712311123354812314431341835584535911911183475929155451117133113518354 +3299321782846455776178299242914282826128713775681296642569791332836884518333197171822922357552638257 +4614911396711984669911199281145369229899421149212339819959928831788384791918432316191251591691214353 +4369289134597955589999495348592539727279475199412997118117152888153787932811981712348789921597223884 +1921278987992168289199159228511681682851987138959823165149863424871954671997219162181639788134671239 +8539367723644163113958998812319181651829319522919271727372655732991298341353642799614887987116119991 +9819237823912311318512271116896112568693473129616312762194271883382198451421259591659131149739567431 +3913629226255984248923677172369227529268378689129311591493392989499398541156998151934538421544988198 +9874118273932233256784989122831831438444699999969125597386734339278292411842292935966924611973117536 +3297942819139177814771683635499686478938123535294382195953689425918122743452127119188392213214162719 +6428369731511597131697241921814427613712519849617997822241919837334471918169985497447845215111571111 +4717882166389311599121985911815127671481262152181961791322981241713128381283932879815396748715326116 +9446657145378538332649933726924339585982712752416989637831889841999171924591539949915281695348616119 +1542914874298812536216998196883784913621263443517371816311128619246117922299562938819614239587919693 +1445469798118719191614518343323122521442292174917967445253456563977662989479257751894581593719739991 +7772142417741935423174485817123889139399291273428692734431984124117191994123498115727598161392677699 +6988945923714311219114921397868498885113257552168928846919896189191694261437512499791222278916169288 +7851211433643663591554743152113696322971779195631762592311915771859233266466849696548914971193499364 +4919396661388921921994122948951598619526848887659791912391223398827566916838432249598749774916496711 +1196599655895393416289389977637236641318279616416994991439226589111757355629849933169854118249997919 +5114211499998844843174919884423467219162277687929161558775139511929631962658267678221272328914953732 +8216171512426485781351969231952198433381329983288317413326512138574464114453937223541765367971856788 +2213177288792193388519618281868911182281428936911325912397967192287711833111797518143218673821192899 +2784153192416189911216612291791983219622166389621996117219781639919612667199999129821528411964639199 +4187898219537683365988849129793392557283572786889441274612197286178112735995692535456157587812218711 +3289961986387137451576181267292891928699191488241997579896141161217814198431161774438724446513817347 +1579149591461935819116247565121622891413133538179461264778198149199793117163932219237419521332475723 +8511871311713679914269882644473751984369996191729198493285714245762879942883717594273668937984612859 +1299519281323389918993242297332143893749252414799491177636152119414457637112995194255822953441323767 +5956297531138129799432717521922827212567131222732852611291511239992997934392819583522981699162914417 +9941713968132521114282728119911171371767252117572477196141318371891319144171114944838884899991129662 +3289334178322912999218672177961313951181389283788115263914991671385991338168197891735411426621896437 +3517399198911891116419161659893219997361251111462415147245636698911119144122948941611999537914127921 +7391621997684963324417791261394821117179111599877845791691691999758491717192891377392662426922381649 +9539641387391158465314288999171521516996119112739729425799782424458612492799866313395268329813142998 +7159761151187488213272297981256985319892792222143284319128613282931987743335641992228248391313519531 +3138612956672911883119197936151783665186495653914713496188952389722272421535138125838382521963591562 +2722391699271222281179116691629372616974311231381924211686611666919731221727399213415714891415614991 +7198919263899918891485598237399963318129522299496599371183799311118199698219813639932192422592379521 +7368622164517278632222981928929692926994317935549341915121242459537164841789531795135523197651979291 +1926148892518314965269213317792781877993491381788416765975716755185279549699712281281784581861751169 +9249985391769615964945784311129911697198267954993689957729719133276621353583195921579141925315925166 +6822113216689392191133553173276588849489996679488414961829594191993816192923712718939527186629116941 +5929189959684777622871367188254399766777395794834448572421243984636768429891326273999953635499781823 +3968641911437319438596991911526912992916952278875428199179942114261598893262717938299221167273799979 +3581738249268299998729188711271131183463978189544984397511934495858934421812219983183226727177137114 +1631458422911129912835999399394913599312249165919497857822112997138599391899427114543933588882749375 +7751959887233838373994262343677972499854568863234916814662714417494468417237214895924711139913939931 +4591349111791721157991319331898365223999499119349939111219419624872719169431985811875181468395293861 +9792291732129325192193663689331995249571212989662591947284119882841111636726819362215311819211795897 +1488399771452298411953629967461723138977649994883655382185266168282297595892929374412297962677511168 +7924861111421119789911192623416874981293118241238722492254626547593951768791776297212239248219618114 +8735129436119198495916414425995513415961489114319948429491748935119857139517121738987938966891125783 +9669648319182921264115692232751318121116373481894266491823915963139471491859149397216775362939414969 +9956144986618983299822988922918999922211819753624127131799113139524343936443128596821789648269963896 +7991139371219143999647978711473188557939866849119391117191869921928812871649882975753469934691399149 +5512138553215161592622431858481393373361674599955358483792512195323411931199662281891856487591112893 +9417295659949511519279658459111995961867134373999356883483499622281215996711111747445985881745648997 +5869918917951981844765591591191412765331147258751421475964719757299891817418117775918693188123993417 +1624257425257726748957618898694796968997367176999981891437592613316142593927894818699625341211118521 +2691266599149129279888396797262149311989598668888453732682612511116669997393343711966114278812466911 +3871919914394816781582584188751221559169429281577559622382565992458117893269798921374515671374711269 +2937696914977492589611351118178169911891394771517293921914627713178322419232244298725129511451733882 +8914885347357182842138897239419948884639745551712216898133998524382831475347911516291799198921935134 +5527717416681927222852118761365169418317189819727214551585891949313611155917969911112533919284572421 \ No newline at end of file diff --git a/data/advent15a.txt b/data/advent15a.txt new file mode 100644 index 0000000..7d9d562 --- /dev/null +++ b/data/advent15a.txt @@ -0,0 +1,10 @@ +1163751742 +1381373672 +2136511328 +3694931569 +7463417111 +1319128137 +1359912421 +3125421639 +1293138521 +2311944581 \ No newline at end of file diff --git a/problems/day14.html b/problems/day14.html new file mode 100644 index 0000000..a3e0d04 --- /dev/null +++ b/problems/day14.html @@ -0,0 +1,165 @@ + + + + +Day 14 - Advent of Code 2021 + + + + + + + +

Advent of Code

Neil Smith (AoC++) 30*

          2021

+ + + +
+ +

--- Day 14: Extended Polymerization ---

The incredible pressures at this depth are starting to put a strain on your submarine. The submarine has polymerization equipment that would produce suitable materials to reinforce the submarine, and the nearby volcanically-active caves should even have the necessary input elements in sufficient quantities.

+

The submarine manual contains instructions for finding the optimal polymer formula; specifically, it offers a polymer template and a list of pair insertion rules (your puzzle input). You just need to work out what polymer would result after repeating the pair insertion process a few times.

+

For example:

+
NNCB
+
+CH -> B
+HH -> N
+CB -> H
+NH -> C
+HB -> C
+HC -> B
+HN -> C
+NN -> C
+BH -> H
+NC -> B
+NB -> B
+BN -> B
+BB -> N
+BC -> B
+CC -> N
+CN -> C
+
+

The first line is the polymer template - this is the starting point of the process.

+

The following section defines the pair insertion rules. A rule like AB -> C means that when elements A and B are immediately adjacent, element C should be inserted between them. These insertions all happen simultaneously.

+

So, starting with the polymer template NNCB, the first step simultaneously considers all three pairs:

+
    +
  • The first pair (NN) matches the rule NN -> C, so element C is inserted between the first N and the second N.
  • +
  • The second pair (NC) matches the rule NC -> B, so element B is inserted between the N and the C.
  • +
  • The third pair (CB) matches the rule CB -> H, so element H is inserted between the C and the B.
  • +
+

Note that these pairs overlap: the second element of one pair is the first element of the next pair. Also, because all pairs are considered simultaneously, inserted elements are not considered to be part of a pair until the next step.

+

After the first step of this process, the polymer becomes NCNBCHB.

+

Here are the results of a few steps using the above rules:

+
Template:     NNCB
+After step 1: NCNBCHB
+After step 2: NBCCNBBBCBHCB
+After step 3: NBBBCNCCNBBNBNBBCHBHHBCHB
+After step 4: NBBNBNBBCCNBCNCCNBBNBBNBBBNBBNBBCBHCBHHNHCBBCBHCB
+
+

This polymer grows quickly. After step 5, it has length 97; After step 10, it has length 3073. After step 10, B occurs 1749 times, C occurs 298 times, H occurs 161 times, and N occurs 865 times; taking the quantity of the most common element (B, 1749) and subtracting the quantity of the least common element (H, 161) produces 1749 - 161 = 1588.

+

Apply 10 steps of pair insertion to the polymer template and find the most and least common elements in the result. What do you get if you take the quantity of the most common element and subtract the quantity of the least common element?

+
+

Your puzzle answer was 2712.

--- Part Two ---

The resulting polymer isn't nearly strong enough to reinforce the submarine. You'll need to run more steps of the pair insertion process; a total of 40 steps should do it.

+

In the above example, the most common element is B (occurring 2192039569602 times) and the least common element is H (occurring 3849876073 times); subtracting these produces 2188189693529.

+

Apply 40 steps of pair insertion to the polymer template and find the most and least common elements in the result. What do you get if you take the quantity of the most common element and subtract the quantity of the least common element?

+
+

Your puzzle answer was 8336623059567.

Both parts of this puzzle are complete! They provide two gold stars: **

+

At this point, you should return to your Advent calendar and try another puzzle.

+

If you still want to see it, you can get your puzzle input.

+

You can also this puzzle.

+
+ + + + + + \ No newline at end of file diff --git a/problems/day15.html b/problems/day15.html new file mode 100644 index 0000000..b61e18f --- /dev/null +++ b/problems/day15.html @@ -0,0 +1,264 @@ + + + + +Day 15 - Advent of Code 2021 + + + + + + + +

Advent of Code

Neil Smith (AoC++) 30*

   sub y{2021}

+ + + +
+ +

--- Day 15: Chiton ---

You've almost reached the exit of the cave, but the walls are getting closer together. Your submarine can barely still fit, though; the main problem is that the walls of the cave are covered in chitons, and it would be best not to bump any of them.

+

The cavern is large, but has a very low ceiling, restricting your motion to two dimensions. The shape of the cavern resembles a square; a quick scan of chiton density produces a map of risk level throughout the cave (your puzzle input). For example:

+
1163751742
+1381373672
+2136511328
+3694931569
+7463417111
+1319128137
+1359912421
+3125421639
+1293138521
+2311944581
+
+

You start in the top left position, your destination is the bottom right position, and you cannot move diagonally. The number at each position is its risk level; to determine the total risk of an entire path, add up the risk levels of each position you enter (that is, don't count the risk level of your starting position unless you enter it; leaving it adds no risk to your total).

+

Your goal is to find a path with the lowest total risk. In this example, a path with the lowest total risk is highlighted here:

+
1163751742
+1381373672
+2136511328
+3694931569
+7463417111
+1319128137
+1359912421
+3125421639
+1293138521
+2311944581
+
+

The total risk of this path is 40 (the starting position is never entered, so its risk is not counted).

+

What is the lowest total risk of any path from the top left to the bottom right?

+
+

Your puzzle answer was 503.

--- Part Two ---

Now that you know how to find low-risk paths in the cave, you can try to find your way out.

+

The entire cave is actually five times larger in both dimensions than you thought; the area you originally scanned is just one tile in a 5x5 tile area that forms the full map. Your original map tile repeats to the right and downward; each time the tile repeats to the right or downward, all of its risk levels are 1 higher than the tile immediately up or left of it. However, risk levels above 9 wrap back around to 1. So, if your original map had some position with a risk level of 8, then that same position on each of the 25 total tiles would be as follows:

+
8 9 1 2 3
+9 1 2 3 4
+1 2 3 4 5
+2 3 4 5 6
+3 4 5 6 7
+
+

Each single digit above corresponds to the example position with a value of 8 on the top-left tile. Because the full map is actually five times larger in both dimensions, that position appears a total of 25 times, once in each duplicated tile, with the values shown above.

+

Here is the full five-times-as-large version of the first example above, with the original map in the top left corner highlighted:

+
11637517422274862853338597396444961841755517295286
+13813736722492484783351359589446246169155735727126
+21365113283247622439435873354154698446526571955763
+36949315694715142671582625378269373648937148475914
+74634171118574528222968563933317967414442817852555
+13191281372421239248353234135946434524615754563572
+13599124212461123532357223464346833457545794456865
+31254216394236532741534764385264587549637569865174
+12931385212314249632342535174345364628545647573965
+23119445813422155692453326671356443778246755488935
+22748628533385973964449618417555172952866628316397
+24924847833513595894462461691557357271266846838237
+32476224394358733541546984465265719557637682166874
+47151426715826253782693736489371484759148259586125
+85745282229685639333179674144428178525553928963666
+24212392483532341359464345246157545635726865674683
+24611235323572234643468334575457944568656815567976
+42365327415347643852645875496375698651748671976285
+23142496323425351743453646285456475739656758684176
+34221556924533266713564437782467554889357866599146
+33859739644496184175551729528666283163977739427418
+35135958944624616915573572712668468382377957949348
+43587335415469844652657195576376821668748793277985
+58262537826937364893714847591482595861259361697236
+96856393331796741444281785255539289636664139174777
+35323413594643452461575456357268656746837976785794
+35722346434683345754579445686568155679767926678187
+53476438526458754963756986517486719762859782187396
+34253517434536462854564757396567586841767869795287
+45332667135644377824675548893578665991468977611257
+44961841755517295286662831639777394274188841538529
+46246169155735727126684683823779579493488168151459
+54698446526571955763768216687487932779859814388196
+69373648937148475914825958612593616972361472718347
+17967414442817852555392896366641391747775241285888
+46434524615754563572686567468379767857948187896815
+46833457545794456865681556797679266781878137789298
+64587549637569865174867197628597821873961893298417
+45364628545647573965675868417678697952878971816398
+56443778246755488935786659914689776112579188722368
+55172952866628316397773942741888415385299952649631
+57357271266846838237795794934881681514599279262561
+65719557637682166874879327798598143881961925499217
+71484759148259586125936169723614727183472583829458
+28178525553928963666413917477752412858886352396999
+57545635726865674683797678579481878968159298917926
+57944568656815567976792667818781377892989248891319
+75698651748671976285978218739618932984172914319528
+56475739656758684176786979528789718163989182927419
+67554889357866599146897761125791887223681299833479
+
+

Equipped with the full map, you can now find a path from the top left corner to the bottom right corner with the lowest total risk:

+
11637517422274862853338597396444961841755517295286
+13813736722492484783351359589446246169155735727126
+21365113283247622439435873354154698446526571955763
+36949315694715142671582625378269373648937148475914
+74634171118574528222968563933317967414442817852555
+13191281372421239248353234135946434524615754563572
+13599124212461123532357223464346833457545794456865
+31254216394236532741534764385264587549637569865174
+12931385212314249632342535174345364628545647573965
+23119445813422155692453326671356443778246755488935
+22748628533385973964449618417555172952866628316397
+24924847833513595894462461691557357271266846838237
+32476224394358733541546984465265719557637682166874
+47151426715826253782693736489371484759148259586125
+85745282229685639333179674144428178525553928963666
+24212392483532341359464345246157545635726865674683
+24611235323572234643468334575457944568656815567976
+42365327415347643852645875496375698651748671976285
+23142496323425351743453646285456475739656758684176
+34221556924533266713564437782467554889357866599146
+33859739644496184175551729528666283163977739427418
+35135958944624616915573572712668468382377957949348
+43587335415469844652657195576376821668748793277985
+58262537826937364893714847591482595861259361697236
+96856393331796741444281785255539289636664139174777
+35323413594643452461575456357268656746837976785794
+35722346434683345754579445686568155679767926678187
+53476438526458754963756986517486719762859782187396
+34253517434536462854564757396567586841767869795287
+45332667135644377824675548893578665991468977611257
+44961841755517295286662831639777394274188841538529
+46246169155735727126684683823779579493488168151459
+54698446526571955763768216687487932779859814388196
+69373648937148475914825958612593616972361472718347
+17967414442817852555392896366641391747775241285888
+46434524615754563572686567468379767857948187896815
+46833457545794456865681556797679266781878137789298
+64587549637569865174867197628597821873961893298417
+45364628545647573965675868417678697952878971816398
+56443778246755488935786659914689776112579188722368
+55172952866628316397773942741888415385299952649631
+57357271266846838237795794934881681514599279262561
+65719557637682166874879327798598143881961925499217
+71484759148259586125936169723614727183472583829458
+28178525553928963666413917477752412858886352396999
+57545635726865674683797678579481878968159298917926
+57944568656815567976792667818781377892989248891319
+75698651748671976285978218739618932984172914319528
+56475739656758684176786979528789718163989182927419
+67554889357866599146897761125791887223681299833479
+
+

The total risk of this path is 315 (the starting position is still never entered, so its risk is not counted).

+

Using the full map, what is the lowest total risk of any path from the top left to the bottom right?

+
+

Your puzzle answer was 2853.

Both parts of this puzzle are complete! They provide two gold stars: **

+

At this point, you should return to your Advent calendar and try another puzzle.

+

If you still want to see it, you can get your puzzle input.

+

You can also this puzzle.

+
+ + + + + + \ No newline at end of file