From 622c739c817ce4688fa4d6ea9b3d98680787321d Mon Sep 17 00:00:00 2001 From: Patrick Auernig Date: Thu, 16 Dec 2021 10:27:35 +0100 Subject: [PATCH] Add solution for 2021 day 15 part 1 --- 2021/README.md | 3 +- 2021/day-15/.gitignore | 1 + 2021/day-15/Justfile | 6 ++ 2021/day-15/common.d | 191 ++++++++++++++++++++++++++++++++++ 2021/day-15/inputs/puzzle.txt | 100 ++++++++++++++++++ 2021/day-15/inputs/sample.txt | 10 ++ 2021/day-15/part_one.d | 12 +++ README.md | 2 +- 8 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 2021/day-15/.gitignore create mode 100644 2021/day-15/Justfile create mode 100644 2021/day-15/common.d create mode 100644 2021/day-15/inputs/puzzle.txt create mode 100644 2021/day-15/inputs/sample.txt create mode 100644 2021/day-15/part_one.d diff --git a/2021/README.md b/2021/README.md index b5243c9..44049f8 100644 --- a/2021/README.md +++ b/2021/README.md @@ -18,7 +18,7 @@ | 12 | ✓ | ✓ | [Python] | | 13 | ✓ | ✓ | [C++] | | 14 | ✓ | ✓ | [Erlang] | -| 15 | | | | +| 15 | ✓ | | [D] | | 16 | | | | | 17 | | | | | 18 | | | | @@ -50,3 +50,4 @@ [python]: https://www.python.org [c++]: https://isocpp.org [erlang]: https://www.erlang.org +[d]: https://dlang.org diff --git a/2021/day-15/.gitignore b/2021/day-15/.gitignore new file mode 100644 index 0000000..5761abc --- /dev/null +++ b/2021/day-15/.gitignore @@ -0,0 +1 @@ +*.o diff --git a/2021/day-15/Justfile b/2021/day-15/Justfile new file mode 100644 index 0000000..a4bb3b6 --- /dev/null +++ b/2021/day-15/Justfile @@ -0,0 +1,6 @@ +@part PART INPUT_FILE="inputs/puzzle.txt": + dmd -of=part_{{PART}} part_{{PART}}.d common.d + ./part_{{PART}} {{INPUT_FILE}} + +clean: + rm -f *.o part_one part_two diff --git a/2021/day-15/common.d b/2021/day-15/common.d new file mode 100644 index 0000000..a76815c --- /dev/null +++ b/2021/day-15/common.d @@ -0,0 +1,191 @@ +module common; + +import std.algorithm.iteration : filter, map; +import std.algorithm.searching : minElement, canFind; +import std.array : split; +import std.container.array : Array; +import std.conv : to; +import std.stdio; +import std.string : stripRight; +import std.typecons : tuple, Tuple; + +private alias Buffer = Array!(Array!(uint)); + +struct CaveMap +{ + private Buffer positions; + + this(string path) + { + positions = parseFile(path); + } + + private Array!(Array!uint) parseFile(string path) + { + auto file = File(path, "r"); + + auto buffer = Buffer(); + string line; + while ((line = file.readln()) !is null) + { + auto line_buffer = Array!uint(); + + foreach (weight; split(stripRight(line), "").map!(to!uint)) + { + line_buffer.insertBack(weight); + } + + buffer.insertBack(line_buffer); + } + + return buffer; + + } +} + +private alias NodeId = Tuple!(uint, uint); + +private struct Node +{ + private NodeId id; + private uint weight; + + void toString(scope void delegate(const(char)[]) sink) const + { + sink("("); + sink(to!string(this.id[0])); + sink(","); + sink(to!string(this.id[1])); + sink(";"); + sink(to!string(this.weight)); + sink(")"); + } +} + +struct Cave +{ + private Array!Node[NodeId] nodes; + private NodeId start_node; + private NodeId end_node; + + this(CaveMap cave_map) + { + auto node_id = NodeId(0, 0); + start_node = node_id; + + uint y = 0; + foreach (row; cave_map.positions) + { + uint x = 0; + foreach (weight; row) + { + node_id = tuple(x, y); + nodes[node_id] = getNeighbors(x, y, cave_map.positions); + + x++; + } + + y++; + } + + end_node = node_id; + } + + uint lowestRisk() + { + auto safest_path = dijkstraSlow(); + return safest_path[1][end_node]; + } + + private Tuple!(NodeId[NodeId], uint[NodeId]) dijkstraSlow() + { + bool[NodeId] unvisited; + uint[NodeId] distance; + NodeId[NodeId] previous; + + foreach (node_id; nodes.byKey()) + { + unvisited[node_id] = true; + distance[node_id] = uint.max; + } + + distance[start_node] = 0; + + unvisited.rehash; + distance.rehash; + + while (unvisited.length != 0) + { + auto cur_node = unvisited.keys.minElement!(x => distance[x]); + + if (cur_node == end_node) + { + break; + } + + unvisited.remove(cur_node); + + foreach (neighbor; nodes[cur_node]) + { + if ((neighbor.id in unvisited) is null) + continue; + + auto total_distance = distance[cur_node] + neighbor.weight; + + if (total_distance < distance[neighbor.id]) + { + distance[neighbor.id] = total_distance; + previous[neighbor.id] = cur_node; + } + } + } + + return tuple(previous, distance); + } + + private immutable int[2][4] DIRECTIONS = [ + [-1, 0], [1, 0], + [0, -1], [0, 1], + ]; + + private Array!Node getNeighbors(uint x, uint y, Buffer buf) + { + auto nodes = Array!Node(); + + foreach (dir; DIRECTIONS) + { + int dx = x + dir[0]; + int dy = y + dir[1]; + + if (dx < 0 || dy < 0) + continue; + if (dx >= buf[0].length() || dy >= buf.length()) + continue; + + Node node = {id: tuple(dx, dy), buf[dy][dx]}; + + nodes.insertBack(node); + } + + return nodes; + } + + void toString(scope void delegate(const(char)[]) sink) const + { + foreach (id; this.nodes.byKey()) + { + auto nodes = this.nodes[id]; + sink("("); + sink(to!string(id[0])); + sink(","); + sink(to!string(id[1])); + sink(") { "); + foreach (node; nodes) + { + sink(to!string(node)); + sink(" "); + } + sink("}\n"); + } + } +} diff --git a/2021/day-15/inputs/puzzle.txt b/2021/day-15/inputs/puzzle.txt new file mode 100644 index 0000000..a6ac055 --- /dev/null +++ b/2021/day-15/inputs/puzzle.txt @@ -0,0 +1,100 @@ +1124751783612228519483416186391693192764152281421133194141163183224351733212394799536339411529842112 +1299938854391228215712461147511117912185733411491416388811646391912138661213722223824151532652174491 +3339197559983134739317425934547716331696227221882122961476799987711635499267472178182145359213635923 +3275111279884782539314241187762113814171394161491634629424134127254634143155261122133724143114517171 +3719252118791433135122231855197812222238914994648147192141951214948299478914959275216261881654181459 +1611117951314292139456114142392662772939225937136486428161234281216234329234315111776511563151948482 +2568826483341639224876553822412669632282339258375519267395999314194775717338955473111882125281113119 +3211535497996954958315977618271374429983722314139733843419727946959246752499319415154271225547899217 +9182381814515842193317619241122295417132515941811977373112934221316141138111911121121111793678163186 +3844189817214722127981149242928145957137126937131386516329118218111198674162815191994371914762733967 +2341991198198671797918854491942998311516141218456591158159195192211227471918835699934872448189793938 +4914562622368117861639397331397217328431182986624263992197435816915439591962133158497224891382954532 +7626651214813838216185911429272999894518636231382989678893369367388711391734813452975811156327428911 +6619547343521975253174481211413831293662121339851815212317311237391545399111182897667911821424149598 +9973191187241313192815214227191649743296915314888729322114168515823743777711899119191553298115729119 +1139287494922611751257731929722771498336139611251121442114394245137973342111145499332316959261235284 +2957197428427162517942347211164151149912112158641321995248419171621811597221619949431227171998811472 +3942647388316719894411111531921126183713231811198382654685441319271454138942281133619242611612293827 +7937119217256311112391437861121498616811956123353462521891125694135126297129995285155114368995531781 +3451961913122271833382989211151286596622992323752134162138122516383189222433812253226845819142198221 +2778119153629891339923532321818124533756116181684147179833125112111826952511175359231299984985971323 +3111241849191534385261731569341927433476113958471723118832747854529179328115274125434719722218912131 +3142339531392581988128137411211196234548128214999949588185228836196627923352221497911291281534111199 +2247331434479875142918842833898559624238445292211715118881294135283574749565172271411631413491566199 +5942278576394177315387294721122691617961774138211922471397191215938266718124567292193989959261637132 +3165937631221963265792414421441393495719931248192344794567976762321141859115829128661211272472736862 +6245216271127518123199222191484234611151315582117171596574729739922992724612599562343116361844622764 +8113544322656226212151951279235114941989556194198115559251582213981835589429635885493383187341531965 +9167334539972119189967382996641594933763662148772253141953186111414742999511119411388291132416516449 +3613823811913288411123382135529243111267199921121439155729919326116169791514491996989971122517181152 +8673611192477161631212112481894911858892968239143914865319658975331149334747126743512225484277694151 +1573562476555619452428261559215411721579288335558515411134313992163812836653437129992833619198146362 +1985275213511588337218921661953495211191671194622531866114745941231929893241192939732541431596251229 +1265136118282217612545222191931962743537199362634214512441818421145212152171522295123221817416511192 +8297798221482948311881157477219864767525628534952929138168821168196211119111519681828383199111919196 +2534111997313111473186996839118152776719511994169115192212165984228917912783244345623614586619121326 +5841498181267192895193154811932281737529524821838531213993721717189699211939288511893237393416182963 +4291365191619323711913413926441339411267931111249294286234263722174939997111633217333235111582923441 +1287162672582123747413148471918114922719181577167138269131143162782619895168443398922587114315692159 +1265925622411611266789112299971891313715613359912627191225939742625214121139321211686759611131173819 +2138953588999163543822384688714958315246965691333881631171314291246656696539111996811849918124146199 +1246641611311144149732152211911939355725818779248359199268117115556131393567479697235189376137881341 +2899323821125691382122622121279464139996512843263627599964991689326381239953514685697311811566519319 +2736949532739218813892326217621918912123391961114292438971239114718244292915281445924621121161621333 +3284227711481113791259114169152546556372395121491214478676766673451539272714243257528999117191132191 +1491645992221246232691159831148693751711539199173418148515113374123227919399121713163369423119344294 +9132112419279766149552388219119879126631964411873291514292382629182256527396923261916197289667422219 +4435263531452645499818123111966429163563711994892138163281911392712947829833494132517185151159797235 +3377999473376535692397871161267942211991447319627223732643859136911321291147933161219919912554143594 +3949323991733462336411199416212721417161994737197381813716349241925143828318311249159179991229329171 +1762136928289612837322111798838212828232194159395467913129898285979511558911359718111211715278482292 +1118257643855683112121972927223668654922187717441698273158822189761169916992651219511457913769191141 +1658133214212128183392871646163111119424394424612113962259435119311183885137744192432918197134375132 +3591713174418138371811543613511348758114531127679321532212958111147949196891591688991927112311822659 +1236514266615278952886111333113128112861958723136379141934411821192618183131222512832888648251713999 +8123213361595969218132551112914729944243931512311795497816271296492513311341682399128274945195119112 +2462825227696446183996491353919233459561152451155132169141431681617413626542619881461141223688519198 +9621989515111471113381577698758628164221411666452251895517161458991756482464135232192737151721333241 +1845633941916891433521922233371928968912324239271162428588753196413672815131973146761647212761387593 +1213191632931181293214711139975148754136566435292974252811697693911887328591189183554433169371667213 +4519131126388191338914531223891121466796183273431621945951424794146112514299112124121572531131372111 +1331344969619935133794416261913442341424183712193444133541852317113515211181326734947129151289182833 +1355758512615534971555911998128211268588155773916181718217932133414645114253821929111112911181223396 +1921812718591189155234925136611421141621741789512111114849236968196293982164297416554297277314296498 +2925818269222199331695127966441449818292484293218699694191219141796929886179788888289778893154112915 +7349332956191336793938825411116431794116518627151175184126599498959181846349128914531693382871224114 +2975711544499872811921879322745419629143299769241363453113298718372441111116129736331374245812629681 +2419398835867978148157517197312837563211153716146118174293922233694112229384117648726494771916746336 +2322473321962284111112435812293374144731592114895311931296931978723998962913118278111921783414789472 +7421933294181593157278951313456166911311561151111468883991937345182554571275781533927232981213941792 +1668835358177241114335636733193482471442299199859434499861711136613117473328576171139593142184617345 +5339642815719926226879311379167325793396941892597215179614941121636812111539912741116971188971946499 +7581333191573246312732795518731212368211299298495989164122116531125184283943222911391615243311251361 +9492966914243222969499792183412424152773224381646928911135496174621299924524112331962952547214129323 +2729194232211462151119459711313211822621531163797412446181172721913949189555142143791213834886518948 +2754215791553781642269915399358262512494443343121198134218639979927842122994421127962456193396136699 +8271611911227341219949383285981988595252121593129637541475392137413899839912239225135459931743267972 +1332131171959982211855642861212718138325111114239233279171544919563891942832117949581464743292494391 +5144166291493181763279457131141327146537961189933599395341461291371919123151359118199368625742376117 +1636191619675379923419873222911119821251129276117414194193998142948136713325351617571519395951914216 +6863238911796142259595658671251783127926389189168272138182549591741951937121824471372228139189226966 +1398611275788896954682838421735924943417195641181143853286733633811931911189111341679192676374118319 +7425912442414194918974222966129621141925526265112323617731363617133673511925955331462169117293471296 +8311915233126172592295451734596934578641991127992454954549337724839691119685881916643781992923996572 +7168461267393883112656311283191232322499117185912521188899182419918914911212513325386275539329721472 +4418929132119621184239621272934448319225211997924183117861911136919317465941177911127948161449124731 +9271153581452542386794695144559617972331134217961265186239771199325391879412411821372724989746391111 +3752522113112162859371199119415298331514424128999524132149996846199915924629121214916277199845231181 +8461129155427192357991128752552628161188794894374724397322312139214838121389889613819783991892292158 +4999141138619713275215481369646529918918936887478711111135124192624311852137911719581517593373711112 +9228956819912994881488113276489314945969876898139152128325918347915249723837311238669717631918756448 +1272313111232619631582529173782417217912411245971957172218911853664936489571219898133821585115925152 +1324983253974657485632276593196749111921819449973115611494598217724911344731933114417612111528118291 +8521515271325847484517496514692991413334913117194153459926716822674627611191634943962214123151399931 +1141639315518932691635973515217951611118329247113938399181114133617465682162932426295992195929458883 +8229351197214731215324515139273121165384915712119675514893281751526119183679227515364941156137548174 +6116894132781317191382191142114151317798773795981911112434921641114411589131331717998932176521898319 +5362677393912312215419378899211815319464811111851912257961211293814411559971191515896993251933358962 +6926527339383986515331739126963132928923957918814875739969162479336291216879152811764569629328261149 +7598541186247351172883789213137911264491891391569216562276119911413437411237411934123311912324427449 diff --git a/2021/day-15/inputs/sample.txt b/2021/day-15/inputs/sample.txt new file mode 100644 index 0000000..ab80887 --- /dev/null +++ b/2021/day-15/inputs/sample.txt @@ -0,0 +1,10 @@ +1163751742 +1381373672 +2136511328 +3694931569 +7463417111 +1319128137 +1359912421 +3125421639 +1293138521 +2311944581 diff --git a/2021/day-15/part_one.d b/2021/day-15/part_one.d new file mode 100644 index 0000000..94e7a0d --- /dev/null +++ b/2021/day-15/part_one.d @@ -0,0 +1,12 @@ +import std.stdio; +import common : CaveMap, Cave; + +void main(string[] args) +{ + auto immutable path = args[1]; + + auto cave_map = CaveMap(path); + auto graph = Cave(cave_map); + + writeln(graph.lowestRisk()); +} diff --git a/README.md b/README.md index bbc390f..492e284 100644 --- a/README.md +++ b/README.md @@ -8,4 +8,4 @@ - [2018](2018/README.md) (0% completed) - [2019](2019/README.md) (0% completed) - [2020](2020/README.md) (20% completed) -- [2021](2021/README.md) (56% completed) +- [2021](2021/README.md) (58% completed)