diff --git a/2023/Cargo.toml b/2023/Cargo.toml index cdfe5f6..44571fc 100644 --- a/2023/Cargo.toml +++ b/2023/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] anyhow = "1.0.75" lazy_static = "1.4.0" +nalgebra = "0.32.3" regex = "1.10.2" [features] diff --git a/2023/input/24/input b/2023/input/24/input new file mode 100644 index 0000000..4326d4a --- /dev/null +++ b/2023/input/24/input @@ -0,0 +1,300 @@ +225004689740965, 150875733412640, 116049940893518 @ 275, 389, 375 +338282582546422, 191340608518886, 340003210160681 @ -162, 84, -46 +276063330011297, 506267063607948, 451688278442130 @ -9, -360, -275 +184895220833040, 346432574551322, 295370687370609 @ 190, -100, -32 +191652244794317, 228752744289266, 232281189081226 @ -31, 21, 81 +243836903069805, 200950090690864, 278486291904150 @ -28, 88, 22 +99537538414359, 156839976263080, 330139497485318 @ 130, 130, -37 +326389764039501, 504331313318919, 418345965619340 @ -131, -307, -163 +148876210640065, 290152398181516, 301374612836089 @ 33, -38, 6 +142515087922560, 255308120704690, 257170878718743 @ 68, 8, 52 +295642841582982, 242101259588587, 104022418418097 @ -64, 55, 272 +212300793229561, 261391853816696, 365490993544222 @ 18, 12, -93 +165229346379582, 248276965460071, 161312784455361 @ 228, 79, 212 +146531979069180, 97089275376773, 332003690930340 @ 22, 161, -23 +120800899092132, 184913721524842, 473900231780358 @ 46, 68, -169 +245193974976343, 210971062189687, 268026939360343 @ -33, 73, 36 +442753793796843, 328612846899973, 283609914942486 @ -197, 51, -361 +386255632768587, 458845472549101, 186183322563756 @ -53, -509, 253 +31284818403777, 378560063574625, 130525938014247 @ 121, -131, 182 +215792555249349, 255251601506749, 291132823173402 @ 53, 35, -5 +440576428992381, 341794624061173, 283489603116870 @ -195, -71, -297 +406821058032927, 358552748013016, 243495622599474 @ -84, -158, 37 +333985935471117, 348387381803596, 196037336476056 @ 173, -110, 229 +194315236713487, 480470439040782, 378290083309208 @ 51, -280, -115 +423624567819357, 338961555301801, 243582531901236 @ 61, -23, -31 +94275761968037, 416415875088596, 405203801734006 @ 101, -177, -111 +182423650573104, 175953021338356, 485228050020492 @ 54, 122, -247 +132946860128942, 343413209165262, 326300668034478 @ 36, -96, -17 +372535536228591, 339775824243596, 291460134306860 @ -5, -78, -127 +234895872588063, 62247228662200, 328601789968998 @ -48, 226, -29 +219739080638176, 286527796435798, 280981600608968 @ 12, -20, 17 +189527420319587, 44893660278076, 188459541975566 @ 71, 322, 143 +380267121502632, 171933783462296, 62327709907551 @ -50, 486, 658 +147002248372043, 129217307469322, 20610734515794 @ 72, 163, 337 +378116309343993, 323069130988612, 248918730482046 @ 12, -7, 19 +319333653031698, 278859269969079, 223866268814703 @ 52, 75, 106 +236992756588085, 304463145397792, 340194522655246 @ -12, -44, -61 +361033750565555, 283496102799226, 443655113595562 @ -186, -23, -175 +235897203512717, 294114281232674, 253551760349992 @ -39, -37, 56 +408102536955573, 333380318039952, 224743862672053 @ 133, 14, 168 +293102890051939, 344678920502642, 319027665541226 @ -52, -97, -51 +314560583563263, 247853680623604, 53638099642518 @ 168, 228, 683 +358957968197762, 345732142415154, 247473914297280 @ 176, -100, 13 +97749293379345, 58712595993126, 391620120825632 @ 43, 177, -72 +322867629724035, 340590948643122, 203289896708124 @ 172, -81, 190 +80125950337563, 291162150272609, 183137679036856 @ 67, -45, 129 +258374458616771, 177916772961046, 144952832827550 @ -106, 67, 167 +278357116203837, 305712540709126, 313477667351106 @ 25, -25, -67 +264809045616867, 264739862065576, 262895162556366 @ 124, 82, 15 +336748098976080, 273218710413310, 322060564461324 @ 30, 104, -167 +429928385950838, 314414397421203, 244915322264740 @ -58, 209, -27 +372274398572112, 231105491529412, 287140067936409 @ -124, 146, -34 +300041946642210, 361805878294414, 348779219055194 @ 94, -140, -213 +82333630198830, 239193100253797, 257911560955197 @ 188, 41, 48 +226279166994495, 154940662484512, 108839076271560 @ -50, 110, 216 +236988945746136, 219126354714877, 501245149354293 @ -46, 49, -232 +290809399876260, 49865784333280, 261940365787665 @ 108, 638, 10 +192479192269869, 89960784106480, 410601225475806 @ 72, 264, -171 +154572048488187, 298722566659266, 216167781614996 @ 16, -49, 98 +61402524224229, 314643942049666, 423478145912151 @ 85, -68, -106 +358766524042277, 346694443835744, 276844061172806 @ -19, -102, -46 +256397938412229, 266514037892864, 308510441425550 @ -38, 6, -19 +111247170663991, 233159373163332, 468697849329816 @ 74, 24, -176 +344810608922213, 303615399145216, 281518317463374 @ -63, -8, -23 +362788311911379, 251466951828550, 193750060069434 @ -150, 55, 145 +399463771643109, 390830800397568, 348214912693582 @ -56, -300, -427 +410955878203009, 271492271760398, 451677568130560 @ -193, 83, -454 +295197906839637, 437418987102341, 193165330189036 @ -59, -237, 141 +154537540976799, 195927505433626, 181308919987650 @ 52, 77, 141 +325985149258473, 250194915217672, 334102012662690 @ 108, 204, -238 +124543315501773, 231620946800590, 338561758249206 @ 17, 11, -21 +335269288780847, 561799450130906, 273598366143466 @ -160, -351, 33 +406349536830357, 371696898098416, 244982099083326 @ -5, -260, 13 +429820668866290, 271277644477337, 428343413274584 @ -246, 63, -343 +285494082255787, 310483982523226, 238112394898756 @ 6, -35, 72 +427654917316453, 283119550914376, 289816166586310 @ -171, 202, -189 +183305780754531, 169697372808382, 507117795342356 @ -26, 79, -196 +297993284172727, 148019247408016, 478413943821759 @ -109, 142, -218 +448790421243093, 337156090194256, 245685544768734 @ -213, 32, -103 +148786447967448, 318009921450292, 479155605119109 @ 14, -70, -172 +179096144122083, 244536042632162, 235756205266522 @ 64, 35, 77 +244534188760433, 150524896619640, 152520925860732 @ -45, 138, 178 +292496348928869, 340309322862336, 330659178034254 @ -138, -93, -17 +238428943280004, 398422698354598, 128738013198711 @ 18, -176, 234 +313779278881410, 287246060199107, 290633760886106 @ -50, 5, -21 +343288891378891, 429120523686379, 473870061316574 @ -25, -305, -513 +446216226005587, 312289649316651, 248176797177231 @ -177, 407, -134 +163307384848257, 225448720602800, 322389319780406 @ 31, 38, -21 +311268063816389, 463933000929952, 394657123402262 @ -111, -254, -132 +399765834273075, 254798002778062, 319132923186840 @ -106, 223, -222 +349356303383841, 65751874037920, 238304141643426 @ 88, 934, 64 +426197942876982, 275075125500838, 175524119141824 @ -134, 316, 425 +244846911821769, 323674066198300, 382631479290586 @ -38, -71, -106 +385903898932938, 293744669483637, 303997079396164 @ 28, 149, -255 +122406691475152, 265274118970726, 228903355635336 @ 74, -8, 85 +428147883934287, 336265506735295, 236428743456129 @ -49, -11, 58 +155366097136407, 212516717519496, 138064536136086 @ 223, 134, 247 +290272064856077, 53447685751876, 200629668873066 @ -21, 397, 136 +289398699960341, 335225479948172, 258338577180554 @ -87, -85, 48 +246644560074906, 346069755754627, 184752533814789 @ -18, -99, 146 +325161489522083, 312478142191119, 272239125652590 @ 27, -15, -17 +302526838060353, 250137788997644, 293451658437046 @ 34, 111, -51 +381454405428627, 309591627716605, 247524198319020 @ -69, 15, 37 +126242659748529, 415333404708478, 502742367002526 @ 43, -171, -201 +391122049921137, 340901601859651, 268790805641181 @ 57, -73, -116 +408757147462249, 380607987804743, 399264436774194 @ -223, -157, -197 +447450951270780, 284852883292954, 255232938787050 @ -218, 628, -173 +406627106978321, 345331129547776, 278775433455838 @ -252, -98, 35 +102526860990768, 109719841541566, 426220057678866 @ 104, 172, -141 +271417363832745, 226632607078180, 157778251273146 @ -48, 65, 184 +380523128506570, 154723202351541, 260313283860234 @ 74, 867, -53 +238921206316929, 132829025707360, 47904689664486 @ 244, 438, 549 +307266763229071, 270719901259624, 186135881961708 @ 150, 130, 226 +230319046492045, 395641124538336, 193363618743976 @ 57, -178, 144 +392920766921985, 250496505188886, 306460703608653 @ -215, 32, -20 +175231757780249, 44786823183916, 276624943135376 @ 63, 292, 24 +313832948811675, 318445186003239, 306518285955873 @ 103, -21, -128 +306551125497277, 524521381609762, 241622859608944 @ -79, -365, 68 +400554436289624, 347460919638512, 297202409231189 @ 104, -114, -394 +389736340819305, 335315093086228, 265059063401646 @ -48, -59, -41 +59503995507231, 201984360420538, 424714963719588 @ 103, 48, -115 +297143002633785, 96825557449276, 268699929004798 @ -62, 277, 27 +390931858919397, 287914464138976, 302923821502446 @ -7, 167, -238 +214729565570253, 278072872648670, 319237187952896 @ 25, -7, -36 +96351544542113, 114755362054564, 394569159543638 @ 134, 181, -115 +253200235356037, 258399369622746, 348809514314886 @ 101, 75, -149 +382994713688163, 275642293727644, 356448448140994 @ -158, 40, -163 +148649354883135, 340481142733222, 248790450117468 @ 142, -91, 58 +134854692785701, 187209426614464, 175332404267278 @ 113, 106, 155 +382031589203352, 338688148083646, 244506915572916 @ -60, -76, 45 +369770189029605, 317508155457520, 250790362193010 @ 53, 18, 10 +372683763999567, 414017337323254, 290899929550854 @ 6, -355, -133 +147854567396103, 296200494966013, 360438786344609 @ 19, -47, -52 +176792353279606, 312467680727934, 476850067726169 @ -12, -64, -172 +302158177857665, 261529363847256, 256986683221090 @ -45, 42, 41 +249078363310055, 282217233889320, 271610559471576 @ -52, -22, 34 +221596566426841, 219861193819496, 360675578753842 @ -58, 32, -52 +179819260650432, 199340653470439, 329496686830650 @ -34, 43, -13 +276958462187159, 486380812406192, 159075856045308 @ -108, -250, 160 +144557079593697, 131195974673911, 166883422178271 @ 9, 115, 146 +490712615276709, 481688438412223, 460171428210714 @ -363, -337, -317 +284673415638495, 320722646046907, 349991504659375 @ -113, -71, -48 +184676509506952, 270068378274990, 290179021025201 @ -34, -24, 24 +345990299479461, 297990031232524, 222968799598746 @ -107, -14, 99 +233819171964981, 152061935722588, 108309431253774 @ -47, 123, 223 +285477411975405, 291008044172421, 261721579922515 @ -35, -13, 36 +407602868256117, 224700153604072, 183502997645982 @ -119, 368, 275 +291327574782249, 286013931920310, 431294230944710 @ -137, -39, -117 +443300983193571, 324683157114472, 251351540903257 @ -185, 118, -100 +189572883657070, 462200497610916, 280153455698611 @ 18, -238, 24 +308690692200416, 333877160265007, 236361595096541 @ 44, -71, 74 +418654017001235, 348182837861720, 229046306673408 @ 50, -126, 130 +378681238387569, 296901565820215, 156807910380587 @ -23, 79, 362 +409371660135117, 326653269520726, 231465493326930 @ 121, 77, 105 +426752119836365, 343370672093228, 244558686803006 @ -33, -79, -21 +375852403443021, 293233964850016, 265899535913214 @ 92, 162, -79 +326707607783589, 316318773568392, 309836065113046 @ 13, -27, -106 +142911217221157, 261672665797202, 40658695646315 @ 21, -12, 278 +244255603614037, 327276038377380, 279588160520382 @ 201, -55, -29 +365680112763191, 94848689754348, 298094328264472 @ 24, 816, -154 +330900038715639, 333095401980622, 263888598778833 @ -37, -72, 16 +233128904088757, 257737506484816, 140807291739982 @ -34, 7, 191 +296148164930181, 562101587574141, 250704068764416 @ -11, -493, 49 +194944987544711, 293883929666758, 290731532680414 @ -42, -47, 23 +322305098222037, 370061146918651, 477144215849956 @ -59, -143, -363 +182728803240756, 281103277585801, 285622771243386 @ 18, -23, 19 +383519700815905, 345082260451353, 403471475241446 @ -15, -97, -601 +321303031096657, 382801663317526, 207761312476516 @ -33, -173, 132 +82652246408061, 397368423356176, 12561618050022 @ 58, -148, 292 +386132571381159, 290050051464719, 201828131188626 @ 79, 209, 259 +179334089326071, 197614868629114, 332406359271651 @ -5, 60, -26 +262093968892863, 107075329722362, 414807233851420 @ 34, 315, -234 +229016437887321, 253800281514190, 442412418387360 @ -21, 15, -178 +435464268415533, 304740242014684, 308396918820801 @ -83, 370, -776 +434507208806365, 509232372383340, 444474239318010 @ -265, -381, -284 +268752689610051, 291591481519324, 295468449312780 @ 122, 24, -60 +388988596465428, 462487948867582, 429870272877633 @ -122, -416, -452 +66784011152624, 361184408854064, 406644902129688 @ 92, -114, -95 +417437370920109, 239344427883568, 200940613813092 @ 9, 790, 358 +258122981051685, 455818141956768, 500343012517998 @ -47, -240, -263 +428885056879621, 395958064188608, 336285404809233 @ -267, -162, -50 +371904496065333, 505347295365256, 482265546690900 @ -83, -518, -572 +268921212718412, 421249637667076, 105902059281656 @ -94, -182, 221 +245666370615068, 296820628562753, 359611784427307 @ 32, -21, -120 +266636285971089, 251550010433302, 261367259665596 @ -57, 23, 44 +381991540551663, 283471564116926, 250211504748680 @ 22, 177, 8 +107026635297788, 445380665254476, 456350458942680 @ 48, -198, -143 +436947285540239, 350951442595312, 282325390191614 @ -78, -170, -537 +145398660803727, 195609983658656, 242158434889096 @ 130, 110, 68 +297475449394982, 131750381092515, 165719703479968 @ -84, 195, 173 +382981082215082, 318082716962228, 217519872859947 @ -184, -54, 106 +274508569926281, 337480597564942, 249069272308048 @ 113, -80, 45 +409006873082037, 404306234256766, 306773089718196 @ 101, -620, -563 +304326995325327, 252632813540085, 317502450159756 @ -29, 69, -71 +335336102392062, 349032727458751, 147869871751056 @ -10, -107, 289 +224490789327707, 138112263823786, 214964316118086 @ -13, 160, 103 +257483144012212, 310616650691101, 220817557849225 @ 126, -23, 108 +378616249658565, 487631090875856, 211845741661518 @ -137, -403, 127 +256962996060820, 363038059754788, 382290100571323 @ 102, -134, -222 +376113767407764, 419697564588036, 503311772819474 @ -68, -318, -717 +411690063697784, 334901544443134, 250358939380980 @ -30, -32, -23 +378730592174173, 292937924939892, 216595109883586 @ -21, 95, 144 +386233907852537, 102017803023726, 148605073075956 @ -49, 797, 394 +401023678402335, 326392143373252, 250508593182692 @ -80, -20, 12 +187386788876757, 222440010076216, 5544716539566 @ 107, 89, 427 +211506671096437, 295843684641176, 394227297865006 @ 59, -25, -157 +170237159382989, 228511580730636, 335783635953320 @ 17, 32, -34 +293589456751485, 294178241627518, 249641359155174 @ -7, -5, 51 +439854842455119, 383935112515580, 293031876578902 @ -218, -316, -253 +295518506383932, 200374788948199, 229951840543641 @ -114, 71, 84 +394189872421409, 331448531001974, 256407864771135 @ -31, -36, -20 +311925984995885, 332357949681136, 293917117060350 @ 30, -68, -59 +389447608973881, 380513707763144, 244720406589022 @ -126, -192, 51 +366016540138437, 277293281705376, 413687743953006 @ 130, 233, -794 +298178291530224, 268217681216719, 304180593974067 @ -38, 31, -38 +308018243676123, 296892693397840, 274894177156788 @ -130, -42, 32 +60232254901961, 170686288518732, 262671045190162 @ 89, 74, 51 +124745624448567, 151652758178730, 163358199121217 @ 31, 96, 150 +321860786503481, 302448169248892, 261445808573098 @ -12, -5, 20 +205692521446297, 89407037159596, 410049214010034 @ 36, 247, -158 +239982788772333, 137286217774368, 174295345603502 @ -56, 138, 147 +86731844681439, 259688488792764, 210340217835198 @ 70, -12, 103 +170808423768189, 228588666791260, 293948466808818 @ 19, 33, 12 +441057939686395, 343398690648711, 549228030221401 @ -265, -93, -736 +302443946246812, 240143840858176, 379420862083931 @ -22, 94, -186 +345088720716403, 315552253051151, 268545755397918 @ 159, 27, -65 +423724795313077, 308659354107536, 180782338151766 @ -63, 186, 493 +406798864217260, 293663253737166, 320278735045387 @ -88, 132, -304 +195154781190237, 364862205409626, 254799516896806 @ -47, -117, 59 +178932977335797, 251708835992206, 247843728908376 @ 45, 19, 62 +253349271834117, 283691186580304, 303498852558606 @ -9, -9, -21 +376761673051257, 285602705599686, 270257629743006 @ -41, 101, -41 +300882491178039, 290243550583162, 189772203039720 @ -68, -15, 146 +235369194657157, 421562658281976, 408227743490686 @ -55, -183, -115 +188646633711105, 318918710332479, 369157982422215 @ 73, -61, -110 +395512774201357, 315616825750976, 285497663723286 @ 96, 102, -266 +421677117457729, 302462002478370, 260176983480688 @ -57, 221, -114 +177175197731565, 341281080915196, 331441656855726 @ 43, -93, -41 +325478665927397, 441871023252256, 224988749860460 @ 21, -338, 102 +402136003642932, 333799366036756, 296817265196841 @ 8, -30, -290 +182104997730129, 336028786762480, 74550271859558 @ 52, -86, 285 +292043981673693, 259010054670568, 310880696340486 @ -98, 9, -16 +327463887597202, 275386444030262, 281725872502210 @ 96, 120, -69 +180350572694521, 204046517624548, 270869833505754 @ 15, 64, 37 +261796476524925, 143723242270984, 124690998413814 @ -90, 121, 198 +382022380467301, 363084132643328, 342504705272910 @ -51, -159, -293 +359686755049611, 309851948068594, 254216163279732 @ 18, 21, 12 +432383902550757, 325288945907500, 237103658765274 @ -139, 49, 58 +199141995287962, 12205123960005, 135322914113123 @ 276, 653, 302 +388209037680334, 326840502219633, 280212599819923 @ 90, 11, -192 +398309490013959, 467459019065502, 435027019897864 @ -245, -216, -115 +438077885264229, 338437435266016, 251421696960654 @ -147, -33, -83 +142623030672997, 313922309635776, 172051026248046 @ 197, -48, 178 +211793103082053, 258637524078497, 413519499042315 @ -11, 5, -134 +316227539793914, 330807868031342, 320059762270916 @ -90, -76, -51 +363745515105897, 308033947226491, 241876133298636 @ 9, 29, 53 +229073101043463, 182441744874760, 375616182031518 @ -6, 114, -105 +311663766702322, 293169473612442, 266993157354132 @ -64, -12, 25 +165743821901955, 245775966807730, 293803407552466 @ 40, 19, 9 +349142785799508, 280261145006550, 287389255673128 @ 124, 164, -135 +299220074031339, 172470550513459, 207086145840829 @ -65, 163, 120 +51599932704531, 110067755093612, 120750763264579 @ 187, 186, 216 +362339688007455, 128526862135900, 213561367782111 @ 123, 898, 174 +318235966547318, 236743583502987, 172190463362498 @ -150, 21, 147 +243218064862137, 146112647037076, 312898709705706 @ -12, 173, -28 +248532762868587, 127913038997386, 306713186523936 @ -89, 124, 5 +356833591049452, 288318963368346, 175747488009196 @ -36, 56, 237 +429258217460035, 281264286545936, 199918966637106 @ -81, 462, 379 +288595615758281, 286112367984743, 301320148789454 @ 17, 15, -49 +434137829300957, 385164566787576, 251517643175406 @ -90, -513, -101 +226684015769909, 393228920796224, 237234101626834 @ 5, -162, 75 +277608974085399, 484613028229744, 346163443971816 @ -86, -266, -56 +439564663355742, 339477585210058, 360927913554417 @ -264, -84, -224 +243540738730971, 359735080690960, 250444934709888 @ -65, -114, 61 +414936626664123, 309300663907822, 216629185840824 @ -56, 125, 188 +397872703252389, 212898395772056, 240610671804790 @ -131, 297, 60 +123154693229737, 203455201989076, 290045021180228 @ 51, 52, 20 +268437039198703, 312957758717668, 372983507517126 @ -58, -56, -101 +290041101495914, 452525408726809, 261168521158394 @ 18, -305, 27 +94022340218020, 214444823962799, 233285115180485 @ 78, 39, 80 +187758784146701, 308231925236552, 42842321977264 @ 17, -54, 306 +298993330355122, 276052686620461, 298685552862006 @ -10, 31, -41 +332169842700025, 298970888104540, 302981537331018 @ -70, -11, -50 +194328822595255, 76283873425353, 136668594275728 @ 239, 459, 281 +120250832193905, 241032280181964, 229456138785466 @ 50, 11, 84 +151422919814977, 301022504515816, 378981998111542 @ 111, -38, -117 +96990387183037, 372867516983776, 14714289836806 @ 168, -134, 366 +274942199061477, 481640626788556, 14527007819946 @ -11, -317, 432 +224838145952262, 313821556817251, 263551720120806 @ 14, -55, 39 +403167845873627, 244787413886076, 196299464895806 @ -30, 432, 279 +423651938100112, 435225368641841, 336353363207841 @ -264, -201, -38 +289166585859768, 74894176976193, 138452721266517 @ 130, 605, 328 +431669875459573, 325370084156409, 252462190860946 @ -27, 143, -141 +390448274978984, 338265610742420, 231189470189675 @ 98, -54, 98 +237855310336712, 79275006966921, 512264534723696 @ -64, 191, -223 +430777549022346, 301130642558299, 294289756858713 @ -166, 153, -262 +222272412127973, 253877615323776, 267895382908238 @ 18, 27, 33 +165432519670262, 95007658128776, 226194378092481 @ 24, 182, 88 +281007118242885, 330242484331812, 296563154696266 @ -35, -75, -16 +359290360054469, 394969290711776, 300557072988910 @ -60, -223, -88 diff --git a/2023/input/24/test-1 b/2023/input/24/test-1 new file mode 100644 index 0000000..35963dc --- /dev/null +++ b/2023/input/24/test-1 @@ -0,0 +1,5 @@ +19, 13, 30 @ -2, 1, -2 +18, 19, 22 @ -1, -1, -2 +20, 25, 34 @ -2, -2, -4 +12, 31, 28 @ -1, -2, -1 +20, 19, 15 @ 1, -5, -3 diff --git a/2023/src/bin/day24.rs b/2023/src/bin/day24.rs new file mode 100644 index 0000000..569ecb0 --- /dev/null +++ b/2023/src/bin/day24.rs @@ -0,0 +1,221 @@ +#![feature(test)] +extern crate nalgebra as na; +use std::{str::FromStr, convert::Infallible, collections::HashMap}; + +use anyhow::Result; +use aoc::Solver; +use na::{SMatrix, SVector}; + +// -- Runners -- +fn main() -> Result<()> { + Day::solve() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn part1_test1() -> Result<()> { + Day::test(Day::part1, "test-1", 2) + } + + #[test] + fn part1_solution() -> Result<()> { + Day::test(Day::part1, "input", 13149) + } + + #[test] + fn part2_test1() -> Result<()> { + Day::test(Day::part2, "test-1", 47) + } + + #[test] + fn part2_solution() -> Result<()> { + Day::test(Day::part2, "input", 1033770143421619) + } + + // Benchmarks + extern crate test; + #[bench] + #[ignore] + fn part1_bench(b: &mut test::Bencher) { + Day::benchmark(Day::part1, b) + } + #[bench] + #[ignore] + fn part2_bench(b: &mut test::Bencher) { + Day::benchmark(Day::part2, b) + } +} + +#[derive(Debug, Clone, Copy)] +struct Hailstone { + px: f64, + py: f64, + pz: f64, + vx: f64, + vy: f64, + vz: f64 +} + +impl Hailstone { + fn intersect_2d(&self, other: &Hailstone) -> Option<(f64, f64)> { + let dx = self.px - other.px; + let dy = self.py - other.py; + + let d = self.vy * other.vx - self.vx * other.vy; + + let t1 = (other.vy*dx - other.vx * dy) / d; + let t2 = (self.vy * dx - self.vx*dy) / d; + + if t1.is_sign_negative() || t2.is_sign_negative() { + // Intersection is in the past + return None; + } + + let x = self.px + self.vx * t1; + let y = self.py + self.vy * t1; + + if x.is_infinite() || y.is_infinite() { + // Paths are parallel + return None; + } + + Some((x, y)) + } +} + +impl FromStr for Hailstone { + type Err = Infallible; + + fn from_str(s: &str) -> Result { + let parts: Vec = s.split([',', '@']).map(|part| part.trim().parse().unwrap()).collect(); + + Ok(Hailstone { + px: parts[0], + py: parts[1], + pz: parts[2], + vx: parts[3], + vy: parts[4], + vz: parts[5], + }) + } +} + +fn mode(numbers: &[usize]) -> usize { + let mut occurrences = HashMap::<_, usize>::new(); + + for &value in numbers { + *occurrences.entry(value).or_insert(0) += 1; + } + + println!("{occurrences:?}"); + + occurrences.into_iter().max_by_key(|&(_, count)| count).map(|(value, _)| value).unwrap() +} + +// -- Solution -- +pub struct Day; +impl aoc::Solver for Day { + type Output1 = usize; + type Output2 = usize; + + fn day() -> u8 { + 24 + } + + fn part1(input: &str) -> Self::Output1 { + let hailstones: Vec<_> = input.lines().flat_map(Hailstone::from_str).collect(); + + let range = if hailstones.len() == 5 { + 7.0..=27.0 + } else { + 200000000000000.0..=400000000000000.0 + }; + + hailstones.iter().enumerate().flat_map(|(index_a, a)| { + hailstones.iter().enumerate().filter(|(index_b, _)| index_b < &index_a).filter_map(|(_, b)| { + a.intersect_2d(b) + }).collect::>() + }).filter(|&(x, y)| range.contains(&x) && range.contains(&y)).count() + } + + fn part2(input: &str) -> Self::Output2 { + let h: Vec<_> = input.lines().flat_map(Hailstone::from_str).collect(); + + // Key insight for part 2 is + // p_rock + v_rock * t_i = p_i + v_i * t_i + // for every hailstone i + // + // This can be rewritten as + // p_rock - p_i = t_i * (v_i - v_rock) + // and since t_i is a scalar this means that + // (p_rock - p_i) is parallel to (v_i - v_rock) + // and therefore + // c_i = (p_rock - p_i) x (v_i - v_rock) = 0 + // This holds true for every hailstone i, so + // c_i = c_j + // c_i = c_k + // with i != j != k + // Writing out these equations leads to a set of six linear equations + // And can therefore be written in matrix form + // A * solution = constant + // And the solution can now be found using + // solution = A^-1 * constant + + let i = 0; + let j = 1; + // Due to numerical instability we run this with several different options for the third + // hailstone + let solutions: Vec<_> = (2..h.len()).map(|k| { + // Constant in the matrix + let c1 = h[i].vz - h[j].vz; + let c2 = h[i].py - h[j].py; + let c3 = h[j].vy - h[i].vy; + let c4 = h[j].pz - h[i].pz; + let c5 = h[i].vx - h[j].vx; + let c6 = h[j].px - h[i].px; + + let c7 = h[i].vz - h[k].vz; + let c8 = h[i].py - h[k].py; + let c9 = h[k].vy - h[i].vy; + let c10 = h[k].pz - h[i].pz; + let c11 = h[i].vx - h[k].vx; + let c12 = h[k].px - h[i].px; + + // Setup the matrix + let matrix = SMatrix::::new( + 0.0, c1, c3, 0.0, c4, c2, + -c1, 0.0, c5, -c4, 0.0, c6, + -c3, -c5, 0.0, -c2, -c6, 0.0, + 0.0, c7, c9, 0.0, c10, c8, + -c7, 0.0, c11, -c10, 0.0, c12, + -c9, -c11, 0.0, -c8, -c12, 0.0 + ); + + // Get the inverse of the matrix + let inverse = matrix.try_inverse().unwrap(); + + // Constant on the rhs + let k1 = h[i].py*h[i].vz - h[j].py*h[j].vz + h[j].pz*h[j].vy - h[i].pz*h[i].vy; + let k2 = h[i].pz*h[i].vx - h[j].pz*h[j].vx + h[j].px*h[j].vz - h[i].px*h[i].vz; + let k3 = h[i].px*h[i].vy - h[j].px*h[j].vy + h[j].py*h[j].vx - h[i].py*h[i].vx; + let k4 = h[i].py*h[i].vz - h[k].py*h[k].vz + h[k].pz*h[k].vy - h[i].pz*h[i].vy; + let k5 = h[i].pz*h[i].vx - h[k].pz*h[k].vx + h[k].px*h[k].vz - h[i].px*h[i].vz; + let k6 = h[i].px*h[i].vy - h[k].px*h[k].vy + h[k].py*h[k].vx - h[i].py*h[i].vx; + + // Put them into a vector + let k = SVector::::new(k1, k2, k3, k4, k5, k6); + + // Calclate the solution + let solution = inverse * k; + + // The sum of all elements of the starting position is the answer + (solution[0] + solution[1] + solution[2]).round() as usize + }).collect(); + + // The most common solution is the actual solution + mode(&solutions) + } +}