From: Neil Smith <neil.git@njae.me.uk> 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 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> +<meta charset="utf-8"/> +<title>Day 14 - Advent of Code 2021</title> +<!--[if lt IE 9]><script src="/static/html5.js"></script><![endif]--> +<link href='//fonts.googleapis.com/css?family=Source+Code+Pro:300&subset=latin,latin-ext' rel='stylesheet' type='text/css'/> +<link rel="stylesheet" type="text/css" href="/static/style.css?26"/> +<link rel="stylesheet alternate" type="text/css" href="/static/highcontrast.css?0" title="High Contrast"/> +<link rel="shortcut icon" href="/favicon.png"/> +</head><!-- + + + + +Oh, hello! Funny seeing you here. + +I appreciate your enthusiasm, but you aren't going to find much down here. +There certainly aren't clues to any of the puzzles. The best surprises don't +even appear in the source until you unlock them for real. + +Please be careful with automated requests; I'm not a massive company, and I can +only take so much traffic. Please be considerate so that everyone gets to play. + +If you're curious about how Advent of Code works, it's running on some custom +Perl code. Other than a few integrations (auth, analytics, social media), I +built the whole thing myself, including the design, animations, prose, and all +of the puzzles. + +The puzzles are most of the work; preparing a new calendar and a new set of +puzzles each year takes all of my free time for 4-5 months. A lot of effort +went into building this thing - I hope you're enjoying playing it as much as I +enjoyed making it for you! + +If you'd like to hang out, I'm @ericwastl on Twitter. + +- Eric Wastl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--> +<body> +<header><div><h1 class="title-global"><a href="/">Advent of Code</a></h1><nav><ul><li><a href="/2021/about">[About]</a></li><li><a href="/2021/events">[Events]</a></li><li><a href="https://teespring.com/stores/advent-of-code" target="_blank">[Shop]</a></li><li><a href="/2021/settings">[Settings]</a></li><li><a href="/2021/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <a href="/2021/support" class="supporter-badge" title="Advent of Code Supporter">(AoC++)</a> <span class="star-count">30*</span></div></div><div><h1 class="title-event"> <span class="title-event-wrap"></span><a href="/2021">2021</a><span class="title-event-wrap"></span></h1><nav><ul><li><a href="/2021">[Calendar]</a></li><li><a href="/2021/support">[AoC++]</a></li><li><a href="/2021/sponsors">[Sponsors]</a></li><li><a href="/2021/leaderboard">[Leaderboard]</a></li><li><a href="/2021/stats">[Stats]</a></li></ul></nav></div></header> + +<div id="sidebar"> +<div id="sponsor"><div class="quiet">Our <a href="/2021/sponsors">sponsors</a> help make Advent of Code possible:</div><div class="sponsor"><a href="https://www.tcgplayer.com/adventofcode/?utm_campaign=aoc&utm_source=adventOfCode&utm_medium=aocPromo" target="_blank" onclick="if(ga)ga('send','event','sponsor','sidebar',this.href);" rel="noopener">TCGplayer.com</a> - - . Hiring .NET & . . JS engineers. . . Help us serve . . our community . . of game stores. . & hobbyists!! . ---- JOIN US ----</div></div> +</div><!--/sidebar--> + +<main> +<script>window.addEventListener('click', function(e,s,r){if(e.target.nodeName==='CODE'&&e.detail===3){s=window.getSelection();s.removeAllRanges();r=document.createRange();r.selectNodeContents(e.target);s.addRange(r);}});</script> +<article class="day-desc"><h2>--- Day 14: Extended Polymerization ---</h2><p>The incredible pressures at this depth are starting to put a strain on your submarine. The submarine has <a href="https://en.wikipedia.org/wiki/Polymerization" target="_blank">polymerization</a> 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.</p> +<p>The submarine manual contains <span title="HO

HO -> OH">instructions</span> for finding the optimal polymer formula; specifically, it offers a <em>polymer template</em> and a list of <em>pair insertion</em> rules (your puzzle input). You just need to work out what polymer would result after repeating the pair insertion process a few times.</p> +<p>For example:</p> +<pre><code>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 +</code></pre> +<p>The first line is the <em>polymer template</em> - this is the starting point of the process.</p> +<p>The following section defines the <em>pair insertion</em> rules. A rule like <code>AB -> C</code> means that when elements <code>A</code> and <code>B</code> are immediately adjacent, element <code>C</code> should be inserted between them. These insertions all happen simultaneously.</p> +<p>So, starting with the polymer template <code>NNCB</code>, the first step simultaneously considers all three pairs:</p> +<ul> +<li>The first pair (<code>NN</code>) matches the rule <code>NN -> C</code>, so element <code><em>C</em></code> is inserted between the first <code>N</code> and the second <code>N</code>.</li> +<li>The second pair (<code>NC</code>) matches the rule <code>NC -> B</code>, so element <code><em>B</em></code> is inserted between the <code>N</code> and the <code>C</code>.</li> +<li>The third pair (<code>CB</code>) matches the rule <code>CB -> H</code>, so element <code><em>H</em></code> is inserted between the <code>C</code> and the <code>B</code>.</li> +</ul> +<p>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.</p> +<p>After the first step of this process, the polymer becomes <code>N<em>C</em>N<em>B</em>C<em>H</em>B</code>.</p> +<p>Here are the results of a few steps using the above rules:</p> +<pre><code>Template: NNCB +After step 1: NCNBCHB +After step 2: NBCCNBBBCBHCB +After step 3: NBBBCNCCNBBNBNBBCHBHHBCHB +After step 4: NBBNBNBBCCNBCNCCNBBNBBNBBBNBBNBBCBHCBHHNHCBBCBHCB +</code></pre> +<p>This polymer grows quickly. After step 5, it has length 97; After step 10, it has length 3073. After step 10, <code>B</code> occurs 1749 times, <code>C</code> occurs 298 times, <code>H</code> occurs 161 times, and <code>N</code> occurs 865 times; taking the quantity of the most common element (<code>B</code>, 1749) and subtracting the quantity of the least common element (<code>H</code>, 161) produces <code>1749 - 161 = <em>1588</em></code>.</p> +<p>Apply 10 steps of pair insertion to the polymer template and find the most and least common elements in the result. <em>What do you get if you take the quantity of the most common element and subtract the quantity of the least common element?</em></p> +</article> +<p>Your puzzle answer was <code>2712</code>.</p><article class="day-desc"><h2 id="part2">--- Part Two ---</h2><p>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 <em>40 steps</em> should do it.</p> +<p>In the above example, the most common element is <code>B</code> (occurring <code>2192039569602</code> times) and the least common element is <code>H</code> (occurring <code>3849876073</code> times); subtracting these produces <code><em>2188189693529</em></code>.</p> +<p>Apply <em>40</em> steps of pair insertion to the polymer template and find the most and least common elements in the result. <em>What do you get if you take the quantity of the most common element and subtract the quantity of the least common element?</em></p> +</article> +<p>Your puzzle answer was <code>8336623059567</code>.</p><p class="day-success">Both parts of this puzzle are complete! They provide two gold stars: **</p> +<p>At this point, you should <a href="/2021">return to your Advent calendar</a> and try another puzzle.</p> +<p>If you still want to see it, you can <a href="14/input" target="_blank">get your puzzle input</a>.</p> +<p>You can also <span class="share">[Share<span class="share-content">on + <a href="https://twitter.com/intent/tweet?text=I%27ve+completed+%22Extended+Polymerization%22+%2D+Day+14+%2D+Advent+of+Code+2021&url=https%3A%2F%2Fadventofcode%2Ecom%2F2021%2Fday%2F14&related=ericwastl&hashtags=AdventOfCode" target="_blank">Twitter</a> + <a href="javascript:void(0);" onclick="var mastodon_instance=prompt('Mastodon Instance / Server Name?'); if(typeof mastodon_instance==='string' && mastodon_instance.length){this.href='https://'+mastodon_instance+'/share?text=I%27ve+completed+%22Extended+Polymerization%22+%2D+Day+14+%2D+Advent+of+Code+2021+%23AdventOfCode+https%3A%2F%2Fadventofcode%2Ecom%2F2021%2Fday%2F14'}else{return false;}" target="_blank">Mastodon</a +></span>]</span> this puzzle.</p> +</main> + +<!-- ga --> +<script> +(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ +(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), +m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) +})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); +ga('create', 'UA-69522494-1', 'auto'); +ga('set', 'anonymizeIp', true); +ga('send', 'pageview'); +</script> +<!-- /ga --> +</body> +</html> \ 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 @@ +<!DOCTYPE html> +<html lang="en-us"> +<head> +<meta charset="utf-8"/> +<title>Day 15 - Advent of Code 2021</title> +<!--[if lt IE 9]><script src="/static/html5.js"></script><![endif]--> +<link href='//fonts.googleapis.com/css?family=Source+Code+Pro:300&subset=latin,latin-ext' rel='stylesheet' type='text/css'/> +<link rel="stylesheet" type="text/css" href="/static/style.css?26"/> +<link rel="stylesheet alternate" type="text/css" href="/static/highcontrast.css?0" title="High Contrast"/> +<link rel="shortcut icon" href="/favicon.png"/> +</head><!-- + + + + +Oh, hello! Funny seeing you here. + +I appreciate your enthusiasm, but you aren't going to find much down here. +There certainly aren't clues to any of the puzzles. The best surprises don't +even appear in the source until you unlock them for real. + +Please be careful with automated requests; I'm not a massive company, and I can +only take so much traffic. Please be considerate so that everyone gets to play. + +If you're curious about how Advent of Code works, it's running on some custom +Perl code. Other than a few integrations (auth, analytics, social media), I +built the whole thing myself, including the design, animations, prose, and all +of the puzzles. + +The puzzles are most of the work; preparing a new calendar and a new set of +puzzles each year takes all of my free time for 4-5 months. A lot of effort +went into building this thing - I hope you're enjoying playing it as much as I +enjoyed making it for you! + +If you'd like to hang out, I'm @ericwastl on Twitter. + +- Eric Wastl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +--> +<body> +<header><div><h1 class="title-global"><a href="/">Advent of Code</a></h1><nav><ul><li><a href="/2021/about">[About]</a></li><li><a href="/2021/events">[Events]</a></li><li><a href="https://teespring.com/stores/advent-of-code" target="_blank">[Shop]</a></li><li><a href="/2021/settings">[Settings]</a></li><li><a href="/2021/auth/logout">[Log Out]</a></li></ul></nav><div class="user">Neil Smith <a href="/2021/support" class="supporter-badge" title="Advent of Code Supporter">(AoC++)</a> <span class="star-count">30*</span></div></div><div><h1 class="title-event"> <span class="title-event-wrap">sub y{</span><a href="/2021">2021</a><span class="title-event-wrap">}</span></h1><nav><ul><li><a href="/2021">[Calendar]</a></li><li><a href="/2021/support">[AoC++]</a></li><li><a href="/2021/sponsors">[Sponsors]</a></li><li><a href="/2021/leaderboard">[Leaderboard]</a></li><li><a href="/2021/stats">[Stats]</a></li></ul></nav></div></header> + +<div id="sidebar"> +<div id="sponsor"><div class="quiet">Our <a href="/2021/sponsors">sponsors</a> help make Advent of Code possible:</div><div class="sponsor"><a href="https://rick379856.typeform.com/to/oQ0e2jpi?utm_source=event&utm_medium=ad&utm_campaign=adventofcode2021" target="_blank" onclick="if(ga)ga('send','event','sponsor','sidebar',this.href);" rel="noopener">Honeycomb</a> - You like performant, correct code. So do we. Distributed systems should be easy to understand. Use Honeycomb for free to debug your distributed systems and get a free shirt. Download our white papers and watch our demo.</div></div> +</div><!--/sidebar--> + +<main> +<script>window.addEventListener('click', function(e,s,r){if(e.target.nodeName==='CODE'&&e.detail===3){s=window.getSelection();s.removeAllRanges();r=document.createRange();r.selectNodeContents(e.target);s.addRange(r);}});</script> +<article class="day-desc"><h2>--- Day 15: Chiton ---</h2><p>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 <a href="https://en.wikipedia.org/wiki/Chiton" target="_blank">chitons</a>, and it would be best not to bump any of them.</p> +<p>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 <em>risk level</em> throughout the cave (your puzzle input). For example:</p> +<pre><code>1163751742 +1381373672 +2136511328 +3694931569 +7463417111 +1319128137 +1359912421 +3125421639 +1293138521 +2311944581 +</code></pre> +<p>You start in the top left position, your destination is the bottom right position, and you <span title="Can't go diagonal until we can repair the caterpillar unit. Could be the liquid helium or the superconductors.">cannot move diagonally</span>. The number at each position is its <em>risk level</em>; to determine the total risk of an entire path, add up the risk levels of each position you <em>enter</em> (that is, don't count the risk level of your starting position unless you enter it; leaving it adds no risk to your total).</p> +<p>Your goal is to find a path with the <em>lowest total risk</em>. In this example, a path with the lowest total risk is highlighted here:</p> +<pre><code><em>1</em>163751742 +<em>1</em>381373672 +<em>2136511</em>328 +369493<em>15</em>69 +7463417<em>1</em>11 +1319128<em>13</em>7 +13599124<em>2</em>1 +31254216<em>3</em>9 +12931385<em>21</em> +231194458<em>1</em> +</code></pre> +<p>The total risk of this path is <code><em>40</em></code> (the starting position is never entered, so its risk is not counted).</p> +<p><em>What is the lowest total risk of any path from the top left to the bottom right?</em></p> +</article> +<p>Your puzzle answer was <code>503</code>.</p><article class="day-desc"><h2 id="part2">--- Part Two ---</h2><p>Now that you know how to find low-risk paths in the cave, you can try to find your way out.</p> +<p>The entire cave is actually <em>five times larger in both dimensions</em> 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 <em>are 1 higher</em> than the tile immediately up or left of it. However, risk levels above <code>9</code> wrap back around to <code>1</code>. So, if your original map had some position with a risk level of <code>8</code>, then that same position on each of the 25 total tiles would be as follows:</p> +<pre><code>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 +</code></pre> +<p>Each single digit above corresponds to the example position with a value of <code>8</code> 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.</p> +<p>Here is the full five-times-as-large version of the first example above, with the original map in the top left corner highlighted:</p> +<pre><code><em>1163751742</em>2274862853338597396444961841755517295286 +<em>1381373672</em>2492484783351359589446246169155735727126 +<em>2136511328</em>3247622439435873354154698446526571955763 +<em>3694931569</em>4715142671582625378269373648937148475914 +<em>7463417111</em>8574528222968563933317967414442817852555 +<em>1319128137</em>2421239248353234135946434524615754563572 +<em>1359912421</em>2461123532357223464346833457545794456865 +<em>3125421639</em>4236532741534764385264587549637569865174 +<em>1293138521</em>2314249632342535174345364628545647573965 +<em>2311944581</em>3422155692453326671356443778246755488935 +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 +</code></pre> +<p>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:</p> +<pre><code><em>1</em>1637517422274862853338597396444961841755517295286 +<em>1</em>3813736722492484783351359589446246169155735727126 +<em>2</em>1365113283247622439435873354154698446526571955763 +<em>3</em>6949315694715142671582625378269373648937148475914 +<em>7</em>4634171118574528222968563933317967414442817852555 +<em>1</em>3191281372421239248353234135946434524615754563572 +<em>1</em>3599124212461123532357223464346833457545794456865 +<em>3</em>1254216394236532741534764385264587549637569865174 +<em>1</em>2931385212314249632342535174345364628545647573965 +<em>2</em>3119445813422155692453326671356443778246755488935 +<em>2</em>2748628533385973964449618417555172952866628316397 +<em>2</em>4924847833513595894462461691557357271266846838237 +<em>324</em>76224394358733541546984465265719557637682166874 +47<em>15</em>1426715826253782693736489371484759148259586125 +857<em>4</em>5282229685639333179674144428178525553928963666 +242<em>1</em>2392483532341359464345246157545635726865674683 +246<em>1123532</em>3572234643468334575457944568656815567976 +423653274<em>1</em>5347643852645875496375698651748671976285 +231424963<em>2342</em>5351743453646285456475739656758684176 +342215569245<em>332</em>66713564437782467554889357866599146 +33859739644496<em>1</em>84175551729528666283163977739427418 +35135958944624<em>61</em>6915573572712668468382377957949348 +435873354154698<em>44</em>652657195576376821668748793277985 +5826253782693736<em>4</em>893714847591482595861259361697236 +9685639333179674<em>1</em>444281785255539289636664139174777 +3532341359464345<em>2461</em>575456357268656746837976785794 +3572234643468334575<em>4</em>579445686568155679767926678187 +5347643852645875496<em>3</em>756986517486719762859782187396 +3425351743453646285<em>4564</em>757396567586841767869795287 +4533266713564437782467<em>554</em>8893578665991468977611257 +449618417555172952866628<em>3163</em>9777394274188841538529 +462461691557357271266846838<em>2</em>3779579493488168151459 +546984465265719557637682166<em>8</em>7487932779859814388196 +693736489371484759148259586<em>125</em>93616972361472718347 +17967414442817852555392896366<em>6413</em>91747775241285888 +46434524615754563572686567468379<em>7</em>67857948187896815 +46833457545794456865681556797679<em>26</em>6781878137789298 +645875496375698651748671976285978<em>21</em>873961893298417 +4536462854564757396567586841767869<em>7</em>952878971816398 +5644377824675548893578665991468977<em>6112</em>579188722368 +5517295286662831639777394274188841538<em>5</em>299952649631 +5735727126684683823779579493488168151<em>4</em>599279262561 +6571955763768216687487932779859814388<em>1</em>961925499217 +7148475914825958612593616972361472718<em>34725</em>83829458 +28178525553928963666413917477752412858886<em>3</em>52396999 +57545635726865674683797678579481878968159<em>2</em>98917926 +57944568656815567976792667818781377892989<em>24</em>8891319 +756986517486719762859782187396189329841729<em>1431</em>9528 +564757396567586841767869795287897181639891829<em>2</em>7419 +675548893578665991468977611257918872236812998<em>33479</em> +</code></pre> +<p>The total risk of this path is <code><em>315</em></code> (the starting position is still never entered, so its risk is not counted).</p> +<p>Using the full map, <em>what is the lowest total risk of any path from the top left to the bottom right?</em></p> +</article> +<p>Your puzzle answer was <code>2853</code>.</p><p class="day-success">Both parts of this puzzle are complete! They provide two gold stars: **</p> +<p>At this point, you should <a href="/2021">return to your Advent calendar</a> and try another puzzle.</p> +<p>If you still want to see it, you can <a href="15/input" target="_blank">get your puzzle input</a>.</p> +<p>You can also <span class="share">[Share<span class="share-content">on + <a href="https://twitter.com/intent/tweet?text=I%27ve+completed+%22Chiton%22+%2D+Day+15+%2D+Advent+of+Code+2021&url=https%3A%2F%2Fadventofcode%2Ecom%2F2021%2Fday%2F15&related=ericwastl&hashtags=AdventOfCode" target="_blank">Twitter</a> + <a href="javascript:void(0);" onclick="var mastodon_instance=prompt('Mastodon Instance / Server Name?'); if(typeof mastodon_instance==='string' && mastodon_instance.length){this.href='https://'+mastodon_instance+'/share?text=I%27ve+completed+%22Chiton%22+%2D+Day+15+%2D+Advent+of+Code+2021+%23AdventOfCode+https%3A%2F%2Fadventofcode%2Ecom%2F2021%2Fday%2F15'}else{return false;}" target="_blank">Mastodon</a +></span>]</span> this puzzle.</p> +</main> + +<!-- ga --> +<script> +(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ +(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), +m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) +})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); +ga('create', 'UA-69522494-1', 'auto'); +ga('set', 'anonymizeIp', true); +ga('send', 'pageview'); +</script> +<!-- /ga --> +</body> +</html> \ No newline at end of file