diff --git a/day17.groovy b/day17.groovy new file mode 100644 index 0000000..42732c1 --- /dev/null +++ b/day17.groovy @@ -0,0 +1,183 @@ +import groovy.time.TimeCategory; +import groovy.time.TimeDuration; +import groovy.transform.EqualsAndHashCode; +import groovy.transform.ToString; +import groovy.transform.TupleConstructor; + + +@EqualsAndHashCode +@ToString +@TupleConstructor +class Pos { + final int x; + final int y; +} + +@EqualsAndHashCode +@ToString +@TupleConstructor +class PosX { + final int x; + final int y; + final int z; + final int dir; + + Pos toPos() { + return new Pos(x, y); + } +} + +@EqualsAndHashCode +@ToString +@TupleConstructor +class QueueItem { + final PosX pos; + final int priority; +} + +class CityMap { + int[] arr; + int width; + int height; + + CityMap(List input) { + arr = input.join("").toCharArray().collect { "$it".toInteger() }; + width = input[0].size(); + height = input.size(); + } + + def getAt(Pos pos) { + int arrpos = pos.x + pos.y * width; + return arr[arrpos]; + } + + def putAt(Pos pos, char value) { + int arrpos = pos.x + pos.y * width; + arr[arrpos] = value; + } + + def posOf(char c) { + return arr.findIndexValues { it == c }.collect { + new Pos(it % width as int, Math.floor(it / width) as int) + }; + } + + String toString() { + def result = ""; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + result += this[new Pos(x, y)]; + } + result += "\n"; + } + return result; + } + + String toStringPath(def path) { + def result = ""; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + def p = path.find { it.x == x && it.y == y }; + if (p != null) { + result += this[new Pos(x, y)]; + } else { + result += "."; + } + } + result += "\n"; + } + return result; + } +} + +def input = new File("input/day17.txt").readLines(); +def map = new CityMap(input); +// println(map); + +def nexts(CityMap map, PosX curr, int minBeforeTurn, int maxSameDir) { + def result = []; + + if (curr.z >= maxSameDir) { + return result; + } + + if (curr.y - 1 >= 0 && curr.dir != 2) { + result << new PosX(curr.x, curr.y - 1, curr.dir == 0 ? curr.z + 1 : 0, 0); + } + if (curr.x + 1 < map.width && curr.dir != 3) { + result << new PosX(curr.x + 1, curr.y, curr.dir == 1 ? curr.z + 1 : 0, 1); + } + if (curr.y + 1 < map.height && curr.dir != 0) { + result << new PosX(curr.x, curr.y + 1, curr.dir == 2 ? curr.z + 1 : 0, 2); + } + if (curr.x - 1 >= 0 && curr.dir != 1) { + result << new PosX(curr.x - 1, curr.y, curr.dir == 3 ? curr.z + 1 : 0, 3); + } + + if (curr.z < minBeforeTurn) { + result = result.findAll { it.dir == curr.dir }; + } else { + + } + + return result; +} + +def solve(CityMap map, int minBeforeTurn, int maxSameDir) { + def start = new Pos(0, 0); + def goal = new Pos(map.width - 1, map.height - 1); + + def frontier = new PriorityQueue({ a, b -> a.priority.compareTo(b.priority) }); + frontier.add(new QueueItem(new PosX(start.x, start.y, 0, 1), 0)); + frontier.add(new QueueItem(new PosX(start.x, start.y, 0, 2), 0)); + + reached = [:]; + costSoFar = [:]; + + reached[new PosX(start.x, start.y, 0, 1)] = null; + reached[new PosX(start.x, start.y, 0, 2)] = null; + costSoFar[new PosX(start.x, start.y, 0, 1)] = 0; + costSoFar[new PosX(start.x, start.y, 0, 2)] = 0; + + def actualGoal = null; + while (frontier.size() > 0) { + def curr = frontier.poll().pos; + + if (curr.toPos() == goal && curr.z >= minBeforeTurn && curr.z < (maxSameDir - 1)) { + actualGoal = curr; + break; + } + + for (def next in nexts(map, curr, minBeforeTurn, maxSameDir)) { + def nextCost = costSoFar[curr] + map[next.toPos()]; + if (!(next in costSoFar) || nextCost < costSoFar[next]) { + frontier.add(new QueueItem(next, nextCost)); + reached[next] = curr; + costSoFar[next] = nextCost; + } + } + } + + if (actualGoal == null) { + assert false : "Goal not reached"; + } + + def curr = actualGoal; + def path = []; + while (curr.toPos() != start) { + path.add(curr); + curr = reached[curr]; + } + path.add(start); + path = path.reverse(); + + // println(map.toStringPath(path)); + return costSoFar[actualGoal]; +} + + +// Part 1: +println(solve(map, 0, 3)); + +// Part 2: +println(solve(map, 3, 10)); diff --git a/input/day17.txt b/input/day17.txt new file mode 100644 index 0000000..31a1025 --- /dev/null +++ b/input/day17.txt @@ -0,0 +1,141 @@ +431444433342125215253532112243421421312243436553553344453636546562663445262223253266466626524544425426351331532221114425243121235442231233123 +441141212311422125355521455245244525154336222235236443464623544533326353345334654465356423525455424443363442445114545423443523353533323211123 +114342112144114543311152554541433233552362453243326623466553556255626365635643456243462663446426626545554453554553553323211555325424444242331 +232444321342514552112411521533552565543523542426232453244664554335463465462662266635363635555645465543455365644113113245442134552445431113223 +424434411251543541132513333415242323335534465226323563245265665526554426253643464235226226244354622653623322423614441252215155141411224143213 +323211141535453534235425114254266246224253643436433664554652322544565645226545225335525363243533226556563422265643123452311443154151154242232 +341121223542245313345414352344652335222225354522252226326223624643354663674645436463522352255565655644465244566642531343244415251512444223443 +412241224215324412112143234226463446363532655224263434322266353654733573647333656433436643225663522352445546544252464354322342424241332313433 +424322211125211451214455343254352543463253525652546243643634463533675377734444566667643755623322226653223564362224533224341413422325542233314 +314245435353214233325332556563446522222224262443433536764354544566335676636637464473453667424646232343235646463362453323322444132224511552322 +422313253245145143532113552432524656323422433345636743536646736444354746633337465364756754336753463543345366424335552264555325211233142233424 +331452512312435221513226433363522364444543235437633744354466337344573343667477333756773353644737725656546264454356452363525243552345212523451 +341113122413344211353624234324544424446245425555355564433474755574476573354543755647647455336464656442544652662324322463464414254342415152552 +211311524152525242532263335325465232232354357566574466553654656774556643763746654755556335736555435452463323426264525632523514421314141221321 +412233144222151415643262566654534225322355534456735643644347456466743466545354434755766635354557533354734244646633454456542663411354314122152 +423521155255211142352333236555532652356757344565365355367376777577464543435736766345547747765564344573355343243352654562446442414552551355434 +214225135335435326444424533352343655674344465346356736463754657373663357656533546557455473674756577467433646656224242453663344615535434325135 +452412531235125256646455346534232427463567566464456764334373563375554537367637357454743474535733535557633645245264644624225223424124352123244 +251345513114344324252453226355622446576455334555665766375755575345547637447537764455447664653435353574646773654643263465534645253451524421412 +111221355312324544465542466545326533754637766444445457434646443574753776767475464673456465456345433635537664436322343222664325644631543545555 +245251351322254456554425422523655345574733444543454775647544554564445677487845556575674554553453565356765737553365522535343525225263425415114 +225231213225362552256533266342465463354764535364763756656585574867655847788874888766656735744567747435335637443576426524666425626251214231513 +122235223322662424653465522557533464733673733473444366465456674785586885588647485785745745435544573333767663437647632432342655343353553155412 +224524124354254644324665455563634764764663676543743545757847647684884865868454774565544664583776464676743434346577755454352353234645515352344 +512453455533262624542342626647355556636664563444346754664777778486468565777666455547448787477873464764537563335663765452442535432432664233423 +344141323222423433655432364357545635535666455667545486746674544655755575756657765656876867645885347555757346347667655535244626333254545212243 +344514236663435432425442354476446767663376635548585644456877474457666668688486646867766874658848667377753345446757363453666266653245664325521 +445112252235365356442653744566775375636747434447865658575674688457676887654574857457485685648846865737754445433644574453323324526255323642155 +455151554362624244426244557667374367756744756447487745885474855556768475756866446567744675485655886766333665736773667735352243453664564554152 +145511524452244343542276676375776764774644666644586457888458767447555568575555554684846487447766568586363336463476776444665434256555326242544 +544224224222564365443554746457743546677657688748576865877874585654756845476447586747484657785655656545567336643745344634433444654534443224113 +353334256355263366437677544333674577646846854777877487756764785648546788775748886477648648556787768487668667537445367355745365262443432222335 +331153656266334425453476473333433565454745754877486464848688568747656688665586845775545864774576647568558857653646734756374353555364543345251 +235642566546433526566773344535554463766585586785757584765464647856887789586575884687786767554856458768586586446375677667777432536424332423644 +534242663636554343764466433345463534658454658575466544574566558897577886596996575696886446688645748868748546633643375364446675653242625624661 +435342243245344224436755733777347475486558887488568655777585796697655697868569888985888755878764448577464786643355463435435536262544342242346 +535464556466432266537443555736334655548875476645858677965969577658888958897777977569965954456767645556456885753733764366645573623236624455366 +256533655556244534755334474477565764655585746878757468587976655786779665598888979799759659967558657557767888645376644777576653566536232253234 +124446622656522466675354756754667754867656445474676659976588977895856686986967986698659857587787585775776565474846456465667667653624655525422 +636645436224246766453553364647884486455578875885799669867975588655959776978655586769975667958674686455656444567745743463733573446364242656425 +662425336325535655436647437445785758455466757645858675565959887778665876977778676776996655768655866768577486776655576535774565433322645654632 +256645345655424366347734575764866448464665856577867887996766885677859955757656777765858575656697567558464665568664455556444554577454364356632 +253442236653276643455345576366447754858787886877798779685656998555897756655869578785975986575667575787485647776455744735737343644642622542433 +352263533244647346654667435657555658486487687887675557687999575565578957986588577769767997668968656766584848765546867763376676774532352233665 +635225652532634456555563365566584654687576586599767566985975995687979966855756756899976896958575875748658888747867787354543454345736564556253 +446335322523756545545576468587675848885586956688968999996585589965585856665867766979885967769775956557458747844546467565353366453453634346534 +633436565437444336473656764578644744748764978979766759975798985878989788898988885599555687887585567564847777476668687343336774555475566234345 +525424242346564764765435744776455657487486578865776779659787678876899888686699677877857676788696675895686767667765655833455366744434632566353 +462523443435756337655457578444565455656477699557767957555997679666796697977667899877776766955757768969674676685875478745555574345453242334225 +233334346476355536744677678847455845856955887559856665778988899876878877779778697997977995995559785696678778648647774757437634563365544456264 +424462463636744575475346755668644788688958756665555769888866687879677889786669778696987896868777758887885847748577866776334476433733745324262 +636422646274345775666664666786488544887796686986566867797777978869689897967887997768868787668898795796555846476856775884475636364637346363354 +466264446767673637575767777744868485455797665977658587978769786689986699688776897789766886587595999995966677856655864848377353745333534333256 +323356443456575574733435887785774688658758756765885876996869889669699697787987766668696799877755855678679648557478766756644757433566573556546 +464523454557657554473746475877848848957885768795897687779977786776998886968869799869888676675975989668776576484545774578474633555376662524634 +253233444343445746564377484466545765796799967855559686787989789888689669687788779767796666888955885869578694486686467887636654537546636323236 +224565365433436637463358756668867647756578896956597698697688776787866667996866786696976887876599778557579777858748677787556345657675676435224 +564625527377575653755448654888748546976897578876879768699986989898769698796897999796979888868655556799597967668674486577685655433577457656653 +633526426547434747645845676665488757995987595897598996787967986968768899778878999996886777799958575875866597644888488574564375546574575464552 +423342447654555657355666575767467888666995789968669779769779996788977789778888988779988768696986775966859685686468746576475645735467474663253 +342623334365343574455858484857584675585798778975897879878699668677987987877978996877698797688987977657986969654666465665746574754554566635423 +662326546556546576668747668665658766655777988689768669877799697977877779979978797999779699878796666865579798776747674474787666553555533446333 +352645235366675467744888865564777567696687578878669896976978998978897878997799777697779789687686865576576586554475785448588556666357567524634 +256533643635675743538685568655488577665687966698879888668976888998988778798788777779997779888678887785555695775866766687745545655353765746223 +255352653457346573764576757566758656889889966578786786768896977897979998889889977889977989987767889855999855884868487845868443655756744463362 +545626465757334355658687844764646679798556698589989767679866877977888797889997899899966779777989759699699787868766678844884445744757333525462 +342463246744334433576478546686556655768975885887889798787869787879997887897779798989666988796899969886886869775875544486864763555533464752355 +232355247356654775577854464568756966966957789697868966687897878997899899779999887799976977888886667898865775954448775876586573335766476553546 +453555443465554774636755674585754797888976997677669687779998978878877979887788889999779679978978997657599996986778465468845463453566734763352 +462422655375563634548667467766467995885686577688876886786797887777987987797988997978698699798878775768978966694775765546558634464637667563244 +642634536573635547344854587874448855578677895969968779678867889877989997987877779897877986789766678698875756767674675776757566744667764673562 +336566657633576744374775546467869859877577958767866689779687977987997789789777798797888868776966676769655898656744576666785653355355446456342 +352362467354574374587475448544567668687678678887668867678797987788997897987897898978778999779879967866688767789644688555645766473764763475326 +532336657635557364734456655565845897775976666687688997679989999887978779877978797898896679999966798657666556675756657665788437447376455454654 +653426263346665767558646567646856875995697596868989997778679798877998877797777979889896899896888886698696959678776856688774775736475536445426 +664436353773544367466765676786467698956695595667999679687767888979997888797898797878699897888986889778566787698454884678566344337677344436334 +266434677535567444568845456466464998869598888888988768767678898888799877997799978898799878869699987665889559595766667686475343557775764563653 +436526564657436645364684448856645879795787977976997797799687989798799888899797978877869798679788985569886667678564668458487766377753747546632 +435245564775676645654577545787666798798796555788987897666679789977777988778778789786786678678678986656788575586466578666654636547577366726233 +365226375356737345757557585856484785997989657686699966878976697979887978797997879777987979679786958695698858688576755647446364777767576563236 +652226276454545364366858684787588876897669589877686898888696968889798797799799799769778687969897885886576565555467654546548656763565445356222 +436226344366356553578758587464565787669685695786769989867879997777888888778797778967986987876676576868679579547566878778445553575655757524256 +232464644766735367633767757466478476968675875796769798887686996788788989878899796988896698776669758555999767657746546758773334573537453455333 +442436267654755753364785544867565697666978956755666697876998886689779797877886786788899786799997659987686785758486756688484756645553644325322 +645224323657465455366557878584778588999666767696876999979978796787889878698876786879878798987866956957869956846877648587556645454675733262523 +636333553474655466337664477466557759658958968696696696899786999988797999897677788987699797677688567999685569678777847588686667737647556434656 +665562445466354563335767457675468865888658967777687786969768768869888969766797678677778888888998796895989875685447586645877663744754653546364 +633334635564476473665765445585747777597856699787686768866887686878977676978696989997679888696686698595797874445887674457467453664464445362532 +342222355456456675646778584447777857796678556767589596778679666967876886897687678886876899999697678968558787876587756668545464347735734332343 +423452323474364673555375484848586874659896695699588897798869986686998666687769798699998887569598968598565988867854484877447334564675442325223 +443334544755344435355475487477846876575857786798678698777787879666766769868989877766898988777886569685879588574575867784665473463563676635446 +324325253654537464533564458568745866665986577976776978997686989898687666999668997997888775587888668878955545454686866484434453443354746433534 +354544333535434734437336668877455888788675858657667598889768876896679868688869796976686967858675567877795688746556565565463555677464422355363 +553624226566576554347375446486568867755789979568856886685798896969899688897996878889799999796968985978895787685665564864665473666674636342436 +342664452636447766734773558567844445676866785755759778587959798678769768896866966867875767677759966585785764658577584666366764374463423326224 +423536355537545444377473484774874865667876996758757579665687687888877768977796676696766758555868757765768786576575448566563353577774344556654 +562525523333374755775667574458585654557444956887895879586976888976967888686986796966798676589556568754487744678678858636337646374655632253466 +435552326436467453557747358464667686445868599579596958959567669988956799977957766958898585977677978894444587648876655444663563677473362436245 +246622332666775344664666547665444554768464875977786795755859856898965597787897886957966887585986589974748585874645475363453633733362636364433 +345436642523245674636453735746546675466857887867966998765958676785775977676566686668797955977959655587785784457464433755436437335766463365524 +344345442666436675376557774557487678866756785896869677957957567595895558796875965899665799855776995875664487468767657466744655653532352533642 +446456565323623437454655663476675874758688884859568795797879695867986767675588698799895766795765756868575558554744333557576457564236254555426 +544534243256463636476347377366767574484764464454799588695975798876869756879959789866996759655798758864886875644876456366444347345566666234663 +432265233232543746775353736653568885474546686456865766677866796566688556786685887957787965689766886846874544787565637546654633766253452352664 +544453523654523573364466647545666647758554648646564975778667775666695966759875569689569996684674564578484845767533743776463565734545465534332 +563563436664343533477575344356536654568575687588587596887699568899958688975968858886655597676467557454456444488435434637663674736535343423446 +224622636663434365556743456656765544564554777755685464577688756988865666998955666795698796484876868677875485487357457475634736463554532644535 +225223635234226644555573633335454646464475546648878745486999596887889986599787957557757844674476477888855445475376346673555636655333662564332 +443465524664445553764575757755635765844868854678686566556587697578686756755558856589857787466465657885864657456443554573373765455333644635523 +334465426235336352535377746477343474468765487458784765867484454956968589959687766465458588757868876567745877673674374574677656433322524622454 +121552646554323334566537333377363346774476754455586744876856864657756865688575555844578466655847884765576846666464775737575725355254255254542 +313234642456535226266737677664646677468574858484745464787876556444766585855565478648887547874664774577448573374737456653757534662444523442555 +442144463565624545324476333446644543547875868876577474556856656588444658557886486654476855584864457854455464776757676733452363355352462436124 +321314365322456236443653534643334633776357547848644646845446864485684565784676466647747646558784456864646676643745635743745556423253236443433 +412314333525565544443457775464637743573633877668864584874458547584577645844687785646467678745485775467566546367677473566563233632222322253234 +223545532253536225536225764446353533463463538756648555475474574488686858887485565767585885844644788445334477553345376666355252434364555623231 +554215342624624553436565257566533337475345346668486685464646847758788757774476658685748475657454445537766645767776534524426636264663335322221 +342535513664224623365322237757564453566437747764784484685655847565864584748655757575766548867554633747365635537554744632462242236556543421551 +334333144243653636552336453775335734546545563673457668665688546454657484465444574576448666747775675334566565567745733333266356325445432235435 +451152255562234364636434362536536334557674556377373587844784454654446446866576466766486557543476367653446463576737352564335222535636331421334 +434513212142263243553443244334344667645536554776776376745466776567744676654686844765588663763634344644345733357347235643544443652545322252344 +441114424413362525454345524356654747544537653663364666646868844447686775777656888466565354357575635765375554654372426544346333335324433442531 +522543555431235236432563532246455474457775753646636344533433746584446685665575466857437676574637636544665734357664624625243453253554454343144 +415244541212424326353544545444323377575637657435447463756356445736347384675536673757663347563443534574464343577525525466443224332523212233141 +134115225135544664622244423636546464375443563337774665344356565734346367674677374753446776657534435363344636625632426425654652552142424444511 +113515522155225634535326626222556555736636465655356435435463644734746475463654666446373646433567635634346656523235455523244645662312542542135 +352125333412415534656234355564535642657633374733636576665673566567534347633776545745557637366434645474773545655645366333654346251313321424133 +152514452251142116635656442536556546546633347544547547677543475544673464643466754567666345667436356753736252623436526356326335514455253414334 +411423541315353212226363343252264242255573577444543547476354435364673663536636445656344747356745336444564565526644563424346354545122442243151 +311111113314131324264336263645644326644225663357474633663533346745674667546355463646743636356473456672636455325522654652366411245543244255222 +311421534125232524123364225644624446522363446763774576377673563375735564435534654665463365757436354262455652632543353542455435331351124135325 +432523222344542524224322266663425566455266444256646763565465565375444334537366564353473457465536424565636365336532654633654553411355115525123 +342352513415545111414433356246655542524232632654444354653644533637464657533645347674563635464652635663535264522565433636521115322542243422542 +131244153145322455444312533334633246525433425562662356557636563556546773335536666337664544535542232443552224266342546542434235141441312451232 +211111411143311513152255335252466425566462636553643325276554673447564674545764477677433466253235433442235256455243355525341554254331145124431 +223122245122435534111132445226663326422545652666564553553423746374765563767756454553332646266333242553454523354226222112454432421352523343141 +222434131211151314424512555553255525654254526246224542346653353324346347462226263443225455265266643334543646433454544523522121121211545331334 +324131241324344321552242521315633242334365654564322554634222236256455652355364223246525562425546463633334256562241541321142244124142552121241 +143232241255242135333353413244522466243546636356255633532544255454634464543436435323266433552555232645622344244522432441124145313235232241421 +223213422231532522211423333214543655234545523356426236564663242454326663633626623223322242665455432252566422665253152112312125425155311411114 +243343243443234323113554133135113445364265666343532335534624323444265633364265662465262353425622625246633336154441134534414522341543224211321