From 921c4af1a8d2328e197ae27d11bfa818c5ab0a83 Mon Sep 17 00:00:00 2001 From: Adrian O'Grady Date: Sun, 17 Dec 2023 12:36:35 +0000 Subject: [PATCH] Advent 2023, day 17 --- Advent2018/Day22.cs | 3 +- Advent2023/Data/Day17.txt | 141 ++++++++++++++++++++++++++++ Advent2023/Data/Day17_Test.txt | 13 +++ Advent2023/Day17.cs | 164 +++++++++++++++++++++++++++++++++ Utils/Alogrithms/Astar.cs | 13 ++- 5 files changed, 330 insertions(+), 4 deletions(-) create mode 100644 Advent2023/Data/Day17.txt create mode 100644 Advent2023/Data/Day17_Test.txt create mode 100644 Advent2023/Day17.cs diff --git a/Advent2018/Day22.cs b/Advent2018/Day22.cs index 8cab25e..638ad4e 100644 --- a/Advent2018/Day22.cs +++ b/Advent2018/Day22.cs @@ -126,7 +126,8 @@ public int GetMoveCost((int x, int y, Item item) from, (int x, int y, Item item) public int GetScore((int x, int y, Item item) from, (int x, int y, Item item) to) { - return Math.Abs(from.x - to.x) + Math.Abs(from.y - to.y); + var distance = Math.Abs(from.x - to.x) + Math.Abs(from.y - to.y); + return from.item == to.item ? distance : distance + 1; } } diff --git a/Advent2023/Data/Day17.txt b/Advent2023/Data/Day17.txt new file mode 100644 index 0000000..9772097 --- /dev/null +++ b/Advent2023/Data/Day17.txt @@ -0,0 +1,141 @@ +431114422322445512245245532134313232636612544162142561414163541452144463223212251244641442632436654566415136452143421153322431233344411412412 +313213143443131512214423511341421416622423263326465261144141265644361634326352656536124636432545116464261421641551311135455524543124431413341 +343234141123241523524422135133426632622431625463161556246113254572135132267617762364261122613151554612514415416411412354354524224522521423442 +312134421154452535544142351256416532451556441314536612461531633743467175474616777315235631414541645246535266631435542211554242213115424211114 +414432253551344224415344213231324556454124544512644615162567254166226176612276217176553436446624332311145421653565156344251343451133551543412 +442233354442534254253451555152166433611613254335463165475543514271322363123246362166517442671213343342136321445525311511123331454124331453112 +413444414325555422435255455325324633314232261446521241376421511423736745717227316326712712244347426151324653556543262163541251351511351444333 +222151554145121154224252552442615366466331643774314756635612131736244251625367743135141721433763357351311323133355633634541534222341422244241 +122115414125443244313466121446234356544423241152624773654514551526357426223414576345213211135611127124664423513342253326535113114242343213434 +443122315152354542153346165234143163164367522574736351524643311612446441114571244256415376217271514311353311331355625664116132225211251411533 +324152321123154131322146365263165666425462515234337742226473546433137737562146173744224642672145156526512141363161616331545265245355142413344 +321411313422232214645635645142642112567673217267117261167635727154556343757227255716522425277541623144753575551526215634415556513215255243312 +525334233513531365662625465441213162263111341254411441252254375427623145212175253142521657612417746456435353163311623611555326612111121541344 +353425523512455644344324164152456545434217223325246727725743273773667213547654354166472513353521113264654525124211454352262254665452342343252 +425255245335445456232262425545427754276446511645125333333626573486832687864444663811414726776445716633531634332523152362252611564545334242544 +513335323445444125166446363234251116476251314567272615724248742545327678484386484432886563741655525415244741352673243632315651114312543255252 +132551444145645156233252441636126623546374637173714437223846668774877255734325268367882424713433331623446125522642335514345252633421523244152 +332212213316416634141341153546751166356674344637567227865388465353556637554342684366384254262255561551625626712623223232355524434443455253353 +432225514153622132146655553735657453466613677255723726384258483688885863225536867357463352434681666265727767132731644362341242324165415451233 +332423524314511561431355614716357715235447652174767342784763547224287263835872455245885258433278753532413572644477217755314136455513444352135 +532515221624141115254564131726367237247272336258533842624566525685753863285676446626833757242656585255246136171221454276352153651256112241345 +534225351314561311612616664335175422726114646252675474456364732886372252844673373285487525455484327452162133753772321761111455254445626412311 +251434245361315165313312752341534417375225428356788857853846486643736452637533874453425588867338728556525263636751277737322625523633663154545 +222554334314612556625645713217375562424752757585625742866546783658527473458865882432552765584326884764323546325612612417411343421545612252115 +544556512422243256153651265227637612152847558825856854853576563665648738463758363558354552853722623886754221237771625674473346224234246535122 +234152341111462452615647744464661147536633473377477782632732672652467555856698624265353477223775348862874787176526555526625154333462111531425 +132145542122121216515224462375623324824488826673864654643424477674888454974367884373264543523278476678554534555571276544676346135624453154545 +545623544324311255357166235367743542775265656253232436286447555975984587389888469434962665852354222486665582267265546756133335654615245541652 +211364554653222364464532347222711368877788286366484726675597893438735779568736956498636584252354338383223244723146352625663413313355114233663 +455156254445432274373541237112117443735883376733246757384946766868765475989393495684594484426828785286862434826155445555741722343444641536434 +346634316413143673222564735653554475456772643564533995389563833964435739669844788646486337556886367655524773883327271131731123155435423214531 +213121314542423345432251212412668744457485786244994589688596536569655649885496848686749447674856382422888244877556231366577111713253222253641 +663146362543152366412135575727624384567447654435538668739467473483447877655888463769369638353548942682352222844832471113564235267113355424414 +632153226646135617234532116428737832756665682933565984935976855777959436674364485868758664863879693233452832662622333621652264712335523656356 +342651116244542774471456276425377274675722376344775458936488669384856994346349843753865634667966859378686556525686257641757467645152664516426 +636424144366153336361214164454348236632385494765599333333457887548567544434893536775358745646765973835377642767733468544256225541711431261423 +545534211331674745437214653765426684648379853663577785346977778776676745674878547656378748379699765453225573228463764434576445274142122514325 +143625361526125111775374266233437633283485734599344376985734665579668474959747489864933945849483756388383773324567528621141563617252566213523 +663562656133334146473412727286725237846894646749899343836395398759455479447565787777348774676845956869948347375352485344626414253647736664316 +453422456617462454247653372473242353866664439838389578497777586868789967864489877996558878755889838739355533375288468758547124122615623156241 +142553566176445553315648526423727223846386736966666449889768698854855645746879999977759475444946539894949955538224525782135356423141576112122 +544462515126773552144334423783673436884587448447483676487597856994748587594687548575647867777849379737844782824866446558444322523515313462422 +635256125524574773631872526784725657744739743998336367855454968755758564475955757999956569947775637968545487383552686827646273217311356214336 +122243622164214456417424824655525275853358373587674997698964469769498868865545579768564899968556896857899694766335635528743413317531421224631 +221365116134414544276563766326262897455534453333987489648947667694788444988956676659976684574493465744986978972484825478565113334177146312351 +644311656555334572423772788735823733537859754883579677569697877748945745987788747664957449485468576934358693688563367256384347322423616523142 +416416217741256442382722888444433359865798378986968888996546456847749869546756754876896957897448663964945695378572446347264647722572126331324 +233532377236715613677634523253578998389837999399567987589554957667685458547597879479874647479497754848573564995633338275244557415251312376452 +433516155665755361683668277556258643344365865467986588744564846658554985595759955645967786845997997438673656736362338837564373151274645256363 +213643153463327572667476774467778787596438974595884477676946456878679956759697954595759646966489946468959659889924826328822227726736414112552 +341613351362724355354537282855997364794374589564564456946847858999689996797688997794879889955587955598858484579484775522875627444673347253565 +321566464537661677672334563856697338486736667769574799996747976685858979559767878865567895969796767598975985948455673275322275535414113646234 +244147776231772713328634833324784764896746474955466598667697877597565769755587965857598495456644978665366355764339624773248526147635632615514 +462216665122334446483372866254564785563438995665684776776769566765875699769559776599886879648988847846964933467355687326424276347737573152642 +522571664563626468237483877565635963964454646486748769575966977577589796857578858759788597549449584757586964677464936863385727231411313743213 +631346627146765283447578382485633897474574544848667856667966957669599997997999569767868745759448959855947353454637725457536237663314423311155 +662247343243472256276573646563733358949698997597844865565555875887997898787599877678679595969898968577575348664947772283735244353141177375121 +534232327474574422554272626833353553656757597758488995879789757555778996968995889786886789457797697665665489595754882787845556681467622641543 +646461522532574546563865427464998389397854976788568559985585766576595679858557978999559856695768887669579653784564663554447768763213727251326 +266556642535437255675564453365934559893978765959695487796796559556796579659656757956757988566865558749593477438893743284588245275362174342653 +334335131153763627543665453475764658736679549587599698688988559568869866666599959569877989695466885666848344449558538282432246666531443514112 +236621273133763456773826337789547973757546875594666586856899989865877666786865657595765886959768548455894645699973858757665283726136262325274 +541545771347433836736258678483575955786996794964879777556877969986998987766678978566895567766967578989794597373467335763432452228233424633475 +622457112521726566566573844599593973838755889698848559589669597868668767786798976698957695655846464987566743439775695667686483753311631454636 +354146646267553386588727836447558693556786655688588968997856877999697679868698876596689865798699587699699656593393965356277325648441665466334 +155515554211168237687428584845858466686649458789896656568556579678768668787899686666559797687584785896559636433869759822832422744413261445664 +535622173631463558466774473534878584458685974648677769788668966896689988866797668988799558986687987746655763679533769336753657443344613325644 +262617331243366478277343554336856758385577766494766667777579887676797789798966899687696676896895549886456889333385735333858434547675155145165 +555265372227444563665467334466366898878495777985456889756778786867788899986776678669998656788668778555646543388897646542627664426756247314154 +631136767447758386688466775579868893695859546957959989966579697888696688996867987987989759579657785475468845886339477445583864588141363744455 +261557125745573686634843247637485549385694795585967657768857879966769768788698976867876597888788569656546533847493667536652887238232343147337 +216562775136636777667277248767535447864649789449758758998975669799976697867667778785967779966694458889695485436796445947544726724737523524644 +225721545322147224758583764485633754846875548499896788587696966667889689798666969977686756668897455896776976634447947435626667645456757561621 +111264431524128658778788763543376757479549974659765697958658668878786896966689876979757566789866898646568885699859534472673486676762451517235 +331132723647157327478367436575973465857676788884487798568596968898887676887978978969957967565778576469454477559737846572355767772133315132351 +516532353764615886733222276737483744654975657867967655686795587696699768899989978958555896865564456498445595495835453855462436588375436152175 +467561372562174675823866589657549793855798495946557687656677867776999687986796776987598579569867484669666747538345573444264868375326261414665 +366442236533312823553736859375669369889569998978597676686878958887887877669999768957588677575589998988758437857695737578836583887741552456645 +234757127363562274567233379476564798699859847949997879967576598996897896998699989979699568588595599447577644893493478537535737848517466352666 +135311222577145388747828426755463577837444576659869685776775977979987778768799695557667959557797968789474774856338899762448655838727766774237 +413224161434642424265375529697355589674857686864979778856986989799898678766688986695955795867466767849758863963764695564235687477325717466675 +225232476535663374532845786464645797596568557757994586576856955956769868888689559765869968664896965467696376958566835222574268532375243174412 +526512271342171564657772533438888485383587579477784565957876556598988768668667889855557565977787689774593374598638496757378763365223445675345 +146132415152121385847363253335848399978475555694955696675567659869779758588977895876667699556589474796844883878539564477626446451171375437632 +315153472222442376233847626839544975855568948789859578555759588565889598569955996859598977678887994866498455639745568273656622783557735255322 +553673644143261627285643824853555987339456879957586986676875565987765685987877757976976899656699654678547786797958957657245484645374315644371 +445347145751316545325387854637445865484869874477679679785587778976577857756988787965876987645985795844975957884967853835486378364355733632336 +345463226571127676267734388774956844696995554995665959955669988665969865857699559878598868477677899956439738768759972575262568835362232631746 +355317432745651347248386322793467438583849599946848688456996965898579879556876665985867579655864588946486773584775325554784732521515271543731 +236234531221155748546382578775453874769957984566696877755687956968889975899565998675879989787747575495639859936376628478638886865546712533743 +652221667273131317337533372445885393364599946448989549549576959985867987679877878665669786986987576963449365965663763654786388476537723325154 +611431741155544277826356835478353479464596476779576944675865959967977668588896897975656989647447497496367599598435385223345284165111677641244 +412124117166352321383764367272494375979958864945864567977898575786565666567968569669785656947964964499546788978884755232446742274322712522156 +225565373253766544852253825637259756967849664554584588547674675498779588799967855878677896566565684875989694697838837368265332116431321543156 +235634312556641442754846635875678735345769344565944967964646848479854877998994868974499969498769497978955795387522885374454572416555243324213 +555362256231213473238747762856327563453577388399764648764868997959686546764685557687447444844464786483533593487226222256754743434212672234635 +423156373325315554636477633345333399897855653755496496854756974685586665667485884745947948946878845338898845745886845566774345215533524164515 +614344321361436132154573328772223655967565779836864978649658657948564475778554774697974766579693695988583565482545673832537373776174116162231 +333122235372626566416267383232738378346657966798837446747878556968449996696788996867675475954457839549936558825575677775223112673123326526652 +461342341114423634672322626368825885445957669747949969666788664989959754658687464565679566645987489889734546534587367325641213542444375316163 +224366663123165764724834447237352687557657575959468359985486568969855545894666874468746696438955644854745977727757375852765352557235424561121 +142622164615364162536726635855386326438538443745455778774456765666868448846997499786894546683684949354874777827826726865237137761167453644646 +651526455521342351137747782388462723586836533395498793867557556944894744896859844897954973734465997633794935748265373334465673365526135544233 +154554314351525145722765533658625342336468384883996376554689646777557985664495576655474779894637567533666354673355768355671132276471516435216 +636316252145767412231777656226463885363794744537568874449759788484677668966786866633854485864763984777642283346668252845411713417757232452114 +436265612462362776563726283657272233783767346337458565587737844749477785847676755884787677776344583659357374266654875864672112324673432144455 +615131325247766122356631752384232562285769494746593963974586663839539633396469747937875747979545836585726748665725233225441366275467531142461 +243355412153263351241141564668874782243286539647758336933389873449774569566835384363993839365387483595853763432372236132313523755424452532322 +225561661622622271137323765644235235576456684549947569387993345789393964769479344433895367594378639768745433426347262274573612423223542411266 +662136122114136623563517733537678678778786242433689887583886359873889897686756773797489433894984686476876576283647473312375446567423121256451 +113314361231665133764245634413475825482787674436735463683538985735986735687377835989695956993785883743873222454253457364734613323642162254115 +346664544153226562324461214227557547624233678785699467533475564467583949877653455379887749977572432364446724786226515115711356421415143421542 +313643636431213343262115354223558522764422647543673987679698468376933948637837959488489499466382835888288538763271574731142564524663112651544 +453615436135416267426425131267176328883876486748364285679376436463834867774446458655863484776253286337737653757143272125227273435213225363264 +535243656633353137766257467627437328228324226782822247986369953559785535988389956566749695742684247634623362752361752741711346266625141213161 +325221435355352641315654734215623585647543872456383763443757889376984553996676797545376357728875528333584457267112273477115756411553224445445 +231524465342662332611327211675466217452423788774472344764258675777949597365949965967555342365522564736683445136716772364377445666565541611354 +145345545246423115222747253427365726374242534852627754257433824788638834353896245472343867572478574275435243232244244513273662614162621454341 +531222246252533133441662227144376613113682377634858475845774273726222542824858426752774733677754566485448574764531743514634434462456614364554 +145452154522416665611246343633346573137875452622267274732573688286832538465566722628257232786567827746484416222164257656622565161153324232122 +125254131231236151131271146464451475222116244682864586526577554377737387667664757484368866263874335778152447571253652476262535642352466324531 +554421456552252362265332323624116113741423437448632568345636738657286654763443683763522853846542668441223343217673511761542645554161635511342 +144524152142215331546225416367575567472434625656867727858426442427348332267236823782635657477758454722616242317454647256665135242443342425511 +355514411461621136661653366434164455414725311676653622663752475838377548525587647555523773456232874772731343426177655135156614166464455141522 +151252222451536425615432163637514115747155177663874272565787422673257636282332635888377345633246756452363713625465334435262434154626524313545 +423424144123266653536551262125242647272231777421174324847363872543438327466258756548778644564432223756156534423345415323535144313131411431121 +423445341235611333243534651162476464333464274654312273536348383274847266228324235374327737713326757261223642735424261664332526365555143115224 +223225351253211522323554361151664463553346667341715561771375633688754746326688327634657244337364474731743654337241521165166354444555443253354 +321255313442553355145313632533256575435672324551223342314775688223272635382774634411555446432651475246561654341634621431225235532342111432445 +432351344513112114641332256662666111412635366422541653411277345522335551214446274624764735755136764324566261526643452615644345515131122154151 +432525531224521344333546636321642532325673647374537434662734347552744427716223574623276557314333161127372122415464122431122526323442533511321 +221455341351134343413651624311566343536636131356354545622634714374667737326517536377616375422343431531326425511636424243244262133123242332253 +135414511354524244326653216664241636551711426751667414717171475516356147564363275241633215151737437714411365566132223615356545331452442141321 +232112255534312125144224256146534232554647275132231757636564517575323726325775673752745334535513675376615266643451436443423241345212144253222 +311343332212452414431356351265113626115356133665336336313525376665257341713721534244363574421332122645631125434466424634532234441535254533241 +332133315355113335444416652265133142166314523744552132755573131314266337173525354221325444632515264533626564524415424325415343533245543455213 +142311332145454511234234465234213522361551543566542176473272155624466613641675357245522555766353415624162413633222243451432323351413241122114 +112323441215324543435111113434444421462336465224265452773346573633576327176211722375461262274655631354621621262234261262333355211135412522213 +124432141441415514244534313211433144211411613265245343742675635427135411341626373737667513253152646531263451621565526313314341314343223521131 +412131141412544252411351443234243153615351451441261622512262214774453331734423524757713653524334315656322455344534621515433221252342511221412 +441322214125111135555114151213226511135464246415335122633341553677117131425171676313525541541122111365234446454633122534223332342555543213431 \ No newline at end of file diff --git a/Advent2023/Data/Day17_Test.txt b/Advent2023/Data/Day17_Test.txt new file mode 100644 index 0000000..7556a22 --- /dev/null +++ b/Advent2023/Data/Day17_Test.txt @@ -0,0 +1,13 @@ +2413432311323 +3215453535623 +3255245654254 +3446585845452 +4546657867536 +1438598798454 +4457876987766 +3637877979653 +4654967986887 +4564679986453 +1224686865563 +2546548887735 +4322674655533 \ No newline at end of file diff --git a/Advent2023/Day17.cs b/Advent2023/Day17.cs new file mode 100644 index 0000000..d4f22b7 --- /dev/null +++ b/Advent2023/Day17.cs @@ -0,0 +1,164 @@ +using FluentAssertions; +using System; +using System.Collections.Generic; +using Utils; +using Utils.Alogrithms; +using Xunit; + +namespace Advent2023 +{ + public class Day17 + { + public enum Direction + { + Up, + Down, + Left, + Right, + Any + } + + record State(int x, int y, Direction dir, int count); + + static int ResolveCount1(Direction dir, State node) + { + if (node.dir != dir) + { + return 1; + } + + if (node.count < 3) + { + return node.count + 1; + } + + return -1; + } + + static int ResolveCount2(Direction dir, State node) + { + // Special case handling for the start state + if (node.dir == Direction.Any) + { + return 1; + } + + if (node.dir != dir) + { + if (node.count < 4) return -1; + return 1; + } + + if (node.count < 10) + { + return node.count + 1; + } + + return -1; + } + + class GraphAdapter(int[,] grid, Func resolveCount) : Astar.IGraphAdapter + { + State ResolveDirection(Direction dir, State node) + { + int dX; + int dY; + + switch (dir) + { + case Direction.Up: + if (node.dir == Direction.Down) return null; + dX = 0; + dY = -1; + break; + + case Direction.Down: + if (node.dir == Direction.Up) return null; + dX = 0; + dY = 1; + break; + + case Direction.Left: + if (node.dir == Direction.Right) return null; + dX = -1; + dY = 0; + break; + + case Direction.Right: + if (node.dir == Direction.Left) return null; + dX = 1; + dY = 0; + break; + + default: + throw new Exception(); + }; + + int x = node.x + dX; + int y = node.y + dY; + + if (!grid.IsInBounds(x, y)) return null; + + int count = resolveCount(dir, node); + if (count == -1) return null; + + return new(x, y, dir, count); + } + + public IEnumerable GetLinked(State node) + { + var newState = ResolveDirection(Direction.Up, node); + if (newState != null) yield return newState; + + newState = ResolveDirection(Direction.Down, node); + if (newState != null) yield return newState; + + newState = ResolveDirection(Direction.Left, node); + if (newState != null) yield return newState; + + newState = ResolveDirection(Direction.Right, node); + if (newState != null) yield return newState; + } + + public int GetMoveCost(State from, State to) + { + return grid[to.x, to.y]; + } + + public int GetScore(State from, State to) + { + return Math.Abs(from.x - to.x) + Math.Abs(from.y - to.y); + } + } + + long Solve(string filename, Func resolveCount) + { + var grid = FileIterator.LoadGrid(filename, (c, x, y) => c - '0'); + var path = Astar.FindPath( + new GraphAdapter(grid, resolveCount), + new State(0, 0, Direction.Any, 0), + new State(grid.GetLength(0) - 1, grid.GetLength(1) - 1, Direction.Any, 0) + ); + + long total = 0; + foreach (var step in path) + { + total += grid[step.x, step.y]; + } + // Remove the starting cell's heat value as we only incur it if we explicitly move into it + total -= grid[0, 0]; + + return total; + } + + [Theory] + [InlineData("Data/Day17_Test.txt", 102)] + [InlineData("Data/Day17.txt", 814)] + public void Part1(string filename, long expectedAnswer) => Solve(filename, ResolveCount1).Should().Be(expectedAnswer); + + [Theory] + [InlineData("Data/Day17_Test.txt", 94)] + [InlineData("Data/Day17.txt", 974)] + public void Part2(string filename, long expectedAnswer) => Solve(filename, ResolveCount2).Should().Be(expectedAnswer); + } +} diff --git a/Utils/Alogrithms/Astar.cs b/Utils/Alogrithms/Astar.cs index d98181f..b30f562 100644 --- a/Utils/Alogrithms/Astar.cs +++ b/Utils/Alogrithms/Astar.cs @@ -13,13 +13,13 @@ public interface IGraphAdapter // Usually 1 for simple grids int GetMoveCost(Node from, Node to); // Get rough estimated score for navigating from one node to another - // Lower is better, Manhatten distance is a suitable score for simple grids + // Lower is better, Manhattan distance is a suitable score for simple grids + // A score of 0 means the nodes are equal int GetScore(Node from, Node to); } public static IList FindPath(IGraphAdapter graph, Node start, Node goal) { - var comparer = EqualityComparer.Default; var searchSpace = new PriorityQueue(); var pathMap = new Dictionary(); var costSoFar = new Dictionary(); @@ -30,7 +30,14 @@ public static IList FindPath(IGraphAdapter graph, Node start, while (searchSpace.Count != 0) { var current = searchSpace.Dequeue(); - if (comparer.Equals(current, goal)) break; + if (graph.GetScore(current, goal) == 0) + { + // We need to substitute the current node for the goal as although the current node might be + // equivalent to the goal, the goal itself might not be in the path map if reaching it only + // requires partial matching of the node state. + goal = current; + break; + } var linked = graph.GetLinked(current); foreach (var linkedNode in linked)