From 78a829c809dae2fe952b938ce0f8a29b0e3df76b Mon Sep 17 00:00:00 2001 From: Paul-Henri Froidmont Date: Sun, 17 Dec 2023 22:34:47 +0100 Subject: [PATCH] Day 17 --- input/day17 | 141 ++++++++++++++++++++++++++++++++++++++++++++++++ src/day17.scala | 87 ++++++++++++++++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 input/day17 create mode 100644 src/day17.scala diff --git a/input/day17 b/input/day17 new file mode 100644 index 0000000..f4b929e --- /dev/null +++ b/input/day17 @@ -0,0 +1,141 @@ +145252442331211155222424236242365444543645635235263636335736365356746366644447336554353563345665632525253546422366223363656565532234321555355 +522215435215452265232324235345243632455542526545463655474773777444364534335746445366547435436764665263646344324364254333325655244343525322431 +524242255113544455422566443565622262556356547455544657646573446646476763543566735465733355534457464656646562423535436246456664262133415344423 +213212242232534545645233665636646554254337444677343455533377365754455446754763636334657564657556363655343645424253443245353443342251251113414 +253213544345626534323322325565644242664667355656546656647643635553337574737557355747736366345353334536535324634346465653624366224534551325221 +441144444346566642224443435532624535544736735574367577666653463635547543734576675367554736433473576773653434265444234565636423252662321414411 +351451434142243522556446332534232423456745367355363654465445534637633735764737664735433375556477353463673744535332255625523554456632431431353 +125545544453543233523465363566546545746677653353767644546436647775557455756544374533633737457346567753534667373446222545423325665463261521422 +334125324525446665254343565362447333546733743365437435354644467733657436543636446645353775656343543756634565467555223552425324345226443133225 +252444456254253242625244426422664347573775534454673656746537573674456576573437365735737437365364537453767654354474623422266454646633434655123 +123552536332564665422566326546336456374335474357736666733434754774477777463636556557336747366676743657646637457436232542523443435236523345241 +255532433536433362224363353544754663357733345344473374655734466457646335433456664766545335546453556677337366437757762562666434634265226533144 +211326234445525442242243344333463765666547537774436437663544575856744745656787848536343463764764353756444637445574433535562422233263544666451 +153565244633235252645253247653747636455663563543436736653688474544885675858765865847677775547637446673537735543667463443424562463253442652361 +322633255636342256543635674745735434335354636336667564857868556865477568775584745447665544755676653553773437476463773334325245352452242253525 +256546563662633436563554744776757735554433436474355566876854648887768686577844776488847666884456337576754336633375375565365545645332454256633 +356652656246364546336763464575753734547353344766446868575675667455458747546884866565644686744564737763664544374653455547736536346335246563366 +662354345224456446435763567444536466436737543674687756646874464766666646786856644487686468884557466353374533346556366764654533654334424224453 +623232353524654566477543666736775457674366354865885765767647584865848868465566658664848774475776457674335773357775453474453536453222362633435 +524464325344243544373765576553644767647463658665758558485677464586445674578785775856788744777866545467437735666566337743375674334332256535225 +254564653622344224763466355746737374443785686746768687788766886654644484444878747866778558866578788757776565574567343473536767565662446432354 +356643355563563473466553645336435477746785888468464567855484666687588665846675445784848458657457554868866353533756567364376453765364353452423 +264332626656332347657555543656334676384547684457884486474648478474584875584754477558778758576747755845485756536764747656333645335235634654263 +264455352344426644365777473564756376687586574468745748486454646787756858887877847864548684884874657656585554676655476674637445336464665342344 +456645432463533547555665357737557445565548455684786667856588454466544466745747747465586465457466478577786685367335357347735767643446535234564 +266254426263246433574674546474774678886775566855456854446846466867885688445678687566664786544464764586685856574653376635654336436655432664263 +664645232353773634577467543656364547577686676784847664887777884776784887777466684885885488875854765557447688747766633743676575544466323642226 +535222463367574536344375373356457486685868486678768775548776465995986857665975765868767545648476455667867878577857474467473634546576234246544 +345525225357534447375474334645685466547564875688855448768747966758666866967699565877467865784776468847687444544765446576355676637647542363464 +543554426633767635443553577675867544777844446547848647646987796665977569895799867868686687447456484475866587847765537575564744646453555264334 +344664256475354736367647373576666764874557554668755467857758686669585997578886557676876898865654787656754674854784853573554465334667676646364 +644534444754333467567756655885575547557784674887557857799879769878697577699678759855688997875874757468478648484465547674576374756363575344223 +653235225565733663755653576877844456774847566746567666965778959857869599677557785865789596789768665664446786465858768577353634475457545445253 +326244455756643753347547365855555588758458855745996877765795677886859975956576766977566967979885466888768555655755564833735634756536376745232 +646345254654353743365575664655456587756555466499586988658575667879885599998875998695977877788569684854865478474575476836347537537345643633535 +542264477654575544455663755645848687677486567758878579656986595958967768795756887666696856587958568784448667774465656584546775644435547674323 +262534745453456737444744546775684655744478856695775666877566985779975997697865767687755988568598677866877458655448574686573375635335657536356 +342346455773453553553764578868687848446788878856866557955899969576997568596566755775867658875559897994466465648484565846466463753654565646643 +346353473343645544373684467487666587787585999556795795599798769776997868996756969665897978667886666887546747847855445844766643353653367447656 +434536353567375333633888667667755864666856567976868585955685876859687999786687788795967855877767957658784668845548755577584376745465346533345 +543355577555344474768675656475755446764899699768897568595788698677876967595959957685977956568577899977878555764668857784444343374733676574425 +535735575534747376755855666466657474478858975576859778559777578869558658599785798785975656889975568877896688444677444746788356375547574473734 +566355343747354637648654746848445846689887699699799678758889596698789889788777775577565698567567577676588668454645476647786865737364555643362 +536564477775537557487556586475475656455696888656757857886658978988798798779666678696985678999899676877579755676466474687668677775664366757474 +326565356567567566687644684846755484767755785675778777595887989989777886797977767999876676595685598867556996467788488844586745573364553657474 +267644363763757466687564856476578557759999867985656758685666888799787779867767989799798957686967576657999786848864544564865564336673537375675 +444646645466777744464474658565488477577966596676688879566688687796997699779979686797896695955598688977687989886777857647445786433356775673674 +277355745533357738475474685885587789889698958698699798669767789867878866667968676899697886986985888995665668987574644447676478563775663374677 +357676735755556355586666856684865798777758566798797979869899777699986966777886767967779698995695588686767887874785586746456456467757536644565 +355453764347445366858886544646677899678986598578669697779698877967678968667868778988687896799987696859696959755645856584548867545477354645757 +674573464365364474488477888677885877898596968657567676996889699777976867999666797966697876899998999976676768758467477857445487643665334343743 +375777434363677644454556766847888689956876798575768997796969876869987686687989996879877999869785785985586885555946866654587466754536754653643 +436474477633534878787456644777679959895567696969768866866866779979867867896886887976688699989977976596889996859865586584745445864545765735377 +333734554535366688778444465786857896597666675778786978887996666979699777669779998686677886888787867996769756786685764867845585866377565345675 +433663334743478576546584486848866758555765568966896679978998766886878689699896669989779787988997679968975966676664468668557767445474655374455 +373746573647567878846485647647867776965568767769986769798997799789678877987966776798869879689669695558866788856688567766685675855646443343377 +333465546544536565766844664875559887577759598778697886989879689766696666668799867687788976798869758657998768786669656656477677687343343347743 +634434343363377487746577846768556979697559755889787897787876897877898879989799896767968776786998996555789887887769775558457774657534366546334 +665733766436448847864886648845886879576858785876768669979686899798989987877997967978669997987787995957999859899679854844868576575866436467767 +655333456654547444776587884577859899787699768676896866786867976897898787897887896976989869977899777685675766556985686475766477786447646635435 +545755474554764685586684756785575857556675876687666997987778789797787779797779799796888787687996767658798855966679546848584456747733376557336 +667635776355658777687778776867589759695895788968779689787879977979879997979789999998666997986867986796869887975758984784575486757644667456574 +373654674534884758775556588588775677667697688679669787679997898777887897889987997898769796788788898978889597799889688876654677567767356453753 +535563744446456877745565486698879979968888877987778669897979898888797877988779998899978979898998966886979956788686688648458656568483437544343 +764356735666547547664454668877979777758885977666798789988698878978978777879989788989797667976686997866988897567879764885584456654484737633333 +643335346566568885486487658589787686797969896977986776889787987799979799978879989777869988969877679677987996687959856776544846587763376337767 +666537643667564446768654545599887697657986967667887776797777997999997777978878899789897678877969996686676696687658677468545888854475733657556 +375433756556548854756678844957969957565598666898979788999899779878979897999988999899999777689897999967767968868779787678774478577653473637635 +434454366445556865476546548889778878576795986796997799868987998887877999989997779889898797766987696977695756566768898577576758475577554357563 +564666577654686888865648565577989987877568769879997677688777889999779889879979899797898968667867789676658877597857667668544756474765367665774 +376453473677856776758547476958566887866797996879688888797977998889797787997997978787877779679666666797789559588585764865665868546576566345365 +335743747656847867757457876696969986879865669887996966699799777779777989979888889999878696976987897798775878798876576688548664688483354743755 +443344574345656766874887476958599569897898768969698877966779979998777878878988878897777666696677777798955668665996764855748647457446653453433 +444473464454465677887585748659985865598858868999989978868988888879997999797789978877996687889796967686956699975678566778786585758846775777455 +774367455764665448645567884659565789979689897678777888879798879789897988997997898798776668769966687887856987595887898788688558646473356434733 +747435344333488888866765456589557867668598696767777697877897898898778999989799788978797969767988969795976978787795996588766755774547477574546 +434334733636674688845567484856885996595768668667869788869997798879797978788787799798777687668797789698786995866895796865576584557453456573466 +636333557675888874845787446598678685556699667968898998787978899888798877997888979899967689767967688875557589858898766854755586757456747466436 +463753337466788456756478574577987689659666869969977779888789787798779998998787898777868876897769699775898575579795685558474448658773556336677 +474367347456666855777588784575568589986569966669878767789768788988789987778998977889866888976967866957787998799756794567457778676745557544555 +745447666345475844888854484686987989667585588798778967766986779797799787998897779786688687767888998978968675879685885486586676646775734365574 +666655454434755646444468665678696756687788978667799799979679898779997899779778777897969777799768788968558868767776988558788555886574745536576 +677557336565688576544487644676587999566859997896888979669969998898898778997999997976967988768698689965767796989886745887778767888436654574773 +474773774656556656555647578676856766877788557889979696688889887897779979879789879877779788886868988586697566796996886578587688876843573343643 +376447647535684875566456664865768998956785976698897888899868986679799797788779776998978687678787889695587676865559648445446675464567663336676 +336545765544557776447585857559888688676789858766769868899979776886989787779887669698698777669867667859669788569695646555476877666746677743637 +636645337534648457864848664788995699798569879569786887976977686967766786886767778877976689787978996568698679996689687448448466448757576376436 +356766353357456665877444658786698579776755887879976699688766668666968696777967796778969896766966775855977685858968676777784665454647645353465 +335445556343347876686755564464575958977678696769667896796777696697989877976796666669868776866976596796596685685796848754784847466553763466365 +467566365776533775677686487666595896855659777689888687798976779969776677886886688868689699867665765759569866777658466575467478885354733473457 +447637676656557468766765755755456679796868968655669879799676886868879698779669699679677686686969868887668699657888548545665557883753364674466 +443557467634436477746757846885656795797956989689868767879768698686896767879798798689686787789966887985676889986855767785757674886757344435754 +336733374544765676885754578744666767869998797995779869789888799677976967886788798999969797699576885788888987858684486585768555433433535546754 +344573337357464345474557845656475598777597778687857877967699886867897876968879788769877966975575579675855566677667474455876678454756666756433 +266764533436346386866867457566544958556987698886969776979689779696888979876968978696769977686896568989775758866554545666474457874674745556465 +253575345344374335557768576555747859576575587789868766977979668878876777967877877788897766787675799687666977857676564576678745447673736743646 +437736735434563566858488845766667558958685686775695559879878677979898687667897698768966686877798698795885997564487686547845676367446556675633 +264334737576744575678565486647455847997978987987677996755996766998999879887897869996668787859866988776966777856774645848866673764377635566657 +465354467474677443777457678557886656757968569866959996999856676689696898996899698868575688977775667785869677565485574686674574766654774744646 +643655366434643467575747666487687558658986899666656559878686768769698668667987967766595959778597677589667767644455478746644664355766767675475 +235464656733737677586767868665474768486776988575969688755765976879977897876767685989787858696679867769679947776476488755688556677353443543745 +535455576637765745445466688866747584565567757885695775895598985586765896779559567858575698978657677688559754764884486546674365554675734373334 +552233346535466555638644564684766645458699697588896766756899697779785768958697575977968759766765657577588875568566486655856466777566456566752 +446353633744354556346787674658576758756477775775565757766686785769556875875998958777956779998899566777565444477448846888756357566644334567352 +655645633466767573454377784557677746485849698698998978875987595687996556998665978766788755756999979577647764458557877585467635636453645664432 +353563467374657344543456778567646768654478589956977665765775769675558758787668975599797598667569657854545475585787456787737647667455363654244 +556526654475667335744747567488654644885786887979575889598956586569657586569758669855686867978868689567484466858448744648445344463366633746326 +463532654574757356543547665586444447556757657579699555987855975795988559559987557566766567666697666785457845758844486743774476465546467765663 +545244674454656474567365445458454584588788684598787856555579986587598798778869869696888596599878684464464874464546787745744645346545353444232 +563446455756657764574745554456866478676868768665655795676978596869765576997957987777877687798865778858568555656466778866664476476775665646435 +252456546475636475446675556478475476767677775766658887776869897869968975568567769776665696666688565547868456666854477755366774634366363665345 +566643647753743747465347533887874674567456887545554978857778965769776585957959565975657889687457786486446858568585566346445443656637663334254 +443536464434736666667345534574878754744644558478668857776698697786656888897959985895967667574645845884874686888565545777564376357443636333553 +225324626275366374345666733655777458855775465766856684478599578799687668559678765766976685444886776847884686885656463677646356437363426623564 +433432534246665554443733473653568648647887856647858856765875759799966576556856759987555584664666544488648657867873576553643333343564426666655 +652663356656564375645534635763644564845574584666447486764785458878755577885678776848486645447474785677554746557676656664567436345374653456442 +456444224254753754363546677665568856585877874585464548876556757787478454887868458788454547678644688844557685476773546564567333566642565442665 +245542625256265553745435364663343684668665646844566676684768476677577457467445546557747675666565487545467658884454573466645547765325653534264 +222642544552637635533473554777335736456665486585486655854645466677446748456746547547476787444844655745586668744643577453355355474333332625546 +466552255422333477736577646344763656586766585477578686555866564454656844768886778678847486788558686644848787675533465467474643375523544663653 +332555544442423365344776347665336666644667464854454448748668887475448786678788884785545768468686875857847556667335474447663764436552665456434 +545435555543363236456744653555674453655454645567558454684676675484484778588644544888887557775584546647583656577436463766643737644252635342654 +552336225435263356777637555664663744354355585547767647645476567674555588876755688657844885865748565687755565557443543736337333626523565324524 +646422364232455436335444633435343745443634854855644784575687887878564546778555645478445556665785585886563354336336444433556336453222655556535 +436462432562653652546646667674563476544346738884684778845875575447688556566874454856774868765587485543556465754736366374566735246332623464465 +335435345653523323434665646346754673464667535775644464867487887556647685485478556847664868684878754355555664635443355463644524635352554634354 +546644645626532445425353543674655676565336344637867458648477465475487485444448457875857456646865347556567735337353454356774556434346433525452 +122535464556632424243656354643447766347645745473366688768774547777687586444787787686454644884566576357333334734574446665466536335663545332433 +212222624265236535223564356577665357335763663466667747867476864455446675787466848656747774333747677454453566734755336367355264325425324363226 +335433465532235444222624334366767774747355636776744356746574764555848647647666587884856647776665777355545745356443557464245425546536243355551 +335464556436632424664545543544766433646534334444546464373574577476847474845656845447543347474763575573665633664557664235666432526365462525251 +323223343525436446563344535474753343355435435667466475476373635663534344546333566754376735356756476455754374733676353423345535432446356262411 +133343442522544634536443646655367744564737365677755436375656635456775763446777545676566537663644667575464466736634654523654353254563626345551 +315245252535236323323526356426436376637653637563766466475455653433553365653356656467775474746775677637434566737676445266324666666426464541325 +315241435553365433443332223333345644576544653473453653447447343446753773566745477777567463743757464745653366635432652546353564445223262142224 +431425522423556262564636635343456466544373436576554446666347756734737566466437477734454645666376757364377734354343563342523556623456434524254 +411253432265545632452233454525453437647474575733754633474634733434544765533733775466544443464536344665765344252444336433425453555252523325525 +245351224522455435223264435336525233254577667355455653433474744576736457735474675453466357773663477736336524622464646453252524366424115345223 +325414345252554565235335632662434465336533357377367634346435555534634773346735575353334653657745434676566353622654454666364645554231133243235 +355141344151466325655635466436632252265537345364766547335554437575766744645647543436336465654636547745265652433346664642444254466211441315314 +323151534315244265342244623532356242424355555757773375563465546675353463745773434553333657745543546462443245554536532556522242363211551123423 diff --git a/src/day17.scala b/src/day17.scala new file mode 100644 index 0000000..bb1154d --- /dev/null +++ b/src/day17.scala @@ -0,0 +1,87 @@ +package aoc +package day17 + +import scala.collection.mutable + +val dayNumber = "17" + +@main def part1: Unit = + println(part1(loadInput(dayNumber))) + +@main def part2: Unit = + println(part2(loadInput(dayNumber))) + +enum D: + case Up, Down, Left, Right +object D: + val opposite: D => D = + case Up => Down + case Down => Up + case Right => Left + case Left => Right + +import D.* + +def leastHeatLoss(grid: Array[Array[Int]], min: Int, max: Int) = + + final case class Crucible( + x: Int, + y: Int, + d: D, + movesCount: Int, + heatLoss: Int + ): + def nextBlocks = + if movesCount < min then Array(go(d).updateMovesCount(d)) + else if movesCount < max then + D.values.filterNot(_ == D.opposite(d)).map(go(_).updateMovesCount(d)) + else + D.values + .filterNot(nextD => nextD == d || nextD == D.opposite(d)) + .map(go(_).updateMovesCount(d)) + def updateMovesCount(prevD: D) = + copy(movesCount = if prevD == d then movesCount + 1 else 1) + val go: D => Crucible = + case Up => copy(y = y - 1, d = Up) + case Down => copy(y = y + 1, d = Down) + case Left => copy(x = x - 1, d = Left) + case Right => copy(x = x + 1, d = Right) + def isOutOfBounds(grid: Array[Array[Int]]) = + x < 0 || x >= grid.head.length || y < 0 || y >= grid.length + def looseHeat(grid: Array[Array[Int]]) = + copy(heatLoss = + heatLoss + (if isOutOfBounds(grid) then 0 else grid(y)(x)) + ) + + given Ordering[Crucible] = Ordering.by(c => -c.heatLoss) + val height = grid.length + val width = grid.head.length + val seen = mutable.Map((0, 0, Up, 0) -> 0) + val queue = mutable.PriorityQueue( + Crucible(1, 0, Right, 1, grid(0)(1)), + Crucible(0, 1, Down, 1, grid(1)(0)) + ) + + def isTheEnd(c: Crucible) = c.x == width - 1 && c.y == height - 1 + def hasSeenBetter(c: Crucible) = + seen + .get((c.x, c.y, c.d, c.movesCount)) + .map(_ <= c.heatLoss) + .getOrElse(false) + + while (!isTheEnd(queue.head)) + val c = queue.dequeue + if !c.isOutOfBounds(grid) && !hasSeenBetter(c) then + seen.update((c.x, c.y, c.d, c.movesCount), c.heatLoss) + c.nextBlocks + .map(_.looseHeat(grid)) + .foreach(queue.enqueue(_)) + queue.head.heatLoss + +def part1(input: String): String = + val grid = input.split('\n').map(_.map(_.asDigit).toArray) + leastHeatLoss(grid, 1, 3).toString + +def part2(input: String): String = + val grid = input.split('\n').map(_.map(_.asDigit).toArray) + leastHeatLoss(grid, 4, 10).toString