diff --git a/src/input/day17 b/src/input/day17 index e69de29..e8ee175 100644 --- a/src/input/day17 +++ b/src/input/day17 @@ -0,0 +1,141 @@ +112222221323213113333323322444342424324235235513233424441521421241545143411145334442432543231425554512423123113114232422242322323132322123322 +112131321311322131441423422433434243225123132352335324453212345444231322442352145135542552454212421113553344423244123342442124331123113111113 +223121133222231141414442234343234443245521353512543323315242154222243251314332452411341515252321341252252352412443224334334423431311331233132 +133112222131222314441334144443223232435425542512121331552541522242524442232241453321512312523525314513351154532323413141343411122222321112113 +322223332322123343222431144122111132424322253553532251352141344412415524331232153525524452112552433423233331423314432421441433324223121332321 +312131333112441323343144232223412255122131134231531222121445422642255246544344351542431215224223522125434152553131142332211443134312222231222 +211211333321123342334144132241233125151214321445224333231666326363643365422544542253625335334412231343533453513253132434122214434413233322212 +322212232222212211422412332251353342454542231312144243545346225253223636324233543632334462331141244415524124153133313132412224312222312331223 +322113211223113212213314342153433525433231555553242434356463363265563563645342336263523343224234524225243335241315411121134133421334443112231 +333131212121412343141114435445224133135245342435446335634363353522253334334325533246432443233534232533451511221534433232211341144331442123133 +233121313211411344244133551335321151454244115435646626433463222346345336345563626454252442243263621312153524415454353452143344333231232312131 +232232213113312132313315315212344412523141424345323355233264433452535644442424523432345335464524334555424255155321443253342432143244233443221 +222312133141411241134354244325155122343355365362644533322246255263355522354533563443355326646646264224131252312153525411224323444133232224333 +111244131344141222413414145434311435455622444665232334443532362335566323622352345532434556256524446255655425132232533115524333143121243132233 +111244311324141411414353111524355312152244242424233562353222623365626223436624662663526623323346624635656242241331544213244531411322111321212 +121424341321422213253122452544151441266334352453236555222246466353633533663225535523525353526632362352264321242524154533123152333422233411413 +214234314114323314314113432131313366255232425525656542422233234633675447633376624644353253553454655364562265441352535145552134124131432133133 +332424433411233341444552444214425242344536442265562456663425666554773446347346677757322356235433365252453666562542223545254213234341442413224 +224324313224121122231213334354554464222243262245563446443457534436665553377347573536453754242646426644353462646354224534444454111443421424223 +344113323141223424312532325552433532226426525244252545567446457377467376776453446546455346324422243324355266242461231132521221421334244122132 +121143243442251514121142215433466252326566252463554376575564647554466444643663736743735467656325234634366624462435225541155451213542412123321 +144144141413521534533235234243446622523424443543366754775333444667747447575555647346575553475442432323322363533534442254251333554224321322412 +133134234431121245414221455544552355254533333554765767646635755346377456576745633435554465565446753562643346625663554454551533413451121411332 +421312141414151251534535145545334635454544355454537445775735777476335374453663376445743543376477537535536333666253254644241451115445221211442 +214221242454533512544542256445353534624666364447645454474464366777664554366343344656674345645533773656334632346233242444145331553411113233212 +334433322134135114521523436665566232456236775457364736647343457564436443366747573543346756667346554433432625455645563443212442225353141432132 +414243144525445132532252446445235642322545533565647777645656674454736444665656347675347444337755333633734244653456533533542525542355122224112 +143433235535325323514555652344336622663673333376467736757366664764488787546574753344663735335476637633573446363332324444531212212313224243124 +233241124442243342213456255656564436473537636467545543637434558584544455845477658673347754347766475535563665626236564655445414511114453531231 +122413431433152134134564353264624256377643443645443356354755477477464754574766768774754774457343446345773673563325242632444445145241315521422 +444312155313125142555226522564323545655757443647535433658788465575486755656545676476875673454545753454675776324224234622254632245552231332241 +412315422413422234626446663654536753546573463454737467446466876468567577575758846484447444874336553567564657772425335653334653113522255423321 +321153543234545221364664522445565745475535455445777484645858586885856446845646587785657668865545453463765545366662426263665424333352132235312 +343333453445435345642254343233244467557455636777477667788648478884457487868658844576875548665767473445373444736746656464542536352221113114241 +341253351244311554666363623465443773334565554654657584758574446865455758468854764677665687585678646675377744747475523236366532643224332224132 +344411335532124555324434522354736737343764736657764444844874845687784647454874576766784678446644654643667667447774422566532425225453355452534 +335114112251353562263552553356673377666433457758767754655756747844667745777466447655544468855548654754473737743747666234326455632232214442144 +225222425444416653643232666446467743675765358546585488658774865746464678468857578676487567565468775655664634567643732532643543645445522444252 +221255251443542444423662624434743655647647485755544664645558854665855956758744886447777544574446664753567664347436446423353325652523452455435 +212553341123245524653233356344465547467357844646488645867475658779695667557996865565887876875848758555665345676567653345354543456553242425211 +124324252454252354346666635555463356466366764765564874466577697988975997976596879775875785557748456786436363464536777534565566666415253122423 +325111152445523442355232556376357645446586854565545874487796699987869778898789789758796467676847647687674374754666446655266222342222512121453 +422455452455632236346335347563767755665865664864458577856687697697897757575876756975777785766686667467465453645675354336442536246544213311553 +152431153324634643246634634574537534484787765688676758867558678897769985796587985868567587844664676845854866536343764366223224355552413433533 +455225414512433464335335554663376546777756858575857696858895899995956775869658676989888796556684445857454545543366637447263623326536514243141 +524115342224323436366656644773636343546686555477778786687586657565875696796775787557759768554777664886776547534776477347433234244365333451111 +215421333526242353653636465465357547566845467548755577777977975755678656957696899555969955788858768884546477536443756377733456462466513124145 +453343353526463442543557773466473748788746547586678875958676769698799659999768879799765585569898888576564856535336575675425634662626651252524 +253412222242626222432346567563634477887454588479765758656676778675685677967575678658786557595758658646657856867375547544646264635345664312123 +555512245345353565334333554535755475454656658475955558765596999697659889686775666956766657687698888564546674855535355576535662632423563514352 +452155524642465255567337367636637568458754776657699979565958998997688697897669678659885685585577665678484556547576343653353623364236355342114 +251134115535345254646474773557574754667855574897588975769766698986877969996889996798555695987767765456474685856753434536637534365446546512524 +313234422435246652257534377665385687648665645596788569696786789978786697996679987795559598588796966846754675786557357475557342553432222432235 +513131443646224422574544654546745887444758657899677778786859698688967688698899668788865595556967568456774646675464566566563565465344345254345 +425125562464224254466637537343365546548668599688675897685696699869799969676788969876779977789779687665687584686536777347563423253545665611435 +345451266444536222376475754743554648687454696595769789668789768977899967996966968676969576965995986698566866588446465347463675654666324235435 +451335564564336426355565754567747765474654777658589876896768999867979697679676878696679769696986599685888778787446443344556555455335666511243 +431112634665335644734656445467555484658575796976986567877688978866769989766996667677998695589967789886865766456575464745767465445354254533555 +512433632236422233776664544337856564786655959898796968679978969688866666876789969976769966596887996859656746868474343474555433522552365631223 +411221632443326333353345355538785468788457759675657968899779969977968978967766967698786999959959586566666855866545536435345655225424564333435 +125553244225343663554546647668554777488497895977977977989879976889886699798769789866786966768689855869648544654476666754667546332352656242232 +224355554426226427543567755487476465685779895867885986776697769877977788779899876877696866699898577596667865786755446366656764525345346652214 +543353654443226563375653756685788855864976688677656786798678878968897888877788787766767677667999799788777566658554736376453746656236265643521 +333454542665465244564546543385875577484956879587989997976867878688779877779997867998896676779588599977986446846457857575453375222324526534133 +434423626556545553466446475455488856664559988679798669679776696977988889799798779898769886668685688567568867666455766733573375324254424424333 +533225466264523655453666547787757785688796959979698979796876798987899788779899877998899786768966859997774474747556755453774466746452244254133 +233236435436355253673373463578478745456869858986757697679796869799978879987997889769887987869577565596997487848475864337675756432243623633531 +445443645256346277544755436848467557768969758685688896676868978787989887899889787997687789898558998998759547884884863344635566465645554432354 +124155465565526266556563654686677668556868898599757776778797887888988977897779988999686788676895975665899884754748675746476666446366566434122 +311322632636455664545565356654586555459659758788888769778889878778989888889879977768787868689659588787568645657844856674376747333534522446543 +524415343336265273534645664487885774877899958977789878799887987999778979989898899778678779769976887767897486768856865666347536432242456664542 +252235255524462643653563335787488774465758755559966788767688888799777989978789988799689669766798657798896668866556647757454363523233452432141 +554143266442623573465776464864468677779678896788767696997998798878978888989787987789877668977695698668769775476667456764644553534342535266444 +455413536263265454754374665847578657465756887596786796998797979999999888879788798976888688779769986569696858754764553336674566736535245655151 +512114234634634573767444646846458576775777999777987768878789699989887887989897788796676878897867796888566884847756544464756535425534226455315 +251156443463246365364555474875454467479655999887576896968768978899998788779887897789889979989657699786956644467567774435633753363336532323342 +141445426456345265535356746554548684745767559885568779778776768799879777888789989989668769966686595795575865744764765734475776446243665665312 +255313332435652474564576376656756744686675669655557676666679698877997977989998789697979798797968689787957447875468666344755353652563622632155 +224116423563545324743733743365788745646698588756789896999878687998797899999988899798788669896659858787568855455865464643565533564255544546532 +221516236634252257644567373678456477746958667867869687797688788679787789789998988796696699996767866797867748675884834535654553562232462446444 +222111335644233545747443657487587784678587675977665966796988869888777989989898699667968869699867555599766476745664645666775635552226635533431 +241152326523236647636365537758576574785686665687979566967789886979989789789999979697678878765757779675564544876778754766557633432263335432511 +452223665243224356754333346474474678677576675785985599688668677799798698998996677899997797955699567757685668857564347474546464442225462343142 +423515353434446536474447535756864467675796567988858996897968776977898767879978776999866889875659796568976567787558564335566653354235265322524 +424351365564252244474735573334647754865559586567858786889698899876966797798786877779998665988798657599446747744777353735666344633653366633443 +454144532463464222765445754444565446664875987986567866796969889878799879989896887889676866687857579687846848686587656737543663254363266523324 +331243324542246263764737537754874877567844787886598656877688968766898868666676679898686677588986579575675875455856366535446674342646656345133 +522321542452233626434565356637848767848544675968869858758769778767787777697696689977777857969959787976545865565865465336346655334223624541112 +114331336626665542353463356774785875587465466585655765656796669877699989689897868896886595898867759985887768874677765363433443254336656344332 +532434544636522322376363476457655864656568487987665885799596699786688688769896699999558576757757888564444674457475554463333463564635325254234 +124123254356322652374367365435367755646457565868966797857755878988869898778676899889996578895679979747465484577746366674577562655552665354451 +355345424663263264544445543664667585455685786595786779565869857888798889686986766559566865596859874668875885786376666576364542563332653314542 +325314554354552336545637736754754776744876584485778875668658679979997779896976785597858967597985685845674676484745335436656336624544354211412 +425414121655523344243575357763653747765444854467696766899955596658589979895566586798588797797556785654784457786766733553775344335552245323245 +321544144325652343334575753536347564556577486666588986855888695796688659778786685995788887556958887766558666576735457565562453342546642134133 +233224244454245562454544567466375464478684468664878689799895787598577866567558998656655957865877684666685656557544654575652253325644325245452 +223253325222626422232344673743536775484847887564746977799768676589955866865598778776977777898654875857658564566565663763455236326342652254352 +155252422533226225634556656344354654464548688886765789889959975988897978898976859996899559995865644767458876575545536564442453242363535453552 +153151534534626342354465665744754474644684754445886465878699957799687876669595855957865598785658456874788777337375336333556425554625213551524 +114131451313553442645435336474563565464846784747667764766877599656867686898598866888669594748747557867644446754575776643342566446456354515545 +341445155413444265442333676464335657464657465576446677768796997589788878566978557586958648788844587858746674657357537556434652546423525233113 +145555453252246666354553464435564354555574754444686748488899567775759856599667996866868645877786666486875457454653577562363344343353254313251 +143522431434132223562456236436453466574664556457854457784587698566798687887857966579455846478558567867734776443433564663645232333432153533433 +215322345321224335635562467377454444547736774447848748685756479895588579586889995685457756468565465686547776773475577554245422325222111541441 +341322153154514433556244432436566644465665747645578576487455785788898555578675846854548778777465446786763336667574642346555656344514521212431 +211411151325556343533222434533637444454335645656474784747848585745568857858857586746545487766766747654736763544346624246343635345312442334513 +332121414344532346433322666546554556647353675587785568474748578865644484548648855868467678744684584637444373533334343524243655231512424415224 +411524544331513352322333546664576374474473653477646577688768554444786477486457545666878757754774535354377435745536263264224334353132254241153 +422211332253552135663623352665455534446547756657668474757847555474767757448784477787467885884668463377464774543773322646356226324142454115544 +431332122243114415654234442342364454375577436734766474846574566767468866458556744747578844486837345647756635665625464262633224523334511522341 +224251132223221313453424254225224554354467533673735745545644556487888454588447577457458774746447435534547557657555442633434462324134522544331 +424111421545541554645653335265444456575347757673576457844645675546487464587674555767765667574773374336533537762544524643353364111515335224142 +223234224455241252363466635222362536376655666633577657645755565564687447466785887788764433664575544537646477666565263426556245422143414551114 +233332452421231352335626354345244256743777467745433457776474466468687755585566566647444755553777776556436777656425255542455334512253244152412 +422112411545554131124444622334525554545646447374565554535566388477546575685584468734376566346747454644555546562335642323543314133325522324241 +413442321241543521354365362526422436656465774657774354765753344464456467766744635674434544657564573463535455526336266353232123151224155411344 +242422423415151112523146354525226366645673535545673375435674565354736655476666475464746664643334676575555355355232463523215233452253211124213 +111143333432524413523436454324432264544544735574336367535553357366667456753344674646463476344445756576624653253446454635325453235235252223333 +332333142443531535113424432366223346242652573755667573455376754446553553657745475456557634557655643365263544656433326353222124154251511343123 +242134112312545355525535253554536455434525565747777346444335464356647647753474356773646733654433665663546244642563345314421211224122331322323 +412433132142141334132434543252622264425454662573753773655373564475543446637637735373477366634444666525263445424664645423315312343452144244311 +344332114244241351525142214566224356456452462326344354764475363746334746646337333637737763345332536642426666635663354355254312322132131323131 +131122332241242144224432125432263364233255422242226745577455737735337775364433433366454374736353664344646633533423434332335151212214413243223 +234242214234112333232155555512323532255465263462233466676735734343577734764766366647564433344543423333456355223241544213123541311212142221331 +141441132112224233454451555413534354322564665444243625534333444434643766364477757477656655464463335535563452453345443233435353224242123124343 +144331231314331344132242232413551365336335442534566254452555534665767376357467637446622223646365466462446552542232412554553522134322422114312 +134214113434441242441523343323532134326253624355324322446664554225677656353747222453535646643544355352452322613134131514514525142433223323211 +323134243341144411245145214232341245635335566666345653633536443645465225362662534525445362323226632632245641512241442214122313344131411414343 +212343323343433323221422422313553433425452324663245554536655554326624422435443626436552256464424624352636413242143535411323321222212134414313 +222324211434321334233532534143131311242353465646253224554652653653422435642254245663622245433355456445562454412533254545222221344143341311122 +322212341224344341433245241234425555552453423346256624666222456636325563532446545362553526364423256422345114245213224541344314433124323411131 +111312132413122144323135414215543225153444362322356525452452452356345555632553532222235354333665362624225212425414412334544114331333221143211 +122332344243113114144314534123511252331523132652452542663432643565426622464544366423233522464666352534215412214222541334342311424433423333321 +211223224243324444224441431521434131252451135224333623265442642225653523535653324236342424534552252111413255122212415314111112313322241221222 +212113121424143212343224342212325341112231455145336543333365466455536246252462365264643466655354352314115541222243143143414144342122431213211 +312323312132421232244144211445241435551135245234253243242342262455222645633446444243345655121234353431542515144235524141411311421233123132122 +131232212122341312221232341344525554312435154254534131334556526542542653426346455252353331523443244421444242555313322312124434113321333111133 +131133221312324313412312432243212515351341414545433521154451412333542424643536635512413124341333222141133451421242143433422134122332233323331 +231113221233222341232124132321211451441554134441534455422411151422513425131244433145554542343113552114533523252113111343313323213211121131123 +322213212211112222114333144342114324353155512533222525434225114221442421414253341433251532554455214224244211311142212433411431311232111313131 +212312221113133244413331343342212424534414254421312155554511123444113433511542332121333125153343511524122121333132411431123332413332322311213 \ No newline at end of file diff --git a/src/input/day17_test1 b/src/input/day17_test1 index e69de29..3c85086 100644 --- a/src/input/day17_test1 +++ b/src/input/day17_test1 @@ -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/src/input/day17_test2 b/src/input/day17_test2 index e69de29..3c85086 100644 --- a/src/input/day17_test2 +++ b/src/input/day17_test2 @@ -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/src/main.rs b/src/main.rs index 9fce061..5fb72ce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,7 @@ async fn main() -> Result<(), Box> { Box::new(day14::Day14 {}), Box::new(day15::Day15 {}), Box::new(day16::Day16 {}), - // Box::new(day17::Day17 {}), + Box::new(day17::Day17 {}), // Box::new(day18::Day18 {}), // Box::new(day19::Day19 {}), // Box::new(day20::Day20 {}), diff --git a/src/solutions/day16.rs b/src/solutions/day16.rs index 68295df..82f10b6 100644 --- a/src/solutions/day16.rs +++ b/src/solutions/day16.rs @@ -1,15 +1,8 @@ use super::Solution; +use crate::utils::Direction; pub struct Day16 {} -#[derive(Clone, Copy, Debug)] -enum Direction { - Up, - Right, - Down, - Left -} - impl Solution for Day16 { fn part1( &self, diff --git a/src/solutions/day17.rs b/src/solutions/day17.rs index 2106b43..fcdfe47 100644 --- a/src/solutions/day17.rs +++ b/src/solutions/day17.rs @@ -1,20 +1,78 @@ use super::Solution; +use crate::utils::Direction; +use std::collections::{HashMap, BinaryHeap}; + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +struct State { + cost: u32, + pos: (usize, usize), + dir: Direction, + steps: u8, +} + +impl Ord for State { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + other + .cost + .cmp(&self.cost) + .then_with(|| self.pos.cmp(&other.pos)) + } +} + +impl PartialOrd for State { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +struct StateKey { + pos: (usize, usize), + dir: Direction, + steps: u8, +} + +impl From for StateKey { + fn from(value: State) -> Self { + Self { + pos: value.pos, + dir: value.dir, + steps: value.steps, + } + } +} pub struct Day17 {} impl Solution for Day17 { fn part1( &self, - _input: &mut Vec, + input: &mut Vec, ) -> Result, Box> { - Ok(Box::new("Ready")) + let mut grid: HashMap<(usize, usize), u32> = HashMap::new(); + + for (y, row) in input.iter().enumerate() { + for (x, col) in row.chars().into_iter().enumerate() { + grid.insert((x, y), col.to_digit(10).unwrap()); + } + } + + Ok(Box::new(self.dijkstra((0, 0), (input[0].len() - 1, input.len() - 1), (input[0].len(), input.len()), 1, 3, grid).unwrap())) } fn part2( &self, - _input: &mut Vec, + input: &mut Vec, ) -> Result, Box> { - Ok(Box::new("Ready")) + let mut grid: HashMap<(usize, usize), u32> = HashMap::new(); + + for (y, row) in input.iter().enumerate() { + for (x, col) in row.chars().into_iter().enumerate() { + grid.insert((x, y), col.to_digit(10).unwrap()); + } + } + + Ok(Box::new(self.dijkstra((0, 0), (input[0].len() - 1, input.len() - 1), (input[0].len(), input.len()), 4, 10, grid).unwrap())) } fn get_day(&self) -> u8 { @@ -22,7 +80,97 @@ impl Solution for Day17 { } } -impl Day17 {} +impl Day17 { + fn dijkstra( + &self, + start: (usize, usize), + end: (usize, usize), + lens: (usize, usize), + min_step: u8, + max_step: u8, + grid: HashMap<(usize, usize), u32>, + ) -> Option { + let mut dist = HashMap::::new(); + let mut heap = BinaryHeap::new(); + let st1 = State { + cost: 0, + pos: start, + dir: Direction::Right, + steps: 0, + }; + let st2 = State { + cost: 0, + pos: start, + dir: Direction::Down, + steps: 0, + }; + dist.insert(st1.into(), 0); + dist.insert(st2.into(), 0); + heap.push(st1); + heap.push(st2); + + while let Some( + state @ State { + cost, + pos, + dir, + steps, + }, + ) = heap.pop() + { + if pos == end && steps >= min_step { + return Some(cost); + } + if dist.get(&state.into()).is_some_and(|&c| c < cost) { + continue; + } + for (n, d) in self.neighbours(pos, dir, lens) { + let next = State { + cost: cost + grid[&n], + pos: n, + dir: d, + steps: if d == dir { steps + 1 } else { 1 }, + }; + if next.steps > max_step || dist.get(&next.into()).is_some_and(|&c| c <= next.cost) { + // For p1 and p2 + // Streak gets too long + // Or a better solution/path already exists + continue; + } + if next.dir != dir && steps < min_step { + // For p2 + // Making a turn but previous streak is too short + continue; + } + heap.push(next); + dist.insert(next.into(), next.cost); + } + } + None + } + + fn neighbours(&self, (x, y): (usize, usize), dir: Direction, (x_len, y_len): (usize, usize)) -> Vec<((usize, usize), Direction)> { + const fn deltas(x: usize, y: usize) -> [((usize, usize), Direction); 4] { + [ + ((x, y.saturating_sub(1)), Direction::Up), + ((x, y + 1), Direction::Down), + ((x.saturating_sub(1), y), Direction::Left), + ((x + 1, y), Direction::Right), + ] + } + + deltas(x, y) + .into_iter() + .filter_map(|(n, d)| { + if n == (x, y) || n.0 > x_len - 1 || n.1 > y_len - 1 || d == dir.flip() { + None + } else { + Some((n, d)) + } + }) + .collect() + } +} /// Test from puzzle input #[cfg(test)] @@ -44,7 +192,7 @@ mod test { .unwrap() .to_string(); - assert_eq!(answer, "Ready"); + assert_eq!(answer, "102"); } #[test] @@ -61,6 +209,6 @@ mod test { .unwrap() .to_string(); - assert_eq!(answer, "Ready"); + assert_eq!(answer, "94"); } } \ No newline at end of file diff --git a/src/utils.rs b/src/utils.rs index 860be43..6b4460b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -57,3 +57,23 @@ pub fn gcd(first: u64, second: u64) -> u64 { min = res; } } + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum Direction { + Up, + Right, + Down, + Left +} + +impl Direction { + /// Returns the oposite direction to the direction specified + pub fn flip(&self) -> Direction { + match *self { + Direction::Up => Direction::Down, + Direction::Down => Direction::Up, + Direction::Left => Direction::Right, + Direction::Right => Direction::Left + } + } +} \ No newline at end of file