diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 70c3a52..c742183 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,7 @@ jobs: - day14 - day15 - day16 + - day17 if: github.ref == 'refs/heads/main' needs: [ omnilint, rust ] runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index 04c58c7..1f17046 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -305,6 +305,16 @@ dependencies = [ "sqrid 0.0.22", ] +[[package]] +name = "day17" +version = "0.1.0" +dependencies = [ + "aoc", + "color-eyre", + "nom", + "sqrid 0.0.23", +] + [[package]] name = "either" version = "1.9.0" @@ -591,6 +601,12 @@ version = "0.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92bfab44888e2fc47178beb71e1ad84bd2a97361a6943019a8602f214ae4c126" +[[package]] +name = "sqrid" +version = "0.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfa174f70d3ecc8171ef9784a74bac0689af9ce41b01d00732a132465f985f3a" + [[package]] name = "thread_local" version = "1.1.7" diff --git a/Cargo.toml b/Cargo.toml index 0ca9120..ebeb64c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,5 +19,6 @@ members = [ "day14", "day15", "day16", + "day17", ] diff --git a/day17/Cargo.toml b/day17/Cargo.toml new file mode 100644 index 0000000..0f2ffc2 --- /dev/null +++ b/day17/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day17" +version = "0.1.0" +edition = "2021" + +[dependencies] +aoc = { path = "../aoc" } +color-eyre = "0.6.2" +nom = "7.1.3" +sqrid = "0.0.23" diff --git a/day17/input.txt b/day17/input.txt new file mode 100644 index 0000000..6824593 --- /dev/null +++ b/day17/input.txt @@ -0,0 +1,141 @@ +254545423522512316212556253616363513772141313221545471254114147264424775176363626536175157455663165613357671775164445244216541344224114542344 +533452113115412653651553516416232127214166214317514455351614641141236617167665233527546442625276752577617466577336424322646262231446111144425 +135223415615563231323231631656125335714773573576246732746745541561135132324317211351214754425424555723117216545245636642222333655651232132214 +254514441564255232145241511133165752167771521753343715772756432253647154642554713554563355766641373746115135522333426462664663461423646223235 +351454665562364455226454356212766653112425341262125335512356363211226287385563251253177571267315415213544161327673313214462514126333212423453 +142246664642244451624526247142361645735453775417152333723617647845664387756367448536336644541271773174452213775263671531453615154462223366112 +234614663315515452314154332235475355353252236514713716284377334443826532736253584237345381255567623516474742711453757243642213265515423515654 +341415145132424415135171175316346667331757375331766555738578477774757448364832544422676862755676212543315646645222753161625126452523113541122 +514424253414521545614753737424526633671526324347357734336458867653772252744722454643438554262541677662327161642345725555356121115242533223542 +226253446611463255167533626342363657677374171738225782677262856266527854458572853583764746446324346615137724514333431776544164621236656165114 +145131565236453513461764773227763621537662272434323375458855876657545663237648454328527876725447848767277533767657721421713536646231244432216 +521642654632522515664626161141611621231628354274724333558234537782267783367473437223685223543686262783362771211623565652165473325416515555263 +556641543613232652536741622552116625512568264546727737583244263554587537537662678253456742473664873384283514254173313544461554423151663425556 +656663356151332273366541727264353545667374235435864287458757326227758475346247257686684334885647482482245547632665352121325536213354452416533 +634512454624115547431313414613722652383636765372882883366348437732384323278664455783843628442355742554564465346354567167262445547665323344232 +552611514336612154142625117557433375378425825375242226764854325684334732888784542752683834666783685574222565652576637523564116154716321161141 +365132355314111576462374456316431634552483366284383635822657874584676265645323448632776643362348568456728664563575525263563133433631663242535 +443353626224551755717513721451288567574763568222633783643685524376234755372537354267264624888852773544542228645872264456517763416276166122644 +546256252564672236236552153733455254528377242775768372763823276684693464468776437844553262267683582678575245674756613647521127142432144632215 +315526321547462144773765153337255274354337462735445624445466383977693565893833845985527533247548478622862763575383155226551425151727534162661 +461332421635435145255536655645574236874266222524252656339678797458586585593694873993654848722833437427665776426654624152451353276555425416322 +112665662525551752247326335786887778463283722525383587746466487765696763885685576399479948867258556274747656434533673752472417374316611336634 +135233125241216737752565185556872455564534877752699993868984845538877568495897888598759577488873235574664253682456786342313316662723562561646 +254463315741332653426735254758482773562877673383776469878698649765349889754999637656468888899384364465476248627475443745325451542725555351663 +233145623563772623744613787477748746777638328988795465954977897933945365734344768474749864344567362578587875463573635542161436674237666311556 +611341462257347643642486675636725654634746533689336599446453756747834587757994847684677333393356967284657532256654324338433215456413126476555 +135534326736134513631732833462636628836333956437886793677744947449669737979694669998333766686859654773726728567566574556251214734375423751424 +431214412715622567757756345467764365347777558763643855956694935698469678877494787763768493733674884443236877368272273782345553623533763674623 +116134125522224614377484225772787844748976568693846868745938998934855384449735569644983393669643644456968226474328277677237214521111146272626 +133741741356772131356432858874564823668944753395883989449367344765375899769666565399999644987496964548858547535763233748364311775422516372632 +216152243563772744232385773545463852393685958435536938678338983969433467446633536648536363935634938844975754437665683838846776524661766276755 +351114247647475328564744632464332264465975687853933335867447767557558954599943748457365563878565397636556977566423847844437733464125375723367 +252764352577543267858275868526582363665664449564765459494676644888685485697477856858995484583849338385959933846687232244534668271267551456635 +143473741322417378563686235568276497487935383595433338939986689778487454944744869849488847949897783699886378553266585276538427644435621325532 +516251433616557525366838654764769587739675745668677746995857464478476854658568584475799857534378939387663536893573447326284682485267677243751 +251334514137664844477882638876667949975753885679648474748946674584599468676758866674874647338489583544845699546387748328387455866425711313524 +772525315111155754382382383734279356776555763585834485898849645648476557866749548777465795574559385757638555993368255283323646557723743126772 +253643544564632436783873282278573968953984483595344466896949668858696654868575785457796974445483585673469773958483476327256533346673462712713 +733277224344144248873862233567373365475349954846779555967796499965999846959557487556985988665844457349875394995654648865334427355861154635412 +636264632621583825666275452298944663395765359564959685644478687465589655579687764946549679446759495686357446864986342285687258447374551755724 +724547361565235744446657247453849868873879733876558885467455979468449965444564757857785578549759968544587698855846683734334622525254357771775 +732557665673552428363243653958484564559858948649888744646488549579975975768745797447564854869499884738334633646654477233345673235762632215344 +774752663562483732465386538635996879977733865795997998875466769577875644797459589464597646584899675458338366866483989582448748455822243151246 +411665456546286223763778674879867475377394554655479584676798596674545754966779755977695997985889479777746534556555783257322542343746567142517 +137276323652746846223222536837376549637699754777488899794449578779785444978749755449685696569997866988747393763643565973462238238442634766435 +615133552688355746344323835795589986944356547485455896589679749865577888997585558955777769469868688768778557349777395678876782322826674556723 +252247341864774777685227549535647573349749879588999967555585878759757869957878756559644756866947456948647479643455933645645737266255435535764 +771623612332465783837439948899457399349988649774458956764695766978665859657789789795557994547445775679874646873685944948326565862547676245277 +613655333847265823625389473875694696786587987877596764589558785577758589567795768559945986477667899997675554986983398396644352477267227724173 +267661646282668475357285557885747755555464859456765984848578777766577665779767597658685576567897457578959653485545734487477624645856325266134 +272771427565563578677459444539548374445586455986757469686698765598887855689996785778769666857574995544746585735835775878338566647878865443125 +153761636834668736767283987643943864955469995545966786677866766898576976966756976669957576944577697797554684875439458675865836485626267432776 +565252163472676334338848589345653748989497665977959795865755895659756685578865969898959796986757964984796764439455797557752684282534427543764 +162554524656736635257356536974459888998766854494769595555875667676595879765998699898567786845787659794869789636497956363668378627323258434537 +437323732375438283655797893467735384757646684959766595698897597866676966555695786558958998967468677895464798738374758493597888273243634437674 +431114432368552523855368657737348567869888684495948699989966588688599959856598775659886877777898895969495998653999849684674352742865578252625 +245472324233433487346694478994665746479978596855699987858869968869795788877777566957688695655588759644694457794779795395657273577887836572524 +375361786657433337339964386443994574946678984849885885575985789596979555686588875588879958789967775456456595685884743885455335478445724442576 +147541387287675887648767336459569647484856584567658655796598776565588669777899867586755867888654677864884754474664997587797744884374726756343 +447213233563253243569674674336345855666677955656978579898866685779987999976687876689655675697996446776577755998944963373993924485355843263551 +245218547687755566557778738354377855646676945596587698969755898968768898666967689888785565677688679598554948779498998694368948246787727427246 +343617624422586383786688898394997696589596545656865878567598588969798897696789786867559795857967574666769979854363994584693966624237652524716 +231425723876652286975543695577759995595897765478789979768956557968768877778998797856788979578998557445578676654557399976776832854875446247557 +625556284868288454983784964476697559948954564586589696679796878666989779877866679986668866668566645595747879687947695586947775374322642878322 +156146832258255432458947545356837847449966787459976698758779996796966866868788699776777799877988698779869594595736964846486875236422687843267 +537132356747867744478567387765597947759557879576767855658758798969787678788866978888688695876955874869794955455968364797967543583827566436113 +215277882446884575599798746754358958787698465587698878695699898696969969978878866799666677656595578854944887679878648439855384764577782677472 +572243238758557877796598635583357488875758656588878795686558769777689698787878966977769865666768867677484755846638568335755335637525436678641 +625587646276377473475779348643896454579574749799967665976787787889686767687876888889897878557985878547959458558795434659397874525442888584712 +247446432646434382868376863634546746586846685766756558596568778999979768778866699967858788786975959756479986494948494775655857557687486434644 +773766547238826726463969645844975886769945674657759767668889879896866978669787776697686796786985965646649748455787973967485375642554663345623 +477585657762358245859789656645346946549989849968798586955999668668886998698797989976768696669878956668576774878677669875363956473258256367853 +731742222468642757883745748355869465568848679575666696696899778888699898796886797769996996658985754496684979588468658548767488532655864885357 +222627427442288825493398333668345694474754474895568565689766986989967978987698877696695895589966976978857784477964457563636894886337554663841 +127676342755528422486969663898869745988654876889989997657589997768776779678669779878657898586758957496756946585489588456749537673845682448874 +767364683384848854686796834755667944794748566656688598598789969667988678667676696679599765789789795758998647559597675959776742882785785583622 +266285824483343868367895999563557754489557546989796865767569698689996778686988699889767696997656569996574574788499887949668845428242676436631 +363376784623884458985576633965839975967667678958777656768796966676779777769668988667689895958668774468867668788779965858365896272258473266317 +421425825236487287653948559453474859449468785496697988658775669676798868996988798779896878676897544449879899899667884894369646752227665558222 +464376424462732757588898678438854975696867767457885576667758586886896677689978697779679789668687967679847496796998698897363677842867357482677 +342323862228867662654379635757678798686954454657578658666778889797677979896898877787677588685777585685854685789788797488346338723822887372276 +121744855476373453468873748874557456654696754969857987558595887699667868868677776659866898567859767997567594679458493799958544383228864857613 +322125545224373885464886554985846856859484588959689775855768986969697876688878686556588768789888789896994895483344897939386983354353552577742 +271658372642832452457358777569887877989986754677677789996858598796899789779686595958669795569965994665447858684457944784938978583458462552552 +641645448662448344347353565876938578475856974847989996686657665798656969769559575785888977877574446447958969453434767386537926686625342726634 +515311785753244647633397337378395976686968998694988979686979778987599975789566887865585667895855545746896588634756373873665864733352684661165 +255167575547342866247933996736367486544666947745858665856556985899977986688596989769799578986986698676744474534997737364537454486658846834311 +362536326232566576446746995593894488496757744585488856558697675885755579796758785878777667695856789676468789898463657633683733233264732587126 +123324677238446272763453865997368984496648979499844869868799885697757568897989977557788785885776866754686485388984575768395836435558722345541 +567637732363852656368838938853379897685695446549886489679677586968999858996596988778888767984857459977894965337458538678587856653732726644766 +667114633586287562352678834346975683975576656794488575555898599977589887888775559797879578786887755568965998468443868879776864556322473426525 +365777365425763485238464387896587896765546475646788548958886677885658597979966576957878884766699564648566953549753878765555376253367872275372 +125636262336746625622774989745866963485554776968596465689969866678878768586675865795597549686745948884747488389483399539353686655342686417577 +565373265287287822632867535934756449566896956897485664967796599575687978678595689676658754646976897547676888974665989454968247857235746337546 +137135378688633466375483946973995668979978664689845889959777897677565956789766565688998464599659969667896577633988584355886327445722575632134 +367415223675632423837474388577986458389856676479949465755485799898759988658567965765778486674855595884773884455746457557337222758427765111725 +554156423286742666756734395656589558468666785966897894588475475978788778879885965485477494947744946685749568738935567472744637347744546135226 +467535647442762235654586987334968594755589998795568989756665645659679595775775549968958969544597944774836543567657453643527652576628444754222 +715661266683664243832642638877786357659467488567568948966456968599899855558596884498499888768569755596749554933598554968355748852285515232431 +733737753566854865562844546775894967385985985888998884474648656794477857674877796998785567755956688897577475836354495563325578567552545425431 +616557333747364423647883284568365547486566765648857554557879699796684446888675595859679758798757798469895547899489466454826778346633367366432 +161223734636768673637866782355337664586386844948474678856467847759585495655999556697859978559795656465755779597567342667252654356425642173755 +267233466246785482838728678837484589465769379498885745579769875896557686645885777559447744867575649848873337668798745833564724654586337512752 +512657132725686225663255343374585488759568945498565474956546798446788455747875489555796985988454746587935775653865667526555223583742326747634 +463664325673225527354268843369948336637949644375987746568465878576587856684879986598786747647988878784493498385669758856288772737844724726522 +147261644236455458675434343522659487537985498756638954697979955949946477595765687496655488494565687368685874675353478646824248662311124644757 +235466422427374533484435576385439579634897653674898568688466668456474897794654489646684554888495996773374795389535862282435878682625552556446 +552242311325336542483476375583858786335387355788843865568684858479948946787685487568866974699468376794849854856685375473373223353164246133166 +362677454434271774573762554837383498369949369636765565385648946997887569494478468996788566895938853597955845587423865252527768234262441246142 +536173574513675133258526577873255637389973376369953458753647498857875956899474759567573877677587488553369999892628433842534676512622127122531 +637631573724432748432437764733287585997776379936393988843499866657766788674775868633784745597934334477873857948443275246324536643456157262456 +461541116163747278678366826383332283765859687689456455689449898458755495876977837757856563373373468953444864425685553552236275724711456332373 +243274171123754547322472287558234885695894378773759946694943795937963984389379474666934986637454353574537324736724838628682523754756235135315 +436436261575137526376785224342326623385698995368955743636557393774885467765869875458745355948839984438498756283338723453886366625111626217671 +141473366515245222772845486686445354334674368366785935378446654395939936565637843849388666799394577766372745225766833675453257127257536732613 +516465155123271531274447452768223285477283987676998874975368939599843853389747449337863484696495673346458435673546663756643561253154163313236 +446326644417224563247773472342224443754538993387674339755637338854768864674883857796746356598846335887733354844584364254563547555376731735456 +366247216327377322361168233454324525348863543355485954643975869873968677346355377585669388496955345742866533852844824623354277222417313111156 +434123555542312511163517833648362352488575235369995776755585699333733695385439667554497733546567345745658845754877537527217532514144471726261 +166122575724634164124232252762873874437644865666744448555468635488739979676393897649489356856885662565265885566876762886334355222337646252342 +324366211123366625753252777628768273457857246768236778348466774869949884436373636645669543743755343456445256588775727661511432152136637552335 +245165254321554455575662411554755266363678884822678743937457456639536386849336843888674497373887474536673275842357346126426637654732213261253 +163626634515363543456225535285227634885543228256585737995383549358858574438838845665989832738537362766576334283866816452771161267127525535646 +342261631266347675565117163776555558863254672888683676643778344884494984455374343988558388275775858332635758373838467224254743621451546165241 +445352242247642176777524536164884836687356855747763653864273526445456798793498467636855572877835278885388784582426347166535466256656636215365 +653142656543425673274431414174728786532865685645574547356352426454255782427327447828327236732428887658868758573444261435361141545243165516556 +154443456225122337552663416435723834558363854544288555244784856437763643248767325726585468275478332335657578364275546613357416414434354424656 +461664156313615615364313164121123523434352684483484477524738283838444663867522486543267628682255626652383822725453627715773131252545412155146 +234225625243114322145774737133426774885886425555732366348478562475768844555835523634235643462475742523882362423641644573135672261255554216631 +321632351264235736336267235717526176255288567854486653484486326333562658654638232587526358323787555835543837372746665355273664312331641251623 +444552416433662166222616345253112323336768356344744237272544563665224858655556582227523435885376562325577736613717361635635444666643331321355 +662556564614223243443575527336167552565727264446446243485425347768686783546227676554733742755326738363523764641717252661565745312132115341231 +523146333614322456556543652174753561371714543785333355586628473626222765378783782383482222348534863417432317133762526256436633642534656656133 +562251232313145521664171776721673314115262542344326882363644337537742478663582558362655227628444674253554764453573257745273356226363333514213 +524563135516511124416437745632122541162667514417356254865387235542335353228576658266835538338854167375473452337137532155155364115664466654212 +321455552525442321662275747746353334427353373527655687873235528635443754478577475574473766845262431371244654261735563533645334643354236231336 +332466416313163212655261555271647637413633666741257312483736456854572224385576674457752873346566562577734573254272747266353665455636155644432 +524331655121364664621411543733362356224413124512576162353712284535845448557873758473675333767653167454143666512615444341563241143623443612412 +113326413461512563415365243276133125133422536666627771544216723446528465276233477613326374732461635743155175426777474532253551335521545143221 +454515535421615341242652144244447135356476667457644547713351231373262635337324427616737757265431174775345223135331314331156122262116251454121 +131543522463532261366356425213735631521656774152356636617225146264656753414613613461267535535461676371723457717676355423142566624555345153555 diff --git a/day17/src/bin/day17a.rs b/day17/src/bin/day17a.rs new file mode 100644 index 0000000..d7e8f00 --- /dev/null +++ b/day17/src/bin/day17a.rs @@ -0,0 +1,86 @@ +// Copyright (C) 2023 Leandro Lisboa Penz +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. + +use day17::*; + +use std::cmp::Reverse; +use std::collections::BinaryHeap; +use std::collections::HashMap; +use std::collections::HashSet; + +pub type Heat = u32; + +#[derive(Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +struct State { + pub pos: Pos, + pub lastdir: Option, + pub dircount: usize, +} + +fn process(size: u16, bufin: impl BufRead) -> Result { + let input = parser::parse(bufin)?; + let gheat = Grid::try_from(input)?; + let mut frontier = BinaryHeap::<(Reverse, State)>::default(); + frontier.push((Reverse(0), State::default())); + let mut visited = HashSet::::default(); + let mut heatacummap = HashMap::::default(); + heatacummap.insert(State::default(), 0); + let goal = Pos::try_from((size - 1, size - 1)).unwrap(); + while let Some((_priority, st)) = frontier.pop() { + let pos = st.pos; + if visited.contains(&st) { + continue; + } + let heatacum = heatacummap[&st]; + if pos == goal { + return Ok(heatacum); + } + for dir in Dir::iter::() { + if st.lastdir == Some(-dir) || (st.lastdir == Some(dir) && st.dircount >= 3) { + // Gets wobbly + continue; + } + let Ok(newpos) = pos + dir else { continue }; + let t = newpos.tuple(); + if t.0 >= size || t.1 >= size { + continue; + } + let heatacum = heatacum + gheat[newpos]; + let dircount = if Some(dir) == st.lastdir { + st.dircount + 1 + } else { + 1 + }; + let newst = State { + pos: newpos, + lastdir: Some(dir), + dircount, + }; + let e = heatacummap.entry(newst).or_insert(heatacum); + if heatacum < *e { + *e = heatacum; + } + if visited.contains(&newst) { + continue; + } + let dist = Pos::manhattan(&newpos, &goal) as u32; + let priority = Reverse(heatacum + dist); + frontier.push((priority, newst)); + } + visited.insert(st); + } + unreachable!(); +} + +#[test] +fn test() -> Result<()> { + let start = std::time::Instant::now(); + assert_eq!(process(13, EXAMPLE.as_bytes())?, 102); + println!("Elapsed: {}", elapsed(&start)); + Ok(()) +} + +fn main() -> Result<()> { + do_main(|| process(141, stdin().lock())) +} diff --git a/day17/src/lib.rs b/day17/src/lib.rs new file mode 100644 index 0000000..5e247d8 --- /dev/null +++ b/day17/src/lib.rs @@ -0,0 +1,74 @@ +// Copyright (C) 2023 Leandro Lisboa Penz +// This file is subject to the terms and conditions defined in +// file 'LICENSE', which is part of this source code package. + +pub use aoc::*; + +pub const EXAMPLE: &str = "2413432311323 +3215453535623 +3255245654254 +3446585845452 +4546657867536 +1438598798454 +4457876987766 +3637877979653 +4654967986887 +4564679986453 +1224686865563 +2546548887735 +4322674655533 +"; + +pub type Cell = u32; + +pub mod parser { + use aoc::parser::*; + + use super::*; + + fn cell(input: &str) -> IResult<&str, Cell> { + let (input, val) = character::one_of("0123456789")(input)?; + Ok((input, val.to_digit(10).unwrap())) + } + + fn line(input: &str) -> IResult<&str, Vec> { + let (input, cells) = multi::many1(cell)(input)?; + let (input, _) = character::newline(input)?; + Ok((input, cells)) + } + + pub fn parse(mut bufin: impl BufRead) -> Result>> { + aoc::parse_with!(multi::many1(line), bufin) + } +} + +#[test] +fn test() -> Result<()> { + let input = parser::parse(EXAMPLE.as_bytes())?; + assert_eq!(input.len(), 13); + assert_eq!(input[0].len(), 13); + Ok(()) +} + +pub use sqrid::Dir; +pub type Sqrid = sqrid::sqrid_create!(141, 141, false); +// pub type Sqrid = sqrid::sqrid_create!(13, 13, false); +pub type Pos = sqrid::pos_create!(Sqrid); +pub type Grid = sqrid::grid_create!(Sqrid, u32); + +pub type Griddir = sqrid::grid_create!(Sqrid, String); + +pub fn path_debug(_size: u16, gheat: &Grid, path: &[Dir]) { + let mut gheatacum = Grid::default(); + let mut pos = Pos::TOP_LEFT; + let mut heat = 0; + let mut gdir = Griddir::default(); + for dir in path { + gdir[pos] = dir.name_utf8().to_string(); + pos = (pos + dir).unwrap(); + heat += gheat[pos]; + gheatacum[pos] = heat; + } + eprintln!("{:1}", gdir); + eprintln!("{:>4}", gheatacum); +}