day 17 solution

there's a small bug in the cost calculation which will be fixed in the
next commit
main
magical 2023-12-17 06:26:31 +00:00
parent 539cf753d0
commit 14ef33326e
4 changed files with 320 additions and 0 deletions

105
day17/astar.py 100644
View File

@ -0,0 +1,105 @@
from heapq import heappush, heappop
def search(start, is_goal, neighbors, heuristic=None, worst=None):
if heuristic == None:
def heuristic(x):
return 0
if not callable(is_goal):
goal = is_goal
def is_goal(this):
return this == goal
if not isinstance(start, list):
start = [start]
i = 0 # tiebreaker
q = []
for s in start:
i += 1
heappush(q, (heuristic(s), i, s, None))
done = {}
if worst:
best_worst = min(worst(s) for s in start)
while q:
z, _, this, prev = heappop(q)
if this in done:
continue
cost_so_far = z - heuristic(this)
#print(this,z, cost_so_far)
done[this] = (cost_so_far, prev)
if is_goal(this):
print("astar: visited", len(done), "nodes")
print("astar: pending", len(q), "nodes")
# reconsruct the path
n = this
path = []
while n is not None:
path.append(n)
_, n = done[n]
path.reverse()
return cost_so_far, this, path
for c, n in neighbors(this):
c = cost_so_far + c
if n not in done or c < done[n][0]:
h = heuristic(n)
if worst:
if c+h > best_worst:
# if the best possible cost for this node
# is worse than the lowest worst-case cost we've seen
# then don't even bother exploring it
continue
w = worst(n)
if c+w < best_worst:
best_worst = c+w
i += 1
heappush(q, (c+h, i, n, this))
return float('inf'), None, []
def test():
data = [
"aabqponm",
"abcryxxl",
"accszzxk",
"acctuvwj",
"abdefghi",
]
#data = [
# "aabbaaba",
# "abcbaaba",
# "accabcbb",
# "accbbbba",
# "abbbabab",
#]
start = (0,0)
goal = (5,2)
def get(x,y):
return ord(data[y][x])
def neighbors(src):
x,y = src
here = get(x,y)
n = []
def push(x,y):
if 0 <= y < len(data):
if 0 <= x < len(data[y]):
if get(x,y) <= here+1:
n.append((1, (x,y)))
push(x-1, y)
push(x+1,y)
push(x, y-1)
push(x, y+1)
return n
def heuristic(n):
return abs(goal[0] - n[0]) + abs(goal[1] - n[1])
c, _, path = search(start, goal, neighbors, heuristic)
print(*data, sep="\n")
print(*path, sep="\n")
assert c == 31, c
if __name__ == '__main__':
test()

141
day17/input 100644
View File

@ -0,0 +1,141 @@
541325532413154112543324624344224545523462433352343463247775356367644347443563677657343744452636444345256642465244525244265544431245144444221
331414241322155325566365653323365536535625534662334663573476555335357734444677365546643757652664642422365232553435632422462652133234221512215
112554244333323423245642454645423242233656354535646574735346555646776767536545363675664344376545324446564445556565525526354621135153235435355
542134154422331162256546652564242435642355365533543774673455365777557755536655735643465454333776472665655234623522255366242524413124115451453
255251321341123224246525356462642224343225675747637556637674454344574363677445356433635464757763654622224224643632533433452565562111314332341
323422512325314235242263655345522326644277643546736735556435374637543437655333567455673737467355557747324624235426622233354356446132133215154
541534415132425356522655256624346542356354755664376557445744476334744743465536755754336555544636554557737333443224244456235552453253423313145
515553552411263445633352624623665533344334337643473435634547645473665346447473446437553466757655455367463472264425533355633442452453213442124
544214521555643342656232623463353546563633737773445375774334667743475334577363467775435576654463636667756476334523533536656245462245431325552
444435344234254322226534364244465643743553676564764753654766336746655546757334456666436757744355475475363753752322654652363332225633645155434
212254314564226533533534434524557665735744735556577636573746346635443434567673456637573775336347467573445644354564643546236422336444661324543
512413516564664633325622256245356466543343753467665546337365773767564653766657446456356444363564457774376334434756443242324324342343553415431
123353233256452626246523564247633554636547453756573433544433634767734774746646334333454765563334375553346673354374344625323266355556655225412
332255633633636625263535525635667435356665377666744736446636545565764577677455774735573646553437444674337675673667576235366552324234533442215
223515534224455443532343536547353366775533575556634444434737867846787446578668886484577736735663344633473457576544343265455656255646522424132
533546255455524366545365473433534564467543663577337455744574545784658875787488555445786876364433545775774533573546546554333656323556264426531
243536232465655424464653354376357773364566775433766547487787585756455675665875447777646868877576375577734473634775475667446545452346443626462
155623534353226323442675576457657475474357735635687785478546678646666448578775875848665587878733645577643473333467575545543563266636464343253
236332623432542664353547736564656564374753553734575675767575568884556566475855685848485654864454663766645444574436774645376563234666326346443
566563433543322264347477663533766545634464344785486845767768576676857744758456485667758884677656583377736363347534654543534433463566366343363
555223422622655243643633767456657367445676386557685464545777868586864564484676684746564574488864774674453365474765677673543553322344356325443
666422265262655424456466666473554475447334585887857754757574584787868465865767476668456448656887677466674546647447665677555645354264545422234
563226422242366336753544557367656637776577466488685868775888744478784748675465587674767868556748745676644554534653566733733676636233445642336
322564234435646554674567377365335337747666488746766875574658858558556446886654658478845478476676888748467647663554665733455654534522662534653
465555623454633354445333653446736364557747546574447766445585886557886678584858674585768866455555764486685853766473443674575654742435232244663
343444333345462646773576447564676464457648776785566755578878787756544684757567485468846844788457564488844564553777663743437536532223424654325
262222464566654745464554475655357345664565788445885684557675677648778887486484857545754565467575775554645447446774764536337467454235536662643
232225445454333756373336674365336584675774545658567674845565785577665785455566754657474747566857554848688844854757347546577375635422363642242
426462234255434436537565533757765666754465558644788765657454865698895866888566895465865676454875485688586685856333457773757443455725433334645
536564545645475634464356564636775454456854468854545858586758597989866959966875956568758855675865676846478855774847754365447455345662662465465
635444422225455545664356536555546766677768765875554767747678579757857766887776587776987878886577846778548485657454356354566563375337625625244
354436534567735673766437774474565877786884768576467564566555758968956556889765687986686987865756455865744655777886676375663557576465533642236
564665643553557647746457345554877775644875885554756589687679868898765598699897996787695896548855684484468767648688664437743364557436753642366
562364622554366374664353374858757467476747844755657868879675897768996785676596568757988866759674578456455784488886586755755657734764436232336
264332654365666637556563657457756576848475886566996976778877778996886659858776775557879588599578845855748764454447585737365747667555744553465
534465655563445763544656646887457545478877655476988979997999978759788955558656988897978799577686578664666466758445658354357534445674363656354
442265464553344643664345447584444584678685788996976769556796788869989699698556766786866576777679974865845548854444757574344344733474574455225
462336673754537443367573555745685445476767587556988776979999959589587557999558699996957667867556799866545875787566646454665453464764454365364
335263637555343654737775467464784587484485585556778965787785896585755977777555689698897596999577598986548777644884557658454754554636344736262
234335766637333434546376845678668845775685795875967556579589797876866976986978887685859995675859857698744557566865874477576747466454533772422
255434574536534753637354455547567667765778595757897575599857866877978577859965585577889676598875996979764867485875854674453536534453655577222
434566643345555356464888454746767544687558976776679678677955866868767765969586776966879879685887568689876475854674445665645643347335464344356
534646336647757665335846455746868845678596765786877885787975659799696678879959758659766657987769879796977674644648784577553743545437435374322
526365737663437746666855544855754657787857895779598797959957869888886986987996999677785876678665985658777858668448457478565773676435774655566
265667734463653544354785567557576787658656969686597997765589868689979668997699966665695687879755957566977888847446885775864346753353374573535
253564543633573537474886666446566577786885575979777887666977886787987986687989689796888859686995995669797794674644768846685566646675743776375
244376776367766633545876687588456786855996899689566986669889969797878866997896967996696665557978668567558875577556657546684545554563757455776
554776573466745737474576745674745567776787959776557766566997867897986769676979869889676685769677969699775595547566885876544885443756344465663
257575556467766775454686547865888598556866678569556978678967688996698696799696998798787699896756867598989557556768454745464684763565434737545
537357564546643674458785745866754665595996755986665596688768796966787669977896868776776989968579766986785786678484777564864885657473634734343
565344664665535477747684777576746876656866585967989886866888699998877899979767668998996876979767669859877688885887574546786886546537664664373
565357774673666664574665685457558689795889587659668986987787779769889769786786677968688676789758795789778799968874554888745884477656333347734
245364636567733378747546688568467886556575995665667899776697867979969896777697699969798666967778955575878757679874445586566685865366343455347
575656654334567568656486467468659899798876975555697877868779698669996796698678666769878689967795566959879555869767654758764456537655557557767
346477444766645357588884555657666698776697587778967998678897767668969786678666998777877898879695965756995895677554566657887857845647373757563
664555364364376544585645485887676665565675956998886886898667766666879668669876889667796967869898765797966889859764865547768786566655366764647
663335573643645757784454578444798978988975897996797676789878998969987867899789769986867999888866857798899566596886878577678866667673443666553
665646477444467687777558754567958897787855565999966889777667798796689979878967869689697689969797678558687999957567777748468868754345565456346
566543636475566856656775656587756577667967799766766879688687889678977997888877768899789968667679679859556898886955486585464677474675534575777
645577757777546568576475846559988557689978768999899878797888686788977998778999799668866998997767768595597566666695577675758886657334537474335
647443537674646775664646644485579879756769756799977696899668878789789997979999998676969697669787776678878565876897478757886554676544436373733
735435337737668684557486784787968675575789587868997868887678797878989898977877897779967796786998868557559568875998648447577777687677333766745
543365534657558846755485555769955989956966898986769788686688788779788887978788778979999776788888866879568986868576657577867745756657476634333
575536335353367864458746645779595756876859568788987698977689998898877788798987888787886766966799886679868555575596986655665884467344356374634
473743773666654456848656885888576959596756697769979988779698977879787779899997998997896679869976797956886957756797747546478877674557735477576
645375747353758646565577776469995878658675789787886696789697888878888779887978789889769798679989886788698567658597588456647457688467657554557
345467535536675474848846568657895799758598699988889898977697988798798789797789877898877968986996666757886787886969865748864884847444663434663
656456334766548844754566855865579785857878878769986899686879798779888888997888797898876768676868879999656856958868968558486468757444637647463
464343374457778676587755854879865876988558978768686966967978999997987897797897799788898988987869996895799965888998677645657757588743463334546
347476457754374656475466676555567667657587886679767677688789978887987778988799997779879669999977768767865586875857875547687554665463564573454
453766454355684874884885874686876989695967697979669789668987897877898978887777778979796779986768878976856765759976868744885877575746735565357
736636647435668778784654646498787999669755687687679986876999779979898978899977999898789768998797877699878975986897764765448684554875364476735
664436647443567755668485684766596755555769978796767678869978778798988789998777777787997666686699786798677785879868965874785748455564663637575
433553345755375866788885748475965768586787978989798989696789999888799989878797978798798968789786967779856877995576767745856455666836337554377
344765347543374446674554858577596665697799687787679778869887879977999987999887979878796886977978987769865666868568956585866764566535774537475
546576646364778657445448847759585995895697878889778996669898789879989987799998979898797868677699766858578859977755677446755745878665767345653
533546474574554677555477646465886687856557896666778797998699899977899878877779778779867866897987667857887599895995588754757778486775455634365
364776533553388544476648645496597697688656897776688987669777788789989798888777777798988866877996776958558977857698778487778775567443437764654
767575643445774646865587678859868695688785899996688688877668879779779878879789879897668976796797988686797559759759646754568666464766356634777
663564774636658444884475474759797966777788768776999686687989799887988789889998777878788897969767689958777798865786678765766587576735546445447
765545346777444457678486575588879885678987596687678987878666897997977897979987978988767978769779979865598988867978478475444464744564356435353
366746667447578457875445867488677995859667698887779896696998788978887788989797887876769887968897796987657789656777858786758778587445346364346
734757577657577844678557878567659668878757786878767979787666669879779997977898778999886989869968789676788565887969468567446757675547746434465
467334563557566456758584574878865795766868658996987868887697669888997898899788998889989668879666986669776669687989566454585878855556675374743
645575457653677884784585588855655968856577875887769876987669779888778799897898777698889967796888787578585855865768848684455877667364474457775
767557477466374868477886488774898767588796985976996797898896789868898899977876979969877766999996989576756859996757575867468868557576573774434
365367356554353486664888444486576978789969667598668798779679967888788999796986688989987679989688677766569979655954458755548884553647454343365
376336736735457876455766664576868899958567899859897696666876898967968667669679868898898888678777677965768667886556674567766854753575675577476
655377576336353777555487674664459995998755596688788868897878878786779897766898666796798699986769596797666758675744757446578744875557637667343
346446435544365588467868786546676559596578965787878788879688679686797787696768968886787989768785998568785579588888765488767877567565467755576
354754743465663748676677684474685586888867755998899878766698966778769666867868877666879989869975667775996755968584457547448868665676574646644
375476567446766648657685558868684876569896777896588689767787787777779797666866966896997697886777658855887666756556865488575868637476356664546
445443376634364754578848556856444996665555889556557986866898987898998767968769789997987768997597899598677768594578757748767547673755546757466
665475644545575348685574648545765657959867595696876978696669997879986966979668799877788966668889557878656677776786455675445767467546444535474
536536364733663343757854644865786455596579777665886777767776796878787689898768677668688795585588869858867558758654576484588863577736365556466
545677765673477647458587675877857747699998588967985579966698996796669968868886777876896876566779758656867579564454754855855877653657775474465
526634533344674357784857678766684666995887697768597868868688669877886679676996996687797775768787576675996687784778756557686657567343466435376
555367765673445476467455475554586466585989789887787769676867966767676796687889896986877586778976986876898895566876577547785676354466367535475
566676343464545754336756566678644764665555658957956858897698698967768969799997687799675666769956667655559976654874668868864344365374536646744
642375475753557633436874464648878466547566967655869789865959766986877898877867796965686987965766886865865675747548555887646747776445567347646
656326775677733743553476855846684858777567795889655999758996557887666699887977775858955696758766587856867888675575847875564373546374366533364
356523464767556365754554458685647747687488976778688855697796599685596579789897557585667697756877865679768565567847486476653374377755437773466
543364557655446374776484667446844587777758978869866755687997557969558968989668567678676658666557568857756646588867747655633365453645345346563
236562656367457666473574756767787484864787678758988675958855996858589889785858687986999988859888998997488777755668648846466573577345536445525
435425454743354543343534475784886747857444675996758965666578678996855698756785979795587987959775967867864775685466445885737645534737473665362
656365663566663445676743748865778774886455467789977566999699575957678987978899885895585598567758556556745674586867685465366373764453753632226
554364645654577774575347585474486665445484788787958557777995767555969688786699755588897576959596976845578586878455558754775543573553676466226
566365526354555656773564765857585674685586764446576595576665977697577778959689988577969857867777544786674878657577858777336353333336763243544
225645463477536636737547746855854577665455586777855595668788968669666569588785557968878679887868765668784484567586587654537447376767635645624
326343324673543334344333453846654874888454446758467889966666595596659955785659698886979596579556454785744657484756587664635335666734746333362
532662633633547457656367653444766558747845867568768765978675586896665555887897795567797775544675848675458648484474634746576546564554542654353
355663354646374655677455353646574544555776878645666884896787558788857879795677987878598875568878457856645555765646757774773335733663526234223
353422562247634437354366757547848484486845777858677644677756767685987785766977575755599856685775568757588558668567757543337544345564535234266
625553254333746337646674767563388458857564687664846777856669755559789686587569959585684667544648664446655584855854567365533744356742364465444
256524322524363455666676457677636858464476685768488658555885585999765659786578666675884764747557458554788587577463354747475464475463564363232
344555253446556735453434354367637586487674456777465645884457744886765674748655466874854454886874745687874444873743475747434554764722562353544
436336633646457553373364653633435565546884675847685764745576446566586448474646588477788544776856755887755886845455353675573457356665354253225
353553554345353455733547735663756547845588454848874587864766784664557578755786484855447586484587747576577446434565477633534576642362554466224
432525456624322674674455473444735465585878467468565785857768745885767848488547466474785564885557558774875737646763773465674537654223644552654
525335354433465274655555537746447754355487677744768868776677444557756865777755446886557446678584767648468645477543475677473764432555343662443
536234524632522465555647777335435334437785748846755474465446555657555454476786768444746644457754678455575643465746465774734443646245244645242
543442426643426534477636563376653536756355858585748486864457846887545584748846488758855855645876464887457465374457355477665635626433523524452
223322223546552553575645377567767764633457777574576586688766475584868555884876446564687754664544674746647356433575667577763565225654256544622
125432653256262246645676433475543465775457456787477566566648476474677745847886586875848787748885486346376633653653363657636242326523563666434
154555463335463666563736355477665434373773447735676677764476767476757886646475666486685555778786577733434376677574533676446342454463463634432
141552262546462536364674453376344346655766473635575565475486864645767844585465884467586667565773377733634663557773445746422526356353452324542
312423654364225622226637376343347535467656737454465678885885746745857776864757467665478865575446666474647437757675757473645242266443443325554
333352266326435462625366644556555677753333564555775666584874665848744466545484587654854464745467733645434647766364433755226524223666554626514
435132545534652226544462427766367457556547533646553733455368768864748656858757658764667566573447736343373755745347737256566566356246552554344
251251242554456622643453332655755467667663776573476475365556464548586464744786567334573766376654353443634574576453465245553624544653336543111
212442344546526645642263244654774376666364765664337477476566755735634734545547537453654634467644564673444576465347666352444336246443534225131
112553156446434342262332632662776733455533536546447357345533465336456677743746473675453643333635675467467446533763524242322555366262662253531
211154334644242354452264624333677734447567476373463347474347444453644577737565635654763766744377535655635747756455462332222243526345542432111
452531315135444354222633542256663373756457456776563646334754543544575364335767774564575736767736775545744343363363624653264666332236225512123
554211544546426525425562633634342635553437466647567764434744664546375647473767773675456535466347457734537637645252643554463622523335443333224
334533452455542655362226365236322545337345466373753756677574663767643737437554464546345477754476745457537446262223644636236336656625515513231
452555231215326224366256565643522266556465346746347363633645746436473667767556763464673664753345776465737364364536446645553352366221223144345
514335112142516342564642545262662364262353574573475464554553456636477477446756645474374646364357353537766264336222226532264353454144251545325
152522253244513266563264433552644226246665674554677745755364563737344773646764375565657457543353753423534335226422232656264234264153315553535
324514541241141455232546254624542356544332452737546335476443477344545643434547765335573737455674436465526432346264244552654644651313224214233
213141543243524321434324633656252333252323653563475667336736466576733354556565346365373663374333256546644423653255346636444624514124522425212

13
day17/sample1.in 100644
View File

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

61
day17/sol.py 100644
View File

@ -0,0 +1,61 @@
import astar
def read_input(f):
map = []
for line in f:
map.append([int(x) for x in line.strip()])
return map
def solve(map,part=1):
start = (0,0,(0,0),0)
goal = (len(map)-1,len(map[-1])-1)
def is_goal(x):
return (x[1],x[0]) == goal
def neighbors(state):
y,x,dir,count = state
next = []
def go(dx,dy):
if (-dx,-dy) == dir:
# can't turn around
return
newx = x + dx
newy = y + dy
if (dx,dy) == dir:
newcount = count+1
else:
newcount = 1
if part == 1:
if newcount > 3:
return
if part == 2:
if newcount > 10:
return
if newcount <= count < 4:
return
if (0 <= newy < len(map)) and (0 <= newx < len(map[newy])):
next.append((map[y][x], (newy, newx, (dx,dy), newcount)))
go(-1,0)
go(+1,0)
go(0,-1)
go(0,+1)
return next
cost, node, path = astar.search(start, is_goal, neighbors)
print(cost) # TODO: off by one somehow?
print([(x,y) for (y,x,_,_) in path])
print(''.join(dir2s(d) for (_,_,d,_) in path))
costs = [map[y][x] for (y,x,_,_) in path[1:]]
print(costs)
print(sum(costs))
def dir2s(d):
if d == (0,1): return "v"
if d == (0,-1): return "^"
if d == (1,0): return ">"
if d == (-1,0): return "<"
return "?"
import sys
map = read_input(sys.stdin)
solve(map, part=1)
solve(map, part=2)