2023 day 17.

This commit is contained in:
Mikaël Capelle 2023-12-17 09:37:31 +01:00
parent 3a7f8e83dc
commit 5b30cc00d5
3 changed files with 377 additions and 3 deletions

View File

@ -1,13 +1,233 @@
from __future__ import annotations
import heapq
import os
import sys
from collections import defaultdict
from dataclasses import dataclass
from typing import Literal, TypeAlias
lines = sys.stdin.read().splitlines()
VERBOSE = os.getenv("AOC_VERBOSE") == "True"
Direction: TypeAlias = Literal[">", "<", "^", "v"]
@dataclass(frozen=True, order=True)
class Label:
row: int
col: int
direction: Direction
count: int
parent: Label | None = None
# mappings from direction to row shift / col shift / opposite direction
MAPPINGS: dict[Direction, tuple[int, int, Direction]] = {
">": (0, +1, "<"),
"<": (0, -1, ">"),
"v": (+1, 0, "^"),
"^": (-1, 0, "v"),
}
def print_shortest_path(
grid: list[list[int]],
target: tuple[int, int],
per_cell: dict[tuple[int, int], list[tuple[Label, int]]],
):
assert len(per_cell[target]) == 1
label = per_cell[target][0][0]
path: list[Label] = []
while True:
path.insert(0, label)
if label.parent is None:
break
label = label.parent
p_grid = [[str(c) for c in r] for r in grid]
for i in range(len(grid)):
for j in range(len(grid[0])):
if per_cell[i, j]:
p_grid[i][j] = f"\033[94m{grid[i][j]}\033[0m"
prev_label = path[0]
for label in path[1:]:
for r in range(
min(prev_label.row, label.row), max(prev_label.row, label.row) + 1
):
for c in range(
min(prev_label.col, label.col),
max(prev_label.col, label.col) + 1,
):
if (r, c) != (prev_label.row, prev_label.col):
p_grid[r][c] = f"\033[93m{grid[r][c]}\033[0m"
p_grid[label.row][label.col] = f"\033[91m{grid[label.row][label.col]}\033[0m"
prev_label = label
p_grid[0][0] = f"\033[92m{grid[0][0]}\033[0m"
print("\n".join("".join(row) for row in p_grid))
def shortest_many_paths(grid: list[list[int]]) -> dict[tuple[int, int], int]:
n_rows, n_cols = len(grid), len(grid[0])
visited: dict[tuple[int, int], tuple[Label, int]] = {}
queue: list[tuple[int, Label]] = [
(0, Label(row=n_rows - 1, col=n_cols - 1, direction="^", count=0))
]
while queue and len(visited) != n_rows * n_cols:
distance, label = heapq.heappop(queue)
if (label.row, label.col) in visited:
continue
visited[label.row, label.col] = (label, distance)
for direction, (c_row, c_col, i_direction) in MAPPINGS.items():
if label.direction == i_direction:
continue
else:
row, col = (label.row + c_row, label.col + c_col)
# exclude labels outside the grid or with too many moves in the same
# direction
if row not in range(0, n_rows) or col not in range(0, n_cols):
continue
heapq.heappush(
queue,
(
distance
+ sum(
grid[r][c]
for r in range(min(row, label.row), max(row, label.row) + 1)
for c in range(min(col, label.col), max(col, label.col) + 1)
)
- grid[row][col],
Label(
row=row,
col=col,
direction=direction,
count=0,
parent=label,
),
),
)
return {(r, c): visited[r, c][1] for r in range(n_rows) for c in range(n_cols)}
def shortest_path(
grid: list[list[int]],
min_straight: int,
max_straight: int,
lower_bounds: dict[tuple[int, int], int],
) -> int:
n_rows, n_cols = len(grid), len(grid[0])
target = (len(grid) - 1, len(grid[0]) - 1)
# for each tuple (row, col, direction, count), the associated label when visited
visited: dict[tuple[int, int, str, int], Label] = {}
# list of all visited labels for a cell (with associated distance)
per_cell: dict[tuple[int, int], list[tuple[Label, int]]] = defaultdict(list)
# need to add two start labels, otherwise one of the two possible direction will
# not be possible
queue: list[tuple[int, int, Label]] = [
(lower_bounds[0, 0], 0, Label(row=0, col=0, direction="^", count=0)),
(lower_bounds[0, 0], 0, Label(row=0, col=0, direction="<", count=0)),
]
while queue:
_, distance, label = heapq.heappop(queue)
if (label.row, label.col, label.direction, label.count) in visited:
continue
visited[label.row, label.col, label.direction, label.count] = label
per_cell[label.row, label.col].append((label, distance))
if (label.row, label.col) == target:
break
for direction, (c_row, c_col, i_direction) in MAPPINGS.items():
# cannot move in the opposite direction
if label.direction == i_direction:
continue
# other direction, move 'min_straight' in the new direction
elif label.direction != direction:
row, col, count = (
label.row + min_straight * c_row,
label.col + min_straight * c_col,
min_straight,
)
# same direction, too many count
elif label.count == max_straight:
continue
# same direction, keep going and increment count
else:
row, col, count = (
label.row + c_row,
label.col + c_col,
label.count + 1,
)
# exclude labels outside the grid or with too many moves in the same
# direction
if row not in range(0, n_rows) or col not in range(0, n_cols):
continue
distance_to = (
distance
+ sum(
grid[r][c]
for r in range(min(row, label.row), max(row, label.row) + 1)
for c in range(min(col, label.col), max(col, label.col) + 1)
)
- grid[label.row][label.col]
)
heapq.heappush(
queue,
(
distance_to + lower_bounds[row, col],
distance_to,
Label(
row=row,
col=col,
direction=direction,
count=count,
parent=label,
),
),
)
if VERBOSE:
print_shortest_path(grid, target, per_cell)
return per_cell[target][0][1]
data = [[int(c) for c in r] for r in sys.stdin.read().splitlines()]
estimates = shortest_many_paths(data)
# part 1
answer_1 = ...
answer_1 = shortest_path(data, 1, 3, lower_bounds=estimates)
print(f"answer 1 is {answer_1}")
# part 2
answer_2 = ...
answer_2 = shortest_path(data, 4, 10, lower_bounds=estimates)
print(f"answer 2 is {answer_2}")

View File

@ -0,0 +1,141 @@
221111112123113232223221211223431421234233422312143231535322415224214525132414123325214251231222122422133431331343133332311121121111311212121
211122211133211332121231312344123432112311144414235315524424354544513135154222442511331423512341112233243413331223414221112333312313311121222
111212111232312122122123411211113414114234314333354231345141532533115144311545125122533135244454413423434214432314333422122112211321213211221
221122231321333121323232442421144114441343141354135215251552232314544323421141432422435232132143452331432111434413312222323323231113332322112
212122131213123131322142314241332133211314312151331433432332431514521525112255111215513512245345521414332333244343214111231211212222232132121
111123113213211133332414213142233142114244132523312543113125235534453513332535213451144531421355514341443143344424114321214311321221332231122
112232122333123313114141331431132343312335514212512215243544431435312315425532253451451424215231324153324242323341231323211431231222232132212
121221332233222231224131442232331124411415411541512445455233142254145354542423112414245455423225113152214424322124242344141423221131222133112
211123323211333211122314412111342425313421345245115433154452323343413321555222415233151414255251123112353514242234244442133421312212111322222
232133222211233221241431322213431215215314441523115315155443414664425562236642232244533532341552323154232254333122312313433132133213322132312
332122221133112432112231324243222522332235351415545113452424343642435522252532463642525245122225514355233335325522121244421224342323122333122
231311332332333311142322323434233412522544532552431113445423235665326565653443644224346253235333445334123523245544212243312322414431222113122
122113122311421231214414223424521424431215345444452232652434632252546664645223366463664553556333515312321524455422314423441131212221221121323
231323311232443422131123331141154145245552322414463423443346436652335432353526466633423445326431251241142425334132444331141434141133313111113
231311222134334243444322213433553532534451411364562625422353666662653235435633433565255342253426455134333221524133151344131311212244222122333
132232112333224443233223312255345414421123446442243633255356525652562423526325222352324654435532532654151225513443514254413134323124321131132
133213332244341333133313444152512133151134664256455526646556226645443652443546256252553342226336242264151412435525415235424141232322311112313
111223321312234111341444545422525542424562426452465363266654265325642426426352536422552462335564225366212223324455311535434233112421444133313
323123314344433441342531354154112553444434246346544445256444252325244354652455262524433434453336443355345545141425544544451134433213344232121
232323344342212142342535212232424335564556533435262656432256432632674366467533224665223363444445442422554345422151544324222334132334241332111
133223232423323122314421354132153323254633422354453624556642463576647564575576343736322665463634555555225562532253215114313324232121332221123
331322234312332132433215545232512544454244642632334546423456776463666745433757744477763344654443452223655354553331221153325121221421414211332
122132242244123121334125321145424442352326565635423643764456355733534673435777746775553553364635436534345663326145555313115543214411244344131
312123333123124214515442233554454542222665262323236376635734563356477573644544675665563356443624333623523336222421233545254544423322243111222
311243114143323115332443421523223242245562522433655444353365443474337667576333336646545433666422464425646455445652335253232523231413322143113
133434112144114322332345224112265663553552465365755633676643745674644466773357577454633466534767353424364562642263521511222454451232431421424
142311311341424423425235325432562442553254655544743656556735456573764375533444333666374774655744745442245452322446543531413444414212342241443
134143333132352313214413231335362455625526633774433343335747733336566357473646567536775776563474755364332323264455244212452324512132442122414
423211433444515553145523455263344624424646753734337534636453463544467353437475546547537434553466757356653446546523522325334433152253422114144
411412434411121221223155546643465236344343444543563644466477774455666645777455746776755565476675463573544246625325636414552153132333432133321
414244324443524134245345463335543235522337656757743453666445755586586558555887565664547564676656535555776432366432655241141233141324331214242
334111441133223534125246255425436443226644375557576354545647876867744557865447764875433334334747354774743236664256233264411542215324213412233
133142311251453243235345634326326343467357363744654765765757678555774467564575668747885356647463436374736324566526243456351525133213342433414
112312311555553421155326422255352435364445357373733435655874445684648657866648647656784486734357564563733474336662426235315535325111432244213
244143214344524313125466464646325536745353665655344684768788458848875777445665687444755744756453353477333343553262656436423511342524215323333
333314412555144321544534226455643245534546563776756476757645657788765555574746757664787576865447374633677654353555325256556443511355152242122
321433455351154545564233552662355754555437564353547875644585466874446886466586654865565574855546776336567735344254222666646434311553441541334
333334413525333452145225266255227546755475333636764564648666746865456654576488454564888664678554366574375343753635252522546323415443433232344
144331343514123354465665522663264635447667474784886464446756556465466788676875567688847856686657447537454544656464224562432445235433221322332
413221315152411413456453353266446755454477455455845764565878868865484664768588464447485687544868664464735564344572463532326262133411252252214
434235535222444454223342363325363577345366377487855678686567757856656769568577654585567784567856668857366437576764253256322235431222125532333
444322241221114243442636622447465374654467877866478847876664676659558887889886755646546474647874754575456466736354266522623653652345533122444
341411442531322555334253534334767677753757676466478446788645785757666855569997799956777644467884687447476455645755543433542465554221251523113
232313541154334642335436446354433666474774867665664666584896595566586557778559586655766564657765878457675433537646574526446566554531313253431
312354232231515426526564464764375356764454687578884457676665986889859869559679968798856886756557745745755633633734763536256362344231244151441
241224131434342656222526627647774473645767657785755475877657876985775985657596589799776695864657684556446545774556543545346266263444411334114
241425521451526266266526363676774635577844868476448547889685557867586598555588955985995978468474475847845677747367566243254444242133353434121
411445444141354464243464476644565546584874464677855675998855879858667958789756969687859778996654667878645735577745647522242422324255123223231
122334143235166252352325336773467435445888565856769776978898697696695975578868569997865868785466564475758666563545746743224466256241432414534
333453331534554533436454464665345374477484876446597887798687857599987766989575755657555988856754574877476747646634636365523644365231541333145
351243555144622636342425667547633664676555545778897559768759887965777887956896958657967669756767757884786444443537755744563364344644353121231
453535141543334326442335357736767744846555585549655757787788768867688876678887886866975676969956587676474777443554534364264362353563244324131
243141131441454666652234665456466648874476884569765665967696667989879677897789985689999669677988465888646687854363374334235526254461321541534
224442441455345463462267767346445748784554687786596678665675776988899766876779789765678595688769746858666875636657676446455324343525245243154
422331243324543522445343376745477644668775585687865775858569696979969866887787667777885587987665968887857486467566755543346465563546453522251
324544511135434245522553353446556747878686845787988759785668767968966688979968789796897896579769997685566757666767767433425466556462255515512
123534122413362355542733337464368674677788667586787675578998778796667897866887799768975579796679897744786768566346644757372253233665444354312
211555134263235454354664566336365876654558769687758697668696669877866966779888798878966887699667986874487555567556557543734524653343333325544
354312451165533323425547433574768865748745779997658978799696966768699676697868978966899958669589755966448467688335367654365666266663412434412
523215222343532535644535645764774574767865689797688697967886878769996797969968988777979999855977785957455577778855537754735424365422244421541
312543142165252532233657654763685644885577778996775957666769788676886669776797686898876876596796998858477644847465547774756423366345511551524
412314233163346653324366543367368447668784977866789766776876678867869897989787889788997998777857679778857556558866475537774463654224623414342
113131235344463344627665353344666847565845688657576658979698967879988989887989699687968798798978969789578486647453735365334663463523555551532
223211131233542556344447434536466668467446996959559966799767796787797889979888967666687676655785787777444774767643745753545425262645464141325
435514122332566223526657333346644545688457597667795979866686769989779788999797899768888879965889996976656476767864446645456224232426564513323
453145222264234464565637476536488455686686859588658997996876986899977778797797898988998677698788669657785458876553356763377225462555232342114
341153235525264666334663447737887676878648779856695779867869968887779997777989987776668798975785598777658864458567573434673563432356425432521
544322112662522623664645567637658585647797556887575969667976677878989899799988798786898888788868566786957466667747455635456322534362322343542
143235433345625465644543477645646555676669685989566697986997799779988899979777788789696688787566688669765778477544363735446746546246443421423
214121314423525422346763545665864746646699659669557678698787899779887797897977787787886866989995899975754646774687545545446662646662233352331
342411323423564425534355477345784848675477789756986687698968979897877897887889797966998969677897888768778658455484656746555623354626425212542
515411425264662333257767547456787845886568897866679687686976878797778979978977787777978688879989765998576648545787654676776764633632643353352
111321555243253666276657477435656765856688658757677967667879798888899879897778877798766778668657768889647788887543775375465753445636342542251
343513142565442562357776474337675854584865785688576696786679888887777899887998889778687888789799857559564444744754664743436526224356653125351
122242125436564354476646576333776756485576788656759799797699777887978878798888979896699987789659686767745458557847447447567633326222225155215
455444253653265624243756373366854467565699676887698976699777967788887887889889797779877787769986879998668845745646645566547536344642235255545
315425355524562466573373356636658777745759876799987999896887969779999897778889997977887679689577558855777866444653457773747344446235655215213
115334354463445432435633734444688676546647598855858879887779689999997878899988988879999879999777767788665448478475734465667444625425652511125
423411425234345634336576473345866675774576979869777886698976977897988887977797766977786888869588889867745764887467573766733263234444532314454
523413443263255443224473454473575744675456758899697768777696889679779888989777889996776677885567878586665464667446677446764344625543321543221
113353121532262463346334355653374758746555997785679598967897788688988877988888786779686878579969886975866666586844547545675452536566535332324
321152241456434226534577664553648557885775697588988668787876686669967879779689998899678786978589687557654757664836575675773232646463435333134
123141441456266452537765766574457654685844678986885875998696989688668898678896689699867897995656579677575564685877636543377342623256425441213
344233152524565546362645357374584568668744656995676766869867989679766686879896876888897797886776857987865584747665354765372565663253511131111
355153434133422632334654364334747458567566899969777758869997777689797876986997777787989985958885566864864845655567756733732566325625225413231
114431353433356242653544373556565467666855556587979695999999689667779896886888997787978767787986778577566445488746747633556553432555424332231
443543233545335352542436735666744686746585788778866655655677688866968869799897786978685989689787689848667458766764735673454226425322412231155
414355431112224332333536567756464445848844877875766875865897996877996869768866677888877996979995567668565865783377745354646645534346253324133
235451144332323523245644735665365844574777848566868797985689697677667968866787879896785986555795688648456567646335455544436524336535152152454
213214541332444656264344777667653574675778476495676877688778586979999987688988887996769576885897886455875567755577335555626323262352541511151
214355111153342562633346464753443458467464555568875756857877755968688676797898667685566856677777477465545885873553353573322626226345431542534
133424543523226436322465347674534665668856744848977999676687787759787776766866886677587768686985446566676585734473334346356524435644324334213
233443124133452345365245657434633446478686854558897577686999798695965978595977756565987765889685575677688745747663637756234232664443224433132
114432125515122654243223363455347344588585556865566995966979598889779887667558865558578876587887865444546887367574447573544536625255551415123
434113123125243252425646663763563543566558757575589866796899878699876675856886688756595756876645848448588436747433334343354534565424113333531
415312423223134536652245255773674746354458885764844965556857797567878858669856979896855655695458867477655447537744767362442266544221212122552
432512134334552653555622625755577434777566767668486647885577585887856665685769698986899798855886584754444373433343573254626456326513345341343
431322251453143463243535627373334676534885555587787554879555888765755898796875655597577677855765774857676754436743376254244624224241134511122
322425542152425626564554236756675764577786446454486686665587756855886689567858565856878676776788556846733653543437654263566562445551511334241
222223414252541366223232362647453543576548647485456688465857855988788666969886858886768555585874474784675675566734762422536334245533323224411
324135241332225346366256336534777643553637774887787778666574986996558665786975969978558676864565768444664734344357655435246465431522134143321
221323125312133154545435263334564433764747474848857475888775787589885579677589858466776877557474765543755543564367423324352546545121132245434
213314154253123446564546356556467653376666744784865888647454856456888767555755578668748875855656486575537353636645665336243452342352114255414
333232431543244252356436446656467664374744743685777866677748867474847578548578655777544778684665564664734446566644435356345644415515215142143
344433553315244454453563264264354635567373545656455675855777788575777684784447475646545664868786565736755346673526535554323634322414514352112
113142221324341425364462435555657767377466773576874644586487667677855647887778748476758577885888545363434446576222246365246422255515533414312
334143221411221412556554466362455334477466743455558748678667485845867877867556667646645474755535636655457455346243542562444555142215215133133
331133333511344143453426662645223444354457377343347746856547845774856555545884657654774468848665664746356454463442342232555555252322425422412
212142143434511513315234562342634323655755745535646646644656874568567575668648558647756875637564343653357754556364644633342525225545432342244
413234344425515111442134642532565452576573464334654673886665444576757766558688765487844745663765763467677372663235265336344545215343231341343
414233433441132244243434533566343434234434566767437744358866655577764554887858864688567346565453446637656663656236565326615313522245121333311
341324242355122322351314564564323664343747636567773667357475856548787648476867557854354655537456333747467446363535464234255241534332331224232
412433321333545115253524555262526323324574736534733737337567467475487578777646756657444546744457673563474344444434332444423253424153411342342
241424222341541433424353364423642226426364566775356555774454377676457363477374373465736756635446356575644323425256265445553534243521441241421
334313222442411122141435216232435544224245754764566747755357353566367536334375636774736456346447733573566443353366446124441231122554224433334
334243243213212134441314442352554533355435634343465446373345433743555567474657664373375434757476357423664634424235654513214124232421234224124
231214242234133322134344454262434464532444624575453673735666647554467675666757344344434676474556555452264224662625642151241421541121214411243
133422321412321521315415414152632465242663446423546456476453447536464353575437476333577676334375434444534643424625515143143125542242122443223
133313424413242132435143145415624425432323342465636373477633334655443375367675734644754744444543655253644424536623311412512255414122232231332
211434114433312255415534254152336656453436642362432756543657654776563733355333775375767673446532434442535552454415513542345325123344322124311
133142123433422412535554325232543335224353432264466563753456566753774666476365366547377555456326365525436265335521131124331451232211413242422
133214314433124434412522135251352233366535226644666262327435765447754777365657457556356355323555453466525643511233512441244413434314231323211
211131222343342224242524255124414422543653344232555334263535564453336637333375357332635324436463655644653464321142553551135324123233211333231
123233234322243443445531354522242541265224366554462456526553424643335377647376533435555454436353464352634531155433531123441143342414414313222
212113141323343313113124515542132431124454356332452466443364225643625462365425543453223226552266322354562115144321531543511131314334141223112
213111133114434224222123524231135315522345254635366223346536655223235642534423253642526446463435556343332441224222442155324132241424113121322
223222321231241122313412543431335251132245645353232542526652653434224222554626366263322655356264633452155451544521214314122334243222421113121
131232332414122232342441453354552333215545165353623522554352256652334326466453635363245464336465552651524123244224254341331222443242112332222
221131111141332114113122223223245133232545533634662444236455452656226446632254453235365564664624461353243551312122131213222112114314232311312
222332312133244424124314434324521342222353512451455246535234536536534363523264534423664452646235525122552333134242253313211122223324122122111
133131131113412132434133112452142521331241432443442226622632522465465365425423456324662622533125242352152452351342234432331424311212221322321
312313111312231122441141224234215431542441154131222223554646555362246635324644232464355626533215423242522444345313324324324232433411331212331
312332312332211141111432433434233421253514444553354253424256255626434565544362656622233332321331524325355155452244211211432413114222112211233
231123222213331342111342344334333452325414125114135254421553133645344245456665245445445411133352351341555111313142122113422232311312122211223
121123132323111314324343143134432145441543533444112222153335113243211134331544531545514234523115432244322244522132334211124411122131131311233
121222233311211131211241414434334412214242211512332245551314511441334422313445555324141134211225113155154522443414123143421422223122133332131
221122232211322333121343424443211412124113553454354415252111413545523252335341312114233241345455552432344224331121212123341131121321123133322
122111232133212333114241342211414432432451525532212541215254352135314151345452314123533254542323111254213312342213222422324223233113312333211
112221312121332223111124124211412322424112443244532125423544253254455521144521222323412142453225133322144423313322213112233113122332123222111
222222213133232221311123322442113434233223134131232412515351432512434332551315534323552531252322544341242341431223321421331112333333332122112
112222121122221212222331122123242441213424442111531144421232221124154331442433155341112524322525212214112321333234222132131323112333212111122

View File

@ -0,0 +1,13 @@
2413432311323
3215453535623
3255245654254
3446585845452
4546657867536
1438598798454
4457876987766
3637877979653
4654967986887
4564679986453
1224686865563
2546548887735
4322674655533