diff --git a/Cargo.lock b/Cargo.lock index 0b40c51..f3a156a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,18 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.2" @@ -41,6 +53,12 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -70,9 +88,11 @@ dependencies = [ "derive_builder", "expanduser", "futures", + "geo", "grid", "indicatif", - "itertools", + "itertools 0.12.0", + "pathfinding", "rayon", "regex", "reqwest", @@ -85,6 +105,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + [[package]] name = "arrayref" version = "0.3.7" @@ -133,6 +162,15 @@ dependencies = [ "syn 2.0.39", ] +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -242,6 +280,12 @@ version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.5.0" @@ -353,6 +397,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + [[package]] name = "crossbeam-deque" version = "0.8.3" @@ -421,6 +471,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "deprecate-until" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a3767f826efbbe5a5ae093920b58b43b01734202be697e1354914e862e8e704" +dependencies = [ + "proc-macro2", + "quote", + "semver", + "syn 2.0.39", +] + [[package]] name = "deranged" version = "0.3.9" @@ -472,6 +534,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "earcutr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79127ed59a85d7687c409e9978547cffb7dc79675355ed22da6b66fd5f6ead01" +dependencies = [ + "itertools 0.11.0", + "num-traits", +] + [[package]] name = "either" version = "1.9.0" @@ -536,6 +608,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "flate2" version = "1.0.28" @@ -546,6 +624,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "float_next_after" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" + [[package]] name = "fnv" version = "1.0.7" @@ -665,6 +749,45 @@ dependencies = [ "slab", ] +[[package]] +name = "geo" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4841b40fdbccd4b7042bd6195e4de91da54af34c50632e371bcbfcdfb558b873" +dependencies = [ + "earcutr", + "float_next_after", + "geo-types", + "geographiclib-rs", + "log", + "num-traits", + "robust", + "rstar", + "serde", + "spade", +] + +[[package]] +name = "geo-types" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567495020b114f1ce9bed679b29975aa0bfae06ac22beacd5cfde5dabe7b05d6" +dependencies = [ + "approx", + "num-traits", + "rstar", + "serde", +] + +[[package]] +name = "geographiclib-rs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea804e7bd3c6a4ca6a01edfa35231557a8a81d4d3f3e1e2b650d028c42592be" +dependencies = [ + "lazy_static", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -723,11 +846,37 @@ dependencies = [ "tracing", ] +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "spin", + "stable_deref_trait", +] [[package]] name = "hermit-abi" @@ -901,12 +1050,30 @@ dependencies = [ "web-sys", ] +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + [[package]] name = "ipnet" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.0" @@ -943,6 +1110,12 @@ version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "linux-raw-sys" version = "0.4.12" @@ -1047,6 +1220,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -1172,6 +1346,21 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "pathfinding" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ea07a6e677e47d6a84724d4fdf88b1e37fcb49ac94e236d7caeefd8fee75c8a" +dependencies = [ + "deprecate-until", + "fixedbitset", + "indexmap", + "integer-sqrt", + "num-traits", + "rustc-hash", + "thiserror", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -1465,6 +1654,23 @@ dependencies = [ "rand", ] +[[package]] +name = "robust" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf4a6aa5f6d6888f39e980649f3ad6b666acdce1d78e95b8a2cb076e687ae30" + +[[package]] +name = "rstar" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73111312eb7a2287d229f06c00ff35b51ddee180f017ab6dec1f69d62ac098d6" +dependencies = [ + "heapless", + "num-traits", + "smallvec", +] + [[package]] name = "rust-argon2" version = "0.8.3" @@ -1489,6 +1695,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.26" @@ -1546,6 +1761,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" + [[package]] name = "serde" version = "1.0.193" @@ -1633,6 +1854,33 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "spade" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87a3ef2efbc408c9051c1a27ce7edff430d74531d31a480b7ca4f618072c2670" +dependencies = [ + "hashbrown", + "num-traits", + "robust", + "smallvec", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_init" version = "1.0.3" @@ -2330,3 +2578,23 @@ dependencies = [ "cfg-if", "windows-sys 0.48.0", ] + +[[package]] +name = "zerocopy" +version = "0.7.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] diff --git a/Cargo.toml b/Cargo.toml index c682ad9..5ba5d13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,8 @@ rayon = "1.8.0" static_init = "1.0.3" grid = { version = "0.12.0", features = ["std", "serde"] } indicatif = "0.17.7" +pathfinding = "4.6.0" +geo = { version = "0.27.0", features = ["serde"] } [features] part1 = [] diff --git a/aoc_puzzle_cache/day_17 b/aoc_puzzle_cache/day_17 new file mode 100644 index 0000000..6e4a811 --- /dev/null +++ b/aoc_puzzle_cache/day_17 @@ -0,0 +1,141 @@ +314412134515235343233533333536633455653353226524463545367577644655564375735567774443767545555476326253354625332434443364224465621314212153555 +541151354452244522426632553456444465355436252633745744545656765664467373344353475666347765767443443552326263264235346622346265464551153535535 +331313213153324653452333663333462335265624455475544677337533645646454544573377667566554353775343377532656434266344566626434262245532313441542 +231231134242452536244266236256525426355273354474573763575656667355645557536446754366667563657447367737456645352222534556245645343351335322223 +251433112552564352445455233433553362245337533756634643733533466354356373567633334767437674677465346746774546242625352644324265246422513313355 +413125324132545243423242425355265226355444733776744656536465355674555733753474534534433566567674774473567333452433553242344623352255235253434 +532355354346566256462226323353453233574773645645433345534463465454533556537575575577754774536656666577567366323533434336553634632645651225243 +455311523432626356642246453352635354666745454767466646743434437774334444766744753773634355543363377575473337333424664332326565454236653544323 +424523363662246263654465624464655447744774567556775663763465367677374675753355374345346677343654333775353543635753655256634466626335324551131 +312234524445243642435564344443643546563334674463666677677375666374376637677377675656367674677655374445445436364656344562424423465563566224112 +115435666634232345425362663436566563773563533376643646553453766464636476757674637467374456676436444363454454565354445236442434463546522456311 +154534345264644332453643233644775666573434664657335643647354474373543563433577357373746663547554745737536477775465743462232356456544633335612 +451266255244444535322452434645573365766537743665343557476666464758667467776574476764465334655477443443745655654457677624263534623665264555224 +353335563222253235535444636573356337445367344474777333557878464768444788856675585565465366454733456455674536433473654575346243664464634353361 +133423654653562566524555363736665736664674537436557377575766444544774854555847644678448674465647577673665776754454646667262236226252353332253 +133244534342626454662664766673363454654775367333568448688558578768686448546868444748457676856473435435676655374655443447465552545633333543332 +243466552334262456344733345534573753356536657446767756788575445478764548775685776647768646456856765643745556543743664466543662642344456546633 +225656624252654654257373356646344537466547455766887558787658686656447855868447485884684656856578745535456436454746473564736542642544625222354 +263225332334642334675643644754654536773763445878468566857854558584444644768557757487854646584847654777756335644546467463376674663436535646452 +462346565445343656664446656746533643745447844866758554785454458448648877657447474444486777886656567775334434446577467565433575636665445223642 +363266453445466566556667366355434346533355777566657774487686846454565466845574688847467448668876766446676776475563644443566363242625262335623 +325363664656255465436433336773567347537767485744446565664446855866487664586568787776655755686868765886664344557456735673467475426333444333354 +622523453334652767737546677766537644476465885765644778876688488446747664448447488668445647744766848776656844776733757447477443333425525625425 +333623242525533576376533574476577337665748887566464644665446655885548856787747865488577777487546544876644587367343333376355575457243464345323 +543454255433367553446637345433677465656546447845788656747548755757888785557588445647856758456654456888685858475473564764673634765655244332245 +623536555425575563774673767455733665777686666786545674684485686454886457575558854685585754647856666454488644483445777757775736767455653333323 +335365452534347455445473435765736686586454476877577676868665648588444785645788688755665567847847585545847774845545765767665374567754666353346 +465462453636344566675354655574674445647778775756448777556676575896785898598558875578854754655544448684755674768743663367375367764556356656544 +363442635343777335564633673354845878587776886578665748646577867786688655765785766556946866764484465548878588568456776747534365377563626244552 +232634453453763747553644733568475457767854754657478566598876656677877858987888958665955775887757458758846446485486633766635574537637743535463 +522344452575745446776443535457848555475857457855478488988789876956765857655568587967855966667854884755868658474447474543647465737337736454553 +663552627334333773546633445548767755868645584584477759875859697897758656889957568796889865757587657865664687876775763343644433447356576623322 +445264645556337754376544665585466787575557454745756756569865889888669678579697997988759885795864747457454586846847864776454355655747776434462 +622455277467655667357753578774565877584888457466786879796679896785676566558958878758687656579956856668584545646457888846333776555447355326455 +332544567353564566667655876454688564476674785685585555898896589897779866986569586598987767875687986855654688558578465866465363654354575635354 +362352774453665775437766846688756656644468774687855675597596697959675558598777586676566558856799988477458485845764474846545665733565465642235 +653443463447775343644765866587748864448654759898689676566898666986677759957898699679989767966696878566674676885568556746354374333576755645346 +233457756564473374745676786648657667555644559576795697887955798889695765895777795769767775857776555687668866577657748875665546353337347453544 +544435543735775756436586648877447574576649986595589858785976896678788775858975897998958798577699775668576788768487847776466567574473543737433 +552254545736366367557746645875766864684655876967787578968965796566679766856567978896897569787898896679846454688458564765474667745344575656652 +446576536675377537777877667464484755588965569999587859678868658589679797766778779556888989997779955859977746666655578676475336765356674466355 +664473477475337634746565456787867874856975589795859955596796869957859878755688955799686898799975987695678655645557444554578533555356365636576 +465574733563457536788876484884757745657879799597655969996679655767876986677677885995975575988689878558975568885475654565747543764777545434764 +655353564364767347457778866577575747857576977959767669999755887968768679988668899777968856587559585695675755788768567745454887754734566654776 +367447364467773735858756877784568848579768578757989966677688997788886686879996878778959688959859779665977976845865465575445443764647473556443 +575575376547735375465674555454756677556699558557789786866688889777886986677798966766867857656867689689857999565775845768554668773553355667455 +234337435764637437477847577878544788568595659969575976666789796968969867888879989998669978798695996588697968856484458578564864454363357443746 +757374646667343374658776784548485699556687968567959887878767769896667677769799977697998887555798975859969987654847844667488486337577646667436 +746675344636443355447847877775585975688786658585856976688798979766676667669777869966786696985578695567558879587875686667857658435634537537574 +565477576353557754765856675584756757758869688899685888866867969967789996777977696786786799899578969989676858577478878648884558444634344565534 +545776547376457656484767664474675785787867996876586886969967867667968766667869896988688866988899565575789556889485458685687857857634755536555 +556547536534744464666677768654665678867877599566799896796696767679697779667679787798778776868867566879877875598887644644556565875437573346464 +475674567766655748846675487577896855868786656856889676967777888896899798696668996799767868967695859567789998779678567645654866474475575474564 +575776574667667488585664655566878858856696985666978969677996768866897769698998978797769697696678578875896978895756568847474676767653445435775 +654337754774366757587856446454599578896669889566879786768967788796796669876779987979768676978667976655798586598867767646745874485743333475573 +654535367644768656654887558678576586959758878969989678877897997899999966989878689799986869688867799655667586798667456578885664544463374435766 +373454367345364747845477877778675566899885865996967677867679667777788676989889796668969976888798995987599977865979678558884576658675654335775 +445765373433585588645685488858679558587596589669677997776969767976999889898898766997786967866698797999857865789796785754485546845444454775674 +337734475564468456565466675695986676969896699869686898678978677788879779787799996887768688996869667576965976777685546448666856777733574373737 +644734774466757856744886858488965696559799868986877886989867976897888778788788798986886797677969698965795977998975557467585758586844655756455 +554577373345575856457564758579875559586586796866798868679677697988989997977997877768988676689966886665767569769698685685548846746574457776477 +667557463566744755788558777855777886587799679787686877796677897998989989988989787886668788678666969975976669795676556888447866647567743646364 +477373654454748646848578744889989655567667976978866867686997789989879798778898999797966898766997896877988557566598698448764657467667475673343 +547767744463684588776576646599966657599868977798867767969869998988789788779979999878667887668677976995895669795776694454475565788475343635657 +575346733753567857486747775687658558698895999787897796978778979899978798987797778998888699888676688686959695889576575786886446768854464455437 +473546446375756484756475658876679886997566686887666679669897979779788997978979778799998867676769798987567787967859975765844867475587534537454 +776453776365684567446656644967786587775958996676668967679898799998788799879898877877989898977976777678699685585766764777775447488756354556446 +736736635634666666775484566586558589788997989786967767799887998789888988797899987888989886989697987667599676976788787665844667557685574343647 +573544375367857645884646554755995555778899999998889786688779888888989988897997798979897867888697867777955555886985854554867878658455476654776 +547366346654785856677675467857768875867789767867687996698877797797899878799797879777887699877699896968665989587996796455854847576445446464566 +553774575776675458645746458988598759889577967677669966899798979999979999789878997799789966699879979775697777599869796745465885585456345737663 +353767574665657756756574574787569598778898766697776969787797997797878998797878779887779986689876898989659798867989978566746888666457646435435 +653737743445665787556877448595787969666796786787697768767778799999788897889878889979979888788689777869688958985877955585488544558456364563435 +763637337773885888664576787665577575587575866776988989688778799898797888889889798798876887679867876995756675876698764657588677588473535647734 +637644466754745688456758488895558797777587677768679999666877988788777879979897997898778676778876797665975669889776876777657444686464667776673 +666575766736756646478667475789986767858855969986999798899899997877987998799899899987896677686676868779995578576986677485854676545866776337365 +766455377434588788655477784898599856578797767798869686878899988797778797777877899788897777699996979975569757859898676546748776486667636474556 +545447346666475474465466565586969777578988877798779686777788998788798997877998897979899997796697788985669755797567897486874854548465473567557 +444655447566445854654474455756878599795979666889787989699799799788789899798878779887786786978766799797798756556977755677546455687663556373733 +457756474767867685745767766688656959868969669698696779769987889977889997879978988997869666968688686686667595765685954465848754645545676346656 +577777634634784475566585487766898679766857589876666797878786899778877977888988789997897987777866866875865657958858898886558674477546645373733 +375564455343464778546576465699596776656969768977898766987868978799797977799899998977676887796966769685566567875598986866656546864673577335644 +764536374744688766576577885877665755778667698767767896866976678787887997777989979797997897886879998588785565797599856764646476874865657375337 +543643663577445575575746865856699797886966697787689988987898997887889778799878876968676879669667867865969569598866786777478684447473535476464 +636376576444445784685557667858867858989886768887678798987997786899978898979778799676976968699687687696799958596989878545477776884836466676544 +763557453467756688577756587779998976955765595888976888986678666799789998989886898897796979988899965969688858788595854765644557856563554676536 +577357635456488886845878554769765556955985655979997878697999677778688978698787966866789866976999769896799668958869464854575446585434637564676 +364747645336576587565657758877675688959786977998788886798766997696767666867669986699686998698989755758698855876979464485786565446476634357363 +764673654455638867657864677868688686876669689896868776679986866978666986986777787686788676788988756558765565677587548746675558674337566464735 +467553475334767444466644884457796887977895865685877786688968766788798869987667677976979679776875687896785677785585464887785478847566336676367 +754553573564374878888686745468795559998559558576899666976769996769969687868797787688689676689897687688897755999976676746558645464445673675377 +654645755747464485667558574456877887787569867679887798667687868677876778669689666779886968896876685659976676658686566557864768873645664376734 +445544646666653788765567845564557669976567696868566987669896966988769778889996997766998998877788995567766676565676856665458647445467373676373 +335345454544774365576884545776447679769795858986755876876678877988676979788677979897688799775658967569577968775874488767645745846353477357637 +366377754753734477674448744864875789898856866979656686786676967688978696879889689678998668967576985558585659776884567855454458533567566333343 +634577374346476446555445785448644766995595858979896666888979689876778998787897688787799698888955955598989698964778556874557885545653374555466 +677556475565736667777484485656567599957978799986798886767978668896669897777678898796786667657569787669575865654655784846475888734563453447733 +436473576775565774677876476556488659989779567768788785959799789889869898668776868679767999878696597975756768458548448585844656454736734654746 +547357337753544344646667465664866846685869885977886995876969889768689977867696698867687576899598699757796587666875856478644854555674435777546 +347756377665473476788767458886747667756788579676986758786598768688666796797777766975688995896569669597986656644477885868658863643356336436767 +435655633356663457687474657867868586557857757898656955676959979987699988668797969575679668986989599968778575744456465555448545746745553656636 +232735335633336435364776478856564678779895856986785956779795856697686755768967786866756967879579989575999767445845658488464367745456563766652 +365534555754666343356858854544586845478695766698595578657657699589559657775566978578796968698978756676686864564748787854774355466336575533356 +332456745574334636435755766547766858677477558867578676869797997655556578565658577689657675777885779856545854766587588785885553755574346447734 +642637766374645667576784676645584544887786985679965689779986669967558768898687899778796895789897896869675566888667844764866335475676646746344 +446266775465654344746545588648865455558567795956557678858587988789596567768697587755599776658585659584746544448586656576843675434737573434342 +224663653636375747635334754667777785765845587767875669699965575665656696965569779879659798977576858957685655475765764488774657635437473366356 +625426436574367576377455445457768877844667877696677657787998676675855585695556989557695768975657585787668568586645766544775754777736377573643 +254365447437365344543734686478587446577464478577858696676989769786995956675995686669859566789766667744858454484774566846375675636477476676335 +422222654656766733456576778578576885587687484547879668859979585659755658767565669789967569955759486556587466846657846867463337773463345653456 +222663564645657663455455778578554485465786786857688856768877956578786888557568998985866787655554855578544846755487777674735775777464734622546 +254425667467346335477743536684857855446886765847878588867978695556586758898799875967867665697587665575484878864786575464647575364434365244232 +545624253753775647574566377467768786547854476484446767697887679959597569976686666989776986887485646865745586658564643373645345733746736652366 +445252323737357543544335573665464678448566785686457785666686788888585959758897989777867765544747588555474847478855647656665644764466453436244 +624334552663634667443673377457587668454844544466745588644789865859879759688676686967574556546474878564576746445776434547637734437356426553336 +646342663527575634777653454344647768685555578668685585747484849669788588997988769574756864788445847464484765785557365333564764664464523466625 +433646226555554733443535333646458856474776865656467548576566554476676858654688585874478857475648667678875678885646635637756557467755533632524 +524224632242777744344347444334366578578575877467887886555676854678445574565875655468577574858767577688754564753666644467764676465333565552463 +332524536526246557754755777633656654474784458587665548686487884874566865658745654485687757788578847456445876553653343573443456766725335256642 +232554544665423736756756355734633455656467675747788778876765845585468587877455867666855787577686557854444777576433354455347456475525443524464 +442536554246245356477665466553537546467888677788466877467686486657667685476657657467447667888766845477874466347633375765374567555252355555234 +466244246525246247457757744364447343554644867457546676778874586655685744567645544464686645886845556867444547446577475333544476334534663633245 +256564536546536663747336555334445355353685446444654655484676486875548856554568564566857447765885764477666734375743576475547457262563335256256 +422666323232323265733677534764557654535733767547847748648476454756566877767566745674454856755477854786445654433454543465347365665232624666552 +424322552553422235336774436334655656753464566788846587546678666644787566484885754665684866448466644745643776645476477537765745622326366565354 +345543454253666434265365537663576573436433745778877446564777478457575846747454774548745457745447684757344355355745445557775262543464556444634 +336332264656464436433635346557737336357437635546658478488856868457865746755647874844656478545747333465337573563736436377474556263642424323626 +522645624243565434556446456664775367336437757757366675878887787775687654585666655745655846458333674745667336355753654677662464322345536366444 +555355255625526523556533365744375654336575555355636447444755865586587665788476558447664564566644433656467374766543333653256234262433543666243 +352442235334564446432432343454456456335337663466436474364547647547857775677445776846844647434465354643576547346346673562543352236432233355555 +513442263654563562566354553554666563746565354466655433636643784876456456474465676577343673465465554337444354653537646325625464335245434545645 +412166442223555666442324255746337746664773367543767373733737677365555364633674664745736555765655345666573457674453644222662456622244462436234 +335154546633442632244453333547453533644646357535376775746533656673644367657346633466673535437637674353457475533764463643233554553226563253531 +344355262636555362325466655254444447336435574534775754465675544754737373636474353733766573766355474364665466456367352423244564562442343664431 +311413135435554264436263252552354346437465375467563776374733477357475637647547553646677354774353547337664736454445366643346246333553342424441 +535433415243554224545433322662227453333764757337343766763564757456745673733566554346344364757363656755345357754222664244523544535662564243331 +134111534364445323222623622364552434633767676433737455655363547774354473747466434563657563745543347455674446543443655424426366324335634323325 +351255341465626465234256523662254632653447333533467334465363354667336765477454734657366335356637333466453444525332662564422333455463641114144 +552341443344524565642265436465366522436473534654637564453564353534556774457633576376544536465446545333744663365656323344662535233245324445313 +221252532115466236652623632522433654526676365575647434775344354564367573777346436744774454673664564335344245253635255564364626663532252232132 +144524115433215643653323636235532663522464736374347774777656443757553555345734367444567773663755546434263345354363654655245244254515334312415 diff --git a/aoc_puzzle_cache/day_18 b/aoc_puzzle_cache/day_18 new file mode 100644 index 0000000..54060e1 --- /dev/null +++ b/aoc_puzzle_cache/day_18 @@ -0,0 +1,738 @@ +L 4 (#3db750) +U 10 (#0e0433) +L 5 (#526490) +U 6 (#3e9193) +L 4 (#526492) +U 5 (#4418e3) +L 5 (#3ad2e0) +U 5 (#579f63) +L 4 (#118202) +D 5 (#411263) +L 5 (#135ac2) +U 4 (#1196f3) +L 4 (#5df7d2) +U 5 (#22e353) +L 4 (#1615c2) +U 5 (#17bc73) +L 9 (#038720) +U 6 (#16cff3) +L 7 (#57beb0) +U 4 (#16cff1) +L 6 (#3da480) +U 8 (#43bb73) +R 4 (#2c2540) +U 8 (#374033) +R 9 (#4f95d0) +U 7 (#374031) +L 9 (#0ff0e0) +U 8 (#12b433) +L 3 (#29b7c0) +U 5 (#57fa93) +L 4 (#3b4d90) +U 5 (#175463) +L 7 (#2945d0) +U 3 (#151b23) +R 6 (#34c720) +U 2 (#1f0a03) +R 8 (#3d8772) +U 4 (#3eba93) +R 7 (#0e4442) +U 2 (#012851) +R 2 (#2618e2) +U 8 (#5ca961) +L 3 (#0a2972) +U 3 (#5980f3) +L 4 (#43a0a2) +U 2 (#0450c3) +L 8 (#09fae2) +U 3 (#320053) +R 4 (#52e1a0) +U 4 (#03ce91) +R 8 (#330070) +U 3 (#03ce93) +L 5 (#43c770) +U 3 (#3d18a3) +L 8 (#488e60) +U 5 (#2d0d63) +L 7 (#1e78d0) +D 4 (#1680c3) +L 9 (#31ee60) +D 3 (#483563) +L 4 (#0c6710) +D 3 (#467ed3) +R 3 (#02df40) +D 2 (#1e2ad3) +R 10 (#3f20c2) +D 4 (#447ef3) +L 5 (#3f20c0) +D 7 (#07f723) +L 6 (#1a71e2) +D 7 (#23f173) +L 2 (#079be2) +D 2 (#5cd243) +L 7 (#3d9fc2) +D 3 (#107ee3) +L 3 (#165230) +D 4 (#69e463) +L 9 (#2159c0) +D 2 (#1dd863) +L 4 (#47e9a0) +D 4 (#1bff13) +R 10 (#12df90) +D 3 (#364e23) +R 3 (#517e12) +D 3 (#0a71a3) +L 8 (#2edfe2) +D 8 (#339f93) +L 5 (#27d7e0) +D 8 (#4a91f3) +L 8 (#44e320) +D 9 (#0ea943) +L 4 (#13a2f0) +D 5 (#6356e3) +R 10 (#05f220) +D 4 (#2644a3) +R 8 (#65bb92) +D 4 (#2ae573) +R 10 (#65bb90) +D 4 (#312573) +L 8 (#3b10c0) +D 6 (#154f21) +L 5 (#018462) +D 5 (#552bb1) +L 7 (#018460) +D 4 (#0a3be1) +L 3 (#2efbf0) +D 12 (#17a7c1) +L 4 (#30d400) +U 4 (#624c61) +L 7 (#38d3f0) +U 3 (#214351) +L 11 (#027d02) +U 4 (#3bdac1) +L 7 (#027d00) +U 6 (#13f621) +R 6 (#1c4f70) +U 6 (#1c1f81) +R 5 (#30ce40) +D 6 (#149481) +R 7 (#0d93b0) +U 5 (#491791) +R 7 (#50ae60) +U 5 (#128a91) +L 4 (#1f7990) +U 7 (#010331) +L 6 (#253e60) +U 6 (#1f2643) +L 3 (#232c10) +U 5 (#3d8083) +L 6 (#294c32) +U 10 (#3fcf53) +L 3 (#294c30) +U 7 (#1c9cd3) +L 8 (#26b342) +U 2 (#2107e3) +L 6 (#26b340) +U 6 (#3a17c3) +L 8 (#232c12) +D 6 (#3199c3) +L 7 (#34c162) +U 9 (#0a6463) +L 4 (#2f5132) +U 9 (#1ef1c3) +R 6 (#2318c0) +U 3 (#21b8f3) +R 3 (#40f9d0) +D 7 (#1a5473) +R 4 (#28adf0) +D 2 (#2e6181) +R 7 (#00d3f2) +U 9 (#355a41) +R 3 (#00d3f0) +D 10 (#1b04c1) +R 2 (#0ddf40) +D 3 (#298111) +R 4 (#42a8e0) +U 2 (#5b93c1) +R 4 (#4282b0) +U 11 (#25af91) +R 3 (#0ff3e0) +U 7 (#002661) +R 5 (#365a20) +U 10 (#3382c1) +R 6 (#3a83a0) +U 3 (#376591) +R 7 (#0894a0) +U 6 (#379891) +R 5 (#44e3d0) +U 3 (#41e791) +R 6 (#0133c0) +U 4 (#070071) +R 4 (#0627e0) +U 4 (#33bea1) +R 7 (#456812) +U 5 (#5ac051) +R 7 (#4254e2) +U 7 (#49a231) +R 5 (#0e82b2) +U 3 (#14b5a1) +R 4 (#320942) +D 8 (#126031) +R 8 (#103262) +U 7 (#3b7aa1) +R 4 (#103260) +U 5 (#30f9c1) +R 5 (#29ced2) +D 8 (#1ac681) +R 7 (#62bf32) +D 4 (#1a4041) +R 4 (#14df02) +U 8 (#443071) +R 4 (#47db32) +D 10 (#1b21b3) +R 4 (#129c02) +D 2 (#3e68b3) +R 11 (#533d52) +D 3 (#09d713) +R 3 (#058242) +D 6 (#52db63) +L 7 (#1c7002) +D 5 (#65d703) +L 4 (#1c7000) +D 7 (#0965f3) +R 6 (#1c20e2) +D 7 (#1d2273) +R 5 (#4389b2) +D 5 (#044e11) +R 4 (#27a040) +D 2 (#1178a1) +R 6 (#120170) +D 9 (#44ebc1) +R 3 (#120172) +D 9 (#152cc1) +R 4 (#27a042) +U 3 (#1f7081) +R 12 (#2fcb02) +U 2 (#1d0f31) +R 8 (#42cb20) +U 4 (#43ab11) +L 4 (#42cb22) +U 2 (#377091) +L 9 (#3b2d12) +U 3 (#1b21b1) +L 7 (#51b2b2) +U 6 (#3caf91) +R 10 (#4018c2) +U 5 (#2d7c51) +L 5 (#525612) +U 4 (#0c3071) +L 4 (#16b6f2) +D 6 (#400511) +L 7 (#263730) +U 6 (#13acb1) +L 4 (#42d5d0) +U 3 (#47f3a1) +R 9 (#4018c0) +U 7 (#154771) +R 2 (#2fbd52) +U 3 (#3a1df1) +L 8 (#51aed2) +U 7 (#4edb11) +L 3 (#120e82) +U 7 (#64c5f1) +R 9 (#0937d2) +U 4 (#1c4f21) +R 7 (#4551f2) +U 5 (#5a5493) +R 4 (#1edfb2) +U 5 (#169093) +R 10 (#37eac2) +D 3 (#188731) +R 5 (#0f1a82) +D 5 (#585df1) +R 3 (#120232) +D 2 (#2ae331) +R 8 (#2287d2) +D 5 (#103e81) +R 6 (#4690b0) +D 4 (#0772d3) +R 7 (#3305c0) +D 3 (#0772d1) +L 10 (#38f400) +D 6 (#380261) +L 6 (#29e240) +D 6 (#06f581) +L 5 (#439b60) +U 12 (#201da1) +L 3 (#402420) +D 6 (#144c91) +L 9 (#22f100) +D 4 (#3870e1) +R 6 (#0c31f2) +D 2 (#03ac33) +R 3 (#5bc432) +D 9 (#137063) +R 3 (#26ea62) +U 4 (#137061) +R 6 (#450eb2) +D 9 (#03ac31) +R 5 (#43b222) +U 9 (#05c961) +R 5 (#4055d0) +D 4 (#20af11) +R 7 (#1c10f0) +D 5 (#3943c1) +R 2 (#26e682) +D 4 (#1129c1) +R 8 (#358042) +D 4 (#070c01) +R 5 (#2956d2) +U 7 (#191821) +R 3 (#224300) +U 3 (#2af351) +R 2 (#0feeb0) +U 6 (#23cac1) +L 5 (#5dfd50) +U 5 (#2a7f41) +L 3 (#527870) +U 5 (#2a7f43) +L 8 (#4aaf60) +U 9 (#287f01) +L 2 (#13a150) +U 4 (#269d21) +R 10 (#35e962) +U 7 (#281351) +R 8 (#35e982) +U 4 (#281353) +R 9 (#15be82) +U 3 (#14d581) +R 3 (#251f22) +D 3 (#42a4e1) +R 4 (#04bf90) +D 9 (#1f56e3) +R 6 (#3438d0) +D 10 (#1f56e1) +R 4 (#36fdd0) +D 9 (#0cd891) +L 4 (#38caa0) +D 6 (#0cd893) +R 6 (#11cc20) +D 7 (#2ca3a1) +L 6 (#3e7d60) +D 7 (#271f11) +R 4 (#20ba00) +D 6 (#53c2b3) +R 3 (#11a9f0) +D 7 (#34ada3) +R 8 (#567fe2) +D 7 (#1f43f3) +R 7 (#10e032) +D 3 (#515b63) +R 7 (#1a0d52) +D 2 (#06c953) +R 3 (#1bd910) +D 8 (#339df3) +R 6 (#483b90) +D 8 (#2b9943) +R 5 (#040ff0) +D 8 (#249a13) +R 2 (#4a2a82) +D 2 (#2be7b3) +R 10 (#1dfa12) +U 4 (#23ec53) +R 4 (#4e4080) +U 4 (#431f73) +R 7 (#332ce0) +U 7 (#151433) +L 6 (#532250) +U 6 (#281c83) +R 6 (#3b2fa0) +U 3 (#580361) +R 2 (#381920) +U 4 (#423571) +R 3 (#365c20) +D 10 (#357b83) +R 4 (#2bc910) +U 10 (#17cef1) +R 6 (#0d2f50) +U 2 (#496f61) +R 5 (#0d2f52) +U 4 (#0a78e1) +L 5 (#0db930) +U 6 (#057ac3) +L 5 (#065930) +D 6 (#4034b3) +L 5 (#065932) +U 5 (#2607c3) +L 3 (#3772f0) +U 6 (#260ff3) +R 6 (#0a16c2) +U 5 (#0984c3) +L 6 (#4ebf82) +U 5 (#0984c1) +L 4 (#181ef2) +U 9 (#1d1d53) +R 4 (#384730) +U 2 (#219013) +R 6 (#065250) +U 6 (#2232b1) +R 5 (#3f4030) +U 5 (#471ca1) +R 6 (#33c210) +U 3 (#37cbe1) +L 7 (#53b020) +U 6 (#070661) +R 6 (#2199f0) +U 9 (#1d8d61) +L 6 (#35c702) +U 4 (#13cc81) +R 7 (#22f592) +U 3 (#36f1d1) +R 6 (#17d3d2) +D 7 (#4a1db1) +R 4 (#161810) +D 12 (#019c31) +R 4 (#46b5a0) +U 9 (#4bc491) +R 4 (#13c2b0) +U 2 (#07bdd1) +R 4 (#1bce00) +U 8 (#48c791) +R 5 (#54aa00) +U 3 (#079a91) +R 5 (#19b550) +D 4 (#2ff601) +R 7 (#1560c2) +D 10 (#3afde1) +R 5 (#1560c0) +D 5 (#19b1e1) +R 4 (#29d140) +D 2 (#1c83b3) +R 6 (#274ae0) +D 9 (#4f3ae3) +R 4 (#2e2280) +U 7 (#12aea3) +R 3 (#121630) +U 9 (#590343) +R 5 (#121632) +D 8 (#0f1813) +R 8 (#2e2282) +D 5 (#01f683) +R 4 (#0b3350) +D 8 (#2582f3) +R 2 (#358bc0) +D 8 (#495e93) +R 2 (#2b6380) +D 6 (#202a83) +R 2 (#025d40) +D 4 (#0600f1) +R 6 (#492c30) +D 9 (#310791) +L 8 (#06d2c0) +D 4 (#328091) +L 2 (#060230) +D 6 (#1d2163) +R 10 (#04a2c0) +D 4 (#201cc1) +R 5 (#047b62) +D 4 (#0e0ec1) +R 4 (#17bd32) +D 7 (#560041) +R 3 (#41b672) +D 5 (#1c40b1) +R 9 (#01fea2) +D 4 (#018691) +L 7 (#13d742) +D 4 (#56c211) +L 5 (#2f7662) +U 4 (#0e8e01) +L 3 (#46d980) +D 5 (#402761) +L 7 (#1e38e0) +D 8 (#402763) +R 3 (#3e28e0) +D 8 (#075c91) +R 3 (#4cd990) +D 2 (#1c83b1) +R 6 (#0df200) +U 6 (#4877c3) +R 2 (#0ab900) +U 4 (#5d14b3) +R 8 (#3f7a60) +D 5 (#061dd3) +R 6 (#265810) +U 3 (#4d7453) +R 4 (#113c80) +U 4 (#300853) +L 6 (#45ab00) +U 2 (#1ced03) +L 6 (#0eace0) +U 5 (#264f53) +R 12 (#41dc40) +U 3 (#199863) +R 5 (#3b2dc2) +U 10 (#0f4223) +R 4 (#482cf2) +D 5 (#1face3) +R 8 (#321642) +U 4 (#56f7a3) +R 4 (#321640) +U 10 (#2b6ef3) +R 5 (#325182) +D 5 (#4040a1) +R 5 (#02d5b2) +D 9 (#61d2d1) +R 8 (#3d5d32) +D 4 (#0f4221) +L 7 (#176402) +D 4 (#03b113) +L 8 (#01d860) +D 3 (#136273) +L 7 (#206090) +D 9 (#0ed183) +R 3 (#21eee0) +D 3 (#4b9c73) +R 4 (#27e9e2) +D 5 (#097b83) +R 5 (#27e9e0) +U 5 (#50f633) +R 5 (#16b820) +D 4 (#138331) +R 5 (#34b750) +D 8 (#5413f1) +R 7 (#134940) +D 7 (#4d4881) +L 6 (#53aa40) +D 7 (#00d6d1) +L 5 (#0a3520) +U 12 (#3c9a03) +L 3 (#4c3bd0) +U 5 (#3c9a01) +L 7 (#24a000) +D 10 (#0fb971) +R 5 (#4631b2) +D 3 (#3f5441) +L 8 (#01d1e0) +D 6 (#46ff21) +R 8 (#3ee970) +D 6 (#00a091) +L 5 (#51a350) +D 4 (#00a093) +L 8 (#46c180) +U 4 (#365041) +L 2 (#47fbe2) +U 4 (#226d01) +R 4 (#67b392) +U 10 (#226d03) +L 4 (#191b92) +U 4 (#416111) +L 2 (#105522) +U 7 (#5b2ce1) +L 7 (#4631b0) +D 8 (#334d41) +L 7 (#1e4350) +D 6 (#3021b1) +L 3 (#299130) +D 3 (#2b4123) +L 3 (#414a00) +U 5 (#2b4121) +L 8 (#0fafb0) +U 2 (#254f91) +L 4 (#3b0f82) +U 4 (#070d61) +L 4 (#0a6292) +U 6 (#070d63) +L 6 (#3518d2) +D 7 (#2b8b01) +L 7 (#1a4b62) +D 3 (#27a0c1) +L 5 (#66c7d2) +D 6 (#37f161) +R 3 (#482732) +D 5 (#1baa01) +R 9 (#45b112) +D 2 (#1baa03) +R 6 (#07fad2) +D 4 (#2f35a1) +R 5 (#4d0002) +D 6 (#1fa731) +L 8 (#696b42) +D 6 (#31c791) +L 9 (#08fd42) +D 2 (#0052f1) +L 3 (#065eb2) +D 5 (#2418b1) +L 5 (#3dbd92) +D 9 (#10bcf1) +L 5 (#09a212) +D 7 (#4ac071) +L 2 (#0c2842) +D 4 (#0299a1) +L 6 (#39aa72) +D 5 (#1eaff1) +L 3 (#302492) +U 4 (#4588d1) +L 8 (#13af62) +D 4 (#35a861) +L 7 (#4c5b02) +U 5 (#2dd353) +L 3 (#0077d2) +D 5 (#0ba793) +L 12 (#38e632) +D 5 (#476a13) +L 5 (#35f252) +U 7 (#5311a1) +L 2 (#047cf2) +U 8 (#267d63) +R 4 (#0affa2) +U 9 (#6a7183) +R 4 (#25b702) +U 7 (#0ab9d3) +L 11 (#1dd902) +U 2 (#0f0bd3) +R 11 (#17dea2) +U 6 (#0c2d03) +R 5 (#18de02) +D 11 (#52bf93) +R 4 (#18de00) +D 4 (#1199a3) +R 4 (#0ddee2) +U 3 (#063403) +R 6 (#46dcc2) +U 5 (#11b683) +R 7 (#0f98c2) +U 3 (#610763) +R 6 (#17f292) +U 6 (#312333) +R 4 (#2fd3e2) +U 4 (#083981) +L 6 (#4b2332) +U 5 (#083983) +L 7 (#161f42) +U 3 (#097733) +R 8 (#079502) +U 5 (#28a1b1) +R 5 (#60e982) +U 5 (#174aa1) +L 4 (#60e980) +U 7 (#2d1801) +L 5 (#3a7fc2) +U 6 (#267c01) +L 8 (#10ae32) +U 5 (#64c141) +L 3 (#39bea2) +U 4 (#0061e1) +L 2 (#03c742) +U 9 (#00fa21) +L 5 (#3f4a42) +D 13 (#0048e1) +L 3 (#21f600) +U 5 (#13e0d1) +L 5 (#57fcf0) +D 5 (#13e0d3) +L 9 (#4e0b20) +U 5 (#2fbea1) +L 10 (#1d7ee2) +D 6 (#5a3821) +L 4 (#187d12) +D 6 (#02da81) +L 5 (#39b022) +D 6 (#1e48d1) +L 5 (#0a01a2) +D 3 (#4f90e1) +L 7 (#0b91d2) +D 6 (#269903) +L 4 (#322902) +U 5 (#412583) +L 10 (#322900) +D 5 (#07dcc3) +L 4 (#416db2) +D 2 (#0118f3) +L 6 (#002942) +D 3 (#46c203) +R 10 (#1ec1c2) +D 7 (#0b31d1) +L 10 (#48d2b2) +D 6 (#499a71) +L 4 (#00dc22) +D 3 (#1adf01) +R 10 (#20c8b2) +D 8 (#2376b3) +L 10 (#34ebc2) +D 8 (#119bd3) +R 4 (#393252) +D 12 (#3a98c3) +L 3 (#6119f2) +D 10 (#22a903) +L 8 (#0f5442) +U 9 (#4466f1) +L 6 (#32ebf2) +U 6 (#291b41) +L 8 (#089fc2) +U 3 (#171d13) +L 6 (#4607a2) +U 6 (#3a53d3) +L 3 (#4607a0) +D 4 (#1c1153) +L 5 (#3aa062) +D 3 (#07ed63) +L 10 (#285362) +D 3 (#2033d3) +R 8 (#053532) +D 7 (#550e63) +R 7 (#233902) +D 7 (#159493) +L 3 (#428bc2) +D 3 (#4d6bc3) +R 10 (#434cf2) +D 2 (#220413) +R 5 (#3b8d52) +D 5 (#2d9a53) +L 6 (#24c242) +D 6 (#192663) +R 4 (#084250) +D 5 (#42e773) +L 4 (#580d40) +D 3 (#221923) +L 3 (#2c4a70) +U 5 (#1955e3) +L 2 (#22aa00) +U 9 (#325ae3) +L 4 (#45a220) +D 5 (#1b6af3) +L 5 (#2e7230) +U 7 (#47b843) +L 6 (#4786f0) +U 8 (#004a03) +L 8 (#25caa0) +D 4 (#2857e3) +L 6 (#2bc040) +D 7 (#216fc3) +L 5 (#28ac22) +D 4 (#0c70e1) +L 4 (#27c792) +D 9 (#0c70e3) +L 8 (#3ccc22) +U 10 (#236703) +L 5 (#248f22) +U 5 (#351f23) +L 8 (#1cdae2) +U 9 (#196223) +L 4 (#262512) +U 5 (#18a9e1) +L 6 (#374d42) +U 9 (#35d761) +L 3 (#1a1ad2) +U 2 (#357863) +L 5 (#124822) +U 5 (#02f933) +L 3 (#09dcf2) +U 3 (#51fde3) +L 8 (#09dcf0) +U 7 (#41c033) +L 6 (#1ddaf2) +U 7 (#15c193) +L 3 (#609412) +U 7 (#0a4e23) +L 8 (#2d99f2) +U 5 (#01ac13) diff --git a/aoc_puzzle_cache/day_19 b/aoc_puzzle_cache/day_19 new file mode 100644 index 0000000..17f111e --- /dev/null +++ b/aoc_puzzle_cache/day_19 @@ -0,0 +1,753 @@ +vhh{m<1253:R,R} +fz{x<607:hgz,A} +nt{s>1658:A,m>2167:R,x<1701:A,knr} +sk{m<662:R,R} +jmf{a>994:A,x>2248:A,s<202:R,A} +vkg{m>304:sv,m<201:lqf,gc} +pd{a>714:R,s<705:R,A} +drf{a<743:jhr,s<2525:bq,jtz} +dnc{x<2550:A,x<2871:A,s<3255:A,R} +sdd{m<3059:R,x>1469:grz,a>643:A,bcm} +bcd{s>1882:ctg,s<1552:sbv,mz} +qlc{m<1024:qvh,vx} +pgt{s<871:R,A} +ss{s<2152:R,jq} +xlv{m<863:gdq,jm} +vf{s>3033:R,s<2916:R,A} +qb{a>1142:lg,m>792:R,A} +hbj{s>1495:R,m<3875:R,R} +lb{a<977:gg,x>674:fxn,zzp} +jjp{a>1402:jzd,a<903:xf,bgp} +xz{s<2053:nn,m<819:jbc,m<1387:rrq,zl} +jl{s>2490:A,x<1531:A,A} +glc{s<861:A,m>625:R,A} +sz{s>3282:dk,x>3252:qjx,vfv} +bn{s>789:A,m>376:A,A} +bk{a<3606:lpk,a>3817:fv,mxd} +xcm{a<1300:A,A} +tqs{a>1227:lzv,s<1984:ql,btm} +qlh{s<1420:R,R} +jfg{m<757:A,a<1311:A,m<1268:A,R} +rpc{m<1054:R,A} +ctn{m>2884:npp,s>1983:R,m>2664:bbl,vq} +zkr{x<918:R,a<2882:A,A} +rfl{s>3583:R,a>353:R,A} +fxn{a<1011:A,m<634:kpz,m<1226:R,R} +lbs{x>2854:R,a>785:R,A} +zr{x<978:A,R} +zc{x<3640:R,m>631:R,A} +vqc{s<3350:R,R} +sq{m>1329:R,R} +hqz{m<3697:ngb,x>892:xhv,R} +gxx{m>968:sn,a<126:qm,x<3104:rtz,zm} +jfp{s<1597:R,R} +rgx{x>3360:hd,rdn} +zx{a>2698:xls,zp} +bhm{x>3186:A,s>2907:js,lt} +sn{a<138:qfp,s>1828:kkb,nc} +hnj{x>401:A,R} +hq{a<2585:vbp,x<1122:zkr,m<3897:A,lff} +plb{x<3671:A,a<921:R,A} +xvn{a<3364:A,R} +hpj{a>519:A,a>315:A,A} +hn{m<1115:A,x<2632:R,x>2764:R,A} +gg{x>897:zhq,s>1653:qs,R} +ck{m<2051:R,x<901:R,A} +qfd{s<3141:A,m>1998:A,m>1909:A,A} +vc{s<409:bv,xs} +rd{s>1755:nq,qrp} +gc{s<2493:mmv,m<256:nk,kdx} +td{x<2197:R,x>2608:A,A} +qpx{x>1028:A,R} +cb{m<785:cjn,s>2054:dnc,xm} +bgn{s>3068:A,R} +rh{s>2433:A,a<651:A,x<3472:R,A} +tdc{s<3243:R,a<2939:R,a>3382:R,A} +smk{x<3796:lq,x<3880:R,s<1792:zs,R} +mkn{a>2659:A,a>2628:A,a>2621:R,A} +tz{s>2615:R,R} +qqn{s>995:A,a>56:R,R} +jlq{s>1442:pnl,a<2722:mkn,s>645:dhd,mcg} +cjn{x>2243:R,m<709:R,x>1956:R,R} +zjf{s<2605:ts,x>3507:fr,kr} +vfv{a<444:zmb,R} +pht{s>1905:ck,m>2063:R,s>991:A,A} +hj{a>3369:R,x>255:A,A} +rlb{a<2239:R,x>3333:A,A} +cls{x>651:R,m<3664:A,R} +dh{m<3872:R,s>2643:A,s<1996:A,A} +zs{a>1056:A,R} +hd{x<3618:bf,s>1990:R,s<805:pb,A} +rch{x>274:R,x>136:R,bs} +xt{m>958:gp,x>1443:tqt,x>713:mh,A} +mv{s>754:R,m>997:R,s>359:A,R} +ht{x<2088:A,R} +ts{s<1514:R,a>1255:xc,s>2161:R,zc} +hlp{s<3320:R,m<2175:A,a<3517:dlb,qh} +bt{x<324:A,A} +vr{s<299:R,x<1347:A,A} +kkz{m>607:R,R} +gz{x>1177:A,s>3045:gcd,a<748:xj,lv} +ptn{a>1251:R,A} +crf{s>2533:bqq,m>3663:R,s<2209:A,A} +pdk{s>2676:vlq,m>386:jkj,dn} +ptb{s<557:A,x<970:R,A} +rsr{m>3073:jhn,rct} +bbc{a>3016:prh,a<2607:zhz,a>2815:fjx,jlq} +sbv{a<1373:A,x<1473:R,R} +jhn{s>2149:tdc,a<2796:cgr,A} +lt{x>2928:A,x<2780:R,A} +hlj{s<492:R,x>1589:A,R} +lbx{m>2195:rt,a>3305:xbd,pht} +zl{x<3098:vjg,s>3015:A,s>2644:R,A} +zmb{m<3304:R,A} +cv{a>2201:A,R} +bqf{x<1277:R,R} +rg{a<3585:ljp,m<2211:A,x<3630:A,R} +mg{s>2602:fn,A} +hc{m>464:A,R} +qj{m<1135:bqf,m>1244:R,sj} +mkg{s<2420:R,R} +kt{m>2215:R,x>3386:A,x<3107:R,R} +jpj{x>1211:A,x<1089:R,A} +sb{a>1109:A,m<1078:R,A} +sc{a>803:A,A} +dtt{m>334:R,R} +sj{m<1177:R,m>1213:R,A} +jv{s<2957:A,a<689:zz,xqx} +nz{a<3414:R,a>3627:A,R} +hm{m<1514:A,s<1415:A,x<439:A,A} +rdn{m<863:A,A} +nx{s>817:A,m>738:A,m<651:R,A} +zhq{s<1894:R,A} +gs{m<2619:xn,mf} +fhq{x>1057:vrs,s<2274:R,R} +vx{s>2163:dzp,m<1317:qj,m>1518:bnf,ffv} +kj{s<2020:jp,s>2358:pm,x<1307:jkp,hv} +tj{s>710:A,A} +dzp{a<1315:R,a>1344:A,x<1344:R,A} +ffd{x>853:A,s<3210:A,x<366:A,qv} +xvv{a<599:R,a>844:A,A} +vj{a>50:A,R} +mnq{a<1168:A,x<2692:A,s<612:A,A} +zzs{s>821:R,x>588:R,A} +lz{m>3378:A,s>1821:A,A} +fm{x>1486:R,m<2571:A,a>1309:R,A} +ll{s<553:R,R} +crl{m>2478:ctn,s<2428:rg,hlp} +tr{a>520:rgf,a>486:fnq,kk} +xh{m<3422:A,A} +ng{a<779:R,s<926:A,R} +kgp{a>1024:R,a<983:A,A} +hpl{s>904:A,a<1300:R,s>558:R,A} +lfr{s>877:hs,a>360:cbs,R} +lxk{s<851:prx,s>1176:tp,s>1014:R,dhp} +md{s<799:qt,x<620:vml,a>3124:nm,hq} +nc{x>2858:A,dj} +zm{m<352:vb,x>3441:cc,m>578:vvj,sl} +kdx{m>282:R,m>268:R,R} +jd{a<2886:R,A} +gp{x>1532:A,m>1022:A,m>999:A,A} +mc{a<869:R,x>960:R,x>546:R,R} +mqs{a>473:R,R} +rcq{m>3330:ffd,sdd} +xrq{m>785:A,x<416:hj,m>700:A,nz} +lhd{s<2000:A,x>376:R,R} +jf{s<1662:R,s>2786:lj,m<244:pvz,A} +vjg{x<2497:R,x<2749:A,m>1548:A,A} +pk{m<3621:R,A} +njz{s<1939:A,A} +zvq{m<230:R,A} +hhj{x>2664:R,x<2502:A,R} +vbp{x>1084:A,s>1181:A,R} +npt{a>1293:klr,mxh} +spt{a>406:R,A} +ffg{a>298:A,s>1625:A,R} +xf{a>559:fg,x<1682:pf,a<362:gxx,qqm} +czb{x<2169:vd,m>579:hsk,a<735:gm,jf} +cq{m>605:A,x<937:A,R} +mxd{s<2598:A,a<3726:xl,m<3903:A,bgn} +zh{x>1813:R,R} +srn{m<1000:fsx,R} +tb{x<2314:tts,s<1629:gzg,x>2644:kz,mg} +bdt{m>340:A,s>3192:R,A} +kp{x<931:kxg,x>1022:R,m>1257:mzl,sb} +zpt{m<699:A,a>1194:A,s>3079:R,A} +fk{m>759:R,s<803:A,qlh} +tcf{a<205:A,m>292:A,a>410:A,R} +grr{a>2840:A,s<3459:R,m>3809:R,A} +hg{s<2052:R,m<2485:R,m>2555:A,A} +nkb{s>1347:zr,x<734:gkt,s<583:pj,lfr} +mzl{a>1112:A,m<1575:A,x<965:A,R} +jbc{a<396:cmx,a>419:hc,R} +fx{a<3812:A,m>3924:R,m<3887:R,R} +pmb{a<3384:R,a>3487:R,s>3022:A,R} +gm{m<364:R,m<438:R,R} +bs{s>1109:R,A} +dc{x<1435:bqk,m>419:glc,m<242:hlj,hpl} +ctg{x<1283:A,a>1373:A,m<566:R,R} +bvp{s<2372:A,A} +zp{a>2648:A,A} +hr{x<2598:R,R} +mxh{m>1096:A,a>1255:R,vqc} +vg{s>1216:A,x>102:A,a>3158:R,R} +qv{x>561:R,m<3759:R,R} +jhr{a<662:ch,A} +smh{s<2163:A,x<1409:A,R} +kks{m<591:vkg,m<885:tg,s>1503:hvj,rr} +rtv{m>768:cdv,dtt} +bqq{m>3706:A,m>3640:R,R} +fck{a>3188:kps,A} +mkj{s<1719:A,s>3137:R,A} +cdv{m<1246:R,a<1145:A,hlx} +qp{a>3555:A,x<1837:A,x<2044:ndg,vl} +txd{s>1260:R,a>2410:A,R} +bd{a>322:A,x>1042:A,qtn} +qt{s<292:qds,m<3916:ptb,s<524:ns,scg} +zzc{s>3127:R,hn} +rnk{a<347:R,R} +kkb{a<234:hr,m>1487:bcr,gk} +rqd{a<1012:R,s>2272:A,s<804:R,R} +brn{a>1086:A,a<935:A,A} +mzb{a<185:R,m<2294:A,A} +rgb{s<1147:R,x<2534:A,A} +dd{x>667:bd,m>1103:jhc,x<384:qk,vn} +xdb{x>3728:A,a<1566:R,a<1677:R,A} +sdv{m<931:R,A} +pt{m<3631:R,R} +cx{a<1042:lb,s<1432:rtv,x<745:qvv,bvk} +prx{m<3771:A,s<430:R,x>860:R,R} +vp{s>3461:A,A} +rqj{a<2350:lls,m>2129:kt,a>2428:A,A} +sx{a<1357:kkz,fj} +dsk{s>1588:mhb,gd} +ns{a<3061:R,a>3401:R,s<433:A,A} +tg{a<3036:bz,s>2191:fcv,x>825:qp,xrq} +lbz{a<210:A,x<3371:R,A} +jb{x>3055:kd,m<1445:dm,lbs} +qfp{a<80:mq,x>2922:A,R} +zsv{a>2555:grr,A} +ljp{s>1204:A,a>3115:A,A} +bv{a<2458:R,m<3711:pt,m>3773:zhl,dkz} +slk{a<847:kn,m<2666:nt,x<1985:mt,cmg} +qgp{m>263:R,m>115:R,m<72:R,A} +gtb{a<1533:A,R} +vml{x<209:vg,m>3897:R,A} +bf{a>510:R,s>2009:A,R} +qm{m>606:xqg,zvq} +cl{s>1521:tz,rzj} +gr{x<1904:A,m>372:R,A} +zz{m<1467:A,A} +qvv{s>2314:fcd,qb} +zj{a>706:R,s<398:A,R} +fcv{a<3531:tf,m<761:A,vdq} +bgp{x>1724:rhh,a<1212:cx,x<1026:gtg,qlc} +mrk{a<3128:A,A} +dzr{a<3025:ctx,m>3794:bk,pcj} +qz{m<3561:nj,x>1738:mj,s<1525:lp,dzr} +rm{x>3171:R,x>2793:A,R} +fr{a>1217:jfg,m>1190:lm,R} +klr{x>863:sdv,R} +qcr{x>1610:R,m<2179:R,R} +kkj{s>2614:R,x<2010:A,s<2264:R,A} +lj{s>3244:A,m<382:A,R} +fhj{s<1885:A,a>824:A,m<558:R,R} +pf{m<624:xgc,s<2448:nkb,dd} +vn{m<929:R,a>324:mqs,A} +bq{m<1220:A,s>975:njz,A} +cxp{s<1911:R,A} +cbs{a<459:R,x>1291:R,m<1391:R,R} +vl{x>2211:R,a<3304:A,s<878:A,R} +lm{s>3149:A,R} +xl{s<3195:A,s<3503:A,R} +tk{x<220:bvp,m<802:bt,gqh} +bh{a>851:R,x<3238:A,m>3147:R,A} +jss{s>1416:snm,x>461:A,ph} +rk{m>322:A,A} +gqh{a<1303:ptn,a>1347:A,A} +rct{m>2928:R,A} +bz{x>1564:A,s<2021:A,x<851:A,R} +ckf{x<3624:A,x>3804:A,s>3001:A,R} +pkp{m<2215:R,m<2460:R,A} +vd{a<682:dx,s<1565:ng,s>2392:R,fhj} +rvs{a>1298:sx,xlv} +qjx{x>3570:xvv,s>2626:R,A} +rn{x>2616:R,s>3454:A,m<1978:R,A} +xbd{s<1931:R,a<3678:qfd,m>1997:A,R} +pm{s>2579:R,x<1132:A,s>2434:A,R} +zpx{m<3773:R,s>816:A,R} +tjp{x<3526:A,s<504:A,A} +bp{x>3649:R,m<1264:A,R} +bqk{m<375:R,R} +vrs{s<1841:R,x<1291:R,a>2903:R,A} +xqx{s>3582:R,A} +tf{a<3254:A,a<3353:A,x>1084:A,A} +mj{m<3800:mzg,lvz} +pnl{x<2813:R,A} +fxb{m<2661:R,x<2111:A,A} +ctx{s>3156:zsv,hth} +hsk{a>697:gq,x>2818:rh,sbz} +vdq{x<1197:R,m>835:A,a>3752:A,R} +rc{m>3702:R,R} +mmp{s>3446:R,m>1291:A,s>3242:A,R} +nj{x>1965:bbc,gfp} +jh{a<2753:svc,m>974:hjh,a<3488:R,R} +qds{x>878:A,m>3885:R,m>3846:R,R} +hrf{x<442:A,x<669:A,x>848:R,A} +glm{a>2786:hpn,ht} +gkt{s>885:R,a<349:rpc,rsx} +zt{s>1459:qtx,fkk} +tq{x<3396:R,s>1507:kgp,x<3427:jgt,sq} +xls{a>2741:R,a>2721:A,m<2100:R,R} +sl{x>3321:lbz,A} +pvz{m<108:A,s>2235:A,R} +drg{s<532:R,R} +lqf{s>1779:A,a<2366:A,x<1301:R,jx} +ph{a>1933:R,m<1747:R,R} +spb{s<896:A,m<660:R,s<1276:A,A} +vq{x>3791:R,m<2600:R,A} +dkz{m>3737:A,x<802:A,R} +jq{m<586:R,a<1256:A,a>1282:A,R} +mzg{s<1564:gnv,a>3269:crf,mqc} +vvj{x<3300:R,m>790:sh,R} +xqg{s>1662:xg,x<2774:vj,m>755:qqn,spb} +zhz{m<3445:lz,cxp} +dk{s>3679:hpj,a<567:R,m<3407:bh,rm} +xc{a>1310:A,x>3386:R,a<1287:R,R} +grz{a>678:A,m<3206:R,x>1960:R,A} +xn{a>564:pkp,a<217:zh,R} +rr{x<1350:hjg,x<1851:jh,mv} +dj{a>220:R,s<1186:A,R} +vhd{x>581:A,crm} +hlx{m<1509:A,A} +kxg{x>855:R,x<791:A,A} +tc{s<2245:R,mrk} +ldq{m>3720:lxk,a>3288:sr,ll} +gdq{s<1090:R,m>376:A,A} +xpz{a<3808:R,a>3872:A,R} +jhc{x>275:rnk,s<3378:A,m<1341:xzs,A} +xgc{s<2067:pcx,s>3152:zg,pdk} +vb{x<3555:R,x<3725:R,jnp} +snm{x<725:R,m<1713:A,x<879:A,R} +qg{m<687:mzm,x<3206:vhh,x<3319:rqd,tq} +lzv{a>1600:zt,qd} +qx{a<312:A,a>412:A,R} +fnq{a<503:R,a>510:sm,x>2449:A,pr} +vt{x>2628:kvq,dzs} +xks{m<3949:A,s<2950:R,R} +blv{a<3304:hrf,A} +np{a<775:A,dcb} +nk{x>863:R,s<3306:A,m<223:A,A} +sdp{x<1476:R,m>3890:R,a<3451:A,A} +nhl{m<2352:R,x>2923:dp,jk} +gnv{m>3707:rrv,m>3637:A,A} +jk{x>2815:A,m<2839:A,R} +gjq{m>2997:qr,R} +mf{s>433:pd,a>622:jmf,hck} +zbl{s<880:zj,R} +qtx{a<1800:fxb,x<1831:dhk,dnz} +hgz{a>1320:A,m>785:A,x<536:R,A} +cmg{x<2985:brn,x>3380:R,x>3241:zn,R} +dlb{x<3684:A,a>3277:R,m<2362:R,R} +cgr{s<1023:R,m<3177:A,m>3227:A,A} +hvj{s>2773:xt,kj} +xvh{m<735:A,m>1413:mkj,a>931:A,plb} +pb{x>3849:R,A} +fv{m<3880:A,x<619:jvb,s>2354:R,hjq} +rrq{x<2862:R,R} +jkp{x<816:R,x>1084:A,a<2935:A,R} +lkx{s>2236:R,x<2351:A,a>2888:A,A} +fg{m<1099:czb,x>2564:nhj,m>1409:qvt,drf} +dv{x<1599:R,m<1517:A,m<1555:R,A} +hb{x>884:A,a<875:A,m>1324:R,A} +npp{s<1927:R,m<3037:A,A} +hth{m<3818:cls,m>3880:R,a<2449:qbx,R} +db{a>172:R,a>87:A,R} +jn{m<1606:dv,R} +lpk{x<587:pmb,a<3274:dh,m<3889:R,xks} +qk{m>849:R,x<242:R,m<753:A,jln} +cd{a>3197:A,R} +pj{m<1029:lqj,m>1387:vr,R} +gkc{a<988:xvh,smk} +ghh{m<1731:A,m>1765:A,R} +rhk{x<3091:R,a>3563:xpz,R} +jtz{m<1294:qjb,a<848:sc,m<1356:hb,mc} +dn{s<2289:R,R} +lff{a<2877:A,a>2976:A,A} +rzj{m<1228:R,s<713:R,R} +ch{s<2218:A,R} +lk{x>1968:A,a>1002:R,x>1816:A,R} +dm{x<2832:A,a>753:A,A} +tts{a<1115:lk,A} +cxn{s>1043:txd,m>3720:zpx,A} +rt{m<2296:A,jl} +sr{a>3689:zzs,pk} +gd{x>2473:A,a>331:spt,db} +tqt{x>1763:R,a<2539:R,R} +xm{x<2530:R,a>175:R,R} +kd{s<708:A,a>788:R,s<1456:A,A} +mzm{s>2314:bdt,s<1540:A,x<3283:A,pg} +knr{s<1390:A,A} +rq{s<541:R,x<674:R,A} +qhs{m<2705:R,a>3248:R,R} +qqm{a<445:xz,x>2962:rgx,tr} +qtn{m<1288:A,x<908:R,a>152:A,R} +pcj{a>3615:vhd,hqz} +xhv{a>3291:R,m<3743:A,A} +nzd{m<3103:A,R} +dzs{m<2395:lbx,m<2840:pbz,x<1544:rsr,glm} +xcv{a>534:R,mzb} +svc{x>1649:R,a<2028:R,s<549:A,A} +bg{m>732:A,x<2224:R,A} +nb{a>2519:R,s>1151:R,a<1781:xdb,R} +xjs{s<3128:qcr,x<2113:xcv,x<2755:qvq,kg} +nck{a>2589:rv,nvd} +rgf{m<688:A,s>2496:bfp,A} +kz{m>1079:A,a>1082:zpt,R} +fsh{m>2354:mqg,s>1339:bhm,a>2579:zx,rqj} +ql{s<1034:gs,a>496:slk,dsk} +css{x>776:cxn,m<3711:rch,hnj} +qvq{x<2502:smc,m>2182:R,rn} +mqg{a>2380:R,s<2169:rlb,a<2245:cv,R} +mz{x<1370:R,s<1734:A,A} +bvk{x>1121:klk,m>764:kp,fp} +mcg{a<2768:R,m<3382:R,A} +jvb{a<3938:A,a>3977:A,m>3920:A,A} +hjg{s<649:fh,R} +rrv{m<3751:R,R} +sd{m>3738:R,R} +sv{m>492:gsq,x>1070:R,a>2386:A,mk} +fp{m>471:cq,R} +hjq{x>1174:A,A} +lq{x<3568:R,s>1780:R,m>696:A,R} +crm{a<3752:A,m>3702:R,m<3609:A,A} +pph{s>3586:A,A} +in{m<1799:jjp,bdz} +lvz{a>3026:rhk,hbj} +fkk{m<2575:pgt,x>1787:R,x<902:tj,R} +mk{m<406:R,R} +hck{m<3321:A,A} +btm{m<2792:xjs,x<2487:rcq,sz} +pbd{a>720:A,a<613:A,R} +bnf{x<1385:A,m>1657:ghh,A} +kr{x<3292:R,m>701:A,x<3394:R,qgp} +dhk{a<1975:R,m<2911:A,s>2707:A,R} +fcd{a<1130:R,s<3191:R,A} +xg{x>2740:A,m<754:R,a>47:A,A} +bcm{s<3214:R,x<764:R,A} +kpz{a>1024:R,a>1016:R,A} +rhn{x<963:R,s<2257:R,A} +bcr{s<2914:R,s>3566:A,a<296:A,R} +gcd{a>690:R,m>1502:R,a<637:R,R} +mq{a<48:A,R} +qh{x<3604:A,A} +jln{x>325:R,s>3443:R,a<210:A,R} +fh{a<2968:A,x>527:A,A} +rv{x<977:blv,tc} +kn{x<1718:zpb,x>2652:A,pbd} +lp{m>3819:md,a>2795:ldq,s<702:vc,css} +gfp{m>3428:zxd,kqq} +pbz{x<1645:fhq,m<2636:hg,x<2254:fck,pss} +lqj{x<1273:R,A} +hhg{x<448:A,x<622:R,R} +lls{m>1995:A,m<1923:A,R} +lv{s<2619:R,s>2894:R,R} +rhh{x<2975:tb,a>1112:zjf,x<3446:qg,gkc} +lr{s<2659:R,R} +scg{s<618:A,R} +fcl{m<651:A,x<3400:R,s<3038:bp,mmp} +kg{a>780:vp,R} +rtz{a>209:df,m>639:cb,mnj} +jx{m>122:R,A} +cr{a<1417:fm,gtb} +mhb{x>1851:R,qx} +hjh{x>1552:A,s<907:A,s>1256:A,R} +xzs{m<1253:R,A} +smc{a>464:R,A} +kvq{a<2814:fsh,x<3395:gvm,crl} +gtg{x<433:tk,x<769:bsc,s>2477:npt,rvs} +fsx{a<2621:A,a<3519:R,R} +nn{m<915:rk,A} +xj{s<2545:A,A} +ffv{m>1422:A,x<1363:jpj,m>1361:R,lmx} +bm{m>982:R,bn} +bfp{s>3213:R,R} +bdz{a<2137:tqs,m<3266:vt,qz} +sbz{a>644:R,A} +qrp{x>3233:nb,x>2759:bm,srn} +mqc{x>2751:R,s<2721:lkx,s<3203:vf,rc} +qvt{m>1626:np,s>2238:gz,x<907:tbj,zbl} +dcb{m>1700:A,R} +dp{x>3217:A,m>2662:A,x>3064:A,A} +cmx{x<3034:A,a<375:R,m>508:R,A} +gq{s<1476:A,a<786:R,a>840:R,R} +mmv{m<262:R,x>1311:A,x<449:R,A} +ndg{x<1971:R,a<3265:R,R} +zpb{x<745:R,R} +ngb{x<798:A,m<3645:R,s<2497:R,A} +pss{s>1672:cd,qhs} +jm{m<1177:A,A} +jp{m>961:A,s>1784:A,A} +bbl{m<2805:R,x>3597:R,m<2849:A,A} +qr{m>3524:R,R} +kps{a>3665:A,R} +dhp{a>3587:R,R} +sm{m<821:R,A} +dnz{x>2559:A,s>2597:A,A} +zg{a<203:pph,x<973:R,x<1362:rfl,A} +prh{s>2052:xvn,x<2877:rgb,s<1031:tjp,xh} +rj{m>3917:R,R} +qvh{s>2604:xcm,s<1359:dc,a<1332:ss,bcd} +qjb{s<3285:A,A} +df{x>2352:R,m<538:ffg,s>1850:kkj,nx} +dx{s>2250:A,R} +klk{s<2623:smh,a>1109:dvl,x>1432:sk,A} +vlq{m<400:R,R} +gk{a>283:R,x>2989:R,A} +kk{m<1175:bg,td} +gvm{s<1760:nhl,hp} +qs{s<2928:A,m>783:R,s<3382:A,R} +nvd{m<1411:cl,x>1123:jn,m<1659:lr,jss} +jkj{m>473:A,x<637:R,a>261:A,A} +kqq{a>3249:rhn,s<1835:R,A} +tbj{s<1246:A,s>1711:hhg,a<755:R,hm} +tp{a>3324:A,m<3763:R,a<3097:R,A} +pmr{s>1708:A,m<3460:A,A} +dhd{s>990:R,m<3426:R,R} +fjx{x<3231:pmr,s>2189:ckf,m<3402:R,jd} +mh{x>1109:R,R} +hpn{s>1992:nzd,A} +lg{x<274:R,R} +hv{s<2197:R,x<1939:R,R} +rsx{s<436:R,A} +sh{a>243:R,m<886:A,R} +nq{x>2986:fcl,zzc} +zxd{a<2811:A,mkg} +bsc{s<1824:fk,fz} +fj{x>928:R,m>1085:R,A} +zhl{m>3798:A,R} +fn{s<3288:R,x<2433:R,x>2525:A,R} +nhj{s<1867:jb,jv} +mnj{x>2286:hhj,s>1392:gr,R} +qbx{m>3852:R,A} +pg{m>390:A,R} +hs{s<1082:A,x>1329:R,a>320:A,A} +xs{m<3677:rq,m<3749:R,a<2400:drg,R} +pcx{s>1363:A,tcf} +lmx{m>1337:R,a<1276:A,R} +cc{m<734:A,R} +hp{s<3126:A,R} +mt{m<3297:jfp,sd} +nm{x>1332:sdp,a>3454:fx,a<3290:qpx,rj} +qd{x>2236:gjq,cr} +zn{m>3552:R,s>1435:A,s>1267:A,A} +gzg{s>1066:R,mnq} +zzp{m<1020:lhd,A} +jzd{x>2390:rd,m<1069:kks,nck} +pr{x>1956:R,s>1500:A,m>843:R,A} +dvl{s<3137:R,m>605:R,A} +js{m<2084:R,x<2870:R,R} +jgt{m<1321:R,x<3410:R,A} +jnp{a<233:A,s>2408:R,x<3862:R,R} +gsq{a>3028:A,a<1961:R,a>2431:A,A} + +{x=1637,m=1909,a=2036,s=1546} +{x=1501,m=118,a=732,s=800} +{x=3014,m=1069,a=3167,s=1318} +{x=435,m=1750,a=41,s=1563} +{x=477,m=185,a=1838,s=193} +{x=1347,m=244,a=2415,s=2626} +{x=578,m=553,a=2510,s=136} +{x=249,m=166,a=762,s=23} +{x=1172,m=489,a=2321,s=1040} +{x=23,m=3874,a=1228,s=980} +{x=2831,m=20,a=2235,s=205} +{x=2087,m=29,a=534,s=1455} +{x=2118,m=229,a=421,s=19} +{x=2014,m=2489,a=99,s=1385} +{x=1211,m=2963,a=1943,s=25} +{x=1342,m=1735,a=1478,s=6} +{x=1991,m=252,a=3415,s=83} +{x=246,m=151,a=321,s=1155} +{x=8,m=2267,a=3,s=2530} +{x=3159,m=558,a=805,s=1871} +{x=2923,m=465,a=1305,s=2882} +{x=1688,m=201,a=257,s=218} +{x=884,m=2083,a=864,s=119} +{x=143,m=2435,a=3623,s=2019} +{x=1667,m=481,a=1905,s=188} +{x=268,m=1858,a=1079,s=913} +{x=860,m=214,a=487,s=143} +{x=558,m=3198,a=2,s=42} +{x=2090,m=92,a=308,s=1373} +{x=767,m=2710,a=362,s=3} +{x=272,m=55,a=189,s=231} +{x=1359,m=87,a=90,s=11} +{x=124,m=42,a=3276,s=1632} +{x=2899,m=2442,a=220,s=3152} +{x=475,m=1049,a=1608,s=683} +{x=2820,m=385,a=266,s=1844} +{x=169,m=2898,a=150,s=179} +{x=44,m=224,a=1315,s=1709} +{x=35,m=45,a=99,s=87} +{x=12,m=338,a=823,s=301} +{x=436,m=2035,a=107,s=822} +{x=1512,m=38,a=469,s=549} +{x=1415,m=15,a=692,s=1507} +{x=1571,m=527,a=439,s=813} +{x=712,m=397,a=380,s=3369} +{x=68,m=958,a=350,s=1372} +{x=1040,m=1452,a=1976,s=526} +{x=2126,m=89,a=115,s=257} +{x=1320,m=534,a=2419,s=2958} +{x=1503,m=855,a=876,s=4} +{x=1448,m=793,a=253,s=1391} +{x=1590,m=569,a=110,s=1817} +{x=1880,m=936,a=322,s=252} +{x=13,m=520,a=1705,s=73} +{x=1668,m=2834,a=2717,s=1858} +{x=1186,m=1567,a=237,s=183} +{x=632,m=113,a=2854,s=342} +{x=1734,m=64,a=530,s=2831} +{x=1282,m=1059,a=213,s=14} +{x=42,m=34,a=2780,s=1054} +{x=662,m=824,a=441,s=39} +{x=728,m=881,a=1238,s=2748} +{x=732,m=742,a=978,s=2641} +{x=132,m=843,a=849,s=1306} +{x=1577,m=586,a=543,s=3118} +{x=4,m=490,a=114,s=990} +{x=3110,m=1960,a=703,s=608} +{x=808,m=1548,a=485,s=352} +{x=739,m=534,a=1613,s=51} +{x=1019,m=2004,a=1847,s=2174} +{x=2984,m=1413,a=169,s=2552} +{x=2762,m=23,a=1118,s=625} +{x=717,m=827,a=909,s=109} +{x=337,m=1378,a=1303,s=578} +{x=1069,m=1421,a=804,s=224} +{x=234,m=581,a=931,s=410} +{x=316,m=570,a=821,s=742} +{x=768,m=1915,a=737,s=281} +{x=9,m=80,a=1088,s=1711} +{x=101,m=37,a=719,s=2625} +{x=1354,m=15,a=395,s=833} +{x=504,m=2989,a=29,s=1744} +{x=1040,m=141,a=2771,s=186} +{x=396,m=947,a=473,s=1942} +{x=1364,m=173,a=15,s=2680} +{x=1823,m=872,a=600,s=367} +{x=717,m=1298,a=1419,s=685} +{x=2922,m=367,a=311,s=95} +{x=405,m=1169,a=272,s=574} +{x=2209,m=8,a=56,s=615} +{x=892,m=39,a=508,s=775} +{x=403,m=868,a=22,s=1485} +{x=17,m=834,a=191,s=612} +{x=30,m=718,a=659,s=199} +{x=1238,m=733,a=169,s=1232} +{x=538,m=66,a=434,s=1821} +{x=1328,m=2134,a=982,s=507} +{x=13,m=1934,a=498,s=3765} +{x=1806,m=445,a=551,s=70} +{x=178,m=540,a=1321,s=412} +{x=2363,m=1979,a=988,s=1604} +{x=61,m=52,a=2250,s=772} +{x=887,m=1865,a=2985,s=23} +{x=1805,m=1366,a=808,s=314} +{x=1542,m=649,a=1405,s=3211} +{x=1685,m=1393,a=359,s=1961} +{x=2482,m=1943,a=1461,s=2809} +{x=879,m=784,a=639,s=860} +{x=2039,m=105,a=659,s=812} +{x=626,m=1428,a=16,s=227} +{x=879,m=1455,a=2669,s=296} +{x=1373,m=1976,a=577,s=1808} +{x=387,m=2,a=2139,s=592} +{x=1127,m=443,a=1010,s=444} +{x=599,m=157,a=217,s=2041} +{x=1626,m=2839,a=388,s=365} +{x=648,m=884,a=2314,s=1900} +{x=1625,m=414,a=1168,s=723} +{x=1019,m=1323,a=715,s=784} +{x=2298,m=2611,a=513,s=383} +{x=222,m=189,a=150,s=1935} +{x=3557,m=122,a=320,s=2309} +{x=138,m=425,a=17,s=170} +{x=696,m=55,a=1910,s=869} +{x=571,m=5,a=1293,s=504} +{x=1024,m=492,a=2218,s=151} +{x=1412,m=1357,a=824,s=1767} +{x=501,m=752,a=243,s=488} +{x=506,m=2264,a=2049,s=1313} +{x=299,m=27,a=1827,s=188} +{x=9,m=2130,a=62,s=375} +{x=599,m=1968,a=1951,s=3584} +{x=162,m=1317,a=177,s=396} +{x=122,m=986,a=16,s=2061} +{x=281,m=79,a=1002,s=105} +{x=3,m=1686,a=830,s=1580} +{x=504,m=378,a=383,s=1149} +{x=763,m=37,a=364,s=808} +{x=146,m=142,a=189,s=1164} +{x=1365,m=1172,a=264,s=360} +{x=118,m=663,a=4,s=1059} +{x=1301,m=2155,a=1253,s=2866} +{x=1517,m=2329,a=366,s=95} +{x=339,m=1735,a=1898,s=1340} +{x=1261,m=2655,a=524,s=1216} +{x=79,m=3221,a=636,s=203} +{x=140,m=38,a=2493,s=733} +{x=1876,m=521,a=766,s=110} +{x=788,m=1326,a=257,s=527} +{x=556,m=58,a=384,s=123} +{x=1766,m=630,a=1054,s=17} +{x=419,m=851,a=190,s=122} +{x=180,m=2229,a=172,s=2138} +{x=29,m=73,a=394,s=53} +{x=785,m=2429,a=259,s=1174} +{x=2157,m=903,a=814,s=2252} +{x=311,m=441,a=158,s=1279} +{x=2662,m=1791,a=836,s=2162} +{x=513,m=536,a=331,s=1346} +{x=223,m=955,a=489,s=386} +{x=2017,m=362,a=931,s=1133} +{x=539,m=409,a=120,s=41} +{x=1686,m=587,a=1738,s=52} +{x=1056,m=552,a=59,s=146} +{x=2807,m=1088,a=88,s=2894} +{x=613,m=253,a=1044,s=1219} +{x=341,m=82,a=349,s=222} +{x=402,m=577,a=1059,s=739} +{x=217,m=3325,a=54,s=1457} +{x=144,m=82,a=951,s=1934} +{x=2731,m=33,a=2289,s=163} +{x=2556,m=873,a=281,s=2512} +{x=1805,m=124,a=2139,s=33} +{x=550,m=2530,a=2411,s=65} +{x=492,m=820,a=625,s=2324} +{x=864,m=377,a=1377,s=2620} +{x=2147,m=1173,a=151,s=116} +{x=201,m=143,a=2566,s=106} +{x=195,m=2048,a=305,s=2786} +{x=37,m=882,a=3088,s=100} +{x=421,m=277,a=2090,s=167} +{x=2032,m=1263,a=1288,s=658} +{x=2244,m=76,a=519,s=455} +{x=23,m=2544,a=699,s=22} +{x=2404,m=1411,a=1417,s=272} +{x=574,m=2109,a=507,s=865} +{x=354,m=471,a=38,s=1162} +{x=865,m=135,a=434,s=391} +{x=205,m=1244,a=942,s=961} +{x=791,m=2963,a=127,s=1359} +{x=3493,m=460,a=906,s=325} +{x=1312,m=237,a=393,s=7} +{x=819,m=1996,a=1259,s=387} +{x=133,m=911,a=161,s=362} +{x=534,m=1999,a=1237,s=114} +{x=62,m=70,a=1019,s=290} +{x=80,m=226,a=78,s=416} +{x=372,m=429,a=134,s=747} +{x=702,m=1387,a=3614,s=2657} +{x=1392,m=101,a=713,s=20} diff --git a/src/bin/day17.rs b/src/bin/day17.rs new file mode 100644 index 0000000..6cafd56 --- /dev/null +++ b/src/bin/day17.rs @@ -0,0 +1,259 @@ +use aoc23::prelude::*; +use derive_builder::Builder; +use grid::Grid; +use itertools::Itertools; +use pathfinding::prelude::dijkstra; +use rayon::prelude::*; +use std::{ + collections::{HashMap, HashSet}, + str::FromStr, + time::Instant, +}; + +static DAY: u8 = 17; +type Pos = (usize, usize); + +fn delta_pos(from: &Pos, to: &Pos) -> (isize, isize) { + return ( + to.0 as isize - from.0 as isize, + to.1 as isize - from.1 as isize, + ); +} + +fn grid(input: &str) -> Grid { + let mut grid = Grid::new(0, 0); + for line in input.lines() { + let weights = line + .trim() + .chars() + .map(|c| c.to_digit(10).expect("invalid weight") as usize) + .collect_vec(); + grid.push_row(weights); + } + grid +} + +struct Graph { + edges: HashMap>, +} + +impl Graph { + fn new_from_weighted_grid(weights: &Grid) -> Self { + let mut edges = HashMap::new(); + for r in 0..weights.rows() { + for c in 0..weights.cols() { + let pos = (r, c); + for (n_pos, n_weight) in weights.neighbors_orthogonal(pos) { + edges + .entry(pos) + .or_insert_with(|| HashMap::new()) + .insert(n_pos, *n_weight); + } + } + } + Self { edges } + } + + fn shortest_path_with_movement_limit( + &self, + start: Pos, + end: Pos, + move_limit_min: usize, + move_limit_max: usize, + ) -> usize { + // TODO min move limit? + let valid_move_in_limit = + |delta: (isize, isize), since: &Pos, predecessors: &HashMap>| { + let mut current = since; + let mut previous = vec![]; + for i in 0..move_limit_max { + if let Some(Some(prev)) = predecessors.get(current) { + let previous_movement = delta_pos(prev, current); + if previous_movement != delta { + // movement is different we are okay + break; + } else if i == (move_limit_max - 1) { + // movement is the same and we are not at the movement limit, break out of this + // path, not allowed + previous.push(*current); + return (false, previous); + } else { + // check the prior element + previous.push(*current); + current = prev; + } + } else { + // no path we are good + break; + } + } + (true, previous) + }; + + // based on https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm + let mut queue: HashMap = HashMap::new(); + let mut distances: HashMap = HashMap::new(); + let mut predecessors: HashMap> = HashMap::new(); + self.edges.iter().for_each(|(pos, _)| { + distances.insert(*pos, usize::MAX); + predecessors.insert(*pos, None); + queue.insert(*pos, 0); + }); + distances.insert(start, 0); + + // go from start node and check all other nodes + while queue.len() > 0 { + let ((current, backtrack), distance) = queue + .iter() + .map(|item| (item, distances.get(item.0).unwrap())) + .sorted_by(|(_, distance_a), (_, distance_b)| distance_a.cmp(distance_b)) + .next() + .unwrap(); + let current = *current; + let distance = *distance; + queue.remove(¤t); + + // Can terminate dijkstra early if we hit our end value. + if current == end { + break; + } + self.edges + .get(¤t) + .unwrap() + .iter() + .filter(|(neighbor, n_dist)| { + let movement = delta_pos(¤t, neighbor); + let in_queue = queue.contains_key(neighbor); + let is_not_backwards = { + let pred = predecessors.get(¤t).unwrap().unwrap(); + let pred_movement = delta_pos(&pred, ¤t); + + // not 180 degree turn + !(pred_movement.0 * -1 == movement.0 && pred_movement.1 * -1 == movement.1) + }; + let (valid_movement, _) = + valid_move_in_limit(movement, ¤t, &predecessors); + if in_queue && is_not_backwards && !valid_movement { + // if not valid movement in limits then backtrack and try those again ... todo + // TODO Do this thing? + } + return in_queue && valid_movement; + }) + .for_each(|(neighbor, n_dist)| { + let current_n_dist = *distances.get(neighbor).unwrap(); + let alt = distance + n_dist; + if alt < current_n_dist { + distances.insert(*neighbor, alt); + predecessors.insert(*neighbor, Some(current.clone())); + } + }); + } + *distances.get(&end).unwrap() + } +} + +fn part1(input: String) -> Result { + // parse + let start = Instant::now(); + let weights = grid(&input); + let graph = Graph::new_from_weighted_grid(&weights); + let root = (0, 0); + let goal = (weights.rows() - 1, weights.cols() - 1); + let parsed_time = start.elapsed(); + + // algo + let a_start = Instant::now(); + let answer = graph.shortest_path_with_movement_limit(root, goal, 1, 3); + let algo_time = a_start.elapsed(); + + // output + println!("part 1: {answer}\t[total: {:?}]", start.elapsed()); + println!("\tparse: {parsed_time:?}"); + println!("\talgo: {algo_time:?}"); + Ok(answer) +} + +fn part2(input: String) -> Result { + // parse + let start = Instant::now(); + let weights = grid(&input); + let graph = Graph::new_from_weighted_grid(&weights); + let root = (0, 0); + let goal = (weights.rows() - 1, weights.cols() - 1); + let parsed_time = start.elapsed(); + + // algo + let a_start = Instant::now(); + let mut answer = 0; + let algo_time = a_start.elapsed(); + + // output + println!("part 2: {answer}\t[total: {:?}]", start.elapsed()); + println!("\tparse: {parsed_time:?}"); + println!("\talgo: {algo_time:?}"); + Ok(answer) +} + +#[tokio::main] +async fn main() -> Result<()> { + println!("Day {DAY}"); + println!("====="); + let input = utils::aoc::get_puzzle_input(DAY).await?; + part1(input.clone())?; + part2(input.clone())?; + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_1() -> Result<()> { + assert_eq!( + part1( + "2413432311323 +3215453535623 +3255245654254 +3446585845452 +4546657867536 +1438598798454 +4457876987766 +3637877979653 +4654967986887 +4564679986453 +1224686865563 +2546548887735 +4322674655533" + .to_owned(), + )?, + 102 + ); + Ok(()) + } + + #[test] + #[ignore] + fn test_part_2() -> Result<()> { + assert_eq!( + part2( + "2413432311323 +3215453535623 +3255245654254 +3446585845452 +4546657867536 +1438598798454 +4457876987766 +3637877979653 +4654967986887 +4564679986453 +1224686865563 +2546548887735 +4322674655533" + .to_owned(), + )?, + 0 + ); + Ok(()) + } +} diff --git a/src/bin/day18.rs b/src/bin/day18.rs new file mode 100644 index 0000000..7bcca5e --- /dev/null +++ b/src/bin/day18.rs @@ -0,0 +1,180 @@ +use aoc23::prelude::*; +use derive_builder::Builder; +use geo::{Area, Coord, Coordinate, LineString, Polygon}; +use itertools::Itertools; +use pathfinding::num_traits::{Float, Signed}; +use rayon::prelude::*; +use std::{collections::HashSet, str::FromStr, time::Instant}; + +static DAY: u8 = 18; + +#[derive(Debug, Clone)] +struct DigCommand { + direction: char, + distance: i32, + color: String, +} + +#[derive(Debug, Clone)] +struct DigPlan { + commands: Vec, +} + +impl DigPlan { + fn new(s: &str) -> Result { + let commands = s + .lines() + .map(|line| { + let parts: Vec<&str> = line.split_whitespace().collect(); + if parts.len() != 3 { + return Err("Invalid command format".into()); + } + Ok(DigCommand { + direction: parts[0].chars().next().ok_or("Invalid direction")?, + distance: parts[1].parse()?, + color: parts[2].to_string(), + }) + }) + .collect::>>()?; + Ok(Self { commands }) + } + + fn calculate_poly(&self) -> geo::Polygon { + let mut position = (0, 0); + let mut visited: Vec<(i32, i32)> = vec![position]; + for command in &self.commands { + let (dx, dy) = match command.direction { + 'U' => (0, -1), + 'D' => (0, 1), + 'L' => (-1, 0), + 'R' => (1, 0), + _ => unreachable!(), + }; + for _ in 0..command.distance { + position.0 += dx; + position.1 += dy; + visited.push(position); + } + } + if *visited.last().unwrap() != *visited.first().unwrap() { + panic!("expected a closed loop") + } + if visited.iter().sorted_unstable().dedup().count() != visited.len() - 1 { + panic!("Loop intersected with itself more than the 1 allowed time for the start node"); + } + println!("visited {}: {visited:?}", visited.len()); + let coordinates: Vec> = visited + .into_iter() + .map(|(x, y)| Coordinate { + x: x as f64, + y: y as f64, + }) + .collect_vec(); + Polygon::new(LineString::from(coordinates), vec![]) + // visited.len() + } +} + +fn part1(input: String) -> Result { + println!("Input\n====\n{input}\n\n"); + + // parse + let start = Instant::now(); + let dig_plan = DigPlan::new(&input)?; + let parsed_time = start.elapsed(); + + // algo + let a_start = Instant::now(); + let polygon = dig_plan.calculate_poly(); + let answer = polygon.signed_area().abs(); + let algo_time = a_start.elapsed(); + + // output + println!("part 1: {answer}\t[total: {:?}]", start.elapsed()); + println!("\tparse: {parsed_time:?}"); + println!("\talgo: {algo_time:?}"); + Ok(answer as usize) +} + +fn part2(input: String) -> Result { + // parse + let start = Instant::now(); + let dig_plan = DigPlan::new(&input)?; + let parsed_time = start.elapsed(); + + // algo + let a_start = Instant::now(); + let mut answer = 0; + let algo_time = a_start.elapsed(); + + // output + println!("part 2: {answer}\t[total: {:?}]", start.elapsed()); + println!("\tparse: {parsed_time:?}"); + println!("\talgo: {algo_time:?}"); + Ok(answer) +} + +#[tokio::main] +async fn main() -> Result<()> { + println!("Day {DAY}"); + println!("====="); + let input = utils::aoc::get_puzzle_input(DAY).await?; + part1(input.clone())?; + part2(input.clone())?; + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_1() -> Result<()> { + assert_eq!( + part1( + "R 6 (#70c710) +D 5 (#0dc571) +L 2 (#5713f0) +D 2 (#d2c081) +R 2 (#59c680) +D 2 (#411b91) +L 5 (#8ceee2) +U 2 (#caa173) +L 1 (#1b58a2) +U 2 (#caa171) +R 2 (#7807d2) +U 3 (#a77fa3) +L 2 (#015232) +U 2 (#7a21e3)" + .to_owned(), + )?, + 62 + ); + Ok(()) + } + + #[test] + fn test_part_2() -> Result<()> { + assert_eq!( + part2( + "R 6 (#70c710) +D 5 (#0dc571) +L 2 (#5713f0) +D 2 (#d2c081) +R 2 (#59c680) +D 2 (#411b91) +L 5 (#8ceee2) +U 2 (#caa173) +L 1 (#1b58a2) +U 2 (#caa171) +R 2 (#7807d2) +U 3 (#a77fa3) +L 2 (#015232) +U 2 (#7a21e3)" + .to_owned(), + )?, + 0 + ); + Ok(()) + } +} diff --git a/src/bin/day19.rs b/src/bin/day19.rs new file mode 100644 index 0000000..4722627 --- /dev/null +++ b/src/bin/day19.rs @@ -0,0 +1,425 @@ +use aoc23::prelude::*; +use itertools::Itertools; +use regex::Regex; +use static_init::dynamic; +use std::{collections::HashMap, time::Instant}; + +static DAY: u8 = 19; +#[dynamic] +static RE_PARSE_PART: Regex = Regex::new(r"x=(?\d+).*m=(?\w+).*a=(?\d+).*s=(?\d+)") + .expect("re_parse_part invalid"); +#[dynamic] +static RE_PARSE_WORKFLOW: Regex = + Regex::new(r"^(?\w+)\{(?.*)}").expect("re_parse_workflow invalid"); + +#[derive(Debug, Clone)] +struct Part { + x: usize, + m: usize, + a: usize, + s: usize, +} + +impl Part { + fn new_from_line(line: &str) -> Self { + let re = RE_PARSE_PART.captures(line).expect("part does not match"); + Self { + x: re.name("x").unwrap().as_str().parse().unwrap(), + m: re.name("m").unwrap().as_str().parse().unwrap(), + a: re.name("a").unwrap().as_str().parse().unwrap(), + s: re.name("s").unwrap().as_str().parse().unwrap(), + } + } +} + +#[derive(Debug, Clone)] +enum PartCategory { + X, + M, + A, + S, +} + +impl PartCategory { + fn new_from_char(c: &char) -> Self { + match c { + 'x' => Self::X, + 'm' => Self::M, + 'a' => Self::A, + 's' => Self::S, + _ => panic!("wee woo"), + } + } + + fn value_of(&self, part: &Part) -> usize { + match self { + PartCategory::X => part.x, + PartCategory::M => part.m, + PartCategory::A => part.a, + PartCategory::S => part.s, + } + } +} + +#[derive(Debug, Clone)] +enum BasicFlowOp { + Accept, + Reject, + Route(String), +} + +impl BasicFlowOp { + fn new_from_line(line: &str) -> Self { + match line { + "A" => Self::Accept, + "R" => Self::Reject, + route => Self::Route(route.to_owned()), + } + } + + fn as_flow_op(&self) -> FlowOp { + match self { + BasicFlowOp::Accept => FlowOp::Accept, + BasicFlowOp::Reject => FlowOp::Reject, + BasicFlowOp::Route(to) => FlowOp::Route(to.to_owned()), + } + } + + fn part2_to(&self) -> String { + match self { + BasicFlowOp::Accept => "A".to_owned(), + BasicFlowOp::Reject => "R".to_owned(), + BasicFlowOp::Route(to) => to.to_owned(), + } + } +} + +#[derive(Debug, Clone)] +enum FlowOp { + LessThan(PartCategory, usize, BasicFlowOp), + GreaterThan(PartCategory, usize, BasicFlowOp), + Accept, + Reject, + Route(String), +} + +impl FlowOp { + fn new_from_line(line: &str) -> Self { + let split = line.split([':', ',', '>', '<']).collect_vec(); + if split.len() == 1 { + BasicFlowOp::new_from_line(split.get(0).unwrap()).as_flow_op() + } else { + if line.contains('>') { + Self::GreaterThan( + PartCategory::new_from_char(&split.get(0).unwrap().chars().next().unwrap()), + split.get(1).unwrap().parse().unwrap(), + BasicFlowOp::new_from_line(split.get(2).unwrap()), + ) + } else { + Self::LessThan( + PartCategory::new_from_char(&split.get(0).unwrap().chars().next().unwrap()), + split.get(1).unwrap().parse().unwrap(), + BasicFlowOp::new_from_line(split.get(2).unwrap()), + ) + } + } + } +} + +#[derive(Debug, Clone)] +struct Workflow { + name: String, + flow: Vec, +} + +impl Workflow { + fn new_from_line(line: &str) -> Self { + let re = RE_PARSE_WORKFLOW + .captures(line) + .expect("workflow does not match"); + Self { + name: re.name("name").unwrap().as_str().to_owned(), + flow: re + .name("ops") + .unwrap() + .as_str() + .split(',') + .map(FlowOp::new_from_line) + .collect(), + } + } +} + +fn parse_system(input: &str) -> (HashMap, Vec) { + let split = input.split("\n\n").collect_vec(); + ( + split + .get(0) + .unwrap() + .lines() + .map(Workflow::new_from_line) + .map(|w| (w.name.clone(), w)) + .collect(), + split + .get(1) + .unwrap() + .lines() + .map(Part::new_from_line) + .collect(), + ) +} + +fn check_part_accepted(part: &Part, workflows: &HashMap) -> bool { + let mut current_workflow = workflows.get("in"); + 'flows: while let Some(workflow) = current_workflow { + current_workflow = None; + for flow_op in workflow.flow.iter() { + let basic_op = match flow_op { + FlowOp::LessThan(cat, num, bop) => { + if cat.value_of(part) < *num { + bop.as_flow_op() + } else { + continue; + } + } + FlowOp::GreaterThan(cat, num, bop) => { + if cat.value_of(part) > *num { + bop.as_flow_op() + } else { + continue; + } + } + op => op.clone(), + }; + match basic_op { + FlowOp::Accept => return true, + FlowOp::Reject => return false, + FlowOp::Route(to) => { + current_workflow = workflows.get(&to); + continue 'flows; + } + _ => panic!("not basic"), + } + } + } + panic!("why are we here?") +} + +fn part1(input: String) -> Result { + // parse + let start = Instant::now(); + let (workflows, parts) = parse_system(&input); + let parsed_time = start.elapsed(); + + // algo + let a_start = Instant::now(); + let answer = parts + .iter() + .filter_map(|p| check_part_accepted(p, &workflows).then(|| p.x + p.m + p.a + p.s)) + .sum(); + let algo_time = a_start.elapsed(); + + // output + println!("part 1: {answer}\t[total: {:?}]", start.elapsed()); + println!("\tparse: {parsed_time:?}"); + println!("\talgo: {algo_time:?}"); + Ok(answer) +} + +fn part2(input: String) -> Result { + // parse + let start = Instant::now(); + let (workflows, _) = parse_system(&input); + let parsed_time = start.elapsed(); + + // algo + let a_start = Instant::now(); + + // LOL yeah right... no no no to brute force on this one + // + // ``` + // let bar = ProgressBar::new(4000 * 4000 * 4000 * 4000); + // let answer = iproduct!(1..=4000usize, 1..=4000usize, 1..=4000usize, 1..=4000usize) + // .par_bridge() + // .map(|(x, m, a, s)| { + // bar.inc(1); + // Part { x, m, a, s } + // }) + // .filter(|part| check_part_accepted(part, &workflows)) + // .count(); + // bar.finish(); + // ``` + // + // Honestly copied someone else's approach for this one... + // https://github.com/klimesf/advent-of-code/blob/master/src/y2023/day19.rs + let mut stack: Vec<( + (usize, usize), + (usize, usize), + (usize, usize), + (usize, usize), + String, + usize, + )> = vec![( + (1, 4000), + (1, 4000), + (1, 4000), + (1, 4000), + "in".to_owned(), + 0, + )]; + let mut accepted: Vec<( + (usize, usize), + (usize, usize), + (usize, usize), + (usize, usize), + )> = vec![]; + while let Some(range) = stack.pop() { + let (x, m, a, s, wf_key, rule_key) = range; + if wf_key == "A" { + accepted.push((x, m, a, s)); + continue; + } else if wf_key == "R" { + continue; + } + + // Invalid bounds check + if x.0 > x.1 || m.0 > m.1 || a.0 > a.1 || s.0 > s.1 { + continue; + } + let workflow = workflows.get(&wf_key).unwrap(); + let flow_op = &workflow.flow[rule_key]; + match flow_op { + FlowOp::Accept => { + accepted.push((x, m, a, s)); + continue; + } + FlowOp::Reject => { + continue; + } + FlowOp::Route(new_wf_key) => { + stack.push((x, m, a, s, new_wf_key.to_owned(), 0)); + continue; + } + FlowOp::GreaterThan(category, number, flow_op) => match category { + PartCategory::X => { + stack.push(((number + 1, x.1), m, a, s, flow_op.part2_to(), 0)); + stack.push(((x.0, *number), m, a, s, wf_key, rule_key + 1)); + } + PartCategory::M => { + stack.push((x, (number + 1, m.1), a, s, flow_op.part2_to(), 0)); + stack.push((x, (m.0, *number), a, s, wf_key, rule_key + 1)); + } + PartCategory::A => { + stack.push((x, m, (number + 1, a.1), s, flow_op.part2_to(), 0)); + stack.push((x, m, (a.0, *number), s, wf_key, rule_key + 1)); + } + PartCategory::S => { + stack.push((x, m, a, (number + 1, s.1), flow_op.part2_to(), 0)); + stack.push((x, m, a, (s.0, *number), wf_key, rule_key + 1)); + } + }, + FlowOp::LessThan(category, number, flow_op) => match category { + PartCategory::X => { + stack.push(((x.0, number - 1), m, a, s, flow_op.part2_to(), 0)); + stack.push(((*number, x.1), m, a, s, wf_key, rule_key + 1)); + } + PartCategory::M => { + stack.push((x, (m.0, number - 1), a, s, flow_op.part2_to(), 0)); + stack.push((x, (*number, m.1), a, s, wf_key, rule_key + 1)); + } + PartCategory::A => { + stack.push((x, m, (a.0, number - 1), s, flow_op.part2_to(), 0)); + stack.push((x, m, (*number, a.1), s, wf_key, rule_key + 1)); + } + PartCategory::S => { + stack.push((x, m, a, (s.0, number - 1), flow_op.part2_to(), 0)); + stack.push((x, m, a, (*number, s.1), wf_key, rule_key + 1)); + } + }, + } + } + let answer = accepted + .iter() + .map(|(x, m, a, s)| (x.1 - x.0 + 1) * (m.1 - m.0 + 1) * (a.1 - a.0 + 1) * (s.1 - s.0 + 1)) + .sum(); + let algo_time = a_start.elapsed(); + + // output + println!("part 2: {answer}\t[total: {:?}]", start.elapsed()); + println!("\tparse: {parsed_time:?}"); + println!("\talgo: {algo_time:?}"); + Ok(answer) +} + +#[tokio::main] +async fn main() -> Result<()> { + println!("Day {DAY}"); + println!("====="); + let input = utils::aoc::get_puzzle_input(DAY).await?; + part1(input.clone())?; + part2(input.clone())?; + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_1() -> Result<()> { + assert_eq!( + part1( + "px{a<2006:qkq,m>2090:A,rfg} +pv{a>1716:R,A} +lnx{m>1548:A,A} +rfg{s<537:gd,x>2440:R,A} +qs{s>3448:A,lnx} +qkq{x<1416:A,crn} +crn{x>2662:A,R} +in{s<1351:px,qqz} +qqz{s>2770:qs,m<1801:hdj,R} +gd{a>3333:R,R} +hdj{m>838:A,pv} + +{x=787,m=2655,a=1222,s=2876} +{x=1679,m=44,a=2067,s=496} +{x=2036,m=264,a=79,s=2244} +{x=2461,m=1339,a=466,s=291} +{x=2127,m=1623,a=2188,s=1013} +" + .to_owned(), + )?, + 19114 + ); + Ok(()) + } + + #[test] + fn test_part_2() -> Result<()> { + assert_eq!( + part2( + "px{a<2006:qkq,m>2090:A,rfg} +pv{a>1716:R,A} +lnx{m>1548:A,A} +rfg{s<537:gd,x>2440:R,A} +qs{s>3448:A,lnx} +qkq{x<1416:A,crn} +crn{x>2662:A,R} +in{s<1351:px,qqz} +qqz{s>2770:qs,m<1801:hdj,R} +gd{a>3333:R,R} +hdj{m>838:A,pv} + +{x=787,m=2655,a=1222,s=2876} +{x=1679,m=44,a=2067,s=496} +{x=2036,m=264,a=79,s=2244} +{x=2461,m=1339,a=466,s=291} +{x=2127,m=1623,a=2188,s=1013} +" + .to_owned(), + )?, + 167409079868000 + ); + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 7b0ac73..8fa2897 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,5 +7,6 @@ pub mod prelude { self, common::{BoxE, Result, SError, SResult}, config::get_config, + grid::GridExtras, }; } diff --git a/src/utils/grid.rs b/src/utils/grid.rs new file mode 100644 index 0000000..a99a263 --- /dev/null +++ b/src/utils/grid.rs @@ -0,0 +1,36 @@ +use super::math::orthogonal_u_bounded; +use grid::Grid; +use std::collections::HashMap; + +pub trait GridExtras { + fn neighbors_all(&self, pos: (usize, usize)) -> HashMap<(usize, usize), &T>; + fn neighbors_orthogonal(&self, pos: (usize, usize)) -> HashMap<(usize, usize), &T>; +} + +impl GridExtras for Grid { + fn neighbors_all(&self, pos: (usize, usize)) -> HashMap<(usize, usize), &T> { + let mut n = HashMap::new(); + for r in -1..=1 { + for c in -1..=1 { + // skip self + if r == 0 && c == 0 { + continue; + } + if let Some(neighbor) = pos.0.checked_add_signed(r).zip(pos.1.checked_add_signed(c)) + { + if let Some(t) = self.get(neighbor.0, neighbor.1) { + n.insert(neighbor, t); + } + } + } + } + n + } + + fn neighbors_orthogonal(&self, pos: (usize, usize)) -> HashMap<(usize, usize), &T> { + orthogonal_u_bounded(pos) + .into_iter() + .filter_map(|(pos, _delta)| self.get(pos.0, pos.1).map(|t| (pos, t))) + .collect() + } +} diff --git a/src/utils/math.rs b/src/utils/math.rs index 2d19ad7..3e0e98d 100644 --- a/src/utils/math.rs +++ b/src/utils/math.rs @@ -13,3 +13,15 @@ fn lcm(a: u64, b: u64) -> u64 { pub fn find_lcm(numbers: &[u64]) -> u64 { numbers.iter().cloned().fold(1, |acc, num| lcm(acc, num)) } + +pub fn orthogonal_u_bounded(root: (usize, usize)) -> Vec<((usize, usize), (isize, isize))> { + [(0, 1), (0, -1), (1, 0), (-1, 0)] + .into_iter() + .filter_map(|delta| { + root.0 + .checked_add_signed(delta.0) + .zip(root.1.checked_add_signed(delta.1)) + .map(|new_pos| (new_pos, delta)) + }) + .collect() +} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index fe592e9..a79d248 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,4 +1,5 @@ pub mod aoc; pub mod common; pub mod config; +pub mod grid; pub mod math;