diff --git a/2021/inputs/day_15 b/2021/inputs/day_15 new file mode 100644 index 0000000..e3cdb36 --- /dev/null +++ b/2021/inputs/day_15 @@ -0,0 +1,100 @@ +6919598227838199913855119231126554696792992136695118448313191841922775524417825151216891429923213541 +9837948917619787189935571922197132977185355128371858691255934311214863828372926993213996998139912118 +9712819911516295249274925911896922213911165843181262181868447395254293349493421938929117229988638933 +2476951876931175825312533142569137931721739713725799446851119715122115753938166842994429692731365577 +3691396937919199853599315812613951281125263711868971256541511653441136543245312424117567151668999674 +9294972854229491498411271321351998983919929272128753711198282397882539157287554149474186951291188213 +1135428214811459993621216218435832221856114139399136248687314682119118892393618575918692412341569411 +2929921158912711182518311271272489732271565129299979967487113812154971756485549913921162939114391994 +5735115881479239217981525718898929221191614222551693914913779439617933359521941311111857328992347824 +1324749414111313198724813856727141934339899617632138746132396173529281922347716643138211113979119317 +3263594941789195782731783751728147419342113519153994137499331274281145119193372917298632271917871525 +5479228191148416221119313323857818519129966727666999721348148577292717477671479138864751785262494159 +7796954213299199792437719283546721912268871561199118418913219166184792518146351339119739123994185981 +9629911853953289553892412891922852724926162185929113819714489559692115112436841311998121591212249911 +2328397217172391111288411918123121111329776726473176893942742194591917882178943718116232271214679483 +8741141538382111791315111111217879577863971972167912427154411516117129128518217911997124249159922143 +1112181727959169888722989121578121121151936427211518922174664147225132238128294879313132991431289481 +3747188357529199195611794131377544398823262189627134618228417441399177613261778632518726968681261168 +2481629985392983495331692197839119129614185425229598989835611557184114492293122195456638299631886877 +9147391211998228191112524911758739341511911573198239147932292971618769152596224169136819211191864121 +5339661183639791381383226488915834355926218173956911914294222986717347842733923158213319912313779114 +5243921116119511826295361157329514912924232445973183228141342999868999739939499749595714929628949881 +1717822297616989111681634446964759597245148141299649442375393616675299961783422585213969182389813979 +9223718278792883969179179831171225547156272493833129568562192687845341671181118782551343181335147329 +2949471233325124981953749291711218145971445981149411417976569225114219698356762679863952545995247124 +5813891161912133536215537881164329141679198579211417483995393171751229139515148551616451451699471962 +9119929859113721717292587192359667211794197356859166313415988219993559879467128483625838972963998323 +3895252513734165951664259349139491161549113632418318988572115611474628679584659333822336264442417161 +1321331549981649293931789932115621285146921639311329258269531211367526813124695472815288349283153957 +9422143143834321616229212182481242959489182311359152235561234325491988881677689362294958313949842287 +2933761954489328463913592166236523429629187282841912685667184712699837199911744132197611144273159928 +9154223693315635418997851912395881642814193154944229782123418943428143338499556944668943742669929821 +7139199155869873192534891585999171659544292341128472349512234761139621941897245995229121715921128221 +6121476298449615119179315279931141828241794783538353767662277163821548137442111115139516117411432154 +2721461614458352311522959322145231893925321191149936561182971937587678991778119969116199785178211249 +2487528361345231828917513711239639891526811157458691118988793531821939487349991122139681411829212122 +8196784988189916854591415361246889241677468137989661782462692224114367584511836128916614929335987963 +1428262253911238199139222239127987864548198367553991618567992112895712539846223268343291112612477881 +4311151291221542315119195139919638851217471142313611628999671999898223151846129413511721416129385444 +9223929419139196512617954741195118176182238863959367576997199569784421619179812898678142615193816961 +3739957281196232999991168188488998188924191959881122119917862162473281529652914854499515417543148211 +1169927398515215962874725929618422947517373431917599117392259119991783219193841762221551623313812112 +1779521141994763421294833117197299835113728789243129423866794976144315588151693917287864658143995545 +1159529199535138199525951914847892791117273918293125411365889356724137416981217218648382141469719663 +1441364449664913814639642968343767978911851669683136385812815592539216123382714745918827782372785978 +6318957234985141489118421889191571779911215699151212991414982923995699851169649235572492514461152781 +7412156483212717161922514861277814977411642186522941564119197181981973336314373991372153411986995122 +8897991112125241713878834617986429813629284553444782988769119316585492828131921114225955339181119115 +7125797134691266318245163258271753447285747349147564189981125236198721219161583235846326176241283216 +9525321171524757914385236188595897464111726911869954146959524288653932322972921175292381219559151292 +3194414111319217199913317211199349199115439486152468914947617154512189983891512878579271819721897263 +2491297212663627482329238221159172168981257191127613528687982291228575192766566677617649837761491989 +1121617881229121329144711662747663125911994277165915132843328895684121414218596361211122111151522917 +1162139629471896711146596151128354981329212568252314552651841992789919922154257915321939255343321996 +8957911396911314198222223175527176652889162319834385792196891372879635461922911398421776885879797419 +7322963541269954962232189653112791497811679512721118141634598993612942952829283995138219829599889896 +1569981859182313594573978911399869123929216923327226499129485126875325886837652725166648848111998112 +1288121399799771382611161143238967371619191852948117758798124866815182266412112994241352156467592687 +9782613685639942816392876435869597448311475929186556881281992238479474821817198267189176811611345259 +8297985291593249832442977492543196751332831189541119469439887728521432991519343374611228237815267521 +4523444992382282221121212292493497226928544945515424945782491119898752191347166219638988944397819329 +1194152129661126528417217522222823524312191626887412455713921129631844996221721711241299731957631929 +1781148994623342655141379243991813598498169894269285915113668982571141718118953985931825748891192931 +7833796895687353814141792216629798237329497911457911619894313529713318488672351472297297179132273189 +9926932996114129354986957691171917584919694139244291829925819193912511541921314292341872312211981115 +2226319158194127721821519888721116941969121519196797413362226317939127758283193749485693516626493951 +3879811393834677889446991895193312948783741921874992118657173911651519457119526249932991374694221158 +3978213824919914931146214425131552342993968699129184834945118939217714393215687129491255112693917989 +2158824391323818951718191147228251313192392116229926329592191642213389282938125431317515594129855892 +2451172759927711235717449878121951114556117149429163518191331765282139179182223474536877622144431352 +2329714311789716815472699771921951445911563498316498268435161242192511134612561842937129461433486692 +9129479162281325294261155111911112642211493851211871231213119335358891917149811789318556889897859341 +3131721472764729312915112753898151151419189179139342154299471832731815961421341134532764798679814835 +2217431514225191812445931219331361111219893144143242969585922236148982273386967781788171191337195416 +1488382763322171811791496513637271436981329581196884183931387898461131393171817212859131421121588819 +3919585217425217131651936339227398135223761428891742188679177616726195628645462878211341521251196219 +1912957445827151319119291131211879781559926431573113691921911897931126976153352174896222328435211744 +8323394392199159213314229519951213933192989466113182874918939393519799992338482811596611494443251292 +9984916453772991188215712124613985265583131698589662217749113142971842194779131373528882783188719171 +3913899817991926921213654613559196179434112197559381516917322458299126529795921728131229913442812145 +5261955321792184295644715972199271318912197112951581231816254223846887618715212638468619569563671225 +9917489994523968382612199487887184382861222418313922422473349162379172311619221982567741824957119114 +9968113457218183711391471141522113356149799928981688713318973119319334121489381212791911983159993251 +5249142618957491198134219822522879839256251251436381811362976119514169213884284373893443751176727125 +2392796498327162272298169491815314812269718889131918964451489919132342117242821633487187151658118395 +2249487296138221889993479576818554862713916146291439161279886228579321318212135384293111391332314217 +8897514868449987835128195533898941832793897879991713214683219511961725984113517647629518912372993316 +1222365183812221239236493126981329745983157171198118191517444419871498512716164392661878952149182524 +4629547769226193136881192975138212468396429891334928131276933521182542469561849129314987648579679814 +4749932538499119949794629935997432846571872718898849574149926819691699199813998733192839462193345835 +9591811516417941413919173999998125925256922487211975464577143226941827972121634167224618848544866381 +1199639929547111431756233793468711319694611716322117618413912797189249351723264174991798896126128931 +9148618989823822894126381717841681947679515811112512179728652138551112276241388773414937399838169113 +2116766171211521721492313143976327275198231584381986141259139981152183551411875421171911111231991471 +9989831137686686132681193914183774211627118849879121936974812614974731981977534928127129133558532219 +4741174282322196153167332691899826553963194736319492127196372119621459827218931141194633228429712327 +8911816487224543464638721721725597897179615822212948111174159112193164482824873198414218689949816972 +9435522297626213549132166931213828698726112979125659542928778787719513418334539737811551126112515196 +7992595817832629549819319199131117919697522116215291142239947517891729618121315294175432217519225146 +1211761163187331332248351681117516631676788555961569685827143481198812137751721875926238173159343258 diff --git a/2021/solutions/day_15.py b/2021/solutions/day_15.py new file mode 100644 index 0000000..b92743e --- /dev/null +++ b/2021/solutions/day_15.py @@ -0,0 +1,110 @@ +"""AOC Day 15""" + +import pathlib +import time +import heapq +from collections import defaultdict +from math import inf + +TEST_INPUT = """1163751742 +1381373672 +2136511328 +3694931569 +7463417111 +1319128137 +1359912421 +3125421639 +1293138521 +2311944581""" + +def read_input(input_path: str) -> str: + """take input file path and return a str with the file's content""" + with open(input_path, 'r') as input_file: + input_data = input_file.read().strip() + return input_data + +def extract(input_data: str) -> list: + """take input data and return the appropriate data structure""" + grid = list() + for row in input_data.split('\n'): + grid.append(list(map(int, row))) + return grid + +def neighbors(row: int, column: int, height: int, width: int) -> tuple: + for inc_row, inc_column in ((1, 0), (-1, 0), (0, 1), (0, -1)): + delta_row, delta_column = (row + inc_row, column + inc_column) + if 0 <= delta_row < height and 0 <= delta_column < width: + yield(delta_row, delta_column) + +def dijkstra(grid: list) -> int: + h, w = len(grid), len(grid[0]) + source = (0, 0) + destination = (h - 1, w - 1) + + queue = [(0, source)] + min_dists = defaultdict(lambda: inf, {source: 0}) + visited = set() + + while queue: + dist, node = heapq.heappop(queue) + if node == destination: + return dist + if node in visited: + continue + + visited.add(node) + r, c = node + for neighbor in neighbors(r, c, h, w): + if neighbor in visited: + continue + nr, nc = neighbor + new_dist = dist + grid[nr][nc] + if new_dist < min_dists[neighbor]: + min_dists[neighbor] = new_dist + heapq.heappush(queue, (new_dist, neighbor)) + return inf + +def part1(grid: list) -> int: + """part1 solver take the entries and return the part1 solution""" + return dijkstra(grid)[0] + +def part2(grid: list) -> int: + """part2 solver take the entries and return the part2 solution""" + tile_w = len(grid) + tile_h = len(grid[0]) + + for _ in range(4): + for row in grid: + tail = row[-tile_w:] + row.extend((x + 1) if x < 9 else 1 for x in tail) + + for _ in range(4): + for row in grid[-tile_h:]: + row = [(x + 1) if x < 9 else 1 for x in row] + grid.append(row) + + return dijkstra(grid)[0] + +def test_input_day_15(): + """pytest testing function""" + entries = extract(TEST_INPUT) + assert part1(entries) == 40 + assert part2(entries) == 315 + +def test_bench_day_15(benchmark): + """pytest-benchmark function""" + benchmark(main) + +def main(): + """main function""" + input_path = str(pathlib.Path(__file__).resolve().parent.parent) + "/inputs/" + str(pathlib.Path(__file__).stem) + start_time = time.time() + input_data = read_input(input_path) + entries = extract(input_data) + print("Part 1: %d" % part1(entries)) + print("Part 2: %d" % part2(entries)) + end_time = time.time() + print("Execution time: %f" % (end_time-start_time)) + +if __name__ == "__main__": + main()