This commit is contained in:
Moritz Hölting 2023-12-17 22:23:31 +01:00
parent 8447f2ddc5
commit 60deaec686
5 changed files with 574 additions and 2 deletions

38
Cargo.lock generated
View File

@ -174,6 +174,14 @@ dependencies = [
"rayon",
]
[[package]]
name = "day-17"
version = "0.0.0"
dependencies = [
"indoc",
"priority-queue",
]
[[package]]
name = "deprecate-until"
version = "0.1.1"
@ -210,12 +218,28 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
]
[[package]]
name = "indexmap"
version = "2.1.0"
@ -223,7 +247,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
dependencies = [
"equivalent",
"hashbrown",
"hashbrown 0.14.3",
]
[[package]]
@ -406,7 +430,7 @@ checksum = "752866d4511516a35883728309499db42696f388263586b70659a5461e641db5"
dependencies = [
"deprecate-until",
"fixedbitset",
"indexmap",
"indexmap 2.1.0",
"integer-sqrt",
"num-traits",
"rustc-hash",
@ -419,6 +443,16 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
[[package]]
name = "priority-queue"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fff39edfcaec0d64e8d0da38564fad195d2d51b680940295fcc307366e101e61"
dependencies = [
"autocfg",
"indexmap 1.9.3",
]
[[package]]
name = "proc-macro2"
version = "1.0.70"

12
day-17/Cargo.toml Normal file
View File

@ -0,0 +1,12 @@
[package]
name = "day-17"
version = "0.0.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
priority-queue = "1.3.2"
[dev-dependencies]
indoc.workspace = true

141
day-17/src/bin/input.txt Normal file
View File

@ -0,0 +1,141 @@
154651534533264223246736313357734657147374325514765434772544275388338442868844847827285753355677536765673622573135621137234461521333452441541
434613344236623124357254431623141437257446714666363524476254466252424656766464543767833234754157661744135677735466542544652224313641123332623
111656244231261643672337356332261667312415742412843278763423442625288648554467623422864383587622427376656341227463517657723745142466436612332
165136343443341162231423452344525473231472466432243883553358332844847863852642574732237457642328251735767616161153526651513633151325531232154
425162642164653166237577573266152444736721465776278554374686666765264272874554378373258465367847432213643665354176363146415334666644611262365
613514122133246516652772625532462433317163648836726654272423253264346888555473666322576243675582732847512756757567731352746543772145452516552
626155453666464414642266742147367271742354522737427852567873742477886873632746327236632385366884343653653426445236345115522726141334361523223
233445262556673526733536651746413563147575357654266553684346345454337877847846826485857685863744744726428867233473156546517773141566416246235
641435561561714375667267366234645272573576875263433732445848523845477733556458883625652227565862866275433576343554562446215213247637244333232
244343112625757756556752527222156354666643654263565663323766825737643238637458432585334687355572258385858683564337413464717236627634614245335
622511244277412256373463253114532558782675534254527477337255738643346838875732373844456288642767446775823833443617342734414445546742464134364
232661653527512136737133242651268568258836768758565476863528846677644827427636564545542254438262634875278785324345217215221573255456364323646
342163125674631636272756741733876753363376365254484536663567875535237563747325556248282475755388234386826265535728451311154711775262253262523
161646332434246516366422434585474757563343222537675475443564782783774933673564723636447725257333384734373455463675443572122357121534335523624
123555731631462631122134547866353487727242558468687856276647673369944498469843695384872374576783338885232325246434234155564347275466216462454
545561174551676651765474785526373744832377726384383267847849549584868485684587555989349824354843733527562653635835267727214114156531564126542
635133373565363436576632865886353776475474363453345866849757894434449454793463649966645799534765882647427848235282432567451572443122673722452
642226414343346747155675285465842267788573563282724966869795865573458488585776599477384366959625458588566727456434728565762651154674131274374
326545253656156161562578528675337448234255352454655474849548843788896745335668448487499693883645886242625428582743772748633323634776454552436
634357257236273434641676333463427456442825557746967373888475656673574387689693878488556877786948848763456868322574633337741346256546411567612
343572626551346472233274435334853326382783274884978386957557837498668659665838883386493565787476374936347252483473833823477525115332425453726
167471726674523523363837576458522768588725379334335435874847993666673495753435963487337677646867787555748763657667654858323765571516453574567
613661427654472164837676527224826677322263548756976866844637934744777345579894573567995439744436565663475865484778637388387376126376311363434
332146564341247714557765355543847575882764745574488845498797677497459393455599796934573958953463478545932625574324664777785864446151571324625
123367743334745273483222463366372346633869953873535576634859598469468947347453697855679865337584868945588464854554233623674788227254426756176
313716535772243853248728528265246652654566478975983939568647946973687746337335358848577685355783475447699742858647578267563735574516276771417
351326535414113548684553432344334573349596795676375444564636797763549997353888378836644956475689446797459458435532447626346738633357463252246
432714122562746337536763783537687679887587456575979586859463433388497439459639787495746737835673686598357785945252876652442226547367411136326
452477371331233435773863458475879846444799475968479835598869696344698586776996537858484577397679965377679774844427852333278645225824472333675
631667433722873827452456736446343968644467697549586388339636948876594954774564686898578875939493356733475795785436286828852682637445635631761
157571413664325828647463283258483939793475673666389978378789857487666974965778997896459656755537744584566437576943327533848572474468414223223
741636266264223763473445236788766685695998546737884839455789746446989657969675647697689754659358868954849359644336588782335457645747644212215
321435623424464345722357766779593883377487399896635576964695845958644484985494588455576796874395364987489785576967732277848732875475336221211
614727555532353583428252782446554758844576767583845944996864866748699877555767875657885878855844357553494394868846987576444453884656642616246
233737327388223853487665523453464346358398956758965449498964674588948549594669946888577967459668467799983438683967655442378326735824386365751
673246768687733758348574857554544393749565738679958946787459754596994459466656464656768897445596779448697593747375756572865436772535557754211
643457614367338742587762445569579447794658688474988797855967585494797688679469695647949677664948989438964885938654847566655273344546288527454
356575457324273366465647997438575963694538459645656465875875558498467756996794875675577589488668578696596764773344453982235353577268774834463
633321623433836843273528383336387495483596994466468678694577448567758874756598679589888787598979974549335494978894935543458468547346753432673
115313556652823374565836834655457357764375575949847558498448584896998857699778897468958484945685859667743587393986455533555622566747274273212
361721666566675563585867769969736437457977596568845687888869944785945999966597767579696498566647648459497896448859646549823383887456845657771
566775333727343683842886855898484535396649789458788775667657895959489857847847649756675645455448487747566544878794363345357465546682547733763
254414735335683264443778939565679883759844669979687799894569984775445958994947697948574467695488965998864836795896346753646446375847874672433
456426575666374752778436466636354345479658879866448567954689488666969789559787778477899466555988658756779836757773759843789762332648335567642
351567742488247372235344934965784578949884446765976579457465797666777576597797888965785566869857948894695988796985877765736522725583254543235
171434334834237673275557953568738485776855786997559987678796998855555979896896895866944648887795876484994597774768735943895342452537684668412
215446886462582568364664365843773343598865897848598887649567985767997987775558897986969587786557664974846754934457657399977443276666265473835
465524642772282674444999688483968744669969697884768968675856667755869588978987777778756688479874858875856485956778383678364848467348336457636
638554888368352558545564466374543474458579449967844985989665687669796778598565665685978996767694896664464488694387435497486857272656744254468
554342247773486773577637634865683778864797597899885495699886665555786598989988566585789756999956469868846587856998747637986452882328285764578
356255862786352224595948895664463858466766678664577998788787578597575759786996576687679888559667577457984696655549836456779437344226426265754
344327728558542223875736798864557946696484758456658865878667986887779858975967769959895855669778574955574444997447784479997697275727678226776
185688448363434853657769586555685584765657675547976766755966769978878585565978896857777886975975457757754555844375839946996747357875666774363
188646847823335339873347753383354898476646746795758759575756858876698756659779998588587595786588878789886996798394645775775377327888343856565
376585835485545576499678444683996657888878888664669568695977899766667798886587765978855577569986868598498597755548375584734396348252446866285
252482488445458564668857694457378544474555679986786959669865687778559756667986678988886997988567476768966857775747448583486837952836458334243
568273875576773636336636468583957477855454476777689899675986667889855957989669588955569859689556778698468859787765973637553557876483557728433
777258855472864748746789568983844987477495868466799568877567566898956786999578985578679856597778556996788864976955787478579536498682877426754
486746238838266398635658476877799564856499847866799676659998588699778869697778668585588858658985987859557944546654553844885868976357783335234
432546538343684464978799898959754899655774466665797976957989656778766969968779986677588865676977795795798984594464376446445456793582467354323
445675445468757649737955496899947848875978944558888595885885986689667889689679786896956687668996875976695968445845466543673733955854882452822
845547862442224993565544479756947896849967456686986898857578566686996698889778666866759667568999765596557497584775656997878746549768672283543
684633267222384334797446939455895977467496667568887675687589777978876877899688978778668696857898788784877884499464569854374757965234458283724
343474688774535748367956535996879848797696747958987698658887777887796976897889897966795988997776568978485587988699379999439469658343436567323
874827456725563636845864834847774697595855795895769566788668898996769887779766978678885778989666865756669564754549795975347599648425422767542
474487685656557779345799756746568987975977788867866578759879666977886698998766896766757785688587998995864889546774859959537979786353486787288
448476622346327344394849633848477676895589999989766965867797986767976867987967887887977787657558855546989574989774864779454675636682853752257
585753566737595834856685897466684454485659499996557697577678968786667879688886698977697667988868697649777848457947944345974539784937645478847
526737422567653736445595557949964875776686677598867565699869787879997676868998688686896569865888567868449548657679536666538839974386426322388
376438532548394485644747385746769987468468898888959968879897998879779699977799797897969655865788768759898775688745787438977689674662622788785
566667755624349557449753755974885754479888679897578959575898887787866996797677898688697775959885896664779888984544757379463567897437482348466
825528865477734846633574535787859669654464755696677659588668766678779988667778889677766969978559877689564579889986966954957579783973722732573
837225443233283579866885735685754565665674887986559766667669768869769878996876777869877576898689699875996898759888667767958398534552644667664
382546845852453743384576376469487666575658657787697887955889678698966776888896679668986958597796878855888476879488546533899866889623484542276
425854787382438755437489897787654748565774869995858858789777778686988988876669976876799669589796888765674849576847946995979368355366743258765
483442763688843758979649983365948689564556655885788658767677676798678966779886988767898866685987877649444567589894973438397644933885537466775
528367522475357954936633653669858868697947975699976879669698668768678896977996879766675875967868668585578799886684784345786679547863735567473
468866437346689694649889646649655864949678459996566656897896997899999877769698877868779797665759988986547876449876578938779833738388227333758
472553765763223394543566558465789556569868968969679786675887768976879798887988777896777978589795987868575789448969886537846993856552322236586
438725732725665543367698347894695644984698687757785876998958878886796788977889776979976565978857795695785658654664639447469336563453345327374
752684527475356858356769538947864887994964777578596868878595786688697996897976966895667778996756655669666786488657449343635753583365623368382
662238474247557543977335574444474789758984575559576896658985668797686899779877676885579756886966569688948849458875663439893748795276728624868
627284635774839657663447478495844795488546775957968689875859669798969976797696768656686786777669657877585775945899734638897465943354826842882
477373683637773963486939884584669688765484745986998599856699886776988977768687897878775965677968598785546859477447979568539788482256884468684
534288352852362776377346644983965648844875899898696767765666979997677798967889668976596579585685579496497879769774656777766443893264888876643
348878668255247558769745438874568966476944676686976778966779695785686666869596757955857669798755886746866867455975943874648364692556332542587
876433645368648657567688587485676946676594869587879768689767567889678899686999579955655688675787564474685498659747566399858547688856852752467
165838473255777377896487667369755674495745586666789878877698797986957777895595985576778676695975447697599685769997443984944733487273735824577
255343267466263654439533888647779686578778848548998567685798767998859796655966789559759756589589565444747869785464433846775549586527386622582
688347884354244359566733875978765767599684767679766786776899765997858797886569669695579876786998844585868864594578478333399944444638276357778
474822284677472748995796373366536495648454558779767985967596678757678775859695989875856769978555456646744484579789563589863775962555354664543
366453867748523683964853389857694764556755958687878689899666869997997689679987796875668755668486745745658664798637377474475787437234834674743
363562443732545545734364378477876584947468648486949668899969899966867768975655955777997859959585998987576648667543378387967948464546462576674
167874878723738768695359348787889369679687558659658987576755889567556689776758986668795696689944585447868455639645644897355596775268377276735
247773478853653687796549535959989449959546696499668794789899987665757658776689876865757679879588877449459645567753465366936963648837272336673
222375652557565346953989358966346785774974899846557784888885988986665659976796788769889785675554474564585855495434667483995476642786278647522
434553576855457275763579584778437435786995668545487658896698895667967697989957979667986476844784464594956585475895336959896782462386883685267
744464444335544467586596755495857785658567959686569979946889595966757978888558655998776575955494577885877899758463587957685933668755858267617
644275628882728232848796456653896337895695744494848785485779867998759685698955589558985868587766859989865684795897478448968365344543535823515
726554686753373724433557537597788655459857468954694749756557957577855756788866959445947689978659899444448757937998673848764884762244885447711
425235653434283265243695843537893943459667974788498948995694446998669697956658867686756569548465998848869369777647664878444453673737576283477
172525262773245785738594463645547368476847645785679966888845665874887674669557565646849594646596968749855675596779956953652455566688444885514
125345375647672378628733466636484343465858784644669555446679787944955965989777595965885958547575976744634884867847766735422537444387487284341
451563673752232342385645834694545383869395797989788799888747845995657848899894698978845959649684959756789856667644834763353725826734536724123
445231632763376268366333999374547793584334775448785549575484889966545779764785868574559544794569754873699793664983958362483248364447634646242
716322647664237245474534587464874573968659769669945685795796989844558996985744994959688886989679999446567976556499947367253663588856888324475
466217513556732443583835736934395945798939399855997765448969987988977494744799597774868776957677763434798998654893377866555842788672354252563
763135318466752356574346279836755543974997968435566559566886997596847997474476797897584954898487345653855575983647743647352622845262265441574
147521211823767363586423837798897397945743434337549865475855647445984746796555559489578468754976956897353479459877538276252245575255335541242
417233764742428782243686786966339493967953973985795894988475767866974465445676859755976567685699473435467494666754468475437273848723743525617
547625222245535364542567568594648354445394446848834969976894876764464749458486798449655994879664856433867583695357525378868728668286856426734
273657757123543764474777486478548473866744349346835475674697449784447954698897997454748746884759678778874739587679237757453868428635424265273
456746564566437628663828342366654383977948778797636598467978879457689784747789889949957354534533955554668885949535875375746632454335316521553
211363223652275752437672233475483898783399588467657653476978947788659649898698788945383535677637669686796559934642752384368225744364116521715
265224427432352425758375427368244858645366579477763477385875649896789548867977464773457834947687979789959699568837855372575838756534135757342
124314564152662653354623284452775537849639978476366763885363339994935443657366978987737333536575865643354964956226857685383362628761664423114
565771232573734555766578226454828526386378333576636354768343534667569774395543985495375389597977697379998746834562748338264728844411337264621
627335323645345235387834463625352332558359775734455333369797673447475847688764359498844684788946345857898652853545873823232847466736535216456
455775554647516626787383523257246878666858668794769883956933696574895888366395894587563576996787973636884676633663736838577725431675114512263
133721554314256176658574327263626746727945537764994546396999334559948963888866347879359987379539997853793554373647454544586286523161622256227
564256725767766664538252754683322232674686696996486363587686584544539745857443887665953554854974988354865277575867762743758572544677365671174
342432131636221665265622536544773525578473465665544949534487559855933653787997577365458355493369777376348425353725478553825664426625171332471
237257216656246677746266656338352742342777643774666393343975467644559536338776396964378977976739496374458262887655527622836765124312475161536
427266616626153776676844276685545238247576745848345568853894764458954393436435475885374588443836966727373376234468755826362721444663771736656
147557137462114333172152683685724484374388878468845559745785559847595584847956963758975763759583262836344766525328423776561343751713555313135
435513555345226574627155725785658623623654368366485663993468394389367686665939737986853747367664243644824584658886754656736776255427771335234
243337713474454142437322262563673668225425656764864438569759947386569988545437398855394537774624724273347477386757358281176113674572131474143
446517731347735351452747574645462778657625382753875786755878793753695787859638943855757868245252276274648626482525487347577175235545312611223
646214451633672457761737726624383832888827252274856742588632746547443538544659389695326634545728874426373466622252624734646767421266547266356
615315257433435511264243747347283584524855646533688522764423462854566967663955265725484756727452548278578588734222835657712271114575426772345
312625411122527753661626644533433776784526283474543685566226555487268787536766288726243547848475264388447642648464531465616414126632121735323
331642216651537545423424157531886246753822224872522257535524633736775252357567687273487847884255777245652785623886341326327554177734653123612
514522335365715616642364654513212884235563878372453676345322272885724648352626225488834732247568353765656578486315734534253677227275174154551
312342353411212641724217467171355638745458746235538653875374228578346242525673575252576582265274547284845384653672644114516666267574626426446
641656535461165653134137137722477635874264666754876537273748764746874224483372752532865454884388684445242625354215454736174156554454113515152
251151226161462453633472466415347646547633244767443532463535583635635877275735264463758778722233266528342272775417356141135631314376665444451
425632161465541424373523554243462375236228647728436237224244444783665877572637583426525378746876552776446464147565673615224667543761522432135
532454562315245552355534656643543315415435287527884778223325668522753852474448867676375387628636286225571754523771223257562736755636513111414
562565135566335125441463772322476616346666766454646466557286832778843766453328868242552727864437867631175455255327417542446331156214261133214
545556525563512364764355571215152443741754226655642557247686658685864827574832252555434336427852877136574545437145171514662256641124656632134
134114445634224644124445174544414343456644375627553722884563486256653482544748584575362474826271174547117176154323461247334336214255363631564

180
day-17/src/bin/part1.rs Normal file
View File

@ -0,0 +1,180 @@
use std::collections::HashMap;
use priority_queue::PriorityQueue;
fn main() {
println!("{}", part1(include_str!("./input.txt")));
}
fn part1(input: &str) -> u32 {
let heat_loss = input
.lines()
.map(|line| {
line.chars()
.map(|c| c.to_digit(10).expect("invalid char") as u8)
.collect()
})
.collect::<Vec<Vec<_>>>();
dijkstra((0, 0), &heat_loss)
}
fn dijkstra((x, y): (usize, usize), heat_loss: &Vec<Vec<u8>>) -> u32 {
let mut distances = HashMap::new();
distances.insert(Node::new(x, y, Direction::None, 0), 0);
let mut queue = PriorityQueue::new();
queue.push(Node::new(x, y, Direction::None, 0_u8), u32::MAX);
let height = heat_loss.len();
let width = heat_loss[0].len();
for y in 1..height {
for x in 1..width {
for d in 0..2_u8 {
queue.push(Node::new(x, y, Direction::Down, d), 0);
queue.push(Node::new(x, y, Direction::Up, d), 0);
queue.push(Node::new(x, y, Direction::Right, d), 0);
queue.push(Node::new(x, y, Direction::Left, d), 0);
}
}
}
while !queue.is_empty() {
let (u, _) = queue.pop().unwrap();
let distance_to_u = distances.get(&u).copied();
if let Some(distance_to_u) = distance_to_u {
for v in u.neighbors(height, width) {
let new_distance = distance_to_u + heat_loss[v.y][v.x] as u32;
if new_distance < *distances.get(&v).unwrap_or(&u32::MAX) {
distances.insert(v, new_distance);
queue.push(v, u32::MAX - new_distance);
}
}
}
}
vec![Direction::Down, Direction::Right]
.into_iter()
.flat_map(|direction| {
(0..=3).map(move |distance| Node::new(width - 1, height - 1, direction, distance))
})
.flat_map(|node| distances.get(&node))
.min()
.copied()
.expect("no minimum")
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct Node {
x: usize,
y: usize,
direction: Direction,
distance: u8,
}
impl Node {
pub fn new(x: usize, y: usize, direction: Direction, distance: u8) -> Self {
Self {
x,
y,
direction,
distance,
}
}
pub fn with_distance(self, distance: u8) -> Node {
Self { distance, ..self }
}
pub fn neighbors(&self, height: usize, width: usize) -> Vec<Node> {
let above = self
.y
.checked_sub(1)
.map(|y| Node::new(self.x, y, Direction::Up, 1));
let below =
(self.y + 1 < height).then_some(Node::new(self.x, self.y + 1, Direction::Down, 1));
let left = self
.x
.checked_sub(1)
.map(|x| Node::new(x, self.y, Direction::Left, 1));
let right =
(self.x + 1 < width).then_some(Node::new(self.x + 1, self.y, Direction::Right, 1));
let mut neighbors = match self.direction {
Direction::Down | Direction::Up => vec![left, right],
Direction::Left | Direction::Right => vec![above, below],
Direction::None => vec![above, below, left, right],
}
.into_iter()
.flatten()
.collect::<Vec<Node>>();
if self.distance < 3 {
match self.direction {
Direction::Down => {
if let Some(node) = below {
neighbors.push(node.with_distance(self.distance + 1));
}
}
Direction::Up => {
if let Some(node) = above {
neighbors.push(node.with_distance(self.distance + 1));
}
}
Direction::Left => {
if let Some(node) = left {
neighbors.push(node.with_distance(self.distance + 1));
}
}
Direction::Right => {
if let Some(node) = right {
neighbors.push(node.with_distance(self.distance + 1));
}
}
Direction::None => {}
}
}
neighbors
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Direction {
Up,
Down,
Left,
Right,
None,
}
#[cfg(test)]
mod tests {
use super::*;
use indoc::indoc;
#[test]
fn test_part1() {
assert_eq!(
part1(indoc!(
"
2413432311323
3215453535623
3255245654254
3446585845452
4546657867536
1438598798454
4457876987766
3637877979653
4654967986887
4564679986453
1224686865563
2546548887735
4322674655533
"
)),
102
)
}
}

205
day-17/src/bin/part2.rs Normal file
View File

@ -0,0 +1,205 @@
use std::collections::HashMap;
use priority_queue::PriorityQueue;
fn main() {
println!("{}", part2(include_str!("./input.txt")));
}
fn part2(input: &str) -> u32 {
let heat_loss = input
.lines()
.map(|line| {
line.chars()
.map(|c| c.to_digit(10).expect("invalid char") as u8)
.collect()
})
.collect::<Vec<Vec<_>>>();
dijkstra((0, 0), &heat_loss)
}
fn dijkstra((x, y): (usize, usize), heat_loss: &Vec<Vec<u8>>) -> u32 {
let mut distances = HashMap::new();
distances.insert(Node::new(x, y, Direction::None, 0), 0);
let mut queue = PriorityQueue::new();
queue.push(Node::new(x, y, Direction::None, 0), u32::MAX);
let height = heat_loss.len();
let width = heat_loss[0].len();
for y in 1..height {
for x in 1..width {
for d in 0..10 {
queue.push(Node::new(x, y, Direction::Down, d), 0);
queue.push(Node::new(x, y, Direction::Up, d), 0);
queue.push(Node::new(x, y, Direction::Right, d), 0);
queue.push(Node::new(x, y, Direction::Left, d), 0);
}
}
}
while !queue.is_empty() {
let (u, p) = queue.pop().unwrap();
if p == 0 {
break;
}
let distance_to_u = distances.get(&u).copied();
if let Some(distance_to_u) = distance_to_u {
for v in u.neighbors(height, width) {
let new_distance = distance_to_u + heat_loss[v.y][v.x] as u32;
if new_distance < *distances.get(&v).unwrap_or(&u32::MAX) {
distances.insert(v, new_distance);
queue.push(v, u32::MAX - new_distance);
}
}
}
}
vec![Direction::Down, Direction::Right]
.into_iter()
.flat_map(|direction| {
(4..=10).map(move |distance| Node::new(width - 1, height - 1, direction, distance))
})
.flat_map(|node| distances.get(&node))
.min()
.copied()
.expect("no minimum")
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct Node {
x: usize,
y: usize,
direction: Direction,
distance: u8,
}
impl Node {
pub fn new(x: usize, y: usize, direction: Direction, distance: u8) -> Self {
Self {
x,
y,
direction,
distance,
}
}
pub fn with_distance(self, distance: u8) -> Node {
Self { distance, ..self }
}
pub fn neighbors(&self, height: usize, width: usize) -> Vec<Node> {
let above = self
.y
.checked_sub(1)
.map(|y| Node::new(self.x, y, Direction::Up, 1));
let below =
(self.y + 1 < height).then_some(Node::new(self.x, self.y + 1, Direction::Down, 1));
let left = self
.x
.checked_sub(1)
.map(|x| Node::new(x, self.y, Direction::Left, 1));
let right =
(self.x + 1 < width).then_some(Node::new(self.x + 1, self.y, Direction::Right, 1));
let mut neighbors = Vec::new();
if self.distance >= 4 && self.distance <= 10 {
match self.direction {
Direction::Down | Direction::Up => vec![left, right],
Direction::Left | Direction::Right => vec![above, below],
Direction::None => vec![above, below, left, right],
}
.into_iter()
.flatten()
.for_each(|node| neighbors.push(node));
}
if self.distance < 10 {
match self.direction {
Direction::Down => {
if let Some(node) = below {
neighbors.push(node.with_distance(self.distance + 1));
}
}
Direction::Up => {
if let Some(node) = above {
neighbors.push(node.with_distance(self.distance + 1));
}
}
Direction::Left => {
if let Some(node) = left {
neighbors.push(node.with_distance(self.distance + 1));
}
}
Direction::Right => {
if let Some(node) = right {
neighbors.push(node.with_distance(self.distance + 1));
}
}
Direction::None => vec![above, below, left, right]
.into_iter()
.flatten()
.for_each(|node| neighbors.push(node.with_distance(self.distance + 1))),
}
}
neighbors
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Direction {
Up,
Down,
Left,
Right,
None,
}
#[cfg(test)]
mod tests {
use super::*;
use indoc::indoc;
#[test]
fn test_part2_a() {
assert_eq!(
part2(indoc!(
"
2413432311323
3215453535623
3255245654254
3446585845452
4546657867536
1438598798454
4457876987766
3637877979653
4654967986887
4564679986453
1224686865563
2546548887735
4322674655533
"
)),
94
);
}
#[test]
fn test_part2_b() {
assert_eq!(
part2(indoc!(
"
111111111111
999999999991
999999999991
999999999991
999999999991
"
)),
71
);
}
}