diff --git a/Cargo.lock b/Cargo.lock index e3c7c0f..61a594c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,15 +7,53 @@ name = "advent2021" version = "0.1.0" dependencies = [ "itertools", + "pathfinding", "thiserror", ] +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + [[package]] name = "either" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "fixedbitset" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "398ea4fabe40b9b0d885340a2a991a44c8a645624075ad966d21f88688e2b69e" + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "indexmap" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770" +dependencies = [ + "num-traits", +] + [[package]] name = "itertools" version = "0.10.3" @@ -25,6 +63,29 @@ dependencies = [ "either", ] +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "pathfinding" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a64bfa665d8821a903701c7bb440e7f72b1f05387b390cc23f498cc23148099" +dependencies = [ + "fixedbitset", + "indexmap", + "integer-sqrt", + "itertools", + "num-traits", + "rustc-hash", +] + [[package]] name = "proc-macro2" version = "1.0.32" @@ -43,6 +104,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "syn" version = "1.0.82" diff --git a/Cargo.toml b/Cargo.toml index c2b53ef..8389627 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,4 +5,5 @@ edition = "2021" [dependencies] itertools = "0.10.3" +pathfinding = "3.0.5" thiserror = "1.0" diff --git a/data/day12a.txt b/data/day12a.txt new file mode 100644 index 0000000..15f1102 --- /dev/null +++ b/data/day12a.txt @@ -0,0 +1,25 @@ +bm-XY +ol-JS +bm-im +RD-ol +bm-QI +JS-ja +im-gq +end-im +ja-ol +JS-gq +bm-AF +RD-start +RD-ja +start-ol +cj-bm +start-JS +AF-ol +end-QI +QI-gq +ja-gq +end-AF +im-QI +bm-gq +ja-QI +gq-RD diff --git a/data/day12t1.txt b/data/day12t1.txt new file mode 100644 index 0000000..6fd8c41 --- /dev/null +++ b/data/day12t1.txt @@ -0,0 +1,7 @@ +start-A +start-b +A-c +A-b +b-d +A-end +b-end diff --git a/data/day12t2.txt b/data/day12t2.txt new file mode 100644 index 0000000..ef30b81 --- /dev/null +++ b/data/day12t2.txt @@ -0,0 +1,10 @@ +dc-end +HN-start +start-kj +dc-start +dc-HN +LN-dc +HN-end +kj-sa +kj-HN +kj-dc \ No newline at end of file diff --git a/data/day13a.txt b/data/day13a.txt new file mode 100644 index 0000000..68728c8 --- /dev/null +++ b/data/day13a.txt @@ -0,0 +1,812 @@ +470,705 +331,196 +1241,728 +1034,161 +181,850 +999,484 +480,680 +798,33 +226,86 +475,226 +113,287 +770,702 +47,35 +848,312 +1129,402 +179,326 +766,404 +1258,717 +470,494 +723,434 +418,291 +100,298 +994,316 +423,434 +985,292 +721,261 +528,572 +595,567 +909,665 +411,292 +1056,291 +1051,434 +311,484 +462,312 +187,273 +715,567 +114,819 +634,861 +79,318 +912,344 +1144,845 +152,745 +201,464 +840,185 +291,100 +1084,31 +1255,434 +909,229 +895,827 +557,29 +441,159 +661,193 +826,215 +535,70 +974,767 +254,739 +512,189 +868,75 +1076,9 +700,86 +684,515 +356,422 +348,344 +605,341 +360,586 +383,824 +239,393 +751,12 +253,229 +403,759 +166,273 +1196,819 +406,301 +343,102 +1119,618 +333,892 +711,789 +283,70 +418,603 +380,714 +756,255 +20,375 +1145,794 +642,180 +1140,273 +984,451 +763,619 +196,427 +869,159 +460,96 +35,548 +512,709 +1231,318 +1163,21 +465,275 +32,187 +212,296 +718,835 +1036,42 +1002,672 +108,492 +321,892 +294,0 +252,350 +377,733 +1196,822 +316,344 +254,519 +1168,49 +1158,745 +142,49 +130,504 +397,56 +718,186 +463,170 +482,463 +1032,752 +649,193 +512,158 +895,501 +1150,122 +537,833 +915,434 +790,262 +1058,539 +764,44 +512,861 +493,296 +472,422 +44,86 +1101,592 +671,276 +977,2 +822,621 +179,668 +415,46 +1067,154 +895,169 +475,728 +231,434 +156,103 +1176,72 +113,607 +301,851 +927,824 +346,870 +892,603 +610,86 +1114,19 +295,353 +402,350 +1118,145 +201,318 +681,732 +338,792 +855,733 +202,364 +125,430 +1140,285 +917,309 +1309,542 +10,540 +246,499 +1038,178 +209,609 +242,16 +10,214 +20,519 +276,173 +540,520 +192,582 +681,891 +830,680 +600,44 +895,848 +1009,219 +425,442 +1049,185 +994,166 +1034,733 +453,240 +605,833 +154,71 +141,607 +840,494 +131,87 +1084,86 +1193,592 +1163,166 +847,724 +329,318 +567,46 +850,798 +554,255 +817,598 +723,658 +1027,70 +1154,103 +822,273 +704,290 +985,72 +386,593 +1015,353 +907,435 +867,847 +711,835 +415,718 +903,343 +252,539 +574,310 +295,801 +156,733 +1173,395 +736,218 +700,360 +865,144 +1044,240 +708,628 +354,262 +1298,42 +987,250 +857,430 +184,185 +1066,14 +130,894 +917,585 +882,596 +156,791 +868,296 +1248,29 +1300,354 +1180,504 +542,385 +710,850 +172,407 +1064,310 +962,166 +458,504 +992,295 +517,667 +95,12 +484,299 +523,390 +865,733 +326,82 +1300,91 +69,728 +470,548 +1015,541 +141,735 +278,756 +1237,140 +642,714 +728,71 +1064,666 +1128,477 +301,403 +677,159 +340,266 +984,812 +972,792 +212,374 +828,463 +987,810 +1109,318 +212,178 +1275,548 +1016,894 +962,128 +840,548 +10,149 +933,833 +80,411 +1136,883 +676,766 +421,632 +242,786 +131,721 +274,189 +407,576 +80,35 +393,361 +425,421 +184,397 +1101,196 +1154,411 +529,878 +711,518 +1223,270 +579,459 +343,838 +428,415 +933,733 +930,628 +55,294 +1226,336 +378,721 +435,553 +546,492 +1019,100 +763,684 +1076,885 +1150,772 +276,876 +574,51 +25,610 +117,644 +410,563 +311,838 +192,817 +626,696 +1309,352 +604,18 +1036,705 +782,124 +338,464 +502,774 +1243,882 +950,756 +1232,593 +25,284 +853,173 +1295,614 +1144,534 +44,534 +1118,312 +954,515 +410,747 +806,348 +1193,644 +1248,59 +700,836 +247,318 +1121,739 +681,715 +1185,430 +759,103 +459,504 +981,292 +1131,668 +798,64 +728,39 +251,435 +688,187 +326,451 +828,351 +654,869 +723,712 +1300,680 +442,598 +1310,645 +688,222 +994,344 +277,833 +309,318 +26,184 +711,387 +418,515 +1109,436 +274,705 +1131,813 +618,614 +229,298 +388,128 +411,366 +125,464 +3,362 +131,173 +1216,772 +830,540 +572,115 +922,576 +830,214 +520,184 +895,718 +808,203 +443,847 +729,453 +781,240 +1078,794 +1282,144 +196,390 +502,203 +992,711 +557,588 +934,828 +1010,632 +212,520 +174,11 +976,630 +1066,147 +913,822 +731,459 +213,93 +244,270 +306,791 +254,155 +103,103 +671,52 +1128,271 +1010,262 +62,708 +412,556 +5,193 +294,446 +828,95 +201,458 +838,271 +47,859 +314,628 +425,473 +571,654 +994,540 +567,841 +236,575 +141,287 +197,621 +480,206 +868,534 +435,822 +62,59 +363,346 +1056,739 +201,10 +994,680 +907,135 +974,743 +1168,64 +380,180 +247,103 +1225,747 +841,287 +79,352 +295,161 +393,306 +864,646 +1158,149 +348,128 +348,469 +189,739 +199,285 +318,711 +888,794 +1109,458 +1068,108 +463,724 +397,822 +1255,294 +917,185 +272,716 +706,466 +979,644 +887,460 +1053,838 +1131,226 +1173,787 +979,196 +557,865 +441,735 +1290,519 +1044,576 +1222,854 +989,165 +107,723 +1238,155 +67,460 +1238,71 +1213,726 +443,47 +316,166 +711,105 +498,273 +70,102 +65,585 +475,442 +599,789 +32,873 +1012,379 +623,609 +10,91 +569,147 +1067,814 +580,798 +321,2 +209,196 +967,410 +1230,411 +1282,870 +731,87 +736,859 +294,894 +546,402 +334,630 +559,12 +651,196 +65,261 +1149,598 +473,492 +393,452 +629,491 +480,763 +1202,44 +1261,61 +1056,519 +992,127 +972,430 +740,562 +344,290 +882,479 +45,644 +1193,302 +1113,273 +58,525 +718,865 +400,515 +1084,479 +1074,603 +835,450 +316,728 +480,373 +1154,733 +892,575 +1097,129 +353,59 +1136,688 +1128,422 +547,619 +587,182 +962,344 +622,707 +626,198 +1154,483 +75,135 +277,161 +894,406 +278,534 +951,609 +711,152 +70,550 +738,432 +907,759 +882,534 +923,327 +933,229 +383,294 +25,3 +1009,851 +507,614 +174,883 +295,129 +276,428 +446,86 +318,767 +703,859 +1094,710 +480,688 +1184,124 +336,127 +923,567 +790,184 +1285,284 +152,579 +599,742 +1197,287 +639,500 +467,273 +785,495 +300,262 +855,285 +277,285 +267,567 +403,459 +1179,56 +1029,801 +551,103 +1289,159 +415,515 +97,596 +1109,884 +885,227 +166,534 +213,129 +927,70 +472,623 +1113,49 +480,354 +166,397 +1034,721 +629,610 +376,590 +442,411 +676,861 +1230,859 +1068,878 +278,590 +49,161 +899,528 +759,791 +1071,169 +1230,758 +1032,380 +271,387 +974,711 +0,197 +70,400 +806,856 +987,698 +1038,380 +395,460 +793,107 +376,828 +405,152 +78,301 +256,550 +1113,497 +892,274 +853,721 +783,865 +397,166 +579,87 +243,154 +454,280 +999,500 +898,502 +55,600 +621,161 +786,894 +1144,808 +192,134 +1126,285 +196,245 +1290,833 +1223,501 +847,276 +835,452 +1228,523 +653,542 +413,250 +1200,490 +278,304 +813,365 +582,855 +633,735 +520,710 +398,344 +1145,122 +740,332 +1131,529 +544,180 +1039,61 +363,548 +981,740 +830,521 +674,865 +736,676 +300,632 +671,170 +572,299 +185,607 +907,459 +1196,72 +687,285 +196,19 +55,434 +999,813 +288,754 +446,646 +981,154 +587,460 +323,810 +1126,497 +110,714 +512,326 +830,354 +1232,301 +266,240 +172,487 +1208,152 +618,280 +766,714 +721,633 +316,680 +987,523 +147,614 +672,380 +467,173 +253,665 +840,189 +673,878 +944,754 +278,75 +1163,813 +927,294 +1310,197 +1183,865 +47,488 +152,315 +472,477 +770,371 +388,766 +108,44 +863,294 +629,715 +1043,775 +924,593 +1179,838 +703,655 +1213,596 +985,766 +830,11 +1031,721 +623,285 +130,448 +380,628 +72,739 +84,749 +977,729 +318,183 +229,227 +687,733 +179,564 +415,270 +606,138 +1274,280 +295,541 +1054,550 +610,836 +239,583 +524,894 +383,600 +1102,808 +830,883 +828,543 +686,845 +252,544 +832,490 +1109,10 +1009,267 +869,765 +822,360 +928,716 +1118,817 +1063,103 +10,680 +497,813 +295,609 +1230,310 +1042,145 +1144,397 +70,494 +226,31 +378,466 +401,441 +592,29 +257,838 +366,754 +174,540 +1253,49 +78,593 +903,576 +764,828 +382,716 +793,499 +1063,576 +316,878 +1128,417 +1298,266 +520,262 +10,354 +388,576 +403,435 +393,451 +626,750 +610,58 +279,721 +358,574 +239,400 +1010,184 +1253,845 +415,67 +867,47 +1032,75 +1156,519 +254,827 +582,603 +360,696 +1071,311 +246,666 +353,851 +838,477 +320,182 +835,220 +1282,24 +200,280 +57,845 +504,856 +741,182 +242,430 +291,794 + +fold along x=655 +fold along y=447 +fold along x=327 +fold along y=223 +fold along x=163 +fold along y=111 +fold along x=81 +fold along y=55 +fold along x=40 +fold along y=27 +fold along y=13 +fold along y=6 diff --git a/data/day13t.txt b/data/day13t.txt new file mode 100644 index 0000000..32a8563 --- /dev/null +++ b/data/day13t.txt @@ -0,0 +1,21 @@ +6,10 +0,14 +9,10 +0,3 +10,4 +4,11 +6,0 +6,12 +4,1 +0,13 +10,12 +3,4 +3,0 +8,4 +1,10 +2,14 +8,10 +9,0 + +fold along y=7 +fold along x=5 \ No newline at end of file diff --git a/data/day14a.txt b/data/day14a.txt new file mode 100644 index 0000000..91ad454 --- /dev/null +++ b/data/day14a.txt @@ -0,0 +1,102 @@ +SHPPPVOFPBFCHHBKBNCV + +HK -> C +SP -> H +VH -> K +KS -> B +BC -> S +PS -> K +PN -> S +NC -> F +CV -> B +SH -> K +SK -> H +KK -> O +HO -> V +HP -> C +HB -> S +NB -> N +HC -> K +SB -> O +SN -> C +BP -> H +FC -> V +CF -> C +FB -> F +VP -> S +PO -> N +HN -> N +BS -> O +NF -> H +BH -> O +NK -> B +KC -> B +OS -> S +BB -> S +SV -> K +CH -> B +OB -> K +FV -> B +CP -> V +FP -> C +VC -> K +FS -> S +SS -> F +VK -> C +SF -> B +VS -> B +CC -> P +SC -> S +HS -> K +CN -> C +BN -> N +BK -> B +FN -> H +OK -> S +FO -> S +VB -> C +FH -> S +KN -> K +CK -> B +KV -> P +NP -> P +CB -> N +KB -> C +FK -> K +BO -> O +OV -> B +OC -> B +NO -> F +VF -> V +VO -> B +FF -> K +PP -> O +VV -> K +PC -> N +OF -> S +PV -> P +PB -> C +KO -> V +BF -> N +OO -> K +NV -> P +PK -> V +BV -> C +HH -> K +PH -> S +OH -> B +HF -> S +NH -> H +NN -> K +KF -> H +ON -> N +PF -> H +CS -> H +CO -> O +SO -> K +HV -> N +NS -> N +KP -> S +OP -> N +KH -> P +VN -> H diff --git a/data/day14t.txt b/data/day14t.txt new file mode 100644 index 0000000..6c1c3a1 --- /dev/null +++ b/data/day14t.txt @@ -0,0 +1,18 @@ +NNCB + +CH -> B +HH -> N +CB -> H +NH -> C +HB -> C +HC -> B +HN -> C +NN -> C +BH -> H +NC -> B +NB -> B +BN -> B +BB -> N +BC -> B +CC -> N +CN -> C \ No newline at end of file diff --git a/data/day15a.txt b/data/day15a.txt new file mode 100644 index 0000000..5e5c416 --- /dev/null +++ b/data/day15a.txt @@ -0,0 +1,100 @@ +4474378939294561989629896994983437978985699596253525532314671357192283111874776269135656912429997578 +7219771638623996974474331969734641552892111142431138735944711231631835799842996212331146124475743238 +2961148417649542737169677941564183516932969881196199629267699818691135791971999512361149183535329621 +9871881628922851313992884355318183839744114854999945898819527955613877899148971997483443895124972749 +1919361485782789198624931971845488739823696439544194485467971198599719115839184879611199597989117999 +1762668465318987168679928273548752326493925445898712574999271872149411413954567149128321356713711996 +9758891114897878442978961731916935611295376892731655257822281645887798623165679892842795149121794562 +8794174313234999832712179769998559998319429239188767268151198118491878742622198897183212759541967655 +2988678541317271143977933951868179839261219262553692783314191948932847911897935195171794197173989921 +7937619183351979421629995717138359299237763666982678128915583393591966489388882278897968133587978187 +1771288861854197689291788182899974391348865254618377682157212997376757227474976188287284936469139151 +9183171919381592591722911886147813851975446285895928831495379146316888188317259118133391938222425326 +8999178115764971149712252879912618793998823997753599775883399792278112838295641244444695117892369594 +1873895726139973829121992299149664519785161871191838821669115381988745189919982189161288151474919995 +4984136373971951668595392799193993899717185589797683743651997948311187535129949925427154914977164128 +9999159992495621281598156294198291771196656252551198178355135412329871819929964915836591711989341781 +7448271118737319391897193945577185237289149161185958425793253988117519337798691129411823525491989579 +1912877398736652997252949361587894888177859385896119191174915547635924182517149861596823312348516838 +7411916158128158526295478182717158294634384119891189918596922443111778313519369151918184392138369342 +3989641959996582997942999622814729287794974299321769978698859937138824918999289852969229264591966121 +8248393694679143264483712911924992583617814177146997918231121311389144659299451133991759578899318192 +3927235872389919653155979999938328728187786191428826154721811577636987639937191152179849749966459891 +1948525667811945875973719911429986557611991729719152988893663912242325911951514496896839921798125311 +4987111141491841355858599711851255968675598926996649953727649597973995225881919322173123485832889187 +1365195963998349531975969939812311357919355589887113191872918217753311788481269124528221117399621391 +2618399161117299311163167989995957247641824731167387813331889776165824292119925999974397616419172118 +6291632879111763162218245818574896537571235342881933628446932929988162198918431515299983116383625972 +4989885351975368919517881131331939647361285982389886925914714583162935321262181334119131787812193875 +4299299298919624924959969574186387338111585431643179184399993147111734367892182112528965596812136913 +1913417117824121122119581991583716146219291199512144882994343791853825968313288116386929568382564187 +1111259582212962927119928188628297964251334111125433112968386513986892961393919529268118897941692493 +2715119997271968941687778579456127393214439129136886489627687923892484915195916991318729518168291959 +2291724998124331715461758417591991226316441238978117126961397713993893999191415391189914953491293518 +6651599814824738431585179992975983597917279992953923879142789688619729867911998791486584911598218845 +2918442247528921633279871699883197935812912988473973121391419422515181381798846124621198681771116747 +7172399883999223589838199921288236965432928913987668795869711289579187827728254357182673543399455211 +3569393618413195995391741993182111311863518792867229192811659349495352298888119612596629417295412514 +3998347219684977173226832679351211849496942187999476517196156923911939957433439827199611519926291969 +9977828541228662797249561538682143142912917199521133659429132814291869965747141895918621158384181577 +3967357136159726912989158186141497914658884759161819339941915817318261777142291971767934513151711191 +8778541261893461761951522343928625399856964371891169438911911122822912841986768693517712511587843892 +3833315936351459473456192583978135792776752315117136132357898139879939295549611194156997971187878978 +2999641761928943389161333525895439191749829143634997999562535389149495518993726784548236849917137469 +4214435519912859292367198497751599991519199621895696677722866184996118129977367158899387561811918658 +7231114979829829321158658131391759347796376211984948269698619841398767854635929631175398998618572335 +9313714946993197143176667115892291898319189491659939292999929988795125299947811314219729882911991887 +2431979557916685876176288971223844899949112179913119728153582922392676827594238311846859276898923985 +2298182669623428768512173915565236181839119711668131839772497512198294739345891359413973166631273169 +8252112361839197878358752854282389886943817597211988118627211731273149928198939566118122128841996531 +2337699983275712849656128989981911537185958574583845722121193117562892294498614395491592899933659212 +7835143227123429411997859131228998886319979718665139818711399818999495433364914764241123721713998422 +2342981165371313441558921141193218916711873656679413979634321347456287987891354613188158163526439664 +9968695782986491149112599371175397912721977143321762942839646919197966291866914197298621385251921577 +3998992498311799137251321139836993298621918948485199967815255118632159287218116971357568151411518924 +1888767584516918979116831969684198131139152419142419199229931716585258963961725216716375611191148939 +8679972994968135896941454213273618172633413893517415398811979928196388336225492953687951759799299494 +9268198998268358914731411728913143173989653793437178974319158741943243387571241681357965185312759759 +4514415891598969983119893138887691162819199829581939189129625117153997172489929659441995563665252756 +9761151889796191211989125275371563715891139933695658126189249913196967329183393395969219863889676661 +2938315992611197591948197275927991961719112797199755413492386942224942718236489121713581914899162893 +4395774214496174235572725299871291344821199963513129911973529221391842392121228344796144961395373279 +7169235111278731299349194879561642927221385965252469499129166943949261126118955691946896131632763991 +4182586898216472291721495499162914796616976593699934121197795791198151975744258153997558688681125324 +2771241899369961675639292111153329919298919888341935788379952838991529795168864334579341944353139918 +1929719796991998842893188199974443739822392912715991758633111534282888557598811717116422289319174234 +8227445999711199165256581394711919882435899194112272635796122499955738435681954751995754828785863335 +8729951893951458193176413529119379912287122558862639638362659118815726858589241612424874965948595588 +8511215326829698921879251514193578281912679118343826143217429129999127819784588298767727133549889612 +6382942339132989347621977329997789611123946187243171299917261115375998629792191171457419111628551833 +5196411177129652468443166759257467191294653897926186178359322737194158687342924625234616743421831915 +3119774454627842122238898938198398383523128289373178928124148914919779921881813499178793921224852955 +7531169319889954774375677294553282895191113131163599175439212797364869867596793921132718138441171912 +6731921588989796739221366138283466411951368178219585181184473112811174364385961459883733385891993199 +4574139868545716129662294787788295397897183864953171131197921294921216787929998139387985941459997892 +9114942724959127928293995753431994317864268467596979991595123389116539473212431173289917364566915973 +9341929934129358191797626852989194781281961649194523995992215232749181878422232253289971438754945431 +9711152565169547161792212418146438141573599572942189811381975633231484186771811384619293994316987371 +6131964633192235767728441171994861691529178511919117275411839951991266231998851948696438627996557551 +3148296295114114748119216197997581912166946469723628251179241221245394648451897828498337979132867349 +5619591141279131179181294531676498187714322291293127899492999728165269816922513816979398883981987125 +9291461484772577319579551995948438439426145159466288861499231447345317187441884819168882981519468534 +7168729632153199693784461154421624968914968952182817868119431781278811691271694391273878312657379273 +9946766299185992112985121571599989161421889915736923711827194941719778878516511122132169474883348691 +9856269294522977396615891811325159414911139194979131992323319999997799632878319169846119312295884989 +4478951999896991194591814281651647293997171866357947886291688317199128157536483298223818685997392164 +6118292371386186497793385499159998311132592238538673922123742571831885763912281733919347629811931136 +1559539789584621626699998299699573848437397472896218368568884152614411988211446699867863392231178582 +3955545111973721673191918166186131172392954394391219111256767119175548689756115339875111299664124644 +8532211187629552833266327798975958598213391751421237299429191278411695787897851286879811159917618734 +2929979895191915513867778943916115416353324189939545761426692999878281933282414635716916418195731288 +1752488277292284446514194696663537222777119194745592921911172268969679581894751682321198962925794788 +9137893929311663938849971741824143649379956797731399631858279684249888929391696496889397231156431327 +1867976767614781682191913943361471819244932778711517643998163299119525998895828969289556719268691861 +7964834798931319884983618211814386951383713141581986214139319531157939294721187371941194911787999195 +9136759325819523117222783968949195359947999675194157265271519931694932993191618368533937986955857334 +1253987569539135869579376395211977798915817921811334441166659757918483967813112499681797768695123417 +1194831387932819991127838412992226682976224442219982251828819129911478993471543959236282538182799247 +9183416999951935493911137611615966391419988372968197976193987713623716848299299431993223458419679991 +4962689198187192592599439628128214183938152641919458516294432194147333651495386497911639332152979188 +8798649298935671297823969873452881511219118163995469811846217496897676246893511198571281879831529181 diff --git a/data/day15t.txt b/data/day15t.txt new file mode 100644 index 0000000..7d9d562 --- /dev/null +++ b/data/day15t.txt @@ -0,0 +1,10 @@ +1163751742 +1381373672 +2136511328 +3694931569 +7463417111 +1319128137 +1359912421 +3125421639 +1293138521 +2311944581 \ No newline at end of file diff --git a/src/bin/day12.rs b/src/bin/day12.rs new file mode 100644 index 0000000..4bc721d --- /dev/null +++ b/src/bin/day12.rs @@ -0,0 +1,145 @@ +use std::collections::{HashMap, HashSet, VecDeque}; +use thiserror::Error; + +#[derive(Debug, Error, PartialEq)] +enum Oopsie { + #[error("Bad line found: {0}")] + BadLine(String), +} + +const TEST1_DATA: &str = include_str!("../../data/day12t1.txt"); +const TEST2_DATA: &str = include_str!("../../data/day12t2.txt"); +const REAL_DATA: &str = include_str!("../../data/day12a.txt"); + +struct Graph<'a> { + edges: HashMap<&'a str, HashSet<&'a str>>, +} + +impl<'a> Graph<'a> { + fn add_edge(&mut self, from: &'a str, to: &'a str) { + match self.edges.get_mut(from) { + None => { + let mut new_set = HashSet::new(); + new_set.insert(to); + self.edges.insert(from, new_set); + } + Some(set) => { + set.insert(to); + } + } + } + + fn paths(&self) -> Paths<'_> { + Paths { + graph: self, + state: VecDeque::from([vec!["start"]]), + } + } +} + +struct Paths<'a> { + graph: &'a Graph<'a>, + state: VecDeque>, +} + +fn count(items: &[T], item: &T) -> usize { + let mut num = 0; + + for x in items.iter() { + if x == item { + num += 1; + } + } + + num +} + +fn still_valid(items: &[&str]) -> bool { + let mut counts = HashMap::new(); + + for item in items.iter() { + if item.chars().all(|x| x.is_lowercase()) { + if counts.contains_key(item) { + counts.insert(item, 2); + } else { + counts.insert(item, 1); + } + } + } + + let mut caught_two = false; + + for count in counts.values() { + if caught_two && count > &1 { + return false; + } + + if count > &1 { + caught_two = true; + } + } + + true +} + +impl<'a> Iterator for Paths<'a> { + type Item = Vec<&'a str>; + + fn next(&mut self) -> Option { + while let Some(possible) = self.state.pop_front() { + match possible.last() { + None => panic!("Internal error; empty path in queue"), + Some(&"end") => return Some(possible), + Some(v) => { + for x in self.graph.edges.get(v).unwrap_or(&HashSet::new()) { + if x == &"start" { + continue; + } + + if !x.chars().all(|x| x.is_lowercase()) || count(&possible, x) < 2 { + let mut copy = possible.clone(); + copy.push(x); + if still_valid(©) { + self.state.push_back(copy); + } + } + } + } + } + } + + None + } +} + +impl<'a> TryFrom<&'a str> for Graph<'a> { + type Error = Oopsie; + + fn try_from(value: &'a str) -> Result { + let mut graph = Graph { + edges: HashMap::new(), + }; + + for line in value.lines() { + match line.split_once('-') { + None => return Err(Oopsie::BadLine(line.to_string())), + Some((left, right)) => { + graph.add_edge(left, right); + graph.add_edge(right, left); + } + } + } + + Ok(graph) + } +} + +fn main() { + let test1 = Graph::try_from(TEST1_DATA).unwrap(); + let test2 = Graph::try_from(TEST2_DATA).unwrap(); + let real = Graph::try_from(REAL_DATA).unwrap(); + + println!("Test #1 count: {}", test1.paths().count()); + println!("Test #2 count: {}", test2.paths().count()); + println!("Real count: {}", real.paths().count()); +} diff --git a/src/bin/day13.rs b/src/bin/day13.rs new file mode 100644 index 0000000..5810e2e --- /dev/null +++ b/src/bin/day13.rs @@ -0,0 +1,141 @@ +use core::num::ParseIntError; +use std::str::FromStr; +use thiserror::Error; + +const TEST_DATA: &str = include_str!("../../data/day13t.txt"); +const REAL_DATA: &str = include_str!("../../data/day13a.txt"); + +#[derive(Debug, Error, PartialEq)] +enum Oopsie { + #[error("Couldn't parse point based on this string: {0}")] + InvalidPoint(String), + #[error("Couldn't parse fold based on this string: {0}")] + BadFold(String), + #[error("Couldn't parse number: {0}")] + ParseIntError(#[from] ParseIntError), +} + +#[derive(Debug, PartialEq, PartialOrd, Eq, Ord)] +struct Point { + x: usize, + y: usize, +} + +impl FromStr for Point { + type Err = Oopsie; + + fn from_str(s: &str) -> Result { + match s.split_once(',') { + None => Err(Oopsie::InvalidPoint(s.to_string())), + Some((xstr, ystr)) => { + let x = usize::from_str(xstr)?; + let y = usize::from_str(ystr)?; + Ok(Point { x, y }) + } + } + } +} + +enum Fold { + AlongX(usize), + AlongY(usize), +} + +impl FromStr for Fold { + type Err = Oopsie; + + fn from_str(s: &str) -> Result { + match s.strip_prefix("fold along ") { + None => Err(Oopsie::BadFold(s.to_string())), + Some(line) => { + if let Some(num) = line.strip_prefix("x=") { + return Ok(Fold::AlongX(usize::from_str(num)?)); + } + + if let Some(num) = line.strip_prefix("y=") { + return Ok(Fold::AlongY(usize::from_str(num)?)); + } + + Err(Oopsie::BadFold(s.to_string())) + } + } + } +} + +fn parse_file(contents: &str) -> Result<(Vec, Vec), Oopsie> { + let mut reading_points = true; + let mut points = Vec::new(); + let mut folds = Vec::new(); + + for line in contents.lines() { + if line.is_empty() { + reading_points = false; + continue; + } + + if reading_points { + points.push(Point::from_str(line)?); + } else { + folds.push(Fold::from_str(line)?); + } + } + + Ok((points, folds)) +} + +impl Point { + fn fold(&mut self, fold: &Fold) { + match fold { + Fold::AlongY(value) => { + if &self.y > value { + let difference = self.y - value; + self.y = value - difference; + } + } + Fold::AlongX(value) => { + if &self.x > value { + let difference = self.x - value; + self.x = value - difference; + } + } + } + } +} + +fn fold(vec: &mut Vec, fold: &Fold) { + for point in vec.iter_mut() { + point.fold(fold); + } + + vec.sort_unstable(); + vec.dedup(); +} + +fn main() -> Result<(), Oopsie> { + let (mut test_points, test_folds) = parse_file(TEST_DATA)?; + + fold(&mut test_points, &test_folds[0]); + println!("{} test points: {:?}", test_points.len(), test_points); + fold(&mut test_points, &test_folds[1]); + println!("{} test points: {:?}", test_points.len(), test_points); + let (mut real_points, real_folds) = parse_file(REAL_DATA)?; + fold(&mut real_points, &real_folds[0]); + println!("{} real points after first fold", real_points.len()); + for instr in real_folds[1..].iter() { + fold(&mut real_points, instr); + } + let max_x = real_points.iter().map(|x| x.x).max().unwrap(); + let max_y = real_points.iter().map(|x| x.y).max().unwrap(); + for y in 0..=max_y { + for x in 0..=max_x { + if real_points.contains(&Point { x, y }) { + print!("#") + } else { + print!(" ") + } + } + println!() + } + + Ok(()) +} diff --git a/src/bin/day14.rs b/src/bin/day14.rs new file mode 100644 index 0000000..a6782f3 --- /dev/null +++ b/src/bin/day14.rs @@ -0,0 +1,183 @@ +use std::collections::HashMap; +use thiserror::Error; + +const TEST_DATA: &str = include_str!("../../data/day14t.txt"); +const REAL_DATA: &str = include_str!("../../data/day14a.txt"); + +#[derive(Debug, Error, PartialEq)] +enum Oopsie { + #[error("Bad transform declaration: {0}")] + BadTransform(String), + #[error("No data found?!")] + NoData, +} + +struct Transform { + lead: char, + follow: char, + inject: char, +} + +impl TryFrom<&str> for Transform { + type Error = Oopsie; + + fn try_from(s: &str) -> Result { + match s.split_once(" -> ") { + None => Err(Oopsie::BadTransform(s.to_string())), + Some((from, to_str)) => Ok(Transform { + lead: from.chars().next().unwrap(), + follow: from.chars().nth(1).unwrap(), + inject: to_str.chars().next().unwrap(), + }), + } + } +} + +fn read_file(contents: &str) -> Result<(String, Vec), Oopsie> { + let mut lines = contents.lines(); + let mut transforms = Vec::new(); + + let base_str = match lines.next() { + None => return Err(Oopsie::NoData), + Some(x) => x.to_string(), + }; + + for line in lines { + if line.is_empty() { + continue; + } + + transforms.push(Transform::try_from(line)?); + } + + Ok((base_str, transforms)) +} + +type Pair = (char, char); +type TransformDictionary = HashMap; + +fn build_transform_dictionary(mut transforms: Vec) -> TransformDictionary { + let mut result = HashMap::with_capacity(transforms.len()); + + for transform in transforms.drain(..) { + result.insert( + (transform.lead, transform.follow), + [ + (transform.lead, transform.inject), + (transform.inject, transform.follow), + ], + ); + } + + result +} + +type State = HashMap; + +macro_rules! insert_update { + ($dict: expr, $key: expr, $value: expr, |$x: ident| $body: expr) => { + match $dict.get_mut(&$key) { + None => { + $dict.insert($key, $value); + } + Some($x) => *$x = $body, + } + }; +} + +fn build_initial_state(base: &str) -> State { + let mut state = HashMap::new(); + let mut chars = base.chars().peekable(); + + while let Some(c1) = chars.next() { + match chars.peek() { + None => break, + Some(c2) => insert_update!(state, (c1, *c2), 1, |v| *v + 1), + } + } + + state +} + +fn step(base: &State, transforms: &TransformDictionary) -> State { + let mut result = HashMap::new(); + + for (pair, count) in base.iter() { + match transforms.get(pair) { + None => insert_update!(result, *pair, *count, |v| *v + count), + Some([p1, p2]) => { + insert_update!(result, *p1, *count, |v| *v + count); + insert_update!(result, *p2, *count, |v| *v + count); + } + } + } + + result +} + +fn steps(base: &State, steps: usize, transforms: &TransformDictionary) -> State { + let mut result = base.clone(); + + for i in 0..steps { + println!("At step {}, length is {}", i, result.len()); + result = step(&result, transforms); + } + + result +} + +fn counts(polymer: &State) -> HashMap { + let mut char_counts = HashMap::new(); + + for ((c1, c2), count) in polymer.iter() { + insert_update!(char_counts, *c1, *count, |v| *v + count); + insert_update!(char_counts, *c2, *count, |v| *v + count); + } + + char_counts +} + +fn score(map: &HashMap) -> usize { + let high = map.values().max().unwrap(); + let low = map.values().min().unwrap(); + + (high - low) / 2 +} + +fn main() -> Result<(), Oopsie> { + let (test_base, test_transforms) = read_file(TEST_DATA)?; + let (real_base, real_transforms) = read_file(REAL_DATA)?; + let test_initial = build_initial_state(&test_base); + let real_initial = build_initial_state(&real_base); + let test_transform_dict = build_transform_dictionary(test_transforms); + let real_transform_dict = build_transform_dictionary(real_transforms); + + println!("test base: {:?}", test_initial); + println!("one step: {:?}", step(&test_initial, &test_transform_dict)); + println!( + "four steps: {:?}", + steps(&test_initial, 4, &test_transform_dict) + ); + println!( + "Length at 10 steps: {:?}", + steps(&test_initial, 10, &test_transform_dict).len() + ); + println!( + "Counts at 10 steps: {:?}", + counts(&steps(&test_initial, 10, &test_transform_dict)) + ); + println!( + "Score at 10 steps: {:?}", + score(&counts(&steps(&test_initial, 10, &test_transform_dict))) + ); + + println!( + "Real score at 10 steps: {:?}", + score(&counts(&steps(&real_initial, 10, &real_transform_dict))) + ); + println!( + "Real score at 40 steps: {:?}", + score(&counts(&steps(&real_initial, 40, &real_transform_dict))) + ); + Ok(()) +} diff --git a/src/bin/day15.rs b/src/bin/day15.rs new file mode 100644 index 0000000..9c93312 --- /dev/null +++ b/src/bin/day15.rs @@ -0,0 +1,128 @@ +use pathfinding::directed::dijkstra::dijkstra; + +use advent2021::map::{Graph, Oopsie}; + +const TEST_DATA: &str = include_str!("../../data/day15t.txt"); +const REAL_DATA: &str = include_str!("../../data/day15a.txt"); + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +struct Risk(usize); + +impl TryFrom for Risk { + type Error = Oopsie; + + fn try_from(value: char) -> Result { + value + .to_digit(10) + .map(|x| Risk(x as usize)) + .ok_or(Oopsie::BadCharacter(value)) + } +} + +impl Risk { + fn inc(&mut self) { + self.0 = if self.0 == 9 { 1 } else { self.0 + 1 }; + } +} + +#[derive(Clone, Debug)] +#[allow(dead_code)] +struct Path { + points: Vec<(usize, usize)>, + cost: usize, +} + +fn shortest_path(graph: &Graph) -> Path { + let target_x = graph.width - 1; + let target_y = graph.height - 1; + + let result = dijkstra( + &(0, 0), + |(x, y)| { + graph + .neighbors(*x, *y) + .into_iter() + .map(|p| ((p.x, p.y), p.value.0)) + }, + |(x, y)| x == &target_x && y == &target_y, + ); + + if let Some((points, cost)) = result { + Path { points, cost } + } else { + panic!("Couldn't find a result."); + } +} + +fn embiggen(graph: &Graph) -> Graph { + let region8 = graph.clone(); + let mut region9 = region8.clone(); + region9.points_mut().for_each(|x| x.value.inc()); + let mut region1 = region9.clone(); + region1.points_mut().for_each(|x| x.value.inc()); + let mut region2 = region1.clone(); + region2.points_mut().for_each(|x| x.value.inc()); + let mut region3 = region2.clone(); + region3.points_mut().for_each(|x| x.value.inc()); + let mut region4 = region3.clone(); + region4.points_mut().for_each(|x| x.value.inc()); + let mut region5 = region4.clone(); + region5.points_mut().for_each(|x| x.value.inc()); + let mut region6 = region5.clone(); + region6.points_mut().for_each(|x| x.value.inc()); + let mut region7 = region6.clone(); + region7.points_mut().for_each(|x| x.value.inc()); + + Graph::from_subgraphs( + 5, + 5, + &[ + region8, + region9.clone(), + region1.clone(), + region2.clone(), + region3.clone(), + region9.clone(), + region1.clone(), + region2.clone(), + region3.clone(), + region4.clone(), + region1.clone(), + region2.clone(), + region3.clone(), + region4.clone(), + region5.clone(), + region2.clone(), + region3.clone(), + region4.clone(), + region5.clone(), + region6.clone(), + region3.clone(), + region4.clone(), + region5.clone(), + region6.clone(), + region7.clone(), + ], + ) +} + +fn main() -> Result<(), Oopsie> { + let test_graph: Graph = Graph::from_file_data(TEST_DATA)?; + let real_graph: Graph = Graph::from_file_data(REAL_DATA)?; + + println!("Test shortest path: {:?}", shortest_path(&test_graph)); + println!("Real shortest path: {:?}", shortest_path(&real_graph)); + + let embiggened_test = embiggen(&test_graph); + println!( + "Larger test shortest path: {:?}", + shortest_path(&embiggened_test) + ); + let embiggened_real = embiggen(&real_graph); + println!( + "Larger real shortest path: {:?}", + shortest_path(&embiggened_real) + ); + + Ok(()) +} diff --git a/src/bin/day8.rs b/src/bin/day8.rs index 0c9559e..b906721 100644 --- a/src/bin/day8.rs +++ b/src/bin/day8.rs @@ -269,7 +269,7 @@ impl<'a> ProblemInput<'a> { .map(build_local_iterator) .multi_cartesian_product() .map(|x| HashMap::from_iter(x.iter().cloned())) - .filter(|x| reasonable_assignments(x)); + .filter(reasonable_assignments); for assignments in possibles { if self.assignments_validate(&assignments) { diff --git a/src/map.rs b/src/map.rs index 7ded17c..37335ad 100644 --- a/src/map.rs +++ b/src/map.rs @@ -13,8 +13,18 @@ pub enum Oopsie { pub struct Graph { data: Vec, - width: usize, - height: usize, + pub width: usize, + pub height: usize, +} + +impl Clone for Graph { + fn clone(&self) -> Self { + Graph { + data: self.data.clone(), + width: self.width, + height: self.height, + } + } } impl> Graph { @@ -59,6 +69,39 @@ impl> Graph { } } +impl Graph { + pub fn from_subgraphs(num_wide: usize, num_high: usize, graphs: &[Graph]) -> Graph { + let inner_width = graphs[0].width; + let inner_height = graphs[0].height; + let width = num_wide * inner_width; + let height = num_high * inner_height; + let mut data = Vec::with_capacity(width * height); + + for y in 0..height { + for x in 0..width { + let graph_x = x / inner_width; + let idx_x = x % inner_width; + let graph_y = y / inner_height; + let idx_y = y % inner_height; + + data.push( + graphs[(graph_y * num_wide) + graph_x] + .get(idx_x, idx_y) + .unwrap() + .value + .clone(), + ); + } + } + + Graph { + data, + width, + height, + } + } +} + impl Graph { pub fn size(&self) -> usize { self.width * self.height