From 190e08be0ec8e9311f93c678884a04e15c478e77 Mon Sep 17 00:00:00 2001 From: jurisk <4895679+jurisk@users.noreply.github.com> Date: Sun, 22 Dec 2024 09:43:50 +0200 Subject: [PATCH] 2024-22 (#38) --- ReadMe.md | 1 + rust/y2024/resources/22-test-00.txt | 4 + rust/y2024/resources/22-test-01.txt | 4 + rust/y2024/resources/22.txt | 1571 ++++++++++++++++ rust/y2024/src/bin/solution_2024_22.rs | 135 ++ scala2/src/main/resources/2024/22-test-00.txt | 5 +- scala2/src/main/resources/2024/22-test-01.txt | 4 + scala2/src/main/resources/2024/22.txt | 1572 ++++++++++++++++- scala2/src/main/resources/2024/23-test-00.txt | 1 + scala2/src/main/resources/2024/23.txt | 1 + .../jurisk/adventofcode/y2018/Advent17.scala | 28 +- .../jurisk/adventofcode/y2022/Advent05.scala | 5 +- .../jurisk/adventofcode/y2022/Advent06.scala | 12 +- .../jurisk/adventofcode/y2022/Advent13.scala | 5 +- .../jurisk/adventofcode/y2022/Advent20.scala | 7 +- .../jurisk/adventofcode/y2022/Advent24.scala | 9 +- .../jurisk/adventofcode/y2023/Advent08.scala | 11 +- .../jurisk/adventofcode/y2024/Advent22.scala | 87 +- .../jurisk/adventofcode/y2024/Advent23.scala | 48 + .../scala/jurisk/utils/CollectionOps.scala | 41 +- .../scala/jurisk/utils/CollectionUtils.scala | 9 + .../adventofcode/y2024/Advent22Spec.scala | 55 +- .../adventofcode/y2024/Advent23Spec.scala | 30 + 23 files changed, 3568 insertions(+), 77 deletions(-) create mode 100644 rust/y2024/resources/22-test-00.txt create mode 100644 rust/y2024/resources/22-test-01.txt create mode 100644 rust/y2024/resources/22.txt create mode 100644 rust/y2024/src/bin/solution_2024_22.rs create mode 100644 scala2/src/main/resources/2024/22-test-01.txt create mode 100644 scala2/src/main/resources/2024/23-test-00.txt create mode 100644 scala2/src/main/resources/2024/23.txt create mode 100644 scala2/src/main/scala/jurisk/adventofcode/y2024/Advent23.scala create mode 100644 scala2/src/main/scala/jurisk/utils/CollectionUtils.scala create mode 100644 scala2/src/test/scala/jurisk/adventofcode/y2024/Advent23Spec.scala diff --git a/ReadMe.md b/ReadMe.md index cd15d7d6..573d89b7 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -6,6 +6,7 @@ | Year-Day | Task | Scala | Rust | Others | |----------|:-------------------------------------------------------------------------------|:-----------------------------------------------------------------------:|:----------------------------------------------:|:----------------------------------------------------------------------:| +| 2024-22 | [Monkey Market](https://adventofcode.com/2024/day/22) | [Scala](scala2/src/main/scala/jurisk/adventofcode/y2024/Advent22.scala) | [Rust](rust/y2024/src/bin/solution_2024_22.rs) | | | 2024-21 | [Keypad Conundrum](https://adventofcode.com/2024/day/21) | [Scala](scala2/src/main/scala/jurisk/adventofcode/y2024/Advent21.scala) | [Rust](rust/y2024/src/bin/solution_2024_21.rs) | | 2024-20 | [Race Condition](https://adventofcode.com/2024/day/20) | [Scala](scala2/src/main/scala/jurisk/adventofcode/y2024/Advent20.scala) | [Rust](rust/y2024/src/bin/solution_2024_20.rs) | | | 2024-19 | [Linen Layout](https://adventofcode.com/2024/day/19) | [Scala](scala2/src/main/scala/jurisk/adventofcode/y2024/Advent19.scala) | [Rust](rust/y2024/src/bin/solution_2024_19.rs) | | diff --git a/rust/y2024/resources/22-test-00.txt b/rust/y2024/resources/22-test-00.txt new file mode 100644 index 00000000..322c9dbf --- /dev/null +++ b/rust/y2024/resources/22-test-00.txt @@ -0,0 +1,4 @@ +1 +10 +100 +2024 \ No newline at end of file diff --git a/rust/y2024/resources/22-test-01.txt b/rust/y2024/resources/22-test-01.txt new file mode 100644 index 00000000..cfb19888 --- /dev/null +++ b/rust/y2024/resources/22-test-01.txt @@ -0,0 +1,4 @@ +1 +2 +3 +2024 \ No newline at end of file diff --git a/rust/y2024/resources/22.txt b/rust/y2024/resources/22.txt new file mode 100644 index 00000000..b91e7417 --- /dev/null +++ b/rust/y2024/resources/22.txt @@ -0,0 +1,1571 @@ +1493754 +10923278 +16546773 +1314471 +6028677 +5073322 +9408335 +7319309 +2564301 +10904573 +7922618 +3614143 +15150274 +12669195 +8741032 +16682330 +3165955 +13943279 +467874 +9819384 +15445038 +7966363 +14317456 +11409808 +3836027 +1614516 +12405256 +15120563 +3279420 +5628109 +15271659 +8124685 +531316 +12051297 +9280023 +5154432 +184568 +927122 +1606161 +15300094 +4269426 +9302392 +7266570 +14380739 +7517283 +9129997 +14716586 +4671555 +8445085 +10039659 +8636521 +16503705 +3385813 +2737105 +6187837 +14789193 +3142062 +14497611 +1508284 +382921 +10748255 +3953504 +5018808 +5619048 +14832913 +15187482 +1510297 +3905045 +3430772 +4761871 +8978600 +5744337 +319824 +12512173 +514961 +11538087 +16610493 +3087105 +12631386 +8938389 +11342950 +15777932 +16767994 +2672119 +9542005 +13554784 +537773 +13047769 +7215387 +1807539 +13026319 +2010601 +3682596 +16635782 +16230848 +5608117 +5564661 +7746468 +12571746 +11968378 +10215191 +1091129 +1037638 +1107419 +15156977 +887746 +16665890 +501946 +12661625 +15554225 +12500919 +9389442 +834189 +10483271 +7829281 +10199154 +2916438 +8488328 +1254424 +12184237 +9144900 +11853535 +14219821 +12373552 +14427517 +650831 +7651733 +12609366 +392226 +328507 +9997988 +1311500 +4712326 +4029923 +9833910 +704900 +2611835 +2729110 +744392 +12401911 +10065383 +4483900 +5485655 +12369885 +13591152 +10737304 +10848212 +252889 +14246763 +16010455 +13385256 +1120200 +6379862 +1480824 +15311423 +13405516 +2417649 +7748212 +397821 +6070932 +12717465 +3053269 +9675829 +3170623 +16163263 +16372805 +9687188 +5924042 +15630149 +15947313 +5916356 +390995 +15576157 +5603907 +4507165 +9111592 +9556922 +14882668 +10969516 +8741430 +6709814 +747482 +12113976 +16608843 +2985916 +14092606 +5957981 +6765514 +9963000 +14115208 +9106091 +1980331 +8837749 +15223571 +14284303 +11367016 +6778874 +15526823 +10780808 +2064344 +9847673 +3401517 +9568646 +14062857 +10902414 +10881811 +1178365 +1090975 +16002427 +14957456 +1588322 +7655837 +16150428 +3291587 +13238928 +2472712 +16127684 +2706048 +2588560 +9991780 +7024986 +7861020 +10081024 +2436826 +14581765 +3349798 +14741964 +11834507 +16682883 +7914769 +8727942 +5006985 +5122476 +3523619 +10878127 +11100130 +11314156 +9094352 +13832369 +742724 +15714122 +1151896 +3776587 +13309172 +3188937 +3075864 +3784861 +4170249 +11870259 +5503358 +15177676 +10325064 +15920776 +9721332 +4701632 +7971946 +3529707 +9027267 +13047068 +13512483 +8248985 +10356468 +14832646 +14574840 +14086268 +14984472 +2039046 +13614981 +8832766 +13717157 +1927032 +15852524 +3788890 +402642 +11387094 +348864 +8145412 +12019551 +7409458 +7876125 +11668710 +16355291 +8361453 +1047402 +8248569 +2013995 +3304149 +1064383 +7940661 +12128266 +8249160 +5696758 +770119 +16689621 +8907331 +16075275 +12376108 +13293799 +4579449 +1597636 +8080066 +3227115 +4717268 +9305675 +4959388 +7632428 +3327237 +12726774 +1196434 +7759050 +9943232 +15013476 +11653485 +8086021 +15035057 +8782538 +15156614 +7214950 +4448004 +9049183 +11264380 +7077746 +3813548 +16632790 +4398656 +7891709 +6077301 +5056512 +8807998 +7780014 +12628245 +1241827 +13294340 +15186523 +13133889 +8976126 +9834454 +1065761 +14679529 +13857982 +2056333 +14418401 +3078037 +10992093 +6019237 +279463 +11247030 +3558084 +9833157 +8200698 +11180464 +5052161 +13421820 +905142 +11409455 +15336054 +11372733 +14026016 +12849422 +10308344 +7415570 +14103868 +1271304 +10255080 +8128700 +2924595 +15991796 +9863832 +4839108 +16651432 +8653602 +321863 +11413955 +6319410 +4711958 +2937071 +6317141 +13488653 +10159476 +16229211 +3340136 +1464859 +9392274 +4841625 +10839222 +7979971 +9506501 +14531636 +2913369 +3288847 +13937141 +6907268 +2846081 +567416 +8319638 +1522917 +3139435 +12462184 +12450712 +9726384 +4300337 +6930461 +7138645 +4567183 +12140178 +9169656 +14335228 +1561846 +15035342 +1402006 +535868 +5494917 +12544662 +8524297 +16464244 +1705314 +16081798 +16461985 +14917863 +174817 +13407721 +5988444 +14811075 +10613551 +790645 +16295124 +14828313 +13450055 +9472117 +5510864 +15697672 +3420394 +9771026 +8703024 +5441199 +11590446 +15296960 +7544012 +11657104 +5447120 +11729023 +2335519 +4417841 +15506549 +8348231 +3899449 +8774129 +14013933 +8887106 +1373535 +9274897 +12152464 +10509406 +15686672 +15129089 +12374285 +5187212 +10225841 +15550461 +2378781 +13653118 +2715210 +6235915 +10860294 +4791971 +11910091 +12454234 +14310440 +9455709 +16551757 +6796774 +12694889 +9961624 +2343532 +12621894 +16484333 +2352035 +1037955 +2725165 +4102187 +10028758 +9263362 +11740732 +1626981 +15632540 +8749388 +4599645 +10947653 +13811632 +15084498 +4665018 +14730346 +11748038 +6138609 +9564692 +13748456 +10061191 +4144903 +8180733 +16208304 +4755610 +9735630 +546074 +1696070 +10272676 +1009303 +6132792 +2633856 +13943130 +4874063 +14634900 +9713271 +3349086 +6508142 +6655325 +6022491 +7070552 +7397887 +6247664 +2156187 +13933746 +5518533 +1624275 +4700522 +11333255 +8946244 +6942454 +9153449 +7579870 +16009744 +10042424 +6202365 +13563560 +11156481 +12842381 +5857808 +7310627 +5254012 +5132173 +6116586 +9355266 +5808317 +7684243 +13591720 +13914437 +15605332 +773341 +776724 +13570294 +11476875 +8944497 +16322817 +3007720 +4691020 +8921294 +4970469 +9603660 +731475 +3833255 +5151901 +8436322 +9179668 +6604575 +13957646 +9351058 +10417573 +4667164 +7629091 +9515303 +9425698 +4170125 +2105169 +4135029 +6784470 +711257 +8993559 +1047135 +15103771 +2018074 +2150562 +7177058 +7015798 +13924981 +12459040 +9427401 +14853840 +9977140 +9556343 +5878097 +10100968 +14667259 +149349 +6212743 +15003698 +16732085 +4260990 +5280283 +8582192 +1323877 +9716759 +13088499 +3283500 +1556542 +12877208 +4413481 +8555956 +14249867 +3098542 +7356933 +11002577 +11305181 +13264728 +3181035 +9968145 +3860910 +3743460 +5146759 +13269959 +15470986 +9920477 +6887135 +9734072 +5530717 +4141560 +7445397 +15936095 +16161644 +1646153 +11130265 +3553915 +9264633 +8830543 +5160338 +16200255 +14772324 +3116969 +11706255 +11403440 +11951881 +16585971 +6126131 +4956945 +2467035 +4794256 +9273123 +3636519 +9275423 +6460167 +1472944 +5161762 +16620879 +9559615 +16520102 +8516237 +2862221 +10362542 +14292160 +10920537 +6151323 +4146076 +10055375 +6473327 +1127072 +13449345 +4474486 +6152819 +6992761 +7547840 +16334446 +8334223 +12176804 +4466453 +4694176 +783093 +15123760 +5228411 +15340728 +11152555 +14283104 +3827617 +3432131 +8839355 +3553527 +8747137 +1708313 +6146671 +10263131 +8873040 +1022795 +6711952 +16130816 +10772126 +13437647 +14223536 +10596752 +14054983 +14746132 +1330621 +16030634 +16480441 +4435518 +11378858 +11857371 +6123255 +12657374 +7646974 +2608857 +9388525 +15580499 +11704159 +9609430 +16271791 +14138832 +14624188 +7147751 +1044617 +9229006 +1650902 +8083558 +474142 +9178015 +10043664 +15383094 +4581952 +2402253 +12952140 +12495275 +14033319 +15538816 +3301211 +11283923 +10460761 +3533445 +2785054 +13948312 +209723 +16375926 +14967552 +9241393 +13157413 +4666480 +8463748 +1458927 +3482275 +14261012 +9121809 +6213234 +6551951 +8953299 +14182863 +10814676 +2622944 +3505255 +12316785 +8418871 +16182022 +14011395 +4286561 +12570811 +13042848 +15629320 +9624895 +3041659 +2526109 +8529717 +2539512 +319982 +5402450 +1403646 +13942288 +2775918 +16282015 +6235195 +6848387 +1201248 +6081772 +8134805 +6582224 +7958228 +403816 +4537873 +7916590 +7502863 +5734898 +13024689 +8427201 +6090197 +9649620 +14244491 +12627408 +5745069 +1112247 +10722255 +14426237 +12963538 +13161222 +12838148 +10848605 +8235215 +2533507 +14517311 +7433327 +2906653 +1572315 +8841584 +11311772 +4198238 +2555528 +11682749 +12440229 +10438700 +11173843 +3729829 +12335032 +9908612 +4718922 +16225795 +8114799 +13935413 +15350971 +15533622 +15258338 +10893519 +5082242 +3652716 +11891639 +13933225 +2923746 +3171274 +362426 +2455758 +2701564 +7330374 +16537463 +14764698 +15342634 +816434 +15698834 +16033501 +5794185 +7104758 +10589504 +5127294 +14648257 +6423097 +13439308 +333402 +14191501 +11517309 +14865721 +12786253 +1948096 +14377584 +3349243 +7374345 +12607285 +12169349 +11016070 +14069873 +4108185 +9532125 +16403695 +747225 +3346648 +2490762 +8932229 +8777362 +7849342 +12471528 +12132177 +1298379 +8065702 +5834056 +16005825 +11279017 +14153382 +2143335 +7062803 +3837492 +9108244 +14915313 +13982998 +6544734 +11947953 +7049750 +15714369 +14675229 +15086123 +6036328 +3337450 +10236472 +10325502 +2334575 +10663289 +11659764 +7073072 +8170754 +7013350 +5151101 +8016944 +7514141 +10107300 +12949578 +15785412 +11681265 +1288738 +601444 +16129473 +1930509 +6213293 +10187238 +15535867 +9938688 +11440933 +12283764 +3148008 +8492116 +3833162 +7224287 +11382904 +14823341 +8504755 +2475680 +15182738 +11190501 +15946656 +9307381 +11666727 +5448768 +1285316 +4962839 +8222159 +14855254 +7535064 +11177199 +15945862 +9012741 +5075364 +3536958 +9150829 +13065391 +10766166 +3547192 +10318634 +7850297 +15323286 +994523 +3562525 +16134018 +2548934 +5611124 +13954159 +15199180 +6249198 +11111648 +8632024 +7594808 +4448421 +3407426 +12922097 +259988 +10251024 +9228766 +258797 +9750260 +5285229 +12659709 +15698644 +932361 +14495804 +5972631 +4653671 +14901459 +14416410 +8363165 +4177512 +10167088 +1460631 +13703588 +5537582 +10189308 +15507248 +2972042 +15766321 +5559483 +12773714 +4964031 +5896605 +9277262 +3847145 +13149579 +11955940 +15069727 +12139120 +1104529 +4345066 +2041097 +6969535 +12560032 +13596010 +5912974 +12854526 +10915993 +14525726 +10709846 +7273980 +9944049 +288350 +14931356 +4759103 +11836953 +6885358 +15401222 +6518387 +1200793 +9557559 +9973389 +10253227 +15335566 +773956 +15036760 +13451291 +3155847 +2038404 +11946487 +6484265 +16062886 +16265663 +6900027 +12287415 +3862570 +10692194 +4554445 +1107079 +7121466 +7172861 +14045138 +15717925 +7757621 +3123626 +8481655 +11620734 +2830652 +7607024 +16158110 +5167003 +15492638 +1182434 +3126025 +4107076 +11296549 +1454355 +11427115 +11703912 +6254511 +9849226 +5049917 +14129678 +8741324 +14140875 +6274973 +12257391 +2497359 +3242949 +11252803 +1455214 +2805813 +201146 +11247346 +4724749 +10009673 +2650086 +984851 +11347460 +16511302 +3819603 +16287584 +2069121 +5606354 +8716289 +14272074 +16612953 +10681312 +7362689 +9679008 +13430688 +8591357 +16374519 +4641596 +7328872 +7520866 +16499615 +9236360 +11303399 +3343712 +15264784 +12765262 +1445035 +16252679 +15052956 +8280017 +563113 +11121837 +8789946 +14175546 +15098158 +7154205 +3856013 +2159966 +8314739 +8505582 +5704037 +2369881 +8539259 +2320025 +1931133 +4658158 +2046823 +4908706 +15459352 +695431 +11315685 +15836406 +225738 +3148671 +1288362 +8605576 +12815555 +15040202 +13352711 +14983143 +1797070 +3766103 +9378200 +10369592 +11299552 +12979788 +783350 +5818838 +8276791 +531709 +4434661 +14610526 +16630115 +10103496 +3457284 +4105640 +2918079 +13998083 +11384161 +15915465 +1939354 +11076878 +2804356 +1464512 +2977444 +3743488 +12341117 +3712520 +7950065 +6881449 +7488644 +11569096 +8734120 +13067668 +6327115 +13418964 +6557751 +5746005 +8620507 +15254316 +12055005 +6405842 +3614489 +12136710 +6717545 +5854547 +6902651 +15526874 +12134928 +5976808 +15892570 +9486671 +14197394 +2860355 +13250174 +15404064 +2249244 +12663404 +15753739 +5592435 +11104709 +15231380 +10727629 +8135761 +5879289 +1917212 +3588407 +8438846 +16356300 +5129518 +12811724 +5266944 +3965124 +5632378 +4432845 +8090102 +7178885 +4562036 +11693575 +6159470 +6072984 +7445010 +3753847 +353918 +6422406 +11384621 +12394039 +15873046 +12199298 +7322839 +3549072 +8531432 +6695698 +10703745 +12372895 +14276317 +3198806 +4261986 +5815034 +8342720 +7138535 +7768985 +10466586 +226770 +4791226 +694909 +7908327 +949422 +1503987 +9701128 +14498263 +15023381 +9045805 +621258 +8185182 +3686860 +8339330 +15923341 +13213732 +5005761 +7057749 +4701167 +3349383 +2405459 +10192352 +4612182 +1953845 +13532527 +5831268 +16490774 +11169165 +1021419 +993812 +1077849 +3170396 +697919 +2862304 +14714146 +7301408 +13235538 +13907368 +1103843 +2036112 +2913770 +7477912 +16584830 +5378403 +704150 +14764312 +13093618 +7097531 +3835354 +12361996 +7637456 +3576914 +5022114 +15234804 +12894592 +14111416 +3287480 +14370597 +9289086 +16323436 +15643734 +3869491 +5473874 +12690018 +13854074 +11637624 +15406930 +8932786 +9183468 +8750813 +10237041 +15112631 +15351664 +13293542 +989477 +3674807 +7867612 +12815736 +13341146 +3901536 +7053873 +6126821 +8411365 +13709292 +372743 +5580639 +11779471 +5786533 +16516619 +11949126 +15507416 +459462 +13717336 +9015683 +10554531 +5971229 +1248463 +7973040 +369776 +9110528 +5470627 +8771743 +8276305 +15826718 +15277707 +1744051 +9643926 +16021905 +8290556 +5288818 +2117324 +2106190 +9103655 +4487600 +7994815 +1574543 +7517745 +6911243 +10040279 +6834496 +551007 +13028453 +2735021 +13109668 +12740548 +755116 +13295041 +4088972 +1953556 +9083499 +2317877 +2073670 +463102 +7640662 +14806254 +15719249 +9719424 +14981495 +9851880 +7265879 +3375470 +5224585 +7240565 +13918082 +10046252 +7216795 +9359095 +15639394 +5443721 +3713348 +13114885 +3065591 +10621766 +15759716 +4994358 +7950361 +1322152 +193485 +16776856 +612265 +6593842 +13540372 +5956495 +10629189 +13287447 +1447509 +2670624 +7094018 +12663024 +6901711 +11618762 +7710420 +9896577 +9996283 +14426563 +3824812 +9531963 +11190525 +9806598 +1229609 +5199982 +12543300 +3936192 +9480919 +10724588 +16051632 +5848754 +13484140 +3661317 +11378054 +14415776 +13983571 +6748308 +14380387 +1207673 +14636268 +8005086 +14270819 +6802629 +5464688 +2268113 +3548876 +4371683 +1757527 +10850329 +13174736 +5648898 +15264278 +13839187 +251427 +650273 +1497323 +11299184 +3720388 +15381572 +9103603 +5911570 +8438673 +14046148 +16381253 +2080141 +9396744 +1305086 +15897403 +11645868 +9418540 +14653913 +2060804 +10842965 +9629769 +12558941 +11697117 +13917549 +4789566 +7146282 +16106986 +1566054 +12557282 +12130038 +10993300 +14368247 +3021596 +15856151 +2381985 +13874317 +12695168 +3033597 +15420624 +14949131 +15364720 +7099088 +15248857 +8916319 +12033053 +4350622 +10339537 +7184494 +441901 +10998878 +1107938 +12649925 +12418910 +14741670 +2046959 +11210335 +1794558 +7517510 +16330104 +6230692 +6037229 +7178235 +1447533 +12497320 +10588805 +4925996 +12503009 +3268972 +16616140 +9313314 +420052 +8188087 +3389996 +816213 +3459091 +13114562 +10253876 +6351697 +5271599 +15412423 +6253525 +5791065 +1878795 +14470914 +202769 +5939257 +4354084 +9312651 +2128446 +13997285 +3002108 +6566101 +283033 +13408539 +3323721 +15892833 +12081237 +4435188 +3445901 +15383964 +571414 +11401813 +12823471 +2076542 +10921052 +3416139 +5882055 +9593571 +15545457 +5396966 +1807109 +13102366 +14658837 +14872216 +8920548 +8162211 +4993144 +2386214 +2378553 +9544221 +4185554 +13822237 +16085672 +7381886 +7257990 +16517426 +3168793 +14597394 \ No newline at end of file diff --git a/rust/y2024/src/bin/solution_2024_22.rs b/rust/y2024/src/bin/solution_2024_22.rs new file mode 100644 index 00000000..452c98cc --- /dev/null +++ b/rust/y2024/src/bin/solution_2024_22.rs @@ -0,0 +1,135 @@ +use std::collections::HashMap; + +use advent_of_code_common::parsing::{Error, parse_lines_to_vec}; + +const DATA: &str = include_str!("../../resources/22.txt"); + +type N = u64; +type Diff = i8; +type Input = Vec; +const SEQUENCE_LENGTH: usize = 4; +type Sequence = [Diff; SEQUENCE_LENGTH]; + +fn parse(input: &str) -> Result { + parse_lines_to_vec(input) +} + +fn next(n: N) -> N { + fn mix_prune(a: N, b: N) -> N { + (a ^ b) % 16_777_216 + } + + let a = mix_prune(n * 64, n); + let b = mix_prune(a / 32, a); + mix_prune(b * 2048, b) +} + +fn nth_secret_number(n: N, n_th: usize) -> N { + if n_th == 0 { + n + } else { + nth_secret_number(next(n), n_th - 1) + } +} + +fn create_bananas_and_diffs(n: N, how_many: usize) -> (Vec, Vec) { + let mut bananas = Vec::with_capacity(how_many + 1); + + bananas.push(n); + + for i in 0 .. how_many { + bananas.push(next(bananas[i])); + } + + let mut diffs = Vec::with_capacity(how_many); + for i in 0 .. how_many { + diffs.push((bananas[i + 1] % 10) as Diff - (bananas[i] % 10) as Diff); + } + + bananas.iter_mut().for_each(|b| *b %= 10); + + (bananas, diffs) +} + +fn create_banana_map(n: N) -> HashMap { + let (bananas, all_diffs) = create_bananas_and_diffs(n, 2000); + + let mut results = HashMap::new(); + + for i in 0 .. (all_diffs.len() - SEQUENCE_LENGTH) { + let slice = &all_diffs[i .. (i + SEQUENCE_LENGTH)]; + let diffs: Sequence = slice.try_into().expect("Slice with incorrect length"); + let result = bananas[i + SEQUENCE_LENGTH]; + results.entry(diffs).or_insert(result); + } + + results +} + +fn solve_1(data: &Input) -> N { + data.iter().map(|n| nth_secret_number(*n, 2000)).sum() +} + +fn solve_2(data: &Input) -> N { + let mut results: HashMap = HashMap::new(); + for n in data { + let banana_map = create_banana_map(*n); + for (k, v) in banana_map { + let new_value = results.entry(k).or_insert(0); + *new_value += v; + } + } + *results.values().max().expect("No max value") +} + +fn main() -> Result<(), Error> { + let data = parse(DATA)?; + + let result_1 = solve_1(&data); + println!("Part 1: {result_1}"); + + let result_2 = solve_2(&data); + println!("Part 2: {result_2}"); + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + const TEST_DATA_0: &str = include_str!("../../resources/22-test-00.txt"); + const TEST_DATA_1: &str = include_str!("../../resources/22-test-01.txt"); + + fn test_data_0() -> Input { + parse(TEST_DATA_0).unwrap() + } + fn test_data_1() -> Input { + parse(TEST_DATA_1).unwrap() + } + + fn real_data() -> Input { + parse(DATA).unwrap() + } + + #[test] + fn test_solve_1_test() { + assert_eq!(solve_1(&test_data_0()), 37_327_623); + } + + #[test] + fn test_solve_1_real() { + assert_eq!(solve_1(&real_data()), 13_022_553_808); + } + + #[test] + fn test_solve_2_test() { + assert_eq!(solve_2(&test_data_1()), 7 + 7 + 9); + } + + #[test] + #[ignore] + fn test_solve_2_real() { + assert_eq!(solve_2(&real_data()), 1555); + } +} diff --git a/scala2/src/main/resources/2024/22-test-00.txt b/scala2/src/main/resources/2024/22-test-00.txt index a8b6c947..322c9dbf 100644 --- a/scala2/src/main/resources/2024/22-test-00.txt +++ b/scala2/src/main/resources/2024/22-test-00.txt @@ -1 +1,4 @@ -noop \ No newline at end of file +1 +10 +100 +2024 \ No newline at end of file diff --git a/scala2/src/main/resources/2024/22-test-01.txt b/scala2/src/main/resources/2024/22-test-01.txt new file mode 100644 index 00000000..cfb19888 --- /dev/null +++ b/scala2/src/main/resources/2024/22-test-01.txt @@ -0,0 +1,4 @@ +1 +2 +3 +2024 \ No newline at end of file diff --git a/scala2/src/main/resources/2024/22.txt b/scala2/src/main/resources/2024/22.txt index a8b6c947..b91e7417 100644 --- a/scala2/src/main/resources/2024/22.txt +++ b/scala2/src/main/resources/2024/22.txt @@ -1 +1,1571 @@ -noop \ No newline at end of file +1493754 +10923278 +16546773 +1314471 +6028677 +5073322 +9408335 +7319309 +2564301 +10904573 +7922618 +3614143 +15150274 +12669195 +8741032 +16682330 +3165955 +13943279 +467874 +9819384 +15445038 +7966363 +14317456 +11409808 +3836027 +1614516 +12405256 +15120563 +3279420 +5628109 +15271659 +8124685 +531316 +12051297 +9280023 +5154432 +184568 +927122 +1606161 +15300094 +4269426 +9302392 +7266570 +14380739 +7517283 +9129997 +14716586 +4671555 +8445085 +10039659 +8636521 +16503705 +3385813 +2737105 +6187837 +14789193 +3142062 +14497611 +1508284 +382921 +10748255 +3953504 +5018808 +5619048 +14832913 +15187482 +1510297 +3905045 +3430772 +4761871 +8978600 +5744337 +319824 +12512173 +514961 +11538087 +16610493 +3087105 +12631386 +8938389 +11342950 +15777932 +16767994 +2672119 +9542005 +13554784 +537773 +13047769 +7215387 +1807539 +13026319 +2010601 +3682596 +16635782 +16230848 +5608117 +5564661 +7746468 +12571746 +11968378 +10215191 +1091129 +1037638 +1107419 +15156977 +887746 +16665890 +501946 +12661625 +15554225 +12500919 +9389442 +834189 +10483271 +7829281 +10199154 +2916438 +8488328 +1254424 +12184237 +9144900 +11853535 +14219821 +12373552 +14427517 +650831 +7651733 +12609366 +392226 +328507 +9997988 +1311500 +4712326 +4029923 +9833910 +704900 +2611835 +2729110 +744392 +12401911 +10065383 +4483900 +5485655 +12369885 +13591152 +10737304 +10848212 +252889 +14246763 +16010455 +13385256 +1120200 +6379862 +1480824 +15311423 +13405516 +2417649 +7748212 +397821 +6070932 +12717465 +3053269 +9675829 +3170623 +16163263 +16372805 +9687188 +5924042 +15630149 +15947313 +5916356 +390995 +15576157 +5603907 +4507165 +9111592 +9556922 +14882668 +10969516 +8741430 +6709814 +747482 +12113976 +16608843 +2985916 +14092606 +5957981 +6765514 +9963000 +14115208 +9106091 +1980331 +8837749 +15223571 +14284303 +11367016 +6778874 +15526823 +10780808 +2064344 +9847673 +3401517 +9568646 +14062857 +10902414 +10881811 +1178365 +1090975 +16002427 +14957456 +1588322 +7655837 +16150428 +3291587 +13238928 +2472712 +16127684 +2706048 +2588560 +9991780 +7024986 +7861020 +10081024 +2436826 +14581765 +3349798 +14741964 +11834507 +16682883 +7914769 +8727942 +5006985 +5122476 +3523619 +10878127 +11100130 +11314156 +9094352 +13832369 +742724 +15714122 +1151896 +3776587 +13309172 +3188937 +3075864 +3784861 +4170249 +11870259 +5503358 +15177676 +10325064 +15920776 +9721332 +4701632 +7971946 +3529707 +9027267 +13047068 +13512483 +8248985 +10356468 +14832646 +14574840 +14086268 +14984472 +2039046 +13614981 +8832766 +13717157 +1927032 +15852524 +3788890 +402642 +11387094 +348864 +8145412 +12019551 +7409458 +7876125 +11668710 +16355291 +8361453 +1047402 +8248569 +2013995 +3304149 +1064383 +7940661 +12128266 +8249160 +5696758 +770119 +16689621 +8907331 +16075275 +12376108 +13293799 +4579449 +1597636 +8080066 +3227115 +4717268 +9305675 +4959388 +7632428 +3327237 +12726774 +1196434 +7759050 +9943232 +15013476 +11653485 +8086021 +15035057 +8782538 +15156614 +7214950 +4448004 +9049183 +11264380 +7077746 +3813548 +16632790 +4398656 +7891709 +6077301 +5056512 +8807998 +7780014 +12628245 +1241827 +13294340 +15186523 +13133889 +8976126 +9834454 +1065761 +14679529 +13857982 +2056333 +14418401 +3078037 +10992093 +6019237 +279463 +11247030 +3558084 +9833157 +8200698 +11180464 +5052161 +13421820 +905142 +11409455 +15336054 +11372733 +14026016 +12849422 +10308344 +7415570 +14103868 +1271304 +10255080 +8128700 +2924595 +15991796 +9863832 +4839108 +16651432 +8653602 +321863 +11413955 +6319410 +4711958 +2937071 +6317141 +13488653 +10159476 +16229211 +3340136 +1464859 +9392274 +4841625 +10839222 +7979971 +9506501 +14531636 +2913369 +3288847 +13937141 +6907268 +2846081 +567416 +8319638 +1522917 +3139435 +12462184 +12450712 +9726384 +4300337 +6930461 +7138645 +4567183 +12140178 +9169656 +14335228 +1561846 +15035342 +1402006 +535868 +5494917 +12544662 +8524297 +16464244 +1705314 +16081798 +16461985 +14917863 +174817 +13407721 +5988444 +14811075 +10613551 +790645 +16295124 +14828313 +13450055 +9472117 +5510864 +15697672 +3420394 +9771026 +8703024 +5441199 +11590446 +15296960 +7544012 +11657104 +5447120 +11729023 +2335519 +4417841 +15506549 +8348231 +3899449 +8774129 +14013933 +8887106 +1373535 +9274897 +12152464 +10509406 +15686672 +15129089 +12374285 +5187212 +10225841 +15550461 +2378781 +13653118 +2715210 +6235915 +10860294 +4791971 +11910091 +12454234 +14310440 +9455709 +16551757 +6796774 +12694889 +9961624 +2343532 +12621894 +16484333 +2352035 +1037955 +2725165 +4102187 +10028758 +9263362 +11740732 +1626981 +15632540 +8749388 +4599645 +10947653 +13811632 +15084498 +4665018 +14730346 +11748038 +6138609 +9564692 +13748456 +10061191 +4144903 +8180733 +16208304 +4755610 +9735630 +546074 +1696070 +10272676 +1009303 +6132792 +2633856 +13943130 +4874063 +14634900 +9713271 +3349086 +6508142 +6655325 +6022491 +7070552 +7397887 +6247664 +2156187 +13933746 +5518533 +1624275 +4700522 +11333255 +8946244 +6942454 +9153449 +7579870 +16009744 +10042424 +6202365 +13563560 +11156481 +12842381 +5857808 +7310627 +5254012 +5132173 +6116586 +9355266 +5808317 +7684243 +13591720 +13914437 +15605332 +773341 +776724 +13570294 +11476875 +8944497 +16322817 +3007720 +4691020 +8921294 +4970469 +9603660 +731475 +3833255 +5151901 +8436322 +9179668 +6604575 +13957646 +9351058 +10417573 +4667164 +7629091 +9515303 +9425698 +4170125 +2105169 +4135029 +6784470 +711257 +8993559 +1047135 +15103771 +2018074 +2150562 +7177058 +7015798 +13924981 +12459040 +9427401 +14853840 +9977140 +9556343 +5878097 +10100968 +14667259 +149349 +6212743 +15003698 +16732085 +4260990 +5280283 +8582192 +1323877 +9716759 +13088499 +3283500 +1556542 +12877208 +4413481 +8555956 +14249867 +3098542 +7356933 +11002577 +11305181 +13264728 +3181035 +9968145 +3860910 +3743460 +5146759 +13269959 +15470986 +9920477 +6887135 +9734072 +5530717 +4141560 +7445397 +15936095 +16161644 +1646153 +11130265 +3553915 +9264633 +8830543 +5160338 +16200255 +14772324 +3116969 +11706255 +11403440 +11951881 +16585971 +6126131 +4956945 +2467035 +4794256 +9273123 +3636519 +9275423 +6460167 +1472944 +5161762 +16620879 +9559615 +16520102 +8516237 +2862221 +10362542 +14292160 +10920537 +6151323 +4146076 +10055375 +6473327 +1127072 +13449345 +4474486 +6152819 +6992761 +7547840 +16334446 +8334223 +12176804 +4466453 +4694176 +783093 +15123760 +5228411 +15340728 +11152555 +14283104 +3827617 +3432131 +8839355 +3553527 +8747137 +1708313 +6146671 +10263131 +8873040 +1022795 +6711952 +16130816 +10772126 +13437647 +14223536 +10596752 +14054983 +14746132 +1330621 +16030634 +16480441 +4435518 +11378858 +11857371 +6123255 +12657374 +7646974 +2608857 +9388525 +15580499 +11704159 +9609430 +16271791 +14138832 +14624188 +7147751 +1044617 +9229006 +1650902 +8083558 +474142 +9178015 +10043664 +15383094 +4581952 +2402253 +12952140 +12495275 +14033319 +15538816 +3301211 +11283923 +10460761 +3533445 +2785054 +13948312 +209723 +16375926 +14967552 +9241393 +13157413 +4666480 +8463748 +1458927 +3482275 +14261012 +9121809 +6213234 +6551951 +8953299 +14182863 +10814676 +2622944 +3505255 +12316785 +8418871 +16182022 +14011395 +4286561 +12570811 +13042848 +15629320 +9624895 +3041659 +2526109 +8529717 +2539512 +319982 +5402450 +1403646 +13942288 +2775918 +16282015 +6235195 +6848387 +1201248 +6081772 +8134805 +6582224 +7958228 +403816 +4537873 +7916590 +7502863 +5734898 +13024689 +8427201 +6090197 +9649620 +14244491 +12627408 +5745069 +1112247 +10722255 +14426237 +12963538 +13161222 +12838148 +10848605 +8235215 +2533507 +14517311 +7433327 +2906653 +1572315 +8841584 +11311772 +4198238 +2555528 +11682749 +12440229 +10438700 +11173843 +3729829 +12335032 +9908612 +4718922 +16225795 +8114799 +13935413 +15350971 +15533622 +15258338 +10893519 +5082242 +3652716 +11891639 +13933225 +2923746 +3171274 +362426 +2455758 +2701564 +7330374 +16537463 +14764698 +15342634 +816434 +15698834 +16033501 +5794185 +7104758 +10589504 +5127294 +14648257 +6423097 +13439308 +333402 +14191501 +11517309 +14865721 +12786253 +1948096 +14377584 +3349243 +7374345 +12607285 +12169349 +11016070 +14069873 +4108185 +9532125 +16403695 +747225 +3346648 +2490762 +8932229 +8777362 +7849342 +12471528 +12132177 +1298379 +8065702 +5834056 +16005825 +11279017 +14153382 +2143335 +7062803 +3837492 +9108244 +14915313 +13982998 +6544734 +11947953 +7049750 +15714369 +14675229 +15086123 +6036328 +3337450 +10236472 +10325502 +2334575 +10663289 +11659764 +7073072 +8170754 +7013350 +5151101 +8016944 +7514141 +10107300 +12949578 +15785412 +11681265 +1288738 +601444 +16129473 +1930509 +6213293 +10187238 +15535867 +9938688 +11440933 +12283764 +3148008 +8492116 +3833162 +7224287 +11382904 +14823341 +8504755 +2475680 +15182738 +11190501 +15946656 +9307381 +11666727 +5448768 +1285316 +4962839 +8222159 +14855254 +7535064 +11177199 +15945862 +9012741 +5075364 +3536958 +9150829 +13065391 +10766166 +3547192 +10318634 +7850297 +15323286 +994523 +3562525 +16134018 +2548934 +5611124 +13954159 +15199180 +6249198 +11111648 +8632024 +7594808 +4448421 +3407426 +12922097 +259988 +10251024 +9228766 +258797 +9750260 +5285229 +12659709 +15698644 +932361 +14495804 +5972631 +4653671 +14901459 +14416410 +8363165 +4177512 +10167088 +1460631 +13703588 +5537582 +10189308 +15507248 +2972042 +15766321 +5559483 +12773714 +4964031 +5896605 +9277262 +3847145 +13149579 +11955940 +15069727 +12139120 +1104529 +4345066 +2041097 +6969535 +12560032 +13596010 +5912974 +12854526 +10915993 +14525726 +10709846 +7273980 +9944049 +288350 +14931356 +4759103 +11836953 +6885358 +15401222 +6518387 +1200793 +9557559 +9973389 +10253227 +15335566 +773956 +15036760 +13451291 +3155847 +2038404 +11946487 +6484265 +16062886 +16265663 +6900027 +12287415 +3862570 +10692194 +4554445 +1107079 +7121466 +7172861 +14045138 +15717925 +7757621 +3123626 +8481655 +11620734 +2830652 +7607024 +16158110 +5167003 +15492638 +1182434 +3126025 +4107076 +11296549 +1454355 +11427115 +11703912 +6254511 +9849226 +5049917 +14129678 +8741324 +14140875 +6274973 +12257391 +2497359 +3242949 +11252803 +1455214 +2805813 +201146 +11247346 +4724749 +10009673 +2650086 +984851 +11347460 +16511302 +3819603 +16287584 +2069121 +5606354 +8716289 +14272074 +16612953 +10681312 +7362689 +9679008 +13430688 +8591357 +16374519 +4641596 +7328872 +7520866 +16499615 +9236360 +11303399 +3343712 +15264784 +12765262 +1445035 +16252679 +15052956 +8280017 +563113 +11121837 +8789946 +14175546 +15098158 +7154205 +3856013 +2159966 +8314739 +8505582 +5704037 +2369881 +8539259 +2320025 +1931133 +4658158 +2046823 +4908706 +15459352 +695431 +11315685 +15836406 +225738 +3148671 +1288362 +8605576 +12815555 +15040202 +13352711 +14983143 +1797070 +3766103 +9378200 +10369592 +11299552 +12979788 +783350 +5818838 +8276791 +531709 +4434661 +14610526 +16630115 +10103496 +3457284 +4105640 +2918079 +13998083 +11384161 +15915465 +1939354 +11076878 +2804356 +1464512 +2977444 +3743488 +12341117 +3712520 +7950065 +6881449 +7488644 +11569096 +8734120 +13067668 +6327115 +13418964 +6557751 +5746005 +8620507 +15254316 +12055005 +6405842 +3614489 +12136710 +6717545 +5854547 +6902651 +15526874 +12134928 +5976808 +15892570 +9486671 +14197394 +2860355 +13250174 +15404064 +2249244 +12663404 +15753739 +5592435 +11104709 +15231380 +10727629 +8135761 +5879289 +1917212 +3588407 +8438846 +16356300 +5129518 +12811724 +5266944 +3965124 +5632378 +4432845 +8090102 +7178885 +4562036 +11693575 +6159470 +6072984 +7445010 +3753847 +353918 +6422406 +11384621 +12394039 +15873046 +12199298 +7322839 +3549072 +8531432 +6695698 +10703745 +12372895 +14276317 +3198806 +4261986 +5815034 +8342720 +7138535 +7768985 +10466586 +226770 +4791226 +694909 +7908327 +949422 +1503987 +9701128 +14498263 +15023381 +9045805 +621258 +8185182 +3686860 +8339330 +15923341 +13213732 +5005761 +7057749 +4701167 +3349383 +2405459 +10192352 +4612182 +1953845 +13532527 +5831268 +16490774 +11169165 +1021419 +993812 +1077849 +3170396 +697919 +2862304 +14714146 +7301408 +13235538 +13907368 +1103843 +2036112 +2913770 +7477912 +16584830 +5378403 +704150 +14764312 +13093618 +7097531 +3835354 +12361996 +7637456 +3576914 +5022114 +15234804 +12894592 +14111416 +3287480 +14370597 +9289086 +16323436 +15643734 +3869491 +5473874 +12690018 +13854074 +11637624 +15406930 +8932786 +9183468 +8750813 +10237041 +15112631 +15351664 +13293542 +989477 +3674807 +7867612 +12815736 +13341146 +3901536 +7053873 +6126821 +8411365 +13709292 +372743 +5580639 +11779471 +5786533 +16516619 +11949126 +15507416 +459462 +13717336 +9015683 +10554531 +5971229 +1248463 +7973040 +369776 +9110528 +5470627 +8771743 +8276305 +15826718 +15277707 +1744051 +9643926 +16021905 +8290556 +5288818 +2117324 +2106190 +9103655 +4487600 +7994815 +1574543 +7517745 +6911243 +10040279 +6834496 +551007 +13028453 +2735021 +13109668 +12740548 +755116 +13295041 +4088972 +1953556 +9083499 +2317877 +2073670 +463102 +7640662 +14806254 +15719249 +9719424 +14981495 +9851880 +7265879 +3375470 +5224585 +7240565 +13918082 +10046252 +7216795 +9359095 +15639394 +5443721 +3713348 +13114885 +3065591 +10621766 +15759716 +4994358 +7950361 +1322152 +193485 +16776856 +612265 +6593842 +13540372 +5956495 +10629189 +13287447 +1447509 +2670624 +7094018 +12663024 +6901711 +11618762 +7710420 +9896577 +9996283 +14426563 +3824812 +9531963 +11190525 +9806598 +1229609 +5199982 +12543300 +3936192 +9480919 +10724588 +16051632 +5848754 +13484140 +3661317 +11378054 +14415776 +13983571 +6748308 +14380387 +1207673 +14636268 +8005086 +14270819 +6802629 +5464688 +2268113 +3548876 +4371683 +1757527 +10850329 +13174736 +5648898 +15264278 +13839187 +251427 +650273 +1497323 +11299184 +3720388 +15381572 +9103603 +5911570 +8438673 +14046148 +16381253 +2080141 +9396744 +1305086 +15897403 +11645868 +9418540 +14653913 +2060804 +10842965 +9629769 +12558941 +11697117 +13917549 +4789566 +7146282 +16106986 +1566054 +12557282 +12130038 +10993300 +14368247 +3021596 +15856151 +2381985 +13874317 +12695168 +3033597 +15420624 +14949131 +15364720 +7099088 +15248857 +8916319 +12033053 +4350622 +10339537 +7184494 +441901 +10998878 +1107938 +12649925 +12418910 +14741670 +2046959 +11210335 +1794558 +7517510 +16330104 +6230692 +6037229 +7178235 +1447533 +12497320 +10588805 +4925996 +12503009 +3268972 +16616140 +9313314 +420052 +8188087 +3389996 +816213 +3459091 +13114562 +10253876 +6351697 +5271599 +15412423 +6253525 +5791065 +1878795 +14470914 +202769 +5939257 +4354084 +9312651 +2128446 +13997285 +3002108 +6566101 +283033 +13408539 +3323721 +15892833 +12081237 +4435188 +3445901 +15383964 +571414 +11401813 +12823471 +2076542 +10921052 +3416139 +5882055 +9593571 +15545457 +5396966 +1807109 +13102366 +14658837 +14872216 +8920548 +8162211 +4993144 +2386214 +2378553 +9544221 +4185554 +13822237 +16085672 +7381886 +7257990 +16517426 +3168793 +14597394 \ No newline at end of file diff --git a/scala2/src/main/resources/2024/23-test-00.txt b/scala2/src/main/resources/2024/23-test-00.txt new file mode 100644 index 00000000..a8b6c947 --- /dev/null +++ b/scala2/src/main/resources/2024/23-test-00.txt @@ -0,0 +1 @@ +noop \ No newline at end of file diff --git a/scala2/src/main/resources/2024/23.txt b/scala2/src/main/resources/2024/23.txt new file mode 100644 index 00000000..a8b6c947 --- /dev/null +++ b/scala2/src/main/resources/2024/23.txt @@ -0,0 +1 @@ +noop \ No newline at end of file diff --git a/scala2/src/main/scala/jurisk/adventofcode/y2018/Advent17.scala b/scala2/src/main/scala/jurisk/adventofcode/y2018/Advent17.scala index 87f2b34f..f05ec7b4 100644 --- a/scala2/src/main/scala/jurisk/adventofcode/y2018/Advent17.scala +++ b/scala2/src/main/scala/jurisk/adventofcode/y2018/Advent17.scala @@ -8,6 +8,7 @@ import jurisk.adventofcode.y2018.Advent17.State.isSolid import jurisk.geometry.Coordinates2D import jurisk.geometry.Coords2D import jurisk.geometry.Field2D +import jurisk.utils.CollectionOps.SeqOps import jurisk.utils.FileInput._ import jurisk.utils.Parsing.StringOps import jurisk.utils.Simulation @@ -121,21 +122,20 @@ object Advent17 { searchValue: T, offset: Int = 0, acc: List[(Int, Int)] = Nil, - ): List[(Int, Int)] = { - val start = vector.indexOf(searchValue) - if (start == -1) { - acc - } else { - val taken = vector.drop(start).takeWhile(_ == searchValue).length - val added = (offset + start, offset + start + taken - 1) - consecutiveRanges( - vector.drop(start + taken), - searchValue, - offset + start + taken, - added :: acc, - ) + ): List[(Int, Int)] = + vector.firstIndexOf(searchValue) match { + case None => + acc + case Some(start) => + val taken = vector.drop(start).takeWhile(_ == searchValue).length + val added = (offset + start, offset + start + taken - 1) + consecutiveRanges( + vector.drop(start + taken), + searchValue, + offset + start + taken, + added :: acc, + ) } - } } private def parsePoints(s: String): Seq[Coords2D] = diff --git a/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent05.scala b/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent05.scala index 64787889..412d5ea4 100644 --- a/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent05.scala +++ b/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent05.scala @@ -1,5 +1,6 @@ package jurisk.adventofcode.y2022 +import jurisk.utils.CollectionOps.CollectionStringOps import jurisk.utils.CollectionOps.IterableOps import jurisk.utils.FileInput.readLineGroups import jurisk.utils.Parsing.StringOps @@ -55,8 +56,8 @@ object Advent05 { SortedMap.from { stackIdChars map { stackIdChar => - val index = stackIdLine.indexOf(stackIdChar) - require(index != -1) + val index = + stackIdLine.firstIndexOf(stackIdChar).getOrElse("Not found".fail) val contents = stackContents.map(_.lift(index)) ( stackIdChar - '0', diff --git a/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent06.scala b/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent06.scala index aaaa81c1..2ef7c7e6 100644 --- a/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent06.scala +++ b/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent06.scala @@ -1,7 +1,9 @@ package jurisk.adventofcode.y2022 import jurisk.utils.CollectionOps.IterableOps +import jurisk.utils.CollectionOps.IteratorOps import jurisk.utils.FileInput.readSingleFileLine +import jurisk.utils.Parsing.StringOps import org.scalatest.matchers.should.Matchers._ object Advent06 { @@ -10,11 +12,11 @@ object Advent06 { def readFileAndParse(fileName: String): Parsed = readSingleFileLine(fileName) - def solve(data: Parsed, n: Int): Int = { - val found = data.sliding(n).indexWhere(_.toList.allDistinct) - require(found != -1) - found + n - } + def solve(data: Parsed, n: Int): Int = + data + .sliding(n) + .firstIndexWhere(_.toList.allDistinct) + .getOrElse("Not found".fail) + n def part1(data: Parsed): Int = solve(data, 4) diff --git a/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent13.scala b/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent13.scala index 4ac6dcaa..e7dd4355 100644 --- a/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent13.scala +++ b/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent13.scala @@ -2,6 +2,7 @@ package jurisk.adventofcode.y2022 import jurisk.adventofcode.y2022.Advent13.Packet.Lst import jurisk.adventofcode.y2022.Advent13.Packet.Nmb +import jurisk.utils.CollectionOps.SeqOps import jurisk.utils.FileInput._ import jurisk.utils.Parsing.StringOps import mouse.all._ @@ -100,8 +101,8 @@ object Advent13 { val sorted = allPackets.sorted - val indexA = sorted.indexOf(DividerA) - val indexB = sorted.indexOf(DividerB) + val indexA = sorted.firstIndexOfUnsafe(DividerA) + val indexB = sorted.firstIndexOfUnsafe(DividerB) (indexA + 1) * (indexB + 1) } diff --git a/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent20.scala b/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent20.scala index b5bc8bfe..befd1eed 100644 --- a/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent20.scala +++ b/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent20.scala @@ -1,5 +1,6 @@ package jurisk.adventofcode.y2022 +import jurisk.utils.CollectionOps.SeqOps import jurisk.utils.FileInput._ import jurisk.utils.Parsing.StringOps import org.scalatest.matchers.should.Matchers._ @@ -34,8 +35,7 @@ object Advent20 { val vector = Vector.fill(timesToMix)(indices).flatten val result = vector.foldLeft(indices) { case (acc, idx) => - val index = acc.indexOf(idx) - require(index != -1) + val index = acc.firstIndexOf(idx).getOrElse("Not found".fail) moveNumber(acc, index, lookup(idx)) } @@ -49,8 +49,7 @@ object Advent20 { ): Long = { val mixed: Vector[Long] = mix(lookup.map(_ * decryptionKey), timesToMix) require(mixed.length == lookup.length) - val indexOf0 = mixed.indexOf(0L) - require(indexOf0 != -1) + val indexOf0 = mixed.firstIndexOf(0L).getOrElse("Not found".fail) List(1000, 2000, 3000).map { x => mixed((indexOf0 + x) % mixed.length) }.sum diff --git a/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent24.scala b/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent24.scala index 4a077b93..a0ad101d 100644 --- a/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent24.scala +++ b/scala2/src/main/scala/jurisk/adventofcode/y2022/Advent24.scala @@ -9,6 +9,7 @@ import jurisk.geometry.Direction2D.CardinalDirection2D import jurisk.geometry.Field2D import jurisk.math.absForWrappingAround import jurisk.math.lcm +import jurisk.utils.CollectionOps.SeqOps import jurisk.utils.FileInput._ import jurisk.utils.Memoize.memoize1 import jurisk.utils.Parsing.StringOps @@ -75,9 +76,13 @@ object Advent24 { def parse(s: String): Maze = { val charField = Field2D.parseCharField(s) - val start = Coords2D.of(charField.firstRowValues.indexOf('.'), 0) + val start = + Coords2D.of(charField.firstRowValues.firstIndexOfUnsafe('.'), 0) val goal = - Coords2D.of(charField.lastRowValues.indexOf('.'), charField.height - 1) + Coords2D.of( + charField.lastRowValues.firstIndexOfUnsafe('.'), + charField.height - 1, + ) val blizzards = charField.entries.flatMap { case (c, ch) => val direction = Direction2D.parseCaretToOption(ch) diff --git a/scala2/src/main/scala/jurisk/adventofcode/y2023/Advent08.scala b/scala2/src/main/scala/jurisk/adventofcode/y2023/Advent08.scala index 30de8520..f2ceaeb4 100644 --- a/scala2/src/main/scala/jurisk/adventofcode/y2023/Advent08.scala +++ b/scala2/src/main/scala/jurisk/adventofcode/y2023/Advent08.scala @@ -3,6 +3,7 @@ package jurisk.adventofcode.y2023 import cats.implicits._ import jurisk.math.lcmMany import jurisk.utils.CollectionOps.IndexedSeqOps +import jurisk.utils.CollectionOps.SeqOps import jurisk.utils.FileInput._ import jurisk.utils.Parsing.StringOps import jurisk.utils.Simulation @@ -48,14 +49,8 @@ object Advent08 { ): IndexedSeq[NodeId] = mappings.indices.filter(index => predicate(mapping(index).name)) - def findNodeByName(name: NodeName): NodeId = { - val result = mappings.indexWhere(_.name === name) - if (result === -1) { - s"Did not find node $name".fail - } else { - result - } - } + def findNodeByName(name: NodeName): NodeId = + mappings.firstIndexWhereUnsafe(_.name === name) def mapping(nodeId: NodeId): Mapping = mappings(nodeId) } diff --git a/scala2/src/main/scala/jurisk/adventofcode/y2024/Advent22.scala b/scala2/src/main/scala/jurisk/adventofcode/y2024/Advent22.scala index 827950fb..e31d45d0 100644 --- a/scala2/src/main/scala/jurisk/adventofcode/y2024/Advent22.scala +++ b/scala2/src/main/scala/jurisk/adventofcode/y2024/Advent22.scala @@ -1,37 +1,84 @@ package jurisk.adventofcode.y2024 +import cats.implicits.catsSyntaxOptionId +import jurisk.utils.CollectionOps.IteratorOps +import jurisk.utils.CollectionUtils.mergeMaps import jurisk.utils.FileInput._ import jurisk.utils.Parsing.StringOps +import scala.annotation.tailrec +import scala.collection.mutable.ArrayBuffer + object Advent22 { - type Input = List[Command] + type Input = List[N] type N = Long + private val SequenceLength = 4 - sealed trait Command extends Product with Serializable - object Command { - case object Noop extends Command - final case class Something( - values: List[N] - ) extends Command - final case class Other(value: String) extends Command - - def parse(s: String): Command = - s match { - case "noop" => Noop - case s"something $rem" => Something(rem.extractLongList) - case s if s.nonEmpty => Other(s) - case _ => s.failedToParse - } + def parse(input: String): Input = + input.parseLines(_.toLong) + + def next(n: N): N = { + def mixPrune(a: N, b: N): N = + (a ^ b) % 16777216 + + val a = mixPrune(n * 64, n) + val b = mixPrune(a / 32, a) + mixPrune(b * 2048, b) } - def parse(input: String): Input = - input.parseLines(Command.parse) + @tailrec + def nthSecretNumber(n: N, nth: Int): N = + if (nth == 0) { + n + } else { + nthSecretNumber(next(n), nth - 1) + } + + def bananasAndDiffs( + secret: N, + howMany: Int = 2000, + ): (IndexedSeq[N], IndexedSeq[N]) = { + val bananas = ArrayBuffer.fill(howMany + 1)(Long.MaxValue) + bananas(0) = secret + for (i <- 0 until howMany) + bananas(i + 1) = next(bananas(i)) + + val diffs = ArrayBuffer.fill(howMany)(Long.MaxValue) + for (i <- 0 until howMany) + diffs(i) = bananas(i + 1) % 10 - bananas(i) % 10 + + (bananas.map(_ % 10).toIndexedSeq, diffs.toIndexedSeq) + } + + def bananasFromSequence( + bananasAndDiffs: (IndexedSeq[N], IndexedSeq[N]), + sequence: IndexedSeq[N], + ): Option[N] = { + assert(sequence.length == SequenceLength) + val (bananas, diffs) = bananasAndDiffs + diffs + .sliding(SequenceLength) + .firstIndexOf(sequence) + .map(i => bananas(i + SequenceLength)) + } + + def createBananaMap(secret: N): Map[IndexedSeq[N], N] = { + val (bananas, allDiffs) = bananasAndDiffs(secret) + + allDiffs + .sliding(SequenceLength) + .zipWithIndex + .foldLeft(Map.empty[IndexedSeq[N], N]) { case (acc, (diffs, i)) => + val result = bananas(i + SequenceLength) + acc.updatedWith(diffs)(_.getOrElse(result).some) + } + } def part1(data: Input): N = - 0 + data.map(n => nthSecretNumber(n, 2000)).sum def part2(data: Input): N = - 0 + mergeMaps(data.map(createBananaMap)).values.map(_.sum).max def parseFile(fileName: String): Input = parse(readFileText(fileName)) diff --git a/scala2/src/main/scala/jurisk/adventofcode/y2024/Advent23.scala b/scala2/src/main/scala/jurisk/adventofcode/y2024/Advent23.scala new file mode 100644 index 00000000..8b35a59a --- /dev/null +++ b/scala2/src/main/scala/jurisk/adventofcode/y2024/Advent23.scala @@ -0,0 +1,48 @@ +package jurisk.adventofcode.y2024 + +import jurisk.utils.FileInput._ +import jurisk.utils.Parsing.StringOps + +object Advent23 { + type Input = List[Command] + type N = Long + + sealed trait Command extends Product with Serializable + object Command { + case object Noop extends Command + final case class Something( + values: List[N] + ) extends Command + final case class Other(value: String) extends Command + + def parse(s: String): Command = + s match { + case "noop" => Noop + case s"something $rem" => Something(rem.extractLongList) + case s if s.nonEmpty => Other(s) + case _ => s.failedToParse + } + } + + def parse(input: String): Input = + input.parseLines(Command.parse) + + def part1(data: Input): N = + 0 + + def part2(data: Input): N = + 0 + + def parseFile(fileName: String): Input = + parse(readFileText(fileName)) + + def fileName(suffix: String): String = + s"2024/23$suffix.txt" + + def main(args: Array[String]): Unit = { + val realData: Input = parseFile(fileName("")) + + println(s"Part 1: ${part1(realData)}") + println(s"Part 2: ${part2(realData)}") + } +} diff --git a/scala2/src/main/scala/jurisk/utils/CollectionOps.scala b/scala2/src/main/scala/jurisk/utils/CollectionOps.scala index 4b2820d7..e1225f18 100644 --- a/scala2/src/main/scala/jurisk/utils/CollectionOps.scala +++ b/scala2/src/main/scala/jurisk/utils/CollectionOps.scala @@ -2,7 +2,7 @@ package jurisk.utils import cats.Eq import cats.implicits._ -import jurisk.utils.Parsing.StringOps +import jurisk.utils.Parsing.{StringOps => ParsingStringOps} import scala.annotation.tailrec import scala.collection.immutable.ArraySeq @@ -46,20 +46,39 @@ object CollectionOps { List.fill(times)(list).flatten } + private val NotFound = -1 + + private def excludeNotFound(index: Int): Option[Int] = + index.some.filter(_ != NotFound) + + implicit class CollectionStringOps(s: String) { + def firstIndexOf(value: Char): Option[Int] = + excludeNotFound(s.indexOf(value)) + + def firstIndexWhere(p: Char => Boolean, from: Int = 0): Option[Int] = + excludeNotFound(s.indexWhere(p, from)) + } + implicit class SeqOps[T](seq: Seq[T]) { - private val NotFound = -1 + def firstIndexOfUnsafe(value: T): Int = + firstIndexOf(value).orFail(s"Value $value not found in $seq") def firstIndexOf(value: T): Option[Int] = - seq.indexOf(value).some.filter(_ != NotFound) + excludeNotFound(seq.indexOf(value)) - def firstIndexWhere(p: T => Boolean, from: Int = 0): Option[Int] = { - val result = seq.indexWhere(p, from) - if (result == -1) { - none - } else { - result.some - } - } + def firstIndexWhereUnsafe(p: T => Boolean, from: Int = 0): Int = + firstIndexWhere(p, from).orFail(s"Value not found in $seq") + + def firstIndexWhere(p: T => Boolean, from: Int = 0): Option[Int] = + excludeNotFound(seq.indexWhere(p, from)) + } + + implicit class IteratorOps[T](iterator: Iterator[T]) { + def firstIndexOf(value: T): Option[Int] = + excludeNotFound(iterator.indexOf(value)) + + def firstIndexWhere(p: T => Boolean, from: Int = 0): Option[Int] = + excludeNotFound(iterator.indexWhere(p, from)) } implicit class IterableOnceOps[T](iterableOnce: IterableOnce[T]) { diff --git a/scala2/src/main/scala/jurisk/utils/CollectionUtils.scala b/scala2/src/main/scala/jurisk/utils/CollectionUtils.scala new file mode 100644 index 00000000..dfc078cb --- /dev/null +++ b/scala2/src/main/scala/jurisk/utils/CollectionUtils.scala @@ -0,0 +1,9 @@ +package jurisk.utils + +object CollectionUtils { + def mergeMaps[K, V](maps: Seq[Map[K, V]]): Map[K, Seq[V]] = + maps + .flatMap(_.toList) + .groupBy { case (k, _) => k } + .map { case (k, v1) => k -> v1.map { case (_, v2) => v2 } } +} diff --git a/scala2/src/test/scala/jurisk/adventofcode/y2024/Advent22Spec.scala b/scala2/src/test/scala/jurisk/adventofcode/y2024/Advent22Spec.scala index 6474210c..7cad6059 100644 --- a/scala2/src/test/scala/jurisk/adventofcode/y2024/Advent22Spec.scala +++ b/scala2/src/test/scala/jurisk/adventofcode/y2024/Advent22Spec.scala @@ -1,30 +1,71 @@ package jurisk.adventofcode.y2024 import Advent22._ +import cats.implicits.{catsSyntaxOptionId, none} import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.should.Matchers._ class Advent22Spec extends AnyFreeSpec { - private def testData = parseFile(fileName("-test-00")) - private def realData = parseFile(fileName("")) + private def testData0 = parseFile(fileName("-test-00")) + private def testData1 = parseFile(fileName("-test-01")) + private def realData = parseFile(fileName("")) "part 1" - { + "next" in { + next(123) shouldEqual 15887950 + } + + "test 1" in { + nthSecretNumber(1, 2000) shouldEqual 8685429 + } + "test" in { - part1(testData) shouldEqual 0 + part1(testData0) shouldEqual 37327623 } "real" in { - part1(realData) shouldEqual 0 + part1(realData) shouldEqual 13022553808L } } "part 2" - { + "bananasAndDiffs" in { + val (bananas123, diffs123) = bananasAndDiffs(123) + bananas123.length shouldEqual 2001 + diffs123.length shouldEqual 2000 + bananas123.take(10) shouldEqual IndexedSeq(3, 0, 6, 5, 4, 4, 6, 4, 4, 2) + bananas123.contains(Long.MaxValue) shouldEqual false + diffs123.take(9) shouldEqual IndexedSeq(-3, 6, -1, -1, 0, 2, -2, 0, -2) + diffs123.contains(Long.MaxValue) shouldEqual false + } + + "bananasFromSequence" in { + bananasFromSequence( + bananasAndDiffs(123), + IndexedSeq(-1, -2, 0, 2), + ) shouldEqual Some(6) + + val seq: IndexedSeq[N] = IndexedSeq(-2, 1, -1, 3) + bananasFromSequence(bananasAndDiffs(1), seq) shouldEqual 7.some + bananasFromSequence(bananasAndDiffs(2), seq) shouldEqual 7.some + bananasFromSequence(bananasAndDiffs(3), seq) shouldEqual none + bananasFromSequence(bananasAndDiffs(2024), seq) shouldEqual 9.some + } + + "theMap" in { + val seq: IndexedSeq[N] = IndexedSeq(-2, 1, -1, 3) + createBananaMap(1).get(seq) shouldEqual 7.some + createBananaMap(2).get(seq) shouldEqual 7.some + createBananaMap(3).get(seq) shouldEqual none + createBananaMap(2024).get(seq) shouldEqual 9.some + } + "test" in { - part2(testData) shouldEqual 0 + part2(testData1) shouldEqual 7 + 7 + 9 } - "real" in { - part2(realData) shouldEqual 0 + "real" ignore { + part2(realData) shouldEqual 1555 } } } diff --git a/scala2/src/test/scala/jurisk/adventofcode/y2024/Advent23Spec.scala b/scala2/src/test/scala/jurisk/adventofcode/y2024/Advent23Spec.scala new file mode 100644 index 00000000..ffb39d6f --- /dev/null +++ b/scala2/src/test/scala/jurisk/adventofcode/y2024/Advent23Spec.scala @@ -0,0 +1,30 @@ +package jurisk.adventofcode.y2024 + +import Advent23._ +import org.scalatest.freespec.AnyFreeSpec +import org.scalatest.matchers.should.Matchers._ + +class Advent23Spec extends AnyFreeSpec { + private def testData = parseFile(fileName("-test-00")) + private def realData = parseFile(fileName("")) + + "part 1" - { + "test" in { + part1(testData) shouldEqual 0 + } + + "real" in { + part1(realData) shouldEqual 0 + } + } + + "part 2" - { + "test" in { + part2(testData) shouldEqual 0 + } + + "real" in { + part2(realData) shouldEqual 0 + } + } +}