diff --git a/2021/15/README.md b/2021/15/README.md new file mode 100644 index 0000000..d57bc76 --- /dev/null +++ b/2021/15/README.md @@ -0,0 +1,173 @@ +# 2021 Day 15: Chiton +Copyright (c) Eric Wastl +#### [Direct Link](https://adventofcode.com/2021/day/15) + +## Part 1 + +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](https://en.wikipedia.org/wiki/Chiton), 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?** + +## Part 2 + +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?** diff --git a/2021/15/code.py b/2021/15/code.py new file mode 100644 index 0000000..26d0c18 --- /dev/null +++ b/2021/15/code.py @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: MIT +# Copyright (c) 2021 Akumatic +# +# https://adventofcode.com/2021/day/15 + +from queue import PriorityQueue + +def read_file(filename: str = "input.txt") -> tuple: + with open(f"{__file__.rstrip('code.py')}{filename}", "r") as f: + lines = [line for line in f.read().strip().split("\n")] + data = list() + for line in lines: + data += [int(x) for x in line] + return len(lines[0]), data + +def get_neighbor_idx(idx: int, dim: int) -> list: + y = idx // dim + x = idx - y * dim + neighbors = [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)] + return [n[0] + n[1]*dim for n in neighbors if 0 <= n[0] < dim and 0 <= n[1] < dim] + +def dijkstra(cavern: tuple) -> dict: + dimension, graph = cavern[0], cavern[1] + graph_size = len(graph) + queue = PriorityQueue() + queue.put((0, 0)) + dist = {0: 0} + + while not queue.empty(): + distance, idx = queue.get() + + for neighbor in get_neighbor_idx(idx, dimension): + d = distance + graph[neighbor] + if neighbor not in dist or dist[neighbor] > d: + dist[neighbor] = d + queue.put((d, neighbor)) + + return dist + +def expand(cavern: tuple) -> tuple: + dim = cavern[0] + # expand to the right + tmp = list() + for y in range(dim): + for i in range(5): + for x in range(dim): + idx = x + y * dim + val = cavern[1][idx] + i + if val > 9: + val -= 9 + tmp.append(val) + cave = tmp + + # expand to the bottom + for _ in range(4): + tmp = [n + 1 if n + 1 < 10 else n - 8 for n in tmp] + cave += tmp + + return dim * 5, cave + +def part1(cavern: tuple) -> int: + return dijkstra(cavern)[cavern[0]**2 - 1] + +def part2(cavern: tuple) -> int: + cavern = expand(cavern) + return dijkstra(cavern)[cavern[0]**2 - 1] + +if __name__ == "__main__": + vals = read_file() + print(f"Part 1: {part1(vals)}") + print(f"Part 2: {part2(vals)}") diff --git a/2021/15/input.txt b/2021/15/input.txt new file mode 100644 index 0000000..b62e04e --- /dev/null +++ b/2021/15/input.txt @@ -0,0 +1,100 @@ +9996597169934462866674298311585462164938429595325898982446756778926623312419928462581954959682691967 +2985473821192251974951857599267129581722193984669499111891148299417367918194777369292323577917271689 +9925747219565218292791878884867871912812888438419913951838884629861174692194127299557997716292419899 +5689394257397924968615986194575967939829494536315791891189399346198354797971455482896478478991915819 +7191714231614914258843698935928469828947261253778874596549317179317739769211815941393178993235483164 +8261411311858625525189141927634584957969193998594589831161827486428181822492341148933916699735911951 +8491916338957614879947827918271919292115249669528752137626999289878321718995174471152853256534998862 +2878942979689932518788993693919232994181295141998674786229493444893529921396251916792869778369761577 +5324299179293789278896352999521161196335675668494898163723519189354519915572911924817148697972884595 +3249286984664762888964519927147388331192962971447998569588811898887938916912876838845226891917694396 +8384711585589932817217197266234448864986267887731451266551819546679493985489271887959192715994617118 +8558392988645926497661221561199187591614971862693418259749682995917799111375997911491314618563955283 +8448982133981186899328338219912614175929696865411141936944349293218792978158697238989149481799787693 +6829788549538172915212861761762811411999446212987957999818898769129995716668189729153281278992882961 +8171853935996999759827785274119369819474116329221912117887992386979999931924642786162346838988896998 +1611259796732365683997911728853115978724281285998878729487172937996381111893368427199788995529699915 +5688512981128461937192312761945159148391968976355979921691491771799226893997198194759896799954945399 +4677331887688119697949511996723791999294219225462628938768446491296191832983981819292814141771743713 +6998483931417251929193268819892118766128664979798963467991984184987179579514795981938448296897618517 +1319691989733199973528388427162273193372475922119779921892954934985598398886515997181951338365969481 +4299527919598836712396166784912989538495958199899819597168429291995797395512392555913678895994639498 +1959943162267357312789489261812239925964689121762221787667885625878744214497989669145322976481797489 +2395186851949597519521959999946556211159613271161993818642229693391155187199898781144194699852896652 +8995881734129869469494233213758985566876122341955919419837192269724184297999191789915397161175694514 +1589989198744781329419599199511686425468596978475911132726959429936172193239693316868625965916184839 +9882447993214964282121932219232574629549391691929133268994142998198147342636396881745981998993474912 +7737876929128219459528645811539339996618399972961981295848297621996944591699891682671676889993245341 +2158439725377317758939718768374247166592199417399889641427291896886226693898817697782973998951155297 +9887435694697319583419914934749159528953559489752368919149391989598118395465194898962938213247967394 +5517647144893878432868162191929768517614669477961621993427299179961283174693342728139917919748564391 +9779481169993213628493311246996281191589186121851592447341849279199269441668863494199994929698131648 +2959874885233989493331717181293295698768911881968258917777516222479221154718272378589492728986899898 +6336128726683932115888889787212994762911499913872419883197591582599568128238312873213867483934993736 +4159514962399649263976989199987979698821179147379581119235896886328996193984413131685592771291576266 +1593442591996141992339729558718999183319971698622191712984511552643854986614687182148724814175817656 +9792498287944398191893973114979339967886679599475949871199956319839493957942371899296491239678972934 +6958832763784733851418838934315594789797315719727432698172191667929493981747889875995275627797923389 +2912489714937795668149651893389788991785743292299526654245111715698898839692818936313581913792918926 +7195756671161364812491586641918192917591128991769216529117641729128224625938118993381221258566281874 +4919251993929919793698991748199857829677991159297389859596679221721172471911475458139992481162519175 +2254995628727981496178769799122851151827187992613599888143189293495389836799918172649522571495393365 +4919469549846964135387296992591431749927527554992629919141933995127179342887519454978599414789914783 +8249277916939616589494692899215986219117999611126787797761663947855882548552921696511335319977977276 +8997247891948158197997424577668119969512395999198777982793597792164299869129186219578886115816121295 +6941997972868952192836588639197579791529983259434179858113289553975791179662335714993722671597998927 +6694662791989839799999721874596512192467821383498167219689731819817638219918398599817984591678772498 +8858288185291451396798937151154999428339834613586898546191955738849619381719419835132493839871399615 +7529911675212868597977638119426882947159197216327972592891619718857968144833998898924864651272849995 +9691484419158964971779927177911682159384281915994991576187561796853919134899954697897563168694867221 +4894319635215192279188115698914991697424519884293976389911441262789983112191971613112113166199375431 +1511639279893277978712597619227629471932123889359895191237277184999881711199775191369185982853995942 +9915422489642151365815679799243528945862628419597469996679371174699116156719192447889887994175395158 +1269519797393822199696946291999871185118994883519698996879178838176969819961121912895184999235939982 +8998169189895585969989213678844886699295797199711994499817992161989593968875298663522818358585897162 +7927682215931182986837324955117927481866962848794911121399817493187817199924163786732968396717889912 +8311863849984418139391492994599723197997936818681266467612993599437842931897692691123198157196313828 +3912811962539933372757862888979829436791914818558936298392631514184279598868598428219711472666991639 +6916684642174849949229678714798199182288419234936896995119656411631851528789981973983524139588322938 +3899591899121528899189971692387979612889537681737837516481351153864963849151779816549651236111723594 +3733748925586297882817174179168829219857222829879737341141839283411189725169226158941341846729768669 +9789499627896993539271958577799419338952872815148576127561639829528596519399349651538276989994528487 +7388981178985997387282499451819991165879682469882199551165119298566527989112579262966861989646115399 +5991942761492919732325149912387694118188713956668248812874198274888581191798982696129299728788152392 +4893929462916669917284961278939751989925132199496199189137998549751266279931261714899988486719869185 +4997993581899573559368431987787949249487616996236465166438295477511852952993911916999513819315563739 +5694962633999723232519196778886841863659775543315314187999819975671489384312111125194191191689318842 +8117917171397291331189259254585716591711966747299169269591559696147192299722924212179199479985927778 +5877195869199369738399992996992351916954198321916324999535799172491147977863276571643974197933991225 +9989937132116396991282665553786386787251927628645189196271484472765767798223882649693739891271941718 +9881817923976739289587441977932118769978916716257286976119129982935796939299745998797611525399338946 +7971721113779639519693896636532198958154533493955284625816918678591158938299299514956545289189225246 +1934255841143924219963318212532349185169864629346812611498281935883975296729898789599295275471239935 +9389259195122479459673587535287714317984291529979184993896171591567899939324815119172791936569419171 +1219545154899922238148139999125192284119454489112162247977417126936591683779289118922958941952169529 +8931326645155712193944977992128197782593896232969361888983783158482969662613471498363997158128983917 +9391814334978943893899898719238927345819158859742137386199831611671627868629743974529895867689722899 +8899661813588998957926823145981293975684977898749619148875149895569991796276683223974512522996784281 +8189997341861632296117873952976155948326181517876925234797513284989779614111171824983144719982838692 +6829974748888281152995139169943951978697714989859236979688489367767193968499469271347883923978496486 +3582825929871712773829442944988717183399644827597944269949291896788936218399384642479246326487212216 +1281849189867928125128247997991274988592254197114976969923792926319271988297834927369539637996142862 +6975385386529147231116538827916688428583685119999922155687868872191934969189912616939972416699937619 +9142581394887759489992391495154883364165399163526193468348698682816285172516792933881369365183699737 +3411779799639918597997735278279522191199866497528592736267813281569999199119412823772227677998946384 +2116411967515514942119364428959419118117956378157649922119835139438587436793347611988988395844999146 +4969594274619966968618996995355173423281217195299985411254849697474491117942266985699122594883385615 +4917299221629599799699849452938637368998116959389958177198157236988184989389719268887182197869999794 +9933199734925928814814699974319532158151925514912941886226193291877951342254648694293572133944495113 +9987885196669594244937469588999294967538347679792413734999119397189999758851998539321185392791823319 +6989985129833911782351863869583492932291897395825982916227178892928481149185294531999169898771899993 +8181799944142196786791987474137119471971711249456315997994855914169196337574821618642899989499999967 +9977674398586181511429839918697885836894979877115969228276796238492289811696176629546719787979932155 +9649322578254321813692488189287617696897892613327148796662618417432796649759345844497523367451481152 +5129599141866519189896719299898197851393894869211189289921289673533589213789998748469233769479419838 +1914167773815939689484489593599191199453921623428226899327789139828531391877739791958192158441984193 +8338474519167599455272191263393519999999117471971142469799444885161861196178994691697689794932649387 +1559148889238879814969113114369991178858114182289991437257816149529871139727898999977787479892611941 +2195956622389911468295917219887214665812887892199883687933786497999277478287123418492269694943326749 +9812749311865999362692593879136236263719259266549637913645675293968172469772769845996496649211944289 +2292883723888976611993688774892793962329432919349328271848881342422189315889383193139146839498568176 diff --git a/2021/15/solution.txt b/2021/15/solution.txt new file mode 100644 index 0000000..dccb4cd --- /dev/null +++ b/2021/15/solution.txt @@ -0,0 +1,2 @@ +Part 1: 604 +Part 2: 2907 \ No newline at end of file diff --git a/2021/15/test_code.py b/2021/15/test_code.py new file mode 100644 index 0000000..33c2f38 --- /dev/null +++ b/2021/15/test_code.py @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: MIT +# Copyright (c) 2021 Akumatic + +from code import part1, part2, read_file, expand + +def test(): + vals = read_file("test_input_1.txt") + assert part1(vals) == 40 + print("Passed Part 1") + assert expand(vals) == read_file("test_input_2.txt") + print("Passed expansion") + assert part2(vals) == 315 + print("Passed Part 2") + +if __name__ == "__main__": + test() diff --git a/2021/15/test_input_1.txt b/2021/15/test_input_1.txt new file mode 100644 index 0000000..ab80887 --- /dev/null +++ b/2021/15/test_input_1.txt @@ -0,0 +1,10 @@ +1163751742 +1381373672 +2136511328 +3694931569 +7463417111 +1319128137 +1359912421 +3125421639 +1293138521 +2311944581 diff --git a/2021/15/test_input_2.txt b/2021/15/test_input_2.txt new file mode 100644 index 0000000..e1ea085 --- /dev/null +++ b/2021/15/test_input_2.txt @@ -0,0 +1,50 @@ +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 diff --git a/2021/README.md b/2021/README.md index 20095ed..dc24205 100644 --- a/2021/README.md +++ b/2021/README.md @@ -29,7 +29,7 @@ Collect stars by solving puzzles. Two puzzles will be made available on each day | 12 | :white_check_mark: | :white_check_mark: | [Solution](12/code.py) | [Day 12](https://adventofcode.com/2021/day/12) | | 13 | :white_check_mark: | :white_check_mark: | [Solution](13/code.py) | [Day 13](https://adventofcode.com/2021/day/13) | | 14 | :white_check_mark: | :white_check_mark: | [Solution](14/code.py) | [Day 14](https://adventofcode.com/2021/day/14) | -| 15 | | | | | +| 15 | :white_check_mark: | :white_check_mark: | [Solution](15/code.py) | [Day 15](https://adventofcode.com/2021/day/15) | | 16 | | | | | | 17 | | | | | | 18 | | | | |