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 import sys
from collections import defaultdict from collections import defaultdict
from dataclasses import dataclass 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 # part 1
answer_1 = ... answer_1 = shortest_path(data, 1, 3, lower_bounds=estimates)
print(f"answer 1 is {answer_1}") print(f"answer 1 is {answer_1}")
# part 2 # part 2
answer_2 = ... answer_2 = shortest_path(data, 4, 10, lower_bounds=estimates)
print(f"answer 2 is {answer_2}") 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