From 9d13aceda620cb8836f6791b4d95666cc6ef579f Mon Sep 17 00:00:00 2001 From: artemtam Date: Tue, 3 Dec 2024 14:08:21 +0100 Subject: [PATCH] feat: add 2022 solutions --- 2022/day-01/input.txt | 2253 ++++++++++++++++++++++++++++++ 2022/day-01/solution.test.ts | 16 + 2022/day-01/solution.ts | 43 + 2022/day-02/input.txt | 2500 ++++++++++++++++++++++++++++++++++ 2022/day-02/solution.test.ts | 14 + 2022/day-02/solution.ts | 92 ++ 2022/day-03/input.txt | 300 ++++ 2022/day-03/solution.test.ts | 14 + 2022/day-03/solution.ts | 46 + 2022/day-04/input.txt | 1000 ++++++++++++++ 2022/day-04/solution.test.ts | 14 + 2022/day-04/solution.ts | 33 + 2022/day-05/input.txt | 512 +++++++ 2022/day-05/solution.test.ts | 14 + 2022/day-05/solution.ts | 113 ++ 2022/day-06/input.txt | 1 + 2022/day-06/solution.test.ts | 14 + 2022/day-06/solution.ts | 30 + 2022/day-07/input.txt | 1010 ++++++++++++++ 2022/day-07/solution.test.ts | 14 + 2022/day-07/solution.ts | 191 +++ 2022/day-08/input.txt | 99 ++ 2022/day-08/solution.test.ts | 14 + 2022/day-08/solution.ts | 138 ++ 2022/day-09/input.txt | 2000 +++++++++++++++++++++++++++ 2022/day-09/solution.test.ts | 14 + 2022/day-09/solution.ts | 115 ++ 2022/day-10/input.txt | 140 ++ 2022/day-10/solution.test.ts | 21 + 2022/day-10/solution.ts | 152 +++ 2022/day-11/input.txt | 55 + 2022/day-11/solution.test.ts | 14 + 2022/day-11/solution.ts | 217 +++ 2022/day-12/input.txt | 41 + 2022/day-12/solution.test.ts | 14 + 2022/day-12/solution.ts | 194 +++ 2022/day-13/input.txt | 449 ++++++ 2022/day-13/solution.test.ts | 14 + 2022/day-13/solution.ts | 93 ++ 2022/day-14/input.txt | 137 ++ 2022/day-14/solution.test.ts | 14 + 2022/day-14/solution.ts | 153 +++ 2022/day-15/input.txt | 34 + 2022/day-15/solution.test.ts | 14 + 2022/day-15/solution.ts | 144 ++ 45 files changed, 12504 insertions(+) create mode 100644 2022/day-01/input.txt create mode 100644 2022/day-01/solution.test.ts create mode 100644 2022/day-01/solution.ts create mode 100644 2022/day-02/input.txt create mode 100644 2022/day-02/solution.test.ts create mode 100644 2022/day-02/solution.ts create mode 100644 2022/day-03/input.txt create mode 100644 2022/day-03/solution.test.ts create mode 100644 2022/day-03/solution.ts create mode 100644 2022/day-04/input.txt create mode 100644 2022/day-04/solution.test.ts create mode 100644 2022/day-04/solution.ts create mode 100644 2022/day-05/input.txt create mode 100644 2022/day-05/solution.test.ts create mode 100644 2022/day-05/solution.ts create mode 100644 2022/day-06/input.txt create mode 100644 2022/day-06/solution.test.ts create mode 100644 2022/day-06/solution.ts create mode 100644 2022/day-07/input.txt create mode 100644 2022/day-07/solution.test.ts create mode 100644 2022/day-07/solution.ts create mode 100644 2022/day-08/input.txt create mode 100644 2022/day-08/solution.test.ts create mode 100644 2022/day-08/solution.ts create mode 100644 2022/day-09/input.txt create mode 100644 2022/day-09/solution.test.ts create mode 100644 2022/day-09/solution.ts create mode 100644 2022/day-10/input.txt create mode 100644 2022/day-10/solution.test.ts create mode 100644 2022/day-10/solution.ts create mode 100644 2022/day-11/input.txt create mode 100644 2022/day-11/solution.test.ts create mode 100644 2022/day-11/solution.ts create mode 100644 2022/day-12/input.txt create mode 100644 2022/day-12/solution.test.ts create mode 100644 2022/day-12/solution.ts create mode 100644 2022/day-13/input.txt create mode 100644 2022/day-13/solution.test.ts create mode 100644 2022/day-13/solution.ts create mode 100644 2022/day-14/input.txt create mode 100644 2022/day-14/solution.test.ts create mode 100644 2022/day-14/solution.ts create mode 100644 2022/day-15/input.txt create mode 100644 2022/day-15/solution.test.ts create mode 100644 2022/day-15/solution.ts diff --git a/2022/day-01/input.txt b/2022/day-01/input.txt new file mode 100644 index 0000000..cb243c8 --- /dev/null +++ b/2022/day-01/input.txt @@ -0,0 +1,2253 @@ +4601 +1583 +2995 +5319 +3352 +1722 +4331 +5840 +3339 +5341 +3415 +1297 +1610 +2703 + +5928 +1266 +6405 +4354 +2815 +1621 +3545 +1733 +2162 +1155 +3674 +4055 +4262 +2115 + +25873 +16103 +17042 + +6479 +1521 +6902 +6331 +6146 +1591 +2063 +2149 +1463 +1865 +2598 +6893 +3617 + +1431 +8935 +8134 +8885 +8698 +8884 +7982 +3617 +7079 + +34031 +8383 + +3697 +1199 +3703 +1322 +5679 +1627 +5910 +1092 +6445 +2371 +3672 +2281 +2710 +5111 + +17480 + +58355 + +3711 +2406 +2101 +1406 +5376 +2149 +4608 +6768 +6322 +3792 +4249 +2342 +2014 + +6197 +6908 +8484 +3901 +3001 +7880 +5165 +2536 + +3964 +4229 +4898 +4544 +3535 +6329 +1573 +4988 +1424 + +57606 + +16325 + +6038 +11538 +13026 +12734 +6077 + +4696 +3914 +2375 +1188 +1247 +1594 +1843 +5297 +6053 +1114 +3179 +5968 +1430 +4268 +2514 + +6684 +2321 +3946 +1746 +7583 +10379 +3696 +10110 + +5834 +5944 +9336 +9638 +3373 +4279 +9942 + +7208 +7801 +3771 +8183 +1824 +8217 +1545 +3041 +7369 +5980 + +8368 +6180 +3100 +4801 +4430 +6758 +3023 +3394 + +2545 +4992 +3347 +5830 +3764 +3237 +2431 +3406 +1408 +5601 +6548 +4625 + +32334 + +1112 +5471 +10983 +8298 +4342 +4221 +7807 + +5733 +2012 +5928 +3503 +2785 +4867 +1515 +4819 +3569 +3353 +5997 +4921 +5498 +3234 +5588 + +11040 +5547 +12070 +2168 +7603 +7245 +4966 + +13027 +12518 +15381 +3251 +14935 + +15858 +29295 + +2476 +4289 +10350 +3953 +10089 +6953 +5555 +3007 + +61732 + +5567 +4895 +6095 +4880 +2945 +6022 +2129 +5010 +4100 +3554 +3410 +1820 + +9902 +33605 + +15331 +15615 +5062 +15073 + +5940 +2252 +1233 +2582 +3624 +2754 +2304 +3189 +4060 +3862 +5164 +1487 +2776 +1807 +3385 + +6798 +2385 +3755 +10299 +11500 +6478 +1911 + +1469 +9309 +1785 +17145 + +3363 +3210 +3285 +4491 +5992 +2927 +4098 +2133 +3191 +2810 +4694 + +31006 +1582 + +4356 +6146 +2051 +6503 +9487 +9244 +4808 +7761 +7108 + +1771 +6062 +7135 +5575 +3278 +1221 +2547 +7266 +5444 +7395 + +10634 +1196 + +1361 + +2810 +3106 +8654 +9455 +3778 +4219 +8882 +9387 +5128 + +7114 +1441 +6146 +4752 +2388 +6420 +7350 +1624 +6050 +5469 +6751 + +5570 +4674 + +2074 +3476 +4064 +9446 +2889 +4871 +6298 +2970 +8588 + +3482 +8492 +2226 +4951 +6733 +5463 +3183 +4807 +4806 + +6974 +10251 +4637 +9558 +5153 +4665 + +6860 +6949 +1524 +4201 +4397 +2278 +4909 +1353 +2074 +1920 +7439 +1040 + +4135 +1411 +5536 +8004 +3090 +1036 +6613 +6353 +6810 + +3932 +4743 +1615 +3201 +3791 +6357 +2511 +3440 +2290 +4741 +2844 +3121 +3641 +3497 + +4549 +5142 +4438 +2945 +4576 +4871 +4795 +6007 +4884 +1031 +2111 +4388 +4705 +5725 +3425 + +45444 + +6688 +9460 +2727 +6989 +6789 +12460 + +7310 +5910 +7822 +7627 +7600 +4793 +3152 +5747 +5197 +8006 + +23983 +33879 + +1020 +4783 +5117 +3628 +3065 +6131 +5543 +1576 +1159 +3721 +3182 +1409 +2738 +5084 + +42750 + +8509 +4370 +1042 +5664 + +59445 + +1589 +5133 +6413 +6578 +3301 +8256 +7749 +4321 +8190 +5025 + +27739 +18609 + +5447 +4022 +4069 +1437 +2811 +6929 +2754 +1108 +7390 +3995 +3480 +3225 + +4240 +6959 +3289 +8063 +4751 +4896 +4611 +6256 +1105 +1334 +7598 + +27831 + +1821 +5333 +7853 +6574 +7985 +3972 +2306 +1875 +1857 +6386 + +12780 +2513 +22939 + +9625 +3785 +8050 +7432 +11772 +10914 + +1387 +3439 +4644 +3880 +1878 +3911 +5329 +1480 +5779 +2083 +3886 +5525 +3930 +4813 +2570 + +15763 +2839 +14258 +1460 + +6193 +3397 +3222 +3262 +3735 +2406 +5588 +2068 +2862 +3271 +1401 +3957 +5690 +4632 + +15070 +5164 +8902 +9580 +4271 + +4494 +5665 +7242 +7687 +7031 +6135 +2670 +3315 +6146 +8085 + +2625 +24285 + +4414 +5985 +2681 +7036 +6486 +2501 +4408 +8582 +5150 +4295 + +1082 +1497 +5638 +4643 +1413 +5969 +1515 +4016 +4856 +3287 +3122 +2948 +3711 +5031 +4692 + +6445 +2261 +2132 +3517 +2461 +2767 +2071 +2176 +6357 +1304 +6034 +1346 + +1318 +4719 +2054 +1433 +6514 +3729 +4329 +1026 +1502 +2611 +1363 +6379 +3617 + +1885 +7519 +2849 +5167 +3136 +4819 +8018 +4110 +2666 +6098 +4943 + +6575 +1624 +6004 +4178 +7453 +5979 +6736 +3883 +7109 +1271 +1175 + +9494 +12633 +11576 +3547 + +4653 +6777 +4497 +2246 +4666 +4675 +4440 +7227 +3808 +2425 +6014 +7305 + +2538 +6155 +4321 +6239 +6279 +1445 +5592 + +4920 +5435 +1392 +4122 +10513 +6359 +1574 +7222 + +9013 +2150 +8377 +8884 +4108 +5427 +1605 +6907 + +7861 +10554 +1210 +1346 +5296 +4419 +9147 + +1858 +2956 +2070 +10271 +5810 +2632 +9429 +3941 + +4306 +4972 +6216 +6345 +3971 +3920 +6295 +3552 +1399 +5425 +5218 +4512 +3376 +4460 + +4107 +4484 +5148 +5456 +7902 +2185 +3439 +7199 +9514 + +11030 +12096 + +2886 +1561 +14057 +7480 +12186 + +8600 +4085 +11755 +4564 +1697 +6345 +10176 + +2538 +10138 +8328 +10621 +13322 +13907 + +5450 +3403 +5776 +5967 +3873 +2761 +5992 +2251 +2278 +4673 +3442 +2720 +2556 +4848 +5967 + +2806 +8228 +9047 +10630 +4367 +4917 +4084 +7893 + +2842 +18343 +1497 +19962 + +3985 +10986 +1431 +1569 +8053 +8987 +6474 + +5733 +2237 +6183 +1642 +1005 +4389 +1889 +2385 +2470 +6338 +2200 +3399 +3659 +4092 + +6579 +5872 +4229 +1081 +2254 +1229 +5218 +4267 +6906 +2818 +1084 +3655 +2294 + +1882 +5005 +3805 +2088 +6809 +4982 +1935 +6789 +1961 +1842 +5988 +2859 +3965 + +2313 +1021 +5090 +1309 +5110 +3142 +4102 +2919 +6010 +3079 +5786 +3701 +2659 +5728 + +4251 +1899 +4119 +8941 +6677 +2161 +2119 +2772 +3122 + +7821 +6113 +5150 +3486 +2072 +4089 +2820 +3161 +7589 +1787 +5988 + +10582 +8240 +1934 +1504 +9070 +1186 +7766 +1066 + +6700 +6181 +3238 +1940 +1229 +3688 +1375 +5873 +2328 +6384 +7446 +7246 + +5542 +6771 +1964 +4532 +3011 +2300 +1451 +6726 +4595 +2926 +5237 +5020 +6129 + +15008 +4409 +6769 +2211 + +11825 +8947 +17411 +2893 + +8460 +11664 +2304 +6865 +2132 +9174 + +15540 +16925 +12015 +7621 + +1439 +11886 +3028 + +4604 +1057 +5342 +4723 +7773 +3373 +7488 +8028 +3246 +6355 +1939 + +2921 +4447 +3472 +5175 +5909 +5936 +5263 +3993 +1589 +3906 +4865 +3156 +2010 + +10089 + +5964 +7650 +4692 +1537 +3281 +3162 +1064 +4567 +3910 +2229 +3566 + +15533 +17311 +11818 +6179 + +4583 +4577 +3573 +1379 +3761 +1048 +4799 +4275 +3515 +5637 +5435 +3801 +5933 +1926 + +11841 +16030 +3213 + +4307 +7300 +1237 +5513 +6799 +2402 +2554 + +67023 + +1573 +6798 +3002 +7536 +2373 +5994 +10122 + +1149 +1836 +7129 +6621 +7432 +2468 +4028 +6560 +5127 +3781 +7035 +5845 + +13729 +10212 +10942 +10087 +10080 +6493 + +6850 +5969 +3370 +5400 +6433 +4762 +5702 +6193 +1836 +1507 +2637 +3051 +1394 + +5465 +10565 +4923 +1671 +9789 +9150 +6466 +8013 + +31283 + +2001 +6032 +6765 +3896 +7593 +3175 +3447 +1718 + +6062 +7630 +6302 +4448 +1014 +4756 +4696 +4069 +5663 +2181 +6153 + +9228 +1871 +11739 +10894 + +7435 +6290 +3249 +9358 +9196 +8951 +5023 +4910 +9686 + +3823 +4247 +7159 + +4630 +3352 +7700 +7752 +3343 +4577 +2448 +10326 + +10002 +28943 + +2592 +4430 +4077 +2126 +4628 +6466 +5919 +7019 +2667 +2573 +7038 +3153 + +2837 +12151 +9774 +1574 +3046 +13079 + +6949 + +5306 +7432 +4274 +6835 +7057 +5695 +4727 +5581 +6516 +3903 +3138 + +4083 +4247 +1806 +2753 +3612 +3509 +5498 +2160 +5814 +1502 +5760 +4663 +1354 +1592 + +59040 + +3738 +7624 +4539 +8649 +9418 +5495 +1178 +8389 + +4458 +5283 +2572 +3530 +6228 +4711 +2621 +2131 +6363 +5611 +3236 +2314 +2547 +1905 + +3744 +1413 +2997 + +2214 +4673 +4481 +5827 +3752 +5489 +5301 +7568 +6869 +2928 +2900 + +11668 +7579 +2324 +7245 +14362 + +1191 +5622 +2764 +3241 +3690 +3627 +2637 +4043 +3012 +2773 +4276 +1127 +3649 + +5327 +6535 +4821 +5531 +3037 +4700 +6287 +6476 +2266 +7550 + +3054 +5023 +1296 +4394 +5649 +1822 +6609 +7038 +5836 +6571 +6918 + +9473 +5377 +8449 +4839 +3118 +7861 + +8784 +3880 +5133 +6131 +2114 +5196 +10405 +1040 + +5003 +5888 +6058 +6910 +3155 +3278 +1159 +3863 +4565 +1181 +2716 +6431 +3014 + +7633 +4984 +1297 +4524 +5183 +3717 +12038 + +5908 +7784 +11211 +7635 +2060 +5502 +9179 + +6537 +6895 +3455 +4799 +5557 +3497 +4467 +1694 +5227 +1663 +2377 +3538 +4529 + +9371 +2421 +9789 +7373 +6459 +6405 +7775 +8218 + +2077 +8589 +3417 +7811 +10255 +4325 +7168 + +5963 +2806 +3512 +2369 +5721 +3852 +3022 +3764 +6152 +1158 +6460 +4694 +1909 +2655 + +7789 +3030 +3621 +6269 +3149 +6405 +2288 +3512 +5674 +1301 + +6120 +2629 +6348 +7105 +3459 +6678 +5903 +4519 +3074 +2086 +3927 + +2924 +12290 +1873 +5613 +3098 +8641 + +24464 +37206 + +7180 +13271 +4832 +10691 +9084 + +4915 +1440 +1841 +1476 +7124 +1692 +7480 +4583 +1896 +3475 +5424 + +6864 +3187 +4680 +5159 +4314 +3148 +1060 +7290 +2080 +8308 + +2412 +16405 +15203 +5606 +9411 + +13201 +6242 +11906 +15782 +12558 + +5319 +7968 +6732 +9702 + +7203 +3571 +7241 +8764 +3466 +6032 +6608 +6898 +7189 +2749 + +6184 +7590 +4976 +4289 +8553 +8238 +5844 +8314 + +3264 +2924 +2586 +1234 +3126 +5269 +6147 +6029 +2384 +6440 +6161 +1708 +2928 +2336 + +24565 +31964 + +11118 +10621 +1430 +3312 +1135 +6740 +9456 + +16874 +4385 +8675 +4237 + +1537 +4313 +5552 +2195 +3530 +2433 +3056 +3693 +1151 +4297 +2017 +4917 +3823 +3388 +1580 + +5795 +2642 +3822 +1824 +2366 +3800 +2020 +4065 +2758 +2677 +3951 +5175 +4433 +1199 +3212 + +4183 +2822 +6355 +4427 +6384 +2931 +4892 +3148 +5802 +3885 +4892 +5233 +4269 +4286 + +3711 +5430 +6115 +5561 +5066 +2796 +3886 +1960 +6083 +4657 + +11662 +12901 +6891 +3897 + +1086 +4333 +1477 +1046 +5670 +3996 +1909 +3544 +5143 +1387 +6319 +3084 +3136 +6084 + +36111 +14790 + +6552 +8491 + +6636 +9718 +15736 +1619 + +9531 +7507 +7311 +5991 +6901 +12139 +10580 + +10956 +7878 +9100 +11884 +2906 +10388 + +7767 +4040 +5872 +1060 +2299 +1008 +3597 +2749 +5025 + +1550 + +5364 +7108 +8661 +8894 +9240 +10008 +4243 + +46695 + +4195 +2850 +2978 +4995 +2944 +5773 +3669 +3662 +4471 +6343 +4258 +1252 +6408 +5995 + +9482 +11898 +9022 +8167 +9232 + +2647 +1990 +2948 +5314 +2341 +3828 +2513 +2091 +4173 + +9640 +2690 +8774 +11619 +11201 +2429 +7216 + +3433 +5914 +5223 +4879 +1349 +4692 +2906 +3761 +4416 +4813 +2751 +4474 +2057 +1675 + +9803 +8986 +3617 +2175 +1412 +8370 + +7671 +6448 +6759 +1857 + +25790 +14495 + +1872 +6441 +4585 +4053 +4142 +5844 +2089 +3387 +2660 +5890 +6499 +3769 +2710 + +23432 +16915 + +1351 +2656 +6557 +1149 +5054 +1681 +6871 +2643 +3158 +1617 +4087 +6498 +4993 + +5494 +10055 +2730 +5800 +2923 +8037 +3448 +1527 + +5803 +18165 +21951 + +4766 +3809 +4678 +3184 +9687 +7825 +7222 +6638 +2016 + +1801 +1717 +4955 +6088 +1848 +4033 +7023 +3551 +5970 +1415 +7027 +7411 + +25450 +11523 +22548 + +1566 +4742 +3947 +2708 +2019 +3479 +4735 +6002 +7042 +1828 +7071 +1535 + +14218 +5232 +10228 +3340 +7975 + +8837 +3510 +10363 +11854 +2821 +7627 +10186 + +1102 +3749 +1436 +1561 +3098 +3849 +3726 +2041 +1100 +1532 +5473 +4643 +5922 +4739 +1216 + +4408 +7369 +1369 +4742 +7109 +4368 +3468 +2777 +3296 +6999 +5777 +5019 + +3750 +12190 + +15694 +12690 +14834 +15532 +1955 + +8702 +1209 +3012 +3074 +8390 +6779 +6117 +2544 +3900 +6374 + +4126 +5772 +7149 +3949 +2371 +2374 +2469 +7839 +7898 +2871 +5808 + +1108 + +9610 +4374 +10275 +2595 +9413 +8906 +6402 +1551 + +6560 +8632 +5064 +2152 +3443 +4229 + +13104 +24831 +17968 + +4648 +5332 +4866 +1048 +4089 +4710 +1406 +2544 +5319 +4685 +4622 +6080 +5899 +3266 + +5694 +12879 +4015 +16066 +1600 + +11186 +31873 + +3871 +6382 +5076 +3606 +4283 +7913 +11124 + +9959 +14807 +17825 +5880 + +3914 +14183 + +8104 +8322 +10254 +3957 +1410 +9402 +2012 + +1130 +4640 +5738 +3860 +1510 +3067 +5021 +5321 +2820 +1269 +3433 +5216 +5585 +1344 + +5975 +9879 +4969 +9796 +1404 +6772 +3240 +1954 + +12512 +13741 +6425 +13234 +10597 +12414 + +2031 +2255 +3306 +1831 +1601 +1959 +4452 +5054 +4967 +5392 +4040 +4989 +4385 +5838 +5043 + +3165 +10185 +10580 +1626 +5436 +9644 +10842 + +5139 +8090 +1045 +5867 +5987 +8488 +2409 + +1045 +2843 +3543 +3224 +2855 +3318 +4192 +4600 +5773 +4074 +4705 +4716 +1798 +5274 +2443 + +6325 +7878 +4932 +7543 +8073 +2113 +5481 +8138 +2151 +1296 + +6007 +2506 +2346 +3631 +1526 +4875 +3099 +5253 +6281 +2057 +3209 +2622 +2930 +4926 + +2901 +4561 +2361 +4474 +8508 +6515 +5024 +2201 +4402 +6922 + +4219 +24714 +17196 + +38164 + +1900 +5727 +3935 +5498 +6165 +4621 +3347 +4387 +5982 +4213 +1742 +1302 +2452 +3923 + +9558 +7131 +15662 +9101 +13730 + +6474 +2222 +6539 +3747 +5995 +5573 +6288 +4684 +5121 +2226 +1722 +1117 +1020 + +3565 +3489 + +18395 +20407 + +57158 + +19992 + +3636 +4392 +4584 +5421 +3159 +5817 +2303 +1013 +1758 +1802 +4630 +4261 +1524 +1639 + +4652 +1967 +4765 +4946 +3023 +2732 +2749 +5258 +5935 +6428 +3053 +6328 +2389 +5681 + +5450 +1993 +2824 +3596 +2658 +8545 +6577 +3024 +4001 +1780 + +7902 +6187 + +1349 +6028 +3307 +1964 +5116 +2308 +6108 +4286 +1689 +3324 +3728 +4946 +4267 +3801 +3806 + +14183 +29320 + +32460 +25012 + +3317 +5545 +7302 +4936 +7934 +6094 +7971 +2497 +8130 +3752 + +4195 +2147 +7770 +4214 +4737 +7962 +5942 +4478 +3816 +7508 +6693 + +26013 +8614 +19828 + +1144 +2361 +4371 +4246 +3442 +1693 +5137 +5806 +2434 +1413 +3135 +4028 +4757 +6005 + +2351 +4927 +3004 +3384 +1545 +2172 +3407 +4120 +3954 +1806 +2342 +5847 +5228 +1005 + +11490 +7855 +9775 +10577 +3232 +5211 + +8316 +2984 +13490 +15716 +7433 + +11288 +14551 +10056 +14839 +7241 + +4573 +2731 +3358 +4850 +6352 +5419 +1021 +6611 +6489 +3794 +6089 \ No newline at end of file diff --git a/2022/day-01/solution.test.ts b/2022/day-01/solution.test.ts new file mode 100644 index 0000000..ad3c0b2 --- /dev/null +++ b/2022/day-01/solution.test.ts @@ -0,0 +1,16 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(68923); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(200044); +}) + + diff --git a/2022/day-01/solution.ts b/2022/day-01/solution.ts new file mode 100644 index 0000000..1108aa5 --- /dev/null +++ b/2022/day-01/solution.ts @@ -0,0 +1,43 @@ +const solve = (input: string): [number, number] => { + let maxCalories1 = 0; // calories >= 0 + let maxCalories2 = 0; + let maxCalories3 = 0; + + const elvesCalories = input.split('\n\n'); // \n\n = empty line between elves + + elvesCalories.forEach((elfCalories) => { + const elfCaloriesParsed = elfCalories.split('\n'); + + // count the sum of the elf's calories + const elfCaloriesSum = elfCaloriesParsed.reduce((sum, elfCalorie) => { + return sum + Number(elfCalorie); + }, 0); + + if (elfCaloriesSum >= maxCalories1) { + maxCalories3 = maxCalories2; + maxCalories2 = maxCalories1; + maxCalories1 = elfCaloriesSum; + } else if (elfCaloriesSum >= maxCalories2) { + maxCalories3 = maxCalories2; + maxCalories2 = elfCaloriesSum; + } else if (elfCaloriesSum >= maxCalories3) { + maxCalories3 = elfCaloriesSum; + } + }); + + return [maxCalories1, maxCalories1 + maxCalories2 + maxCalories3]; +} + +const solvePart1 = (input: string): number => { + const [maxCalories] = solve(input) + return maxCalories; +}; + +const solvePart2 = (input: string): number => { + const [_, maxCaloriesTop3] = solve(input) + return maxCaloriesTop3; +}; + +export { solvePart1, solvePart2 }; + + diff --git a/2022/day-02/input.txt b/2022/day-02/input.txt new file mode 100644 index 0000000..0829cce --- /dev/null +++ b/2022/day-02/input.txt @@ -0,0 +1,2500 @@ +C Y +A Z +B X +C Y +B Y +C X +C Y +B X +B X +A Z +C X +B Y +B X +B X +A Z +B X +C Y +C Y +C X +B X +B X +C Y +C Y +A Z +C Y +A X +B Y +C Y +A Z +B X +B X +C Y +A Y +A Y +C Y +C Z +C Y +C X +C X +B X +C Y +A Y +C Z +B X +C Y +B Y +C Y +A Y +B X +B Y +A X +A Y +B X +B X +B X +A Z +C Y +B Y +A X +A Y +C X +C X +C Y +B Y +C X +B X +C X +A Z +B Y +C X +C Y +B X +B X +C Y +B X +C Y +A Z +B Y +B X +B X +B X +C Y +C Y +A Y +C X +C X +A Y +C Y +B X +A Y +C X +C Y +C X +C X +B Z +C Y +B X +C Y +A Y +B Y +B Y +B X +A Y +C Y +B X +B Y +A Y +B X +C Y +C Y +B Y +B Y +C Z +C Y +C X +B X +C Y +B X +C Y +A Y +A Y +A Z +C Z +A Y +B Y +B X +C X +C Y +C X +B X +B X +A Y +A Y +C Y +C Y +A Z +B X +B X +B X +B Y +B X +B X +C Y +C Y +C Y +C X +B X +C Y +B X +A Z +C Y +C X +A Z +A Y +A X +C Y +B X +A Z +C Y +A Z +C Y +B Y +A Z +A Y +A X +A Z +A Z +C Y +B X +C Y +C Y +A Z +B X +C Y +B X +C Y +A Y +B X +A Z +A Z +C Y +A Z +B Y +B X +A Z +B X +B X +B X +B Y +C Y +C Y +C X +A Y +C X +B X +C Z +B Y +C Y +A Y +C X +C X +B X +B X +B X +A Y +B Y +B X +B X +C Y +A Y +B X +B X +A Z +C Y +C Y +B Y +B X +A Y +B X +B X +A Z +C Y +A Y +B X +A Z +C Z +A Z +B X +B X +B Y +A Z +C X +B X +C Y +B X +C Y +C X +A Z +B X +A Z +C Y +B X +C X +A Y +B Y +C Y +B X +B X +B X +B Y +B X +A X +C Y +B Y +B Y +C Y +C Y +C Y +A Y +A Y +A X +A Z +C Y +A Y +C X +C Y +B Y +C Y +C Y +B X +C Y +B X +C Y +C Y +B X +B Y +B Y +B X +B Y +B X +C Y +C Y +C X +C Y +C X +C X +B Y +A X +C Y +A Y +C Z +B X +C Y +A Y +A Y +C Y +C Y +B X +B X +B Y +B Y +C Y +C X +A Z +C Y +C Y +C Y +B Z +A Z +B X +B Y +C Y +C Y +B X +A Z +A Z +B X +C X +C Y +A X +C Y +B Y +B X +B X +C Y +B Y +A Y +B X +B X +C Z +B Y +B X +C Y +C Y +C Y +B X +B Y +C X +B Y +C Y +C Y +C X +B X +C Y +B X +C Y +B X +A Z +C Y +A X +A Z +B Z +B Y +C Y +B X +C Y +C X +B X +B X +B Y +A Y +C Y +B X +A Z +C Y +B X +B X +B X +C Z +B Y +A Y +B X +C X +A Y +B X +B X +B X +C Y +C Y +B X +C Y +C Y +B X +B Y +B Y +C Y +B Y +B X +C X +A Z +B Y +B X +C Z +A Y +B X +C X +B X +B X +C Z +B Y +A X +C X +C X +B X +C Y +A Z +B X +B X +B X +B X +A Y +C Y +B Y +B X +A X +B X +C X +C X +B X +C Y +B Z +A Z +B X +B X +C Y +B Z +B X +A Y +B X +A Z +B X +C X +B X +C X +B X +B X +C Z +B X +A Y +B X +C Z +B X +C Y +B X +B Y +B X +B X +C X +B Y +B Y +A Y +C Y +B X +B X +C Y +C Y +C Y +B X +A Z +C Y +C Y +A Z +B X +A Y +C X +B X +C Y +A Y +B Y +B Y +A Z +B X +B X +C Y +B X +B Y +B X +B X +B X +C Y +C Y +C Y +C X +B X +B X +C X +C X +B X +A Y +C Y +C Y +C Y +C Z +B X +B X +A Y +B X +A Y +C X +B X +B X +C Y +C Y +C Y +A Y +A Y +A Y +B X +C Y +B Y +B X +A Z +C Y +B X +A Y +B Y +B Y +B Y +B Y +C X +A Y +B X +A Y +B X +C X +C Y +B X +A Z +C Y +C Y +B Y +B X +B X +A Z +B Y +B Y +C Y +B X +C X +C Y +B X +B Y +B X +B X +C Y +B X +B Y +B X +C Y +B X +A Y +B X +C Z +B X +C Y +C Y +B X +B X +C Y +C Y +C Y +C X +B Y +B X +C X +B X +C Z +B X +C Y +A Y +B X +A Z +C Y +A Y +B X +A Z +C Y +C Y +B X +C Y +A Y +B X +C X +B Y +C Y +B X +C X +B X +B Y +A Y +A Y +A Y +B X +B X +B X +B X +B Y +B X +B X +B X +A Z +C X +C Y +A Z +C X +B X +C Y +B Y +C Y +B X +C Y +C Y +C Y +C Y +C Y +C Z +B X +B X +C Y +B X +A Y +C Y +C X +B Y +C Y +C Y +A Y +A Y +C Y +B Y +C X +B X +C Y +C Y +B X +B X +B X +A Z +B Y +B Y +A Y +C X +B Y +C Y +C X +B X +B X +C X +B X +C Y +C Y +B Y +C Y +B X +B X +A Z +B Y +A Z +A X +B Z +A Y +C Y +C Y +C Y +B X +A Z +A Y +B Y +C Y +B Y +B X +B X +A Y +C X +C Y +B X +A Y +A Z +B X +B X +C Y +B Y +C Y +C Y +B Y +B Y +B X +A Y +B X +B X +B X +B X +C Y +B X +B Y +C X +C Y +A Y +B Y +A Y +C Y +C Y +A Z +B X +C Y +A Z +A Y +B X +B X +B X +C Y +B X +C Y +B Y +B X +B Y +A Y +B X +C Y +C Y +B X +B X +C Y +C Y +C Y +B Z +C Y +B X +C Y +B Y +C Y +C X +B X +A Y +A X +A Z +A Z +B Y +C X +B X +B Y +B X +B X +A Z +B X +A Y +C Z +C Y +C Y +C Y +A Y +C X +C Y +A Z +C Y +B X +A Y +A Z +B X +A Y +C X +A Z +A Y +B X +B X +C Y +C Y +C Z +A Z +B X +A Y +B X +B X +B X +C Y +A Z +C Y +B X +B Y +C X +C Y +A Z +A Z +C Y +B Y +C Y +C Y +C X +C Y +C Y +B X +C Y +B X +B Y +C Y +C Y +C X +A Z +B X +B X +C X +C Y +C X +C X +B X +B Y +B Y +C Z +A Y +A Z +B X +B X +C Y +C Y +A Y +C Y +B Y +C Y +B X +C Y +B Y +B X +C Y +C Y +B X +C Z +A Y +B X +C Y +A Z +C X +C Y +A Y +B X +A Y +C Y +B X +C Y +B X +A Y +C Y +B Y +B X +B X +C Y +A Z +A Z +C X +A Y +B X +C Y +B X +C X +C Y +C Y +C Y +C Y +C X +B Y +B X +B X +C Y +B Y +B Y +B X +B X +B X +B Y +B X +B X +B X +C Y +A Y +A Y +B X +C Y +C Y +A Y +C Y +B Y +C X +B X +B X +A Y +C Y +B X +B X +B Y +C Y +B X +C X +B Y +A Y +A Y +C Y +C Y +C Y +C Y +C Y +B X +C Y +B Y +B X +B Y +C Y +B X +B X +B X +B Y +B X +B X +B X +C Y +B Y +C Y +B X +B X +B Y +C X +C X +C Y +B Y +B X +A Z +B X +B X +C X +C Y +C Y +B X +A Z +C Z +C Y +C Y +C Y +C X +B Y +B X +C Y +C Y +C Y +B Y +B Y +C Y +C Y +B Y +A Z +C Y +A Z +B X +C Y +A Y +B X +C Y +C Y +B X +A X +B X +B X +C Y +C Z +C Y +A Y +C Y +C Y +B X +B X +B X +B X +A Z +C Y +C Y +B Y +B X +C Y +C Y +C Y +B X +A Y +B X +C Y +B X +B X +C Y +C Y +B Y +B Y +C Y +B Y +C Y +A Y +A Y +A Y +C Y +C Z +B X +A X +C Y +A Y +C Y +A Y +B X +B X +B X +B X +B X +C Z +B X +C Y +C Y +B Y +A Z +A Z +C Y +B Y +C Z +A Z +C X +A Y +C Y +C Y +B X +C Y +B Y +B Y +C Y +A X +C Y +B X +A Y +C X +B Z +C X +B X +B Y +A Z +A X +B Z +C Y +B X +B Y +C X +A Y +C Y +C Z +B Y +B Y +B X +B X +C Y +B X +B Y +C Y +C X +C Z +C Z +C Z +A Y +B X +C Y +C Y +B X +A Y +B X +A Y +C X +C X +B Y +A Y +C Y +A Y +C Y +C Y +B X +B X +A X +B X +A Y +C Y +C Y +C X +A Y +B X +B Y +B X +B X +B Z +B X +A Y +C Y +B X +B X +A Y +A Z +C Y +C Y +A Z +A Z +B X +B X +C Y +B X +B X +A Y +A Z +B Y +B X +C Y +C Y +B X +B X +C X +C Y +B X +B X +B X +B X +B X +C Y +C Y +A Y +B Y +B X +A Z +C Y +B Y +A Z +C Y +C Y +B X +A Z +C Y +A Y +C X +B X +B X +B Y +B X +A Z +C Y +B X +B X +B X +B X +B X +B X +C Y +B X +B Y +B Y +B Y +C Z +C Y +B Y +A Y +A Y +B Z +B Y +B Y +B X +B Y +B Y +C X +A Z +C Y +C Y +C Y +B X +B Y +B X +C Y +C Y +C Y +B Y +A Y +C Y +B X +B X +C Y +B Y +C Y +B X +B X +B Y +A Y +C X +C Z +B X +A Y +C Y +B X +C Y +B X +C Z +C Y +C Y +C Y +A Z +C X +C Y +C Y +A Z +A Z +B X +A Y +C Y +C Y +B X +A Z +B X +C Y +B Y +B X +B X +C Y +C Y +B Y +C X +B Y +C Y +B Y +C Y +B X +C Y +B X +B Y +B Y +C X +C Y +A Z +C Y +C Y +C Y +A X +A Y +B Y +C X +B X +C Y +B X +A Y +B X +C Y +C Y +C Y +A Y +B Y +B Y +B X +A Z +A Z +B Z +C Y +B Y +C Y +B X +A Z +C Z +B X +C Y +C Y +C X +C Y +C Y +C Z +C Y +B Y +B X +B Y +B Y +B X +A Z +C Y +B X +B X +B Y +B Y +B X +C X +C Y +C X +B X +B Y +B Y +A Y +C Y +B X +A Y +C Y +B X +B X +C Y +C Y +C X +B X +C Z +B X +C Y +A Y +C X +B X +C Y +B X +C X +A Y +A Y +A Y +C Y +B X +B X +B X +B Y +A X +C X +B X +C Y +B X +B X +A Y +B X +B X +B X +B X +B Y +B Y +B X +C X +A Z +C Y +C Y +C Y +B Y +C Y +C Y +B X +B Y +C Y +A Z +C Y +B X +B X +C Y +A Z +C Y +A Y +B X +C Y +B X +B Y +C Y +C X +B X +B Y +B X +B X +B X +B X +C Y +C Y +A Y +C Y +B Z +A Y +C Y +C Y +B X +A Y +C Z +C Y +B Y +C Y +C Y +B Y +C Y +B X +B X +C Y +B X +B X +B Y +B X +B X +B Y +C X +C Y +B X +A Y +C X +B X +B X +A X +B Y +C Y +C Y +B X +A X +A Y +B Y +B Y +C Z +B Y +B Y +B X +B X +C Y +A Y +C Y +A Y +B X +C X +B Y +C Y +B Y +B Y +C Y +A Y +C Y +B X +A X +C Y +B X +B X +B X +C Y +C Y +C Y +A Z +A Z +C Y +A Y +C Y +B X +B X +C X +B Y +A Y +A Z +A Y +C X +B X +C Y +B Y +B X +A Y +C Y +B X +A Y +B Y +C Y +B Y +B X +C Y +C Y +B Y +B X +C Y +B Y +C X +C Y +B X +B X +C Y +C Y +A Y +C X +B X +B X +B Y +A Y +B Y +B X +C Y +C Y +C X +B Y +C Z +C Y +C Y +B Y +C Z +B X +C Y +A Y +A Z +B Y +B X +C X +A Y +B X +C Z +B Y +C Y +B X +B X +B Y +C Y +B Y +C Y +C X +B Y +B X +C Z +B X +B X +B X +B X +A X +B X +C Y +C X +B X +A Y +C Y +A Z +C Y +C Y +C Y +A Z +B X +C Y +A Y +B X +B X +C Y +A Z +B X +C Y +A Y +A Z +C Y +A Y +B Y +B Y +C Y +C Y +C Y +B X +C Y +C Y +B X +B X +A Z +C X +C Z +A Z +C Y +B X +B Y +B X +B Y +C Y +B X +B X +B X +B X +B X +B Y +C X +C Y +C Y +B X +B X +B X +C Y +C Y +C Y +C Y +A X +B X +B X +A X +B Y +C Y +C Y +B Z +C Y +C Y +B X +B X +C X +A Y +B Y +B X +C X +B X +B Y +B X +C Y +C Y +C Y +B X +A Z +B X +A X +B X +A Y +C Y +A Y +C X +B X +B Y +B X +B X +C Y +A Y +B Y +A Y +C Y +B Y +B Y +B X +A Z +B X +B X +B X +C Z +B X +C Y +B X +B X +C Y +C X +B X +C Y +B X +C Y +C Z +A Y +B X +C Y +B Y +C Y +C Y +C Y +B Y +B Y +C Y +A Y +A Z +C Y +C Y +C Y +B X +A Y +C Z +B Y +C Y +C Y +B X +B Y +A X +B X +B Y +B X +C Y +B X +B Y +B X +A Z +A Z +B X +B X +B X +C Y +B X +C Y +A Y +C X +C Y +A Z +A Y +B X +B X +C Y +B X +B Y +A Y +B X +B X +C X +C X +B X +B Y +C Y +B X +B X +C Y +B X +B X +C X +B Y +A Y +C Y +B X +B X +B Y +C Y +A Z +B X +C Y +C Y +B X +B X +A Y +C Y +C Y +B X +A Y +B X +B X +A Z +C Y +B X +B X +C Y +B Y +C Y +B X +A Z +C Y +C Y +B Z +A Z +B Z +B X +A Z +C Y +B Y +C X +A Z +C Y +A Y +B X +C Y +C Y +B X +C Y +B X +C Y +C Y +B X +B X +C Y +B Y +A Y +B X +C Y +A Y +C Y +C Y +B X +C Y +B X +B X +B X +C Y +B X +B Y +B Y +A Y +A Y +A Z +B X +C Y +B Y +B X +B X +C Y +B Y +C Y +C Y +A Z +C Y +C Y +B Y +A Y +B Y +C X +B X +B X +B X +B X +A Z +B X +C X +A Y +C Y +B X +C Z +C Y +B X +C Y +B X +B X +A Y +C Z +B X +B X +C Y +A Z +A Y +C X +B Y +B Y +B X +A Y +C Y +B X +B Y +B Y +C Y +C X +A Z +B Y +C Y +B X +C X +C X +B Y +A Z +B Z +B X +B X +A Z +B Y +C Y +C Y +B X +C Z +C Y +C Y +A Y +C Y +B Y +B X +C Y +C Y +A Y +A Z +A Z +B X +C Y +B X +B X +B X +B X +A Z +B X +A X +C Z +C Y +B Y +A Y +B X +B Y +A Z +C Y +C Y +B X +C Y +C Y +C X +C Y +B X +B X +B X +C Y +B Y +B Y +C Y +C Y +B X +B X +B X +B X +A Y +C Y +B X +C X +A Z +C Y +B X +B Y +B Y +B Y +C Z +B Y +A Y +C X +A Z +C Y +C Y +C X +A Y +B Y +A Y +B X +C X +B X +C Y +B Y +B X +C Y +C Y +B X +B Y +B X +A Z +A Z +A Y +B X +B X +B Y +C X +A X +B X +B Y +C X +C Z +C Y +A Y +C Y +B X +A Z +B X +B X +A Z +C X +A Z +C Y +C Y +A Z +A Y +B X +C Z +B X +A Y +B Y +A X +B Y +B Y +B Y +B X +C Y +B X +C Y +C X +C X +A Z +C Y +B X +A Y +C Y +A Y +B X +C Y +C Y +B X +C Y +B X +C Y +A Y +A Z +C Y +B Z +C Y +C Y +B X +C Y +C Y +C Y +B X +A Y +A Z +B X +A X +B Z +C Y +B Z +C Y +B Y +B Y +C Y +C Y +B X +C Y +A Z +B Y +C Y +C X +A Y +A Y +B X +B X +B X +A Y +C Y +A Y +B Y +C Y +A Y +A Y +C Y +B X +C Y +B X +C Y +B X +B X +C Y +C X +A Z +C Y +C Y +A Z +C Y +A Y +A X +A Z +B Y +C Y +B X +C Y +C Y +C Y +C Y +A X +B X +C Y +B Y +B X +B X +A Y +A Z +C X +C Y +C Z +C Y +B Y +C Y +B X +B X +A X +B X +B X +A Y +C Y +B X +A Z +C Y +C Y +A Z +C Y +C X +B X +B X +B X +C Y +B Z +C Y +B X +C X +B X +C Y +C Y +A Y +C Y +C Y +C Z +A Z +C Y +C Y +C Y +B X +C X +B Z +C Y +B X +B X +B X +C Y +B Y +B X +B Y +A Y +B Y +B X +C X +C Y +A Z +B Y +C Y +B X +C Y +C X +B X +B X +A Y +B Y +B X +A Y +B X +C Y +C Y +C Y +A Z +A X +C Y +C Y +C Y +A Z +B X +B X +A Y +C Y +C X +C Y +B X +B X +A Y +A Y +B X +B X +C Y +B X +B X +A Y +A Z +B X +A Y +C Y +C Y +C Y +B X +B X +C X +A Y +C Y +B Y +A Y +C Z +B X +C Y +B Y +B X +C Z +A Y +C X +C Y +C Y +B X +C X +B X +A Y +C X +B Y +A Y +A Y +B X +C Y +B X +C Y +B Y +C Y +C Y +B X +B X +B X +B X +B X +C Y +A Y +C Y +A Z +A Y +B X +C X +B X +B Y +C Z +B Y +B X +C Y +A X +C X +C Y +B X +C X +A Y +C Z +C Y +B X +A Z +A Y +C Y +C Y +C Y +C X +B X +A Z +B Y +C Y +C Y +B X +B Y +C X +C Y +B X +B X +B Z +C Y +B X +B X +B Z +B X +C Y +C Y +C Y +C Z +C Y +B Y +A Z +A Z +B X +B Y +A Z +B Y +B X +B X +B Y +C X +C Y +A Y +C X +C X +B Y +A X +B Y +B X +C Y +C Y +B X +C Y +A X +C X +C X +B X +B X +C X +B Y +B Y +A Y +B X +B X +B X +C X +B X +A Y +C Y +B X +A Z +B Y +A Y +B X +B X +C Y +B Y +A Z +B X +B X +C Y +A Y +A Y +A Z +C Y +A Y +B X +A Y +B X +C Y +C Y +C Y +B X +B Y +B X +C Y +A Z +A Z +B Y +B Y +C X +C X +C Y +B X +C Y +B X +C Y +C Y +A Y +A Y +A Z +A Y +B X +B X +B X +B Y +C Y +C X +C Y +B X +B Y +C Y +C X +C Y +B X +A Z +C Y +C Y +B X +A Z +B X +A Z +A X +A X +B X +B X +C Y +C X +B Y +C Z +B X +C Y +A Z +B X +A Y +C X +B Y +C Y +B Y +C X +C Y +C Y +B X +B Y +C Y +C X +C Y +B Y +B Y +B X +B Z +C Y +C Y +B X +C Y +C Y +C Y +B Y +B Y +C Y +C Y +C X +B Z +C Y +C Y +C Y +B Y +C X +B Y +A Y +B X +B Y +A Z +C Y +B X +A X +C X +B X +B X +A Y +A Y +A Y +A Y +B X +B X +A Z +A Z +C Y +B X +A Z +B X +B X +C Y +A Y +B X +B X +A Y +B X +A X +C Y +B X +B X +A Z +C Y +B Y +C Y +A Z +B X +C X +B Y +C X +B X +B X +C X +A Y +B X +B Y +B X +C Y +B X +A Y +B X +C Y +B Z +B X +A Z +B X +A Z +A Y +B Z +B Y +B X +B X +B Z +B X +C Y +B Y +A Z +C Y +B X +B Y +A Y +C Y +C Y +B X +B X +C Y +B X +C Y +B X +B X +A Y +C Y +A Y +A Y +A Y +C Y +C Y +A Z +B X +A Y +C Y +B X +C X +B Y +C Z +C Y +B X +C Y +C Y +B X +B X +B X +C X +C X +B X +C X +C X +C X +A Z +B Y +B X +B X +B X +C Y +A Z +B Y +B X +B X +B Y +A Z +B X +C Y +C Y +A Z +C Y +B X +A Y +C Y +B X \ No newline at end of file diff --git a/2022/day-02/solution.test.ts b/2022/day-02/solution.test.ts new file mode 100644 index 0000000..694fc79 --- /dev/null +++ b/2022/day-02/solution.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(8392); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(10116); +}) diff --git a/2022/day-02/solution.ts b/2022/day-02/solution.ts new file mode 100644 index 0000000..c7ee2a7 --- /dev/null +++ b/2022/day-02/solution.ts @@ -0,0 +1,92 @@ +// Enum values are scores given for a corresponding gesture / result + +enum Gesture { + ROCK = 1, + PAPER = 2, + SCISSORS = 3 +} + +enum Result { + LOSE = 0, + DRAW = 3, + WIN = 6 +} + +// [ElfGesture][MyGesture] => Result + +const RoundGestureMap = { + [Gesture.ROCK]: { + [Gesture.ROCK]: Result.DRAW, + [Gesture.PAPER]: Result.WIN, + [Gesture.SCISSORS]: Result.LOSE, + }, + [Gesture.PAPER]: { + [Gesture.ROCK]: Result.LOSE, + [Gesture.PAPER]: Result.DRAW, + [Gesture.SCISSORS]: Result.WIN, + }, + [Gesture.SCISSORS]: { + [Gesture.ROCK]: Result.WIN, + [Gesture.PAPER]: Result.LOSE, + [Gesture.SCISSORS]: Result.DRAW, + } +}; + +// [ElfGesture][ExpectedMyResult] => MyGesture + +const RoundResultMap = { + [Gesture.ROCK]: { + [Result.DRAW]: Gesture.ROCK, + [Result.WIN]: Gesture.PAPER, + [Result.LOSE]: Gesture.SCISSORS, + }, + [Gesture.PAPER]: { + [Result.LOSE]: Gesture.ROCK, + [Result.DRAW]: Gesture.PAPER, + [Result.WIN]: Gesture.SCISSORS, + }, + [Gesture.SCISSORS]: { + [Result.WIN]: Gesture.ROCK, + [Result.LOSE]: Gesture.PAPER, + [Result.DRAW]: Gesture.SCISSORS, + } +}; + +// Map input values to enums + +const myGestureMap = { X: Gesture.ROCK, Y: Gesture.PAPER, Z: Gesture.SCISSORS }; +const elfGestureMap = { A: Gesture.ROCK, B: Gesture.PAPER, C: Gesture.SCISSORS }; +const myResultMap = { X: Result.LOSE, Y: Result.DRAW, Z: Result.WIN }; + +const solvePart1 = (input: string): number => { + const games = input.split('\n'); + + return games.reduce((score, game) => { + const [elf, my] = game.split(' '); + + const myGesture = myGestureMap[my as keyof typeof myGestureMap]; + const elfGesture = elfGestureMap[elf as keyof typeof elfGestureMap]; + + const myResult = RoundGestureMap[elfGesture][myGesture]; + + return score + myResult + myGesture; + }, 0); +}; + +const solvePart2 = (input: string): number => { + const games = input.split('\n'); + + return games.reduce((score, game) => { + const [elf, my] = game.split(' '); + + const myResult = myResultMap[my as keyof typeof myResultMap]; + const elfGesture = elfGestureMap[elf as keyof typeof elfGestureMap]; + + const myGesture = RoundResultMap[elfGesture][myResult]; + + return score + myResult + myGesture; + }, 0); +}; + +export { solvePart1, solvePart2 }; + diff --git a/2022/day-03/input.txt b/2022/day-03/input.txt new file mode 100644 index 0000000..06b37e8 --- /dev/null +++ b/2022/day-03/input.txt @@ -0,0 +1,300 @@ +RCMRQjLLWGTjnlnZwwnZJRZH +qnvfhpSbvSppNddNdSqbbmmdPrwttJVrVPDVrJtHtwPZhrPJ +BFpFzSSqSFFSvQsnWgCMjTLzng +DbWVcVRRdlLffvtqjTWNgQ +mJJMpsmrMrJSHJpsHrFHvBvgHvqfNvzffgTvfj +mMhPjmjmFPJhMSGGcDRlwRdcLGPc +qFcbmWFJqqWpRJcQWpqsQQQwSPCPrHRHCPdNZtSrSHwrNZ +jGMjGLhhhgTvghgtGVjnNCrPVwZSZffSNSwHZZdH +DvzDlvvhnjlMlglglGGhDLpqqcJWWtsmszpWbBBBmQmb +SPLPHQbJSbPsvTLmfDvVDctvWhcDlD +jdRRzzGgJqwrpMRMgdjlcVcWqfWWlfDlmmlWhB +rwgRGdpGprNNLQLsbZJPsn +GZhTVLztHrSzrRBz +MJWjMvsfSCLSnrJn +MjglcgWMdccvZGFtTDchLLLh +rgDHBgBjRgRTgwzwthBnQwmBtB +MsMpSfMsTGTFFLdFFFMFsnNmthNnzhthtwmWnznz +pZMpJdvJMGRHVJJTVHjb +TQVqZVBcBBdBfbpN +zvzrtCshrntCHslPMMMFpZHbNSpb +hLWhGLttsvLvrrWvhzVmQgwJZTRcggTjGcgT +SqRGLHtSbtNTbhjFTjDDpF +WwgJgmdmMdwPDVQQBBhSBFwV +JMPlmlSldWZmRqtLsRGRtvls +mZvmvPNmlNJPJzzmgNvNgdqqdBSpfHBqSsHqHfwpsffq +nhDQDrwLrVVnqfGnsBGBGGsH +VjCDMhbDjLjtFhtLhLhQjNZcZPwWWcczmvglgJJN +wwqnwZGGZqqMpMprpZqwGlLDtNDffdBdNVBmNGBN +TSTchTFbRLfLmVhNDm +SCLRvJQvRFTSRjqMqPZrZnrzZzjp +cJfqGjgGJcsgsPnghgBm +FHHbQQHLWLbPQThqQQRnZs +lLLMSCvrlFMwlSlFcNwqDVVpJcfjzVDf +cRdRDhsDFzPztwJdGP +CVqpCqCgSNfCSQBpjtBwtlBBHLlmGjGG +qfQfCVQfgQnVNpQCMqfcrFrwWDhrDnsvcRDsbc +nFWWzqWZQSqnJzNJzslJVsdV +vBBvsLvbBmBmRlGTNJJvRRTD +tBbpmmPwCmHpMHHMrPCCcSnZSgcFcZgWFscSfgth +LLssTJrqrpvrvvpJvdjggMlgzVgVggPlFPqz +HwZwCZfHNtbMzjgVnFPC +RSttfRwZDtBcZwQMQdrQsdTBQQmW +lJnNhMJqljlNhSrdWlGGGQHwwH +vbTpbCsTFCTmbSmcRfVCfRpwcPdwWQQrdwHwBHrPdwrLLB +sVTmDfmCTVmJjgSzzntDtt +DQtMjZHZHvMbwwTSpqLtpJ +FzVFlsNdVczWPzWcslVfSLqLsqJpSwwsJswLrf +dNFFWcmzWFGLWcdcFgvZvvRHQvjMHDMBGD +MVPTmPvbMgrTmmmmMRMvPvBwFGhhDCdFFwLCLdJhDGFRhG +fqqWfpZWzWsDwhwdhwqGLD +ZWSSftStnnplcQLSbVMBvTbrMlbrBvvl +FSsHDmtFLbbFbLGg +vrvzTzWzzzvppzSzTMnfTggjVgbgjbLjgPPnbGbVGL +pdMwrBpfwfSMTTWdMTpBDCBtmsmltslcBDCshDHs +RgbmfGtmRVgLLSVSnSrWWSHhnh +ccTvlvNppsFnbFnhnWnPHJ +pqNjDBjNNjvpZfmtjbCLbCmb +qsSVpSVfWqgNrVtWptpmSfqbPQljbHPHlDnljRSlwSnwQn +dcGBrMFMdLTGGdlwDwMRHwwMbjHP +CFBvhFhTLFCGvFchChBdBTJtsNpWqfVgtszprmVWNqNgvV +sjsTgNSNqSjgMmVPmmmrpH +RftCcWddRCZfPtCfcQZdcZDcrBllBFpVHprHWlHHpHJJmlFp +thPZRtLcDRdDCTTsqbnwjhvNjq +TQPtgfgdPcdSQhjwHhHBLS +RrqCqVVbJmVRJmsrzmJpWljlSHLSBwSSRWllWv +CVrDNbHrJHVMCbrDJsdFdFcPFZngMfFdTPfP +NNlZgndqmGVGGVZNWQmWmbhbbhpbbhtCbhtgCpCtMF +THfLPTzwJTJrvHRwwsbFbhfbMCpphVtBbB +RjrvzHLzPDvLzPHrTJVrwPndZQNlDZGndZWDdNNcmlQq +tjDsjDGtTjVVbQVCggvrbg +qrWWRBllRFrdlSMCdbSJCP +cZcncRnhphpZWRNtrmsrGpHffmwH +qpRjdcqTcMbbMRTwtnplnwnhPzhBhw +FSFLvNrsPNrsGSLsrFSGfnwBQwZnZwhQQLwwQhnn +sWNVmVmCFNWGsCrrjRTmMjRjPRqgJqJg +sVCnzVpmFpVSnNFCmnmzwRFDWDdMllDccMdwDMjWjWlWjg +BJbPJGGGHPZqZQbpMlWWMWlBljjjgDjh +tGQPpZtfTPpqrHsVLSzmRNLtSFsN +WCDlBWWlvMFWlQWpmSZdZnNmGfJZFZ +LqjTjgtjPcHTTJgLThztcLTLnHnmdSpZdpdffnmZSppfGpSn +PtzqzjtqJgggzhqqccqhrQMsMvMwrCwMlBvMwvvsvs +NMsJfsHTMVbjnLnVsC +htWllhmZcWDWBwhZPcmpVRjnVMRLCCjLFpCwRb +PmZMrBtcPmZWhzDWBtMmJQdddHfQGNSqHqQGGTgr +NmfnnsPlHnGqnlsNNmRPltRLvrhvrSGJSJjvFFFSSFJLhb +PzQZccVPVwgPjrJSJjhFFpQr +TdwBgdTVwzdwzlmNfRqPmqqTql +BVLLBPmPmWBlMlLJnJlBlFQVgdRDdRZRZHpZjQzdRdZQdzQZ +trGTsfbTTgHZptzSZW +fsfTNcCqqNhhVhVFVhVBWLLB +LJwgJNfbCvwCJCwBCCNhhHmGHWWSMWmWmbMmTmmGdS +lzRnnltsstZzzRTfHtHWHGWftfHW +ZFFzVFqzqlFcZscZpRZsNphjhjvjfgJhQgQvwvhC +HHzcFNcHFjhjZjlrghLL +pMZJptpZWCmpttRMCWnnDnBGGDLhlLQrhl +MJsMCTZTTpTJRmMCJzfNsNcfNHqzvvfcww +ZDtllsDlVsrQBqQqRfWl +wvJgpPhhscgvpJFNrRjRrWRjqrRjdjRv +zpsNzCsNCJCCPPHSLzznMnDSLGLM +rfrJjFWrwjpnJjjjfrjJJnFVTgTggRWRRRPPLQgCgQcPPT +sSNbSvqmsSZDZZBtNTTPGgMLMRVcgPCMRb +zZDZzNNSmrfpjFCjzj +dbbNJPBbbrFqNqttqrGbqDcmDQRmFmwcwSnQSDcpwS +ZMMTsHjzLlLcnSVwpRRQ +hZTWjWvTZzTTWhszfwbJhrgJqtBbJGdqNPqt +rrqgHrgtcHJRRjWZlRvnnWBn +QbhVmdFppwbdjnMvlnBwMWZP +TpFDdVTFTDfhHfJcSJSzGZGf +sqNTNZHsHjjFBBwJMMNMcCJD +WGLQPjfWfQWPWmtLSRRRLwBJDbtCCJJCbbwCMBbMBc +RnPdLQfPLRdndGGRvfjlgdrTTgTsrgTrZFzF +BfHbjVVqSBFfMSlCLCDrGSQssvlr +tTpnnzpcPnwzhcnJTDtTPRprGlRGGGCWlQsWvrlvrQGQrC +DPwhghDTpPVHqqdgZbZq +ZzPqfGPtRtqfqPbqfGgGZbrhMjmjBCpHpHNCmHtHjmBHnj +QJwllvFWwDvnwCBBzjwwpC +ccJLVQzWFJvVJlVbgrZZLZLRRPSgdr +rBGbLbnTfnZrQbTnHldqsMmHsqlsWfMd +JcJjCCPzPtjCNHdlGGMlll +jjgpRRvcGbwpThVppT +ttDfjtqfjtpTWWwfTbtlWccNGRSZNGPGhZGhGhcwRh +LbCrHdvzLSSHmSRNmc +JCsBvrvBLzFQbbvlVVnpQpDtWlDqfq +vvdvJBfvdTvRBflBJPNmmffmgPCMwDgsss +rFjqLnMcnqrrtMLtjNgCPCsNzzgsPCGFNs +VqLqnLVZqjMZqWnrVtWlZJJSvHvBdRSvBdRvvJ +zZBDzgQQZLlcglzjrCrCMFjGZbMsHm +PnnJVRfttTtwVnnVFGHVsjCFCjrsMM +wPRpRpRnNTpPNlBdQQDdgDNMhN +bNQpFpnwgtDHpbnhWtffmfmhvhhfsZ +LcdLdwCLPPSVSqqwZGhWdJhGJZhlGlsm +TBwSLPSPVRSVqSVqVrcnpMDDngMgnQpbRQFDNH +vPSvBJZSSdJgpJJZBDGDGrdqGdllGrGDrh +HMtsltFlRVVFtlscRjjMcsWwWChWmrnwDWGwChmjGCWq +MQHNlTVHNVHpbbpbTvvBvf +VsbPMwhbWhzdpzNNggnBcTBWNngQ +RmtZZFZqSjqVHmGQNcBHNLGLGHQH +JjRClqCjZlDZmqSqljFZZqRCvsvPfshhMdwsDwbVwzMzhffb +bfGtRgfDtVmsMzTbmz +LjGZwQLLdjFdHLNMhmzBzMNHNmzN +wjQLCFvnnQGdZLGWSjdqWDfPlrRpqRDDRqrpPr +pqnBZqjCNCqQqmllpHGMGdTfML +PsFgrRvSPsWTwWWQwGHLHW +SrvgsFbrrPJJFsrFPtFSCChBDQjqCqtNhDqhCqNC +RJZRWZWMWZPZffRCPWMdRdfQQQjJzHQsssjrSQFVschVHr +NgpnDgvGTNTVFHFFjVFF +jntvgljpGvlnbLtLbBvnLRPlCCwwCfRqMCCqqqddqw +PFBMVDSVPHMTThtMtSBMMVNbQprHbNRgNRRgLnvpnjnN +scGcrcwlswdGlcqvbQgnnpQnqLjnpp +ffwswWzcmlcWWsmcZhrDFrZMFZBMFzhM +LMdZGqdRSSZmCZMRfQjnggvlvggRcznz +tjjFhBrtpthpslcvvlcQzFnFvQ +jrhbjtpJtbZqCLdWLq +HBGBfBttZzbGbljPdpFddFqRmqRzRN +JDWghDDSDqmmDDpc +CLvgMvChCvLphCTSShhMhQsBbfTfsGsrBfjfrljrZZff +RgHgDqDzqQqgcdHqcZGTNlGffGBDGZBTGZ +LFLPWsmvrbwhwwswrTlTTCBNGFfGlNJZNS +vhrLnvhNmWvMsrvwqMdRcptQtztcjptz +sLMLsThhjgqLlsnsLgTLtMFcRbcPcJSwJbbSbtSWScSt +fvrjjDjvNprdPwwJCCSrWPFP +vfZdGzVzfvGGVGpBjnnMglTsgZlqsMlM +TCVMfCfBnHHfLLPFWb +GgQlGJzNzbzHcHHLlcPLHL +tQbNQGgRZZCVtVMZ +QFFMzwjwngsvsBjGGJWbBbBWbB +QdmVDmVDWRPWVPVV +QHtHSdDpLQCCSHrtqrdrttDfLgvnFvFghNszzwgngFwsNF +RzzTNpSRBzSBVpSRlHNSHBSSGPcLNGtjhPPcbcGhPPhcrnct +CCmmCwwdfFJqDmdwsddhsmvdcMbLfcftttbPnjMPbcjPMPbP +mdZQmvssFdqsFZvsZQmvDvmWzgQBWTRzTzHlppWRglHBQh +VWmnfQWzWWnHWMfmmMVNMfWjtBtBNSNSrlStlpjJBBlgBS +cZZvbwsZsbbZvvscCRdFTTTQrBStdBJgSdhjgBjBjJjpJJ +wCFTCbZbFwwCTvFTwsPGccMzMDWVWfzLGmqHnnDHGLQL +sNQQHbbhdlpdrQllqpsqSpGjZDZGgDnVcnjjnnDZ +WWRLGFvJBJPvzzWjnTncDVZTTPgDff +FLRLGRFRJLBWJmJzMRLCvldrMrbbltdhQQlNqtMbsb +HZllwlZSlSZwhvmQjcZhTqcT +sPzzdgpszpzsBdvvMccvcqPThjhM +JDdsDspLzsdzBgVdBGBzCLlwbbwWSnlnnWffHwJcNlHw +nzCTCnpqJqfCnvvjZjWjPcZrmcmZfW +GNdwgVjwRdRglMrPWLPWZWcNWW +dVblgtRwQgSGVBldbQBbBRJnQJTsJHTqnzzJFpjvHnnn +dqpQQrdqQpLfqcGSdggQdgRMmwHBMMBVNRNDFFBDBgNt +vTzsnZCnlCnshbPlvZJbBzVmmVRDNwtHFBwMDVBR +lJCshjTJbVqfVdjjjG +WlLCJlHLcZcJWcWZJnLHnPqlFtSthTnFNThVtNhVhvNVzVtF +QfbgRsspfDRsgfjqqRRpDbSNSTFzBbTbhttVBhVNBzzT +fwgfRdpdfQDqgPHHZJZCcdGddH +sbrbmVmfddzJntZZtwtMMf +PvhwPRlvvWhFvSRhpFMMJGMFppnBTBGJ +RPlCCLDPDClwHbrdzsdNLzgs +HZgqtgbqRZvzwzCh +BFqmGfrNLQfhzJWBhRJwJR +LFqFQjrcrcqFNMmMdHggntDPMnsDbn +NmWmPblGnnTTNlFGPmNWfwdchdlHdBdwcfCfZppZ +rzqzRjgVrJrzzcFdqdCBFBhZhH +VDRsRMjRJJrQsJPTGFNvsbnsnLGm +nrbrBLTffjNRzGQSJHJQGT +tcZqMcppCmHRQPGGCG +pMDcZhpgcpFDfrwNDDrLVjGj +LWlmlmWqvrBMWWBlmjLThBrfPJZfZZCwPCJJwPCTcggCsd +pSbRHbzpHDVFRQRfPdfnZswgcJcppp +SzRNGbzSWNPLWqLv +vqslblpspsvqBFSqcrrZZDdTfFPHccrf +GWRhWmjwhRcQdCDrPjDP +mcWLVnnWJgGRzVSsVSpSSptNpMvb +wHTPfdTvHlPHGpdvvTddGfcJLLWWwWWcCWrqrVMWCVLL +zhsSNZhnshNSnvZmvsCWWSLrVMcrSCLWJcrq +snDnshmNsjnTdHPfDGvdDT +CfrnFFMnnsRNrNCwFCrdssgqgqvVZvZqlTWBNWZqlJBW +htDhDLhwPWWBqTghgB +DPLPzHDtSPStjLGLtzSMwbdMdnCHrRdCFsmfnR +nBNWCvJmVPNnCPNDJWbtmSwqTttcQsSqtqTjQQ +pMflzLlffRRMRdFlflpLddGdsTjwHqzcvwTqtsStQQjtwwsQ +ZhGlphlpvvLLfFGvMLhfrfWNJNNPVPbnPhnDgDbDDNbJ +ZCpCmVlZvlpBBwvvMCrJhrfhMfjjWMSG +qhstFzFFqzHGzNfSMJSGzM +QnHRPRgRQPtPhtnDsqsbDQPBlTcpBwmVmTvbwdwBTVZVpl +PHmqHdddqBWMmTvMvTGMBWPdwhssnnHlhgsNwhwNHQzwrswh +cSbVcDLtbfLSFzhlhJswgtrsww +bSLlFLFFLDZVLpZVjFLdPMdBBqGGPmmqWGdGjM +FQCnQwFRbnrSfgQgwFRCnswmPLpMppPdMMllpLMptMLldPSZ +cJhhJcJVBJjhfHDvJqThvVDcpdGGqdZGdlltpqWdMqpdGWtG +HhzTjJBzJTvNJHvzvvNBzBFnFCNCbCwrbnRbgRwfwQsg +jRzDgbDDQDgVqqDGsjttNdwqNJZNwNdTWrpB +MHvvvlSHFllMhhMrpWBJtlWdpJrTwZ +mFcFFHmCmtcvfvFFHHLDGnRVzjDgnmgmnzGgGg +JJhDpDdmsJJdgmhrpPjGjFLPPSNpjL +WbznbRGnPfrfRSrN +WqGnnVGVMGHtWTCgJvZHggBggZCg +wlrPQtZQvwrzlvNfZLMZBjbbqjqLbSBjTg +PGJDVdsdhsPVPjbTcLcGLgjqbM +VPDRHWRdsRQvpfmmlw +pvTZTSpTZvGGphNvvbDpdrMqrjlWdPqqjWdldNrd +gmmJmsQfJgcRQJQJJncVQjMWllSnqljqBlPPjPHHHH +QVJQRVcwmJcchwpSZLwGbSZZ +zjrDMWcjDzQjDlWrnqqRBRNhBJRBhBJqnf +TTGPPdgGLwdHGwGPTgLbbvhHtRRNRRSfchqRvSqHRJ +TZTccPpdZwPQjllsspjVzD +jHLHhHFRjhcblDRRWbWTdtppLTntTnMmGLMvTp +BBQBgBBCrrgqJqTtMZMpngdtpvpG +QJJJQrsVsQQfQVPCNqsNSjHdhhdRHDNHFHFclh +RbCLnvdtnLRLRbmLPpHdQCvmNJpJSZSJlgDzglGlzcclcDGD +qBBwMjfsFMjsMbfWbwjlzDZlcWclJczgNDGNDl +wqjhrwwhhCvbQPrRnC +vpWDDDWZQQNGllwHlwWVGj +LCPdqdcdtsvdsCtsddvmVrVjjrBwHlmswmBnmw +fLfvSgvMfdCPqzZNThfNNpTJJQ +CVVVLbNVmGNQbGbGHHbHbvdwgQlwJDTFgJQdDZDJFD +ssWBsBWrjSzWrPtBjnSCTwvFZlDjwZDdgwTDwggv +nntPBqBrPsBfnCRCBWzCVcGVHMLNcbHLNmHqGphp +sbbwwzdsbqQQbQnnNbPNGbznHHRdLTggMVHFVvRZTRVRHMZF +mWffDWfflBpfmcWjWrrJVvgRLlMZVVhMFFTlHhMM +rJJCctmjcfvzsqsqbtbqPP +HGWjHWzVctQVcJVtjvRsvLTddqDDDsjRLg +bbMnlNChZQLZhdDs +SMMMMMMNmMllSlrmCczGcVzBcGWFBQGcrt +VwQlqcLfdLGqdqDjjgZrjZBdttjd +zSPPPJzJGjJjZrCBDt +WMTMsTWsccsvGGwH +hZvbQrjTTZjZcjWNrjnQrcTRpGMqcRfRRGzHfHfpfRMqRz +mDJlFmwCVVwbCVbPBRLMMLpRLwRLHqpR +gsCmgJsPDCtCVlvbhgQjhgQbnQbd +fSgbhhGPGJGhRDmlhhHcHDBH +LsMwQWFswsQMsQMvjslcBcDldBTWfDcHRRdl +ZpVFwLQwVLQvCVsMjrJbbCNPbzSJtPbPPf +VDzWMCpfCcCRDzqDzqNnvLZnfntHQnPPLQlt +sJmdbTBdmmGhFhhbJNNQlJnQlQLHPZNn +sdwmwsdrmMRpDRMLcw +JpWmSWpCnCbJBZHZVldbdfZf +rgdrgNdrjgNPrMjwTssrPdfDZqsVfQHDFlQDDHQVsZfB +TRPdNNLgjNwrRTrJpppzCmzmCLSnvS +QbtQJHQmbmfmBRvbQRzBvldqcFljsGcFdGdvsqqGls +ChCPWhDhWZWJVnZpCNChhVDcMcDdcdgGscjgFjGFlsjjGq +WZNTWNhNZfJJbTJTmR +CHGCHFcZvCrchrZrhsVtsBQjMstfZMMBgg +NNqwDLmDjJgQBmVQ +wdWLLTgWRTWcCcbrHCHhGW +bTZZvNjNjLgTCHcWhccfhWJdhvnc +mnFFmPGSwRPShzVPPWPdhhzr +FRtBFGBMFQFttRwtZgTjCTnQNbNLjTCH +bJSqrSpDJbSNbFjSFCfPWGcwGWPrcTCfwr +tRtLhDsvhQZlHRhRtQQnCnCcdwCPwTwdGcGP +HsHvsmBZvmvsmBhHvLssVqDSNgFMDzgbbDVJzbpMVq +nSSDHRRRQRBCLCQC +qGmfPzGmGlrrrpfrqlzrJtLvBlhQbSCvbtCtlFhLFC +zzpmqqJJVVfJfPfMpfdHNndsNwDSMSDDNcsc +CscQsVMhCsMsMHhhVthtwmgZNRqzWLBRLRLmBWmZWBND +JQJdddrjrLqBgDBq +QbFlTffpMbMnsPCh +gDdbVbVDddDfVfWQfBRLQZsZLRQQ +FCCTrGCMStwGHTtTWLQhLZrlRssRhRhp +FSHqtFTmFwmCsSwGTHtMTSdjjcdnVddgzmbVmjmndbbD +JtBBMcLWLdfFLhMttcWWhfWLrTRGFsbwTmRGwmwbbCTGGsbD +PzQpSQQQvzVvpzHqjvNvQSvGRmmTDVRDmsGsRGsrcDcDGC +cQPHSPvPvZHqcZjzpZjnZNtWlLdtldJWfnfhlJJtLdMg +nPPssTBnMJPdtHPVHtRhpv +bSSgGFWDgWwDFFlmWlcShqdpRqpVcHvvnqpvpRHd +bGFnGljgSsjBCTBszz \ No newline at end of file diff --git a/2022/day-03/solution.test.ts b/2022/day-03/solution.test.ts new file mode 100644 index 0000000..5c7e67d --- /dev/null +++ b/2022/day-03/solution.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(7746); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(2604); +}) diff --git a/2022/day-03/solution.ts b/2022/day-03/solution.ts new file mode 100644 index 0000000..c9bad44 --- /dev/null +++ b/2022/day-03/solution.ts @@ -0,0 +1,46 @@ +// index of each item = the priority (_ to skip 0) +const itemPriorities = '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + +const solvePart1 = (input: string): number => { + const rucksacks = input.split('\n'); + + let prioritiesSum = 0; + + for (const rucksack of rucksacks) { + const itemsInFirstComp = rucksack.slice(0, rucksack.length / 2); + + for (let i = rucksack.length / 2; i < rucksack.length; i++) { + if (itemsInFirstComp.includes(rucksack[i])) { + prioritiesSum += itemPriorities.indexOf(rucksack[i]); + break; + } + } + } + + return prioritiesSum; +}; + +const solvePart2 = (input: string): number => { + const rucksacks = input.split('\n'); + + let prioritiesSum = 0; + + // iterate over groups of 3 + + for (let i = 0; i < rucksacks.length - 2; i += 3) { + const rucksackA = rucksacks[i]; + const rucksackB = rucksacks[i + 1]; + const rucksackC = rucksacks[i + 2]; + + for (const item of rucksackC) { + if (rucksackA.includes(item) && rucksackB.includes(item)) { + prioritiesSum += itemPriorities.indexOf(item); + break; + } + } + } + + return prioritiesSum; +}; + +export { solvePart1, solvePart2 }; \ No newline at end of file diff --git a/2022/day-04/input.txt b/2022/day-04/input.txt new file mode 100644 index 0000000..62f6214 --- /dev/null +++ b/2022/day-04/input.txt @@ -0,0 +1,1000 @@ +24-66,23-25 +3-3,2-80 +14-80,13-20 +39-78,40-40 +36-90,89-90 +51-94,50-50 +10-72,10-98 +54-81,2-90 +27-84,27-85 +21-57,21-57 +6-55,4-5 +80-87,87-90 +23-71,22-90 +24-37,2-36 +79-91,78-91 +75-92,91-93 +23-80,23-81 +67-94,68-94 +79-85,79-81 +40-88,39-89 +15-75,14-76 +18-77,34-78 +2-99,4-93 +1-74,15-75 +39-82,39-81 +19-91,18-84 +56-87,57-86 +15-72,14-71 +37-88,36-87 +21-24,18-23 +34-83,34-34 +20-95,94-95 +27-75,26-80 +91-93,27-92 +55-66,56-62 +29-31,30-89 +85-95,89-99 +1-2,1-3 +63-64,13-64 +66-95,30-86 +2-73,3-74 +25-99,6-25 +10-28,28-87 +10-42,9-43 +12-46,46-75 +91-97,91-96 +46-59,46-59 +34-35,5-34 +27-93,93-93 +4-12,21-97 +7-65,5-8 +42-63,2-62 +70-76,64-75 +1-95,1-94 +12-30,13-30 +3-99,2-99 +46-60,58-60 +1-94,93-98 +7-98,8-98 +7-51,8-81 +39-84,40-85 +43-84,8-84 +10-93,11-93 +3-63,2-47 +18-87,18-18 +77-96,95-97 +2-99,1-99 +3-45,2-45 +19-99,8-97 +7-98,8-60 +3-94,2-2 +51-71,21-51 +28-98,10-27 +13-96,13-97 +4-99,1-1 +3-93,93-97 +13-13,14-98 +16-38,17-17 +16-46,16-46 +7-63,4-8 +18-85,13-19 +17-21,18-21 +7-74,8-73 +5-77,4-6 +11-18,1-18 +3-25,4-4 +2-96,2-93 +19-38,18-39 +11-45,10-10 +20-20,21-83 +2-97,97-97 +81-81,2-80 +5-82,58-59 +47-51,4-47 +89-93,40-89 +19-29,18-84 +18-36,16-18 +41-55,47-47 +6-34,7-33 +5-82,6-81 +6-19,18-27 +42-55,43-55 +1-99,2-71 +45-94,45-45 +2-88,1-88 +15-35,14-36 +17-36,10-25 +20-96,84-98 +81-87,81-81 +85-87,85-86 +34-74,73-74 +17-97,16-98 +11-50,12-51 +2-99,3-3 +79-90,79-91 +89-99,1-89 +87-93,72-93 +31-52,30-96 +75-84,45-83 +81-96,81-96 +84-85,24-85 +36-60,35-36 +11-91,10-91 +18-19,19-62 +50-52,50-54 +59-86,52-86 +61-65,70-70 +28-96,58-99 +10-46,46-46 +10-10,10-25 +17-72,18-18 +58-77,34-59 +3-5,5-34 +14-14,14-83 +5-88,6-14 +2-70,3-69 +42-79,48-80 +26-48,26-27 +15-84,14-85 +82-83,33-76 +14-34,5-33 +27-76,26-26 +3-88,2-2 +19-58,20-57 +26-79,25-89 +94-95,13-94 +35-77,35-78 +63-99,69-99 +18-26,27-99 +1-76,76-77 +37-44,22-44 +3-64,3-89 +54-86,55-85 +92-92,92-95 +26-38,26-38 +62-81,19-80 +20-63,8-65 +46-79,46-80 +35-71,70-72 +12-81,11-11 +34-69,18-77 +1-84,2-2 +19-24,18-21 +8-90,89-91 +12-64,64-65 +18-97,17-19 +93-93,5-93 +34-46,34-46 +14-82,13-81 +32-46,46-47 +1-8,9-97 +3-4,3-54 +85-87,69-86 +12-90,12-91 +7-11,10-33 +19-34,18-24 +36-63,26-62 +4-98,6-98 +80-96,80-81 +10-11,10-34 +21-69,8-70 +6-80,5-81 +14-92,3-15 +23-40,16-39 +8-66,20-66 +12-79,12-13 +14-61,15-52 +10-29,10-29 +36-37,36-89 +46-48,18-47 +24-98,23-25 +81-96,13-81 +6-88,1-89 +58-76,57-75 +56-76,57-75 +1-84,1-1 +1-20,2-20 +38-98,38-99 +33-73,32-73 +41-95,40-94 +29-44,28-44 +68-86,67-69 +1-66,1-2 +12-28,13-90 +28-74,19-29 +48-51,51-65 +11-64,11-64 +74-74,66-74 +2-5,5-87 +69-69,4-69 +21-51,51-56 +51-83,13-83 +12-99,5-6 +3-91,4-90 +3-55,8-36 +12-44,36-45 +6-86,5-87 +9-18,8-16 +13-63,14-57 +3-96,4-95 +41-87,42-86 +44-62,22-48 +17-62,46-63 +62-63,63-64 +31-59,30-60 +10-78,9-79 +41-97,20-96 +18-92,18-92 +30-30,30-90 +6-80,4-79 +46-98,13-36 +7-70,7-7 +35-46,25-46 +77-77,76-76 +8-10,9-78 +4-98,5-36 +37-96,41-96 +35-68,34-88 +22-69,40-70 +13-90,12-89 +11-39,12-56 +51-82,50-81 +47-96,46-73 +95-96,2-91 +66-95,56-77 +84-84,83-85 +7-58,8-87 +6-83,5-83 +23-49,14-48 +4-97,5-96 +17-18,17-46 +15-76,93-99 +63-64,63-67 +45-46,29-45 +29-84,13-84 +95-95,95-98 +19-91,11-37 +14-19,19-94 +24-93,75-91 +52-79,78-80 +3-94,4-93 +2-99,2-3 +40-96,38-95 +23-91,23-91 +88-89,66-88 +14-92,91-92 +14-94,6-94 +21-57,36-84 +15-97,99-99 +2-98,1-99 +38-80,38-80 +12-93,29-98 +19-34,20-42 +11-70,10-71 +44-95,45-95 +53-69,54-68 +33-68,10-34 +33-35,33-34 +3-5,4-66 +57-82,56-56 +36-54,36-53 +14-15,10-15 +24-51,38-52 +16-76,72-76 +56-57,3-57 +6-89,5-90 +12-45,13-70 +36-38,37-88 +19-31,25-31 +2-2,8-96 +5-92,4-69 +9-98,8-8 +5-14,5-14 +46-99,9-46 +55-56,2-55 +7-95,7-94 +45-65,41-65 +80-81,4-80 +6-47,48-86 +25-34,35-75 +72-74,71-71 +2-94,1-3 +31-49,32-49 +20-61,19-35 +11-86,11-90 +52-78,52-53 +42-42,18-43 +2-2,4-94 +8-78,78-78 +3-49,2-50 +5-74,11-73 +17-56,16-72 +46-87,47-79 +72-80,47-51 +11-69,12-12 +2-99,3-99 +13-27,12-15 +23-95,22-96 +39-41,40-96 +74-98,73-73 +82-83,80-82 +12-79,11-32 +6-58,7-7 +3-3,3-97 +4-97,24-95 +3-80,4-75 +72-83,71-84 +20-82,21-21 +6-73,6-72 +77-77,77-97 +18-57,57-57 +53-76,46-75 +21-40,20-74 +60-65,55-64 +78-78,32-78 +22-46,42-46 +4-46,3-47 +35-39,39-40 +79-90,80-89 +36-36,37-60 +9-28,13-29 +15-85,82-85 +5-5,4-79 +17-86,9-17 +6-57,57-57 +76-88,76-88 +73-79,78-80 +52-54,2-53 +1-95,6-94 +46-91,23-99 +70-86,11-71 +19-96,18-96 +25-42,24-24 +32-88,88-94 +7-93,8-99 +5-21,5-20 +34-94,93-94 +92-93,15-92 +38-84,39-85 +79-80,7-79 +48-72,72-72 +10-92,93-98 +14-53,15-92 +7-42,7-37 +11-88,11-87 +41-65,64-65 +71-85,11-64 +21-79,79-87 +80-81,22-81 +40-79,39-41 +18-67,67-91 +11-13,12-61 +1-97,96-98 +5-66,4-4 +1-1,2-75 +15-62,16-62 +28-56,28-28 +3-3,4-79 +68-94,3-68 +8-92,7-9 +69-83,69-84 +6-90,22-90 +10-20,5-10 +21-80,20-21 +15-76,14-76 +75-75,74-83 +5-13,6-22 +39-84,83-84 +30-43,34-38 +42-98,43-97 +6-29,5-59 +62-80,63-88 +5-93,6-6 +53-64,54-64 +47-47,4-47 +62-62,59-62 +46-87,46-87 +93-95,43-55 +4-4,4-19 +86-91,48-86 +22-45,23-44 +13-38,38-93 +5-36,4-20 +27-27,27-33 +10-12,11-83 +10-93,3-93 +79-80,35-80 +64-90,53-68 +52-91,47-89 +2-66,2-3 +58-58,22-57 +7-58,5-94 +3-11,4-10 +32-38,31-39 +10-76,21-29 +15-42,15-42 +9-43,9-95 +3-56,4-57 +35-68,36-68 +55-89,56-88 +2-3,2-99 +2-97,97-99 +29-66,30-65 +5-25,4-25 +52-87,51-54 +28-64,36-66 +52-90,51-51 +95-96,33-95 +1-2,1-82 +19-32,20-31 +73-75,74-83 +73-87,87-88 +19-70,70-70 +4-93,5-13 +96-96,6-95 +10-17,10-18 +70-73,24-70 +25-25,26-76 +58-58,10-58 +5-83,4-84 +45-47,46-74 +50-67,66-68 +88-89,89-93 +15-19,16-24 +28-30,2-29 +17-19,18-77 +21-94,21-83 +23-81,81-82 +2-91,3-66 +75-94,76-94 +2-4,3-99 +19-82,82-83 +3-85,3-3 +62-74,45-61 +33-33,33-47 +66-72,66-72 +62-97,61-61 +41-74,40-75 +7-89,4-7 +56-67,55-57 +6-25,25-89 +11-11,10-14 +89-98,16-97 +18-76,18-76 +23-96,61-97 +6-15,16-68 +3-99,2-99 +22-61,9-22 +45-86,44-44 +30-46,45-46 +55-86,1-97 +21-95,20-95 +20-47,48-82 +15-47,16-80 +39-51,39-52 +9-15,9-90 +1-86,85-86 +38-38,38-79 +41-41,18-42 +7-98,87-98 +9-87,60-88 +30-87,87-88 +10-58,1-6 +5-58,5-58 +38-76,37-76 +9-82,81-82 +2-10,5-43 +50-51,2-51 +35-93,34-93 +18-75,17-75 +14-59,14-59 +27-27,28-88 +61-62,46-61 +38-74,38-51 +49-87,50-50 +39-39,38-95 +48-98,2-97 +27-29,28-92 +23-55,22-54 +30-31,29-31 +11-59,10-58 +15-84,59-85 +22-57,24-56 +17-42,6-42 +5-93,92-94 +76-89,76-90 +1-84,84-85 +36-77,13-78 +31-78,31-57 +23-89,22-90 +36-37,36-48 +41-84,34-83 +6-36,5-6 +74-91,45-92 +62-99,62-65 +3-30,4-98 +9-83,9-83 +11-93,13-94 +7-35,6-6 +36-38,37-67 +84-93,1-92 +28-57,27-56 +94-97,95-98 +41-74,40-75 +7-91,12-88 +42-97,43-96 +7-13,14-85 +58-96,4-98 +15-95,47-95 +87-90,5-87 +35-71,36-71 +27-29,29-29 +21-28,28-46 +2-13,13-99 +38-52,39-51 +12-79,61-80 +59-81,19-59 +87-88,15-87 +10-53,8-10 +4-10,2-9 +13-93,69-94 +42-61,82-83 +9-97,10-10 +9-21,8-20 +42-89,89-90 +4-86,79-87 +11-58,11-47 +83-84,14-84 +5-75,32-75 +45-97,97-97 +39-39,38-48 +44-44,43-58 +50-69,49-68 +61-87,55-86 +4-95,94-95 +47-48,47-48 +40-67,39-39 +15-68,15-69 +4-84,4-84 +98-99,1-99 +3-8,8-98 +2-97,3-97 +20-46,46-90 +25-64,43-83 +26-47,26-47 +27-28,1-28 +50-52,51-64 +76-87,91-99 +39-60,38-40 +3-99,4-99 +67-82,10-67 +45-76,46-59 +16-79,15-78 +11-63,19-62 +9-54,10-55 +4-95,96-96 +16-87,15-88 +9-30,29-88 +68-69,10-68 +51-54,52-74 +2-4,4-59 +1-96,97-99 +17-90,54-91 +25-27,26-88 +95-97,57-95 +25-33,25-25 +33-64,33-47 +32-93,33-93 +3-37,37-38 +60-80,54-79 +38-39,21-39 +9-94,94-96 +27-80,27-81 +1-74,22-75 +11-89,11-89 +7-81,82-98 +5-56,56-75 +3-3,3-90 +18-62,18-19 +28-99,29-98 +2-2,2-75 +31-86,12-65 +71-72,20-71 +73-73,56-72 +94-98,7-88 +91-91,92-92 +3-98,4-97 +2-71,70-71 +5-63,63-63 +39-81,21-81 +44-44,44-78 +64-88,15-87 +95-95,92-96 +17-32,32-94 +11-81,12-82 +86-97,85-98 +92-99,8-98 +22-70,23-23 +11-97,10-11 +72-73,61-72 +25-58,24-98 +52-65,53-55 +66-67,1-66 +8-65,53-65 +83-98,82-89 +33-79,33-79 +65-79,65-92 +7-34,8-53 +27-43,34-73 +28-77,28-77 +59-96,27-98 +7-55,19-66 +2-78,3-79 +13-13,12-81 +2-92,91-92 +2-44,1-43 +32-33,32-99 +92-93,20-93 +97-98,8-98 +15-60,16-60 +3-98,2-99 +37-37,13-37 +9-82,82-97 +23-86,22-67 +18-35,9-27 +57-73,57-58 +36-93,36-37 +15-15,15-77 +52-82,51-73 +13-22,14-96 +9-67,8-68 +6-76,7-83 +1-4,1-4 +1-95,1-90 +25-29,29-80 +77-91,39-90 +7-97,8-96 +45-77,46-88 +20-59,59-82 +64-64,63-96 +31-83,32-32 +11-96,96-97 +59-77,59-59 +47-75,47-65 +8-95,2-8 +19-81,19-81 +35-36,36-37 +83-84,83-90 +4-97,2-49 +39-96,38-97 +64-99,6-86 +29-95,29-96 +27-84,7-27 +4-63,6-62 +60-66,61-66 +58-91,90-91 +44-65,62-69 +13-24,23-61 +45-88,88-93 +62-95,95-96 +1-86,1-85 +33-33,12-33 +36-67,37-66 +11-49,48-50 +4-76,1-4 +5-84,4-53 +22-65,22-65 +12-22,13-64 +16-16,16-33 +10-97,44-98 +47-52,48-64 +58-95,59-99 +18-71,37-72 +7-79,8-79 +2-61,3-98 +67-84,83-85 +56-86,82-85 +22-97,28-98 +42-57,41-57 +23-26,11-25 +45-82,5-81 +41-43,42-79 +3-93,93-93 +60-87,59-84 +93-99,44-93 +47-95,74-95 +51-52,40-52 +11-32,12-84 +4-89,1-4 +3-93,93-94 +97-97,17-96 +12-67,11-11 +25-80,39-60 +98-99,3-98 +61-62,60-62 +24-35,34-35 +10-86,11-87 +64-66,4-90 +1-1,2-89 +15-75,46-76 +71-72,17-72 +7-9,8-91 +18-36,18-70 +3-5,4-16 +8-88,7-88 +69-85,69-69 +17-46,18-47 +8-37,37-50 +2-38,1-39 +99-99,9-99 +30-78,31-89 +51-64,52-63 +11-99,1-99 +81-82,23-81 +54-62,53-53 +80-91,24-80 +96-98,75-97 +78-78,46-78 +7-88,7-89 +1-22,1-22 +5-39,5-38 +95-95,13-96 +19-49,17-85 +7-96,6-96 +29-93,49-75 +42-76,43-75 +62-62,61-70 +36-42,37-46 +5-84,91-92 +26-95,25-27 +36-81,63-82 +17-51,18-50 +34-74,34-75 +6-53,53-86 +28-28,28-36 +6-6,6-77 +42-70,41-70 +29-92,92-93 +10-50,9-51 +90-93,80-90 +3-84,28-97 +3-3,2-74 +9-92,8-10 +58-70,58-70 +1-61,2-16 +29-85,29-69 +61-96,31-96 +30-81,12-30 +25-72,24-26 +60-96,60-96 +2-29,2-28 +27-57,26-57 +5-94,2-99 +5-15,4-19 +2-46,3-29 +39-60,38-99 +1-2,1-83 +17-86,18-87 +68-95,69-94 +31-52,8-53 +80-89,81-88 +17-57,16-56 +7-28,6-24 +35-63,63-63 +42-89,88-89 +97-98,71-98 +79-82,6-68 +8-34,34-34 +66-71,38-70 +15-65,66-71 +22-82,21-83 +9-81,10-22 +19-85,18-86 +19-19,20-70 +6-76,45-76 +1-37,36-55 +49-98,98-98 +9-88,4-10 +74-83,17-82 +30-63,22-62 +8-89,4-8 +3-87,2-16 +91-91,49-91 +2-53,53-97 +9-14,13-71 +33-98,34-99 +31-58,27-59 +22-34,34-34 +3-5,4-97 +36-93,25-31 +50-62,35-61 +43-84,43-83 +60-81,19-60 +2-90,2-89 +1-3,5-44 +5-99,8-96 +7-7,8-8 +27-39,28-80 +6-89,4-5 +44-66,11-67 +15-88,7-99 +5-44,5-6 +70-95,71-94 +2-2,2-81 +99-99,4-99 +98-99,22-98 +69-78,65-77 +46-51,45-51 +34-67,66-68 +36-74,35-75 +38-63,39-62 +22-72,39-73 +15-52,16-52 +19-98,19-97 +4-99,3-3 +2-2,3-96 +3-85,4-4 +19-91,10-20 +4-20,20-78 +2-56,6-85 +6-54,5-54 +4-65,5-65 +13-74,15-74 +78-92,79-94 +68-77,62-76 +5-75,5-75 +68-85,69-88 +62-94,21-94 +6-94,5-95 +1-3,3-61 +37-68,37-69 +4-4,5-65 +96-97,3-97 +8-96,7-7 +69-96,8-91 +87-88,8-88 +17-32,74-91 +13-93,13-93 +44-46,21-45 +37-49,49-50 +9-53,53-90 +43-51,49-49 +5-91,6-92 +12-77,12-13 +29-94,30-32 +77-78,53-77 +10-62,26-83 +44-46,45-60 +79-90,79-97 +5-89,89-89 +3-64,2-65 +58-96,73-96 +49-97,16-96 +27-49,26-50 +25-51,51-71 +45-48,46-51 +80-81,3-80 +26-30,25-25 +94-95,50-94 +65-95,63-94 +11-95,3-44 +11-97,10-10 +97-98,2-97 +46-50,53-66 +7-23,22-97 +55-85,55-85 +85-92,11-85 +98-99,5-99 +60-61,4-61 +30-31,8-30 +53-54,38-53 +2-3,4-5 +3-99,2-99 +19-85,21-66 +36-53,36-50 +70-71,24-70 +19-85,20-85 +1-84,15-86 +30-57,30-58 +78-81,77-82 +19-26,26-27 +52-73,51-72 +73-89,69-88 +2-5,4-79 +9-35,10-34 +4-60,3-61 +5-5,4-69 +98-99,16-98 +57-85,85-86 +1-81,2-80 +44-73,44-73 +90-97,68-90 +75-88,1-75 +95-98,12-95 +40-66,39-67 +3-99,4-26 +52-76,93-99 +16-30,30-66 +68-69,68-69 +19-68,9-19 +37-90,37-41 +1-94,94-94 +2-2,1-83 +12-93,2-12 +27-96,17-28 +44-46,36-67 +72-90,73-89 +20-29,21-21 +7-59,59-60 +69-74,66-74 +27-82,69-83 +12-78,12-78 +13-64,63-70 +41-60,40-40 +32-96,59-97 +1-98,1-97 +9-64,8-19 +4-4,3-97 +8-96,8-9 +5-5,4-68 +44-68,45-45 +42-67,41-71 +49-50,18-49 +1-95,83-91 +7-8,7-82 +31-76,32-75 +45-63,54-64 +92-93,84-92 +94-96,95-97 +21-61,20-62 +13-67,5-42 +15-58,16-84 +47-55,29-46 +56-65,55-57 +11-53,12-52 +1-48,48-57 +20-75,15-75 +1-95,21-95 +2-39,3-90 +4-54,24-55 +8-42,41-46 +9-97,9-98 +45-83,39-82 +23-72,22-71 +68-68,62-68 +2-96,1-1 +15-90,16-91 +25-27,26-93 +34-36,30-35 +2-65,3-64 +2-54,53-54 +39-84,38-84 +9-96,10-96 +79-80,70-76 +22-47,31-47 +13-87,12-87 +87-93,87-94 +24-44,25-94 +36-93,6-97 +8-94,28-41 +50-61,56-62 +32-74,74-75 +3-78,13-78 +99-99,23-87 +25-83,25-83 +15-15,14-20 +62-63,32-63 +36-49,35-57 +48-93,14-49 +52-71,51-53 +1-2,1-11 +22-99,98-99 +28-29,28-49 +7-8,7-81 +27-64,64-93 +13-59,14-60 +12-88,10-11 +13-79,14-50 +2-3,5-87 +18-77,18-76 \ No newline at end of file diff --git a/2022/day-04/solution.test.ts b/2022/day-04/solution.test.ts new file mode 100644 index 0000000..b93dde4 --- /dev/null +++ b/2022/day-04/solution.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(518); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(909); +}) diff --git a/2022/day-04/solution.ts b/2022/day-04/solution.ts new file mode 100644 index 0000000..3aa0336 --- /dev/null +++ b/2022/day-04/solution.ts @@ -0,0 +1,33 @@ +const solve = (input: string): [number, number] => { + const pairs = input.split('\n'); + + let fullOverlaps = 0; + let restOfOverlaps = 0; + + pairs.forEach((pair) => { + const [elf1Range, elf2Range] = pair.split(','); + + const [elf1Left, elf1Right] = elf1Range.split('-').map(Number); + const [elf2Left, elf2Right] = elf2Range.split('-').map(Number); + + if ((elf1Left >= elf2Left && elf1Right <= elf2Right) || (elf2Left >= elf1Left && elf2Right <= elf1Right)) { + fullOverlaps++; + } else if ((elf1Left >= elf2Left && elf1Left <= elf2Right) || (elf1Right >= elf2Left && elf1Right <= elf2Right)) { + restOfOverlaps++; + } + }); + + return [fullOverlaps, restOfOverlaps]; +}; + +const solvePart1 = (input: string): number => { + const [fullOverlaps] = solve(input); + return fullOverlaps; +}; + +const solvePart2 = (input: string): number => { + const [fullOverlaps, restOfOverlaps] = solve(input); + return fullOverlaps + restOfOverlaps; +}; + +export { solvePart1, solvePart2 }; \ No newline at end of file diff --git a/2022/day-05/input.txt b/2022/day-05/input.txt new file mode 100644 index 0000000..b0d475c --- /dev/null +++ b/2022/day-05/input.txt @@ -0,0 +1,512 @@ + [R] [J] [W] + [R] [N] [T] [T] [C] +[R] [P] [G] [J] [P] [T] +[Q] [C] [M] [V] [F] [F] [H] +[G] [P] [M] [S] [Z] [Z] [C] [Q] +[P] [C] [P] [Q] [J] [J] [P] [H] [Z] +[C] [T] [H] [T] [H] [P] [G] [L] [V] +[F] [W] [B] [L] [P] [D] [L] [N] [G] + 1 2 3 4 5 6 7 8 9 + +move 2 from 2 to 8 +move 2 from 1 to 6 +move 8 from 7 to 1 +move 7 from 5 to 4 +move 1 from 6 to 4 +move 1 from 6 to 3 +move 6 from 3 to 5 +move 9 from 8 to 1 +move 3 from 6 to 7 +move 14 from 4 to 1 +move 6 from 1 to 7 +move 16 from 1 to 9 +move 6 from 1 to 4 +move 1 from 8 to 6 +move 4 from 1 to 5 +move 11 from 9 to 7 +move 2 from 1 to 8 +move 1 from 6 to 7 +move 1 from 8 to 7 +move 1 from 8 to 3 +move 7 from 4 to 3 +move 14 from 7 to 6 +move 8 from 6 to 9 +move 19 from 9 to 2 +move 1 from 1 to 2 +move 2 from 9 to 7 +move 9 from 7 to 8 +move 2 from 2 to 8 +move 16 from 2 to 9 +move 4 from 8 to 2 +move 1 from 7 to 9 +move 3 from 9 to 6 +move 3 from 3 to 6 +move 11 from 9 to 2 +move 7 from 5 to 3 +move 2 from 5 to 9 +move 6 from 6 to 4 +move 1 from 6 to 4 +move 4 from 6 to 8 +move 5 from 9 to 1 +move 4 from 1 to 7 +move 3 from 2 to 6 +move 3 from 4 to 1 +move 1 from 4 to 1 +move 2 from 1 to 3 +move 4 from 3 to 7 +move 1 from 5 to 2 +move 3 from 1 to 6 +move 15 from 2 to 5 +move 3 from 6 to 3 +move 13 from 3 to 8 +move 2 from 4 to 2 +move 9 from 5 to 4 +move 2 from 2 to 5 +move 5 from 7 to 5 +move 10 from 8 to 6 +move 1 from 2 to 5 +move 10 from 4 to 6 +move 4 from 8 to 6 +move 3 from 7 to 1 +move 3 from 1 to 9 +move 1 from 2 to 1 +move 8 from 5 to 2 +move 3 from 6 to 9 +move 6 from 8 to 5 +move 6 from 9 to 2 +move 1 from 1 to 9 +move 10 from 2 to 1 +move 4 from 8 to 5 +move 10 from 5 to 9 +move 11 from 9 to 7 +move 5 from 7 to 9 +move 1 from 9 to 2 +move 3 from 2 to 9 +move 2 from 2 to 8 +move 4 from 9 to 5 +move 4 from 1 to 9 +move 5 from 5 to 2 +move 5 from 1 to 4 +move 21 from 6 to 9 +move 3 from 2 to 9 +move 2 from 8 to 1 +move 25 from 9 to 6 +move 4 from 5 to 7 +move 1 from 4 to 6 +move 6 from 6 to 4 +move 3 from 4 to 6 +move 7 from 7 to 3 +move 4 from 9 to 1 +move 3 from 7 to 8 +move 2 from 9 to 8 +move 2 from 2 to 8 +move 4 from 1 to 3 +move 9 from 6 to 2 +move 13 from 6 to 4 +move 13 from 4 to 5 +move 1 from 5 to 8 +move 2 from 2 to 3 +move 6 from 5 to 3 +move 19 from 3 to 6 +move 1 from 4 to 9 +move 2 from 8 to 1 +move 5 from 2 to 3 +move 5 from 1 to 9 +move 7 from 5 to 4 +move 1 from 8 to 3 +move 1 from 2 to 6 +move 8 from 6 to 3 +move 1 from 9 to 8 +move 11 from 4 to 2 +move 1 from 4 to 6 +move 1 from 2 to 8 +move 5 from 3 to 4 +move 4 from 9 to 6 +move 1 from 6 to 8 +move 9 from 3 to 1 +move 7 from 2 to 9 +move 1 from 2 to 6 +move 3 from 1 to 8 +move 2 from 2 to 3 +move 3 from 9 to 7 +move 3 from 4 to 7 +move 2 from 4 to 3 +move 2 from 3 to 5 +move 8 from 6 to 4 +move 6 from 8 to 6 +move 2 from 9 to 4 +move 5 from 8 to 6 +move 3 from 7 to 5 +move 1 from 5 to 8 +move 1 from 8 to 2 +move 1 from 5 to 1 +move 11 from 4 to 9 +move 2 from 6 to 3 +move 2 from 2 to 4 +move 6 from 1 to 2 +move 6 from 2 to 1 +move 3 from 7 to 3 +move 2 from 4 to 7 +move 4 from 6 to 5 +move 7 from 3 to 7 +move 5 from 9 to 6 +move 22 from 6 to 8 +move 2 from 6 to 5 +move 2 from 8 to 4 +move 14 from 8 to 7 +move 11 from 7 to 4 +move 3 from 8 to 1 +move 9 from 7 to 8 +move 10 from 1 to 4 +move 1 from 7 to 4 +move 4 from 8 to 7 +move 6 from 4 to 9 +move 7 from 4 to 1 +move 3 from 4 to 8 +move 1 from 5 to 8 +move 8 from 5 to 3 +move 4 from 3 to 9 +move 7 from 8 to 9 +move 3 from 8 to 3 +move 2 from 8 to 2 +move 7 from 9 to 1 +move 2 from 2 to 8 +move 8 from 9 to 1 +move 8 from 1 to 7 +move 7 from 1 to 5 +move 7 from 7 to 1 +move 11 from 9 to 8 +move 9 from 8 to 5 +move 2 from 8 to 5 +move 3 from 1 to 8 +move 2 from 3 to 7 +move 6 from 4 to 1 +move 6 from 1 to 6 +move 5 from 7 to 1 +move 2 from 4 to 6 +move 1 from 3 to 5 +move 4 from 7 to 4 +move 2 from 8 to 7 +move 10 from 5 to 6 +move 9 from 6 to 1 +move 8 from 1 to 6 +move 1 from 7 to 2 +move 9 from 6 to 4 +move 2 from 4 to 3 +move 3 from 8 to 1 +move 1 from 2 to 4 +move 4 from 4 to 1 +move 7 from 4 to 3 +move 3 from 3 to 2 +move 1 from 7 to 6 +move 9 from 6 to 7 +move 6 from 7 to 4 +move 2 from 7 to 2 +move 6 from 4 to 7 +move 2 from 2 to 9 +move 1 from 2 to 4 +move 1 from 7 to 4 +move 4 from 7 to 6 +move 4 from 5 to 4 +move 1 from 2 to 5 +move 1 from 7 to 5 +move 1 from 2 to 6 +move 6 from 4 to 3 +move 9 from 3 to 9 +move 4 from 6 to 2 +move 7 from 3 to 8 +move 22 from 1 to 7 +move 1 from 1 to 7 +move 2 from 8 to 3 +move 4 from 5 to 6 +move 2 from 3 to 2 +move 6 from 2 to 8 +move 3 from 8 to 6 +move 1 from 4 to 8 +move 1 from 1 to 8 +move 8 from 6 to 7 +move 7 from 8 to 9 +move 22 from 7 to 4 +move 3 from 5 to 6 +move 1 from 8 to 1 +move 2 from 8 to 2 +move 3 from 6 to 4 +move 1 from 1 to 3 +move 15 from 9 to 1 +move 5 from 1 to 5 +move 3 from 7 to 6 +move 5 from 5 to 6 +move 4 from 4 to 3 +move 6 from 6 to 9 +move 7 from 7 to 6 +move 5 from 6 to 7 +move 4 from 1 to 9 +move 3 from 7 to 4 +move 2 from 9 to 7 +move 5 from 3 to 5 +move 3 from 6 to 3 +move 5 from 4 to 6 +move 10 from 9 to 5 +move 1 from 2 to 9 +move 1 from 3 to 5 +move 1 from 2 to 9 +move 3 from 1 to 6 +move 2 from 9 to 2 +move 7 from 6 to 5 +move 15 from 4 to 9 +move 2 from 4 to 5 +move 1 from 3 to 4 +move 9 from 9 to 1 +move 1 from 9 to 2 +move 2 from 9 to 4 +move 11 from 5 to 4 +move 1 from 9 to 3 +move 1 from 6 to 8 +move 4 from 7 to 8 +move 4 from 8 to 9 +move 15 from 4 to 7 +move 1 from 6 to 7 +move 1 from 3 to 7 +move 6 from 9 to 6 +move 1 from 3 to 7 +move 1 from 2 to 1 +move 1 from 9 to 5 +move 3 from 6 to 1 +move 11 from 1 to 4 +move 6 from 5 to 1 +move 2 from 2 to 5 +move 1 from 5 to 7 +move 2 from 6 to 1 +move 7 from 5 to 7 +move 3 from 5 to 6 +move 4 from 6 to 1 +move 11 from 4 to 3 +move 1 from 8 to 5 +move 23 from 7 to 6 +move 18 from 6 to 9 +move 1 from 5 to 9 +move 1 from 4 to 2 +move 3 from 3 to 7 +move 3 from 3 to 8 +move 17 from 1 to 8 +move 5 from 6 to 5 +move 2 from 7 to 1 +move 20 from 8 to 2 +move 4 from 7 to 2 +move 3 from 9 to 5 +move 7 from 9 to 7 +move 6 from 9 to 2 +move 1 from 1 to 8 +move 3 from 9 to 4 +move 7 from 5 to 2 +move 6 from 7 to 1 +move 1 from 1 to 8 +move 3 from 2 to 6 +move 1 from 7 to 6 +move 2 from 8 to 9 +move 35 from 2 to 4 +move 3 from 3 to 2 +move 1 from 5 to 7 +move 2 from 3 to 9 +move 3 from 1 to 6 +move 2 from 2 to 1 +move 32 from 4 to 7 +move 3 from 4 to 8 +move 3 from 9 to 5 +move 1 from 1 to 2 +move 21 from 7 to 5 +move 2 from 2 to 1 +move 3 from 1 to 2 +move 15 from 5 to 1 +move 3 from 6 to 7 +move 3 from 4 to 6 +move 3 from 8 to 5 +move 1 from 9 to 3 +move 8 from 7 to 2 +move 6 from 5 to 2 +move 9 from 1 to 6 +move 4 from 7 to 1 +move 2 from 5 to 4 +move 2 from 4 to 3 +move 3 from 5 to 4 +move 17 from 2 to 7 +move 3 from 3 to 5 +move 2 from 4 to 8 +move 1 from 4 to 3 +move 5 from 7 to 9 +move 1 from 3 to 6 +move 4 from 1 to 7 +move 4 from 6 to 7 +move 2 from 5 to 2 +move 1 from 1 to 3 +move 10 from 6 to 4 +move 1 from 3 to 7 +move 20 from 7 to 8 +move 8 from 4 to 8 +move 1 from 2 to 8 +move 4 from 9 to 1 +move 3 from 7 to 4 +move 2 from 4 to 9 +move 2 from 6 to 3 +move 1 from 2 to 8 +move 1 from 7 to 6 +move 1 from 9 to 5 +move 3 from 5 to 9 +move 4 from 9 to 2 +move 1 from 4 to 5 +move 1 from 5 to 3 +move 3 from 2 to 4 +move 1 from 9 to 7 +move 1 from 2 to 1 +move 1 from 7 to 1 +move 11 from 1 to 2 +move 3 from 1 to 7 +move 25 from 8 to 5 +move 1 from 6 to 3 +move 1 from 6 to 2 +move 7 from 8 to 2 +move 9 from 2 to 8 +move 2 from 4 to 7 +move 2 from 5 to 7 +move 2 from 5 to 2 +move 5 from 5 to 1 +move 7 from 5 to 1 +move 2 from 4 to 9 +move 3 from 5 to 6 +move 1 from 1 to 8 +move 1 from 5 to 6 +move 1 from 4 to 7 +move 1 from 9 to 2 +move 3 from 5 to 2 +move 2 from 6 to 9 +move 3 from 9 to 8 +move 1 from 5 to 4 +move 3 from 3 to 9 +move 10 from 1 to 5 +move 4 from 2 to 8 +move 2 from 6 to 1 +move 3 from 9 to 7 +move 1 from 1 to 9 +move 1 from 4 to 3 +move 1 from 9 to 2 +move 9 from 8 to 2 +move 2 from 3 to 7 +move 2 from 7 to 6 +move 3 from 5 to 6 +move 4 from 8 to 6 +move 4 from 8 to 3 +move 4 from 3 to 2 +move 4 from 6 to 8 +move 1 from 7 to 9 +move 2 from 1 to 8 +move 2 from 8 to 3 +move 1 from 9 to 2 +move 13 from 2 to 4 +move 6 from 5 to 7 +move 2 from 5 to 7 +move 10 from 2 to 4 +move 11 from 7 to 8 +move 1 from 6 to 4 +move 4 from 6 to 7 +move 24 from 4 to 9 +move 11 from 7 to 4 +move 1 from 3 to 8 +move 1 from 3 to 5 +move 4 from 4 to 2 +move 5 from 4 to 2 +move 9 from 2 to 5 +move 4 from 9 to 5 +move 1 from 5 to 1 +move 2 from 5 to 7 +move 2 from 2 to 5 +move 1 from 1 to 7 +move 2 from 2 to 3 +move 18 from 9 to 6 +move 9 from 8 to 1 +move 2 from 9 to 5 +move 5 from 1 to 8 +move 2 from 8 to 7 +move 4 from 8 to 4 +move 5 from 8 to 7 +move 10 from 5 to 1 +move 10 from 7 to 4 +move 4 from 5 to 8 +move 14 from 1 to 9 +move 6 from 9 to 8 +move 1 from 5 to 1 +move 12 from 6 to 9 +move 4 from 6 to 8 +move 11 from 8 to 5 +move 1 from 6 to 1 +move 19 from 9 to 7 +move 2 from 3 to 5 +move 13 from 7 to 5 +move 3 from 7 to 1 +move 4 from 8 to 9 +move 2 from 7 to 6 +move 7 from 4 to 8 +move 5 from 8 to 1 +move 1 from 1 to 3 +move 1 from 7 to 2 +move 6 from 1 to 6 +move 1 from 2 to 5 +move 1 from 8 to 1 +move 1 from 8 to 2 +move 2 from 4 to 8 +move 5 from 6 to 1 +move 2 from 4 to 7 +move 2 from 9 to 6 +move 1 from 6 to 5 +move 4 from 6 to 2 +move 1 from 9 to 5 +move 2 from 4 to 5 +move 4 from 2 to 4 +move 2 from 8 to 3 +move 3 from 3 to 2 +move 4 from 1 to 2 +move 2 from 4 to 7 +move 4 from 2 to 3 +move 4 from 1 to 2 +move 13 from 5 to 1 +move 1 from 6 to 2 +move 1 from 1 to 8 +move 15 from 5 to 2 +move 4 from 3 to 1 +move 5 from 4 to 3 +move 1 from 3 to 6 +move 1 from 8 to 7 +move 1 from 9 to 8 +move 1 from 7 to 8 +move 3 from 3 to 2 +move 1 from 8 to 2 +move 1 from 3 to 7 +move 13 from 1 to 4 +move 3 from 5 to 3 +move 1 from 1 to 2 +move 1 from 8 to 5 +move 5 from 7 to 2 +move 1 from 6 to 5 +move 2 from 3 to 4 +move 10 from 2 to 5 +move 1 from 9 to 5 +move 3 from 1 to 8 +move 3 from 8 to 3 +move 11 from 4 to 5 +move 12 from 2 to 8 +move 4 from 4 to 7 +move 10 from 8 to 5 +move 2 from 8 to 1 +move 1 from 7 to 3 +move 1 from 7 to 9 +move 5 from 3 to 7 +move 1 from 9 to 4 +move 7 from 7 to 6 +move 13 from 5 to 8 +move 6 from 6 to 7 +move 5 from 7 to 4 +move 1 from 6 to 4 +move 2 from 4 to 9 +move 1 from 7 to 9 +move 3 from 4 to 3 +move 1 from 3 to 6 +move 4 from 5 to 7 \ No newline at end of file diff --git a/2022/day-05/solution.test.ts b/2022/day-05/solution.test.ts new file mode 100644 index 0000000..4442217 --- /dev/null +++ b/2022/day-05/solution.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual("DHBJQJCCW"); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual("WJVRLSJJT"); +}) diff --git a/2022/day-05/solution.ts b/2022/day-05/solution.ts new file mode 100644 index 0000000..a4fd2c5 --- /dev/null +++ b/2022/day-05/solution.ts @@ -0,0 +1,113 @@ +const solve = (input: string, crane: 'CrateMover 9000' | 'CrateMover 9001'): string => { + const [stacks, commands] = input.split('\n\n'); + + // -- parse initial crates layout -- + + const rows = stacks.split('\n'); + + const stacksMap = new Map(); // stackId -> crates + + // 1. add stacks to stacksMap + + const stackIds = rows[rows.length - 1].trim().split(' '); // exactly 3 spaces between IDs + + for (const stackId of stackIds) { + stacksMap.set(stackId, []); + } + + // 2. fill stacks with crates + + for (let i = 0; i < rows.length - 1; i++) { + for (const { 1: crate, index } of rows[i].matchAll(/\[(.)]/g)) { + if (index !== undefined) { + const stackId = (Math.floor(index / 4) + 1).toString(); + const stack = stacksMap.get(stackId); + + if (stack === undefined) { + throw new Error(`Can't locate stack by id: ${stackId}`); + } + + stack.unshift(crate); + } + } + } + + // -- parse and execute commands -- + + commands.split('\n').forEach((command) => { + // 1. parse a command + + const matches = /move (?\d*) from (?\d*) to (?\d*)/g.exec(command); + + if (matches === null || matches.groups === undefined) { + throw new Error(`Can't parse command: ${command}`); + } + + const cratesCount = Number(matches.groups.count); + const { fromStackId, toStackId } = matches.groups; + + // 2. get source and target stacks + + const fromStack = stacksMap.get(fromStackId); + + if (!fromStack) { + throw new Error(`Can't locate stack by id: ${fromStackId}`); + } + + const toStack = stacksMap.get(toStackId); + + if (!toStack) { + throw new Error(`Can't locate stack by id: ${toStackId}`); + } + + // 3. move crates + + if (crane === 'CrateMover 9000') { + for (let i = 0; i < cratesCount; i++) { + const crate = fromStack.pop(); + + if (!crate) { + throw new Error(`Not enough crates in the stack ${fromStackId}. Expected ${cratesCount}, found ${i + 1}`); + } + + toStack.push(crate); + } + } else if (crane === 'CrateMover 9001') { + const cratesToMove = []; // CrateMover 9001 picks up all crates first + + for (let i = 0; i < cratesCount; i++) { + const crate = fromStack.pop(); + + if (!crate) { + throw new Error(`Not enough crates in the stack ${fromStackId}. Expected ${cratesCount}, found ${i + 1}`); + } + + cratesToMove.unshift(crate); + } + + toStack.push(...cratesToMove); + } else { + throw new Error(`Unsupported crane: ${crane}`); + } + }); + + // -- collect crates on top of each stack -- + + let topCrates = ''; + + for (const stack of stacksMap.values()) { + topCrates += stack.pop(); + } + + return topCrates; +}; + +const solvePart1 = (input: string): string => { + return solve(input, 'CrateMover 9000'); +}; + +const solvePart2 = (input: string): string => { + return solve(input, 'CrateMover 9001'); +}; + +export { solvePart1, solvePart2 }; \ No newline at end of file diff --git a/2022/day-06/input.txt b/2022/day-06/input.txt new file mode 100644 index 0000000..c0231b4 --- /dev/null +++ b/2022/day-06/input.txt @@ -0,0 +1 @@ +dfsfmfbbbjnbbpddfcfjcjbjwjqqbtbntnhtnncfnfpnffwpphwppvbvtvztzszfzhhnqnvnpppmzmczcmzczbznnbssbhhvghhzqzvzttjvtvcccdhccmvccgdgttghthppwlwqlwwcswspsfsdfddhwwzlwzwttlglttsjjthhgcgfcfhfhtftrffwcfcsfccnntmmpvpgpfgfsgfflgfgmffbmmqsmqmmcqqmjjzczwczzpjzzgtgnnqqvdqvqllbttftgtztcztttlslrslrlfldljlwjjnvjjmrrhdrhhflhffgnfnjffmvmvjjspsvvrcchhgngwwdwbwwfhwffmggbsgspsjsfjjdwwbtbdtbdbgdbbbzhzvhhwpwlwfwfswwrgggmggssfwwdrwrccssjttltrrnggdbggvzzzrfzfwzfffnfnmnnzmnznpzzdtzdttbvvgffmnfmfmbbqppcgpgtgpgggcwwlpplslbslblhlmlfmlmldmmjhjjgllglhlssswcssprrqrjrhrvrffpfnpfnppzgztgtdgtdggftgftggqrgrnnqpnpgnpnggsjsvscsnswshwswfwfwqffcrrmprrrcgrrggmnnmzmwzmwzzgzzhnzzthtggtmmdrmrbmmqwwjswwphhzvvjqjrrvzrrmssdvdlvvlhvvjggbwbrwwjqjqmmfllttvpttdvtdtddrttpltpllzrlrwlrrvcvpcphcccqwwtpwwbmmtntfntftvfvfqvvwnvwwvhhlccvrcrlclcqcvqqsvvfjjqmmfhfvvctczzlhlsslpspfsswnsnzsspzpccmssmpmbpbmmvnvsnvsszttrppvgpgnncllrvlrvllcvlvwvhvghgvvnhvvmffclfccvwcvccrwrhhrffqrqcrqqhbqhqssmzsmzsmmzrztzllmclmmbgmbbrmrgrwrgwrrgngvvtqqpbqpppgbgccsjjcmmtdmdjmmjcchvchhbccnjngjjnwjnnrvnrrsqshshszzqnngbnnrnggvwwlzwwlqwqmqdqrdqqrhqhffpgffqgqdggfjgglfglgvgjvjmjtthghrhvhgvhvnncnwcnwntwntnjjqjwwrdwddsggfddnhnsnvsstbbjddfhddhbddwbwbnbrnnrhrqhqdhdllvbbnzzbmbttpjjngnqqcffrsrnsnnhzzgllgvlvcchfhzzmzrmrggdvgvgqqwnqqpdqqvjjvnvhnhhgvhhgllhlzlclbcccwppztzhhvmvzzzsbzbppvdvdtdtdvdsdlsscnnqhnhgngghrrzprzzpddmvvhcvvprplpnlppscctzthtptspttmftmftfjjdfdjfjrfrfbfcchmhnnbddwzwvvpvrvnnslnlnhlnhlltslttqpqvvgzvzsstcstsrtrbtbbzmmzrzqrzqqnmqnnpjpttwgtgzgqqgmgnnzgzrggpbggvssqvssmhmshmssvlvlmvvnhnhddwbbllffgbffbbztthbhdhdghhrccfmfrfmmbdbfdbffzfgfrfqqptpgpjjlvvbjjdzdbbszslzlldnngwgddbmbpbwwhphnhmhhlthhgfhfvvpmvmhvmvdvsddsjtzvfmpsrwrrzgcvnnllfjmvfptwncppfmgqbfzrdpnfddghsqfmnqfwfslrsgjmqtfqwhdddsbhtbtpswcbfppcbhzfzbsqljzndcsrlhrrtstgfhhfsqqrwgnncsmstdmjvfjhqnrczlftzzzhqdzjdcdqcgfpmbqntdhzcvbtpssrvmgjwzwfvtpsrsrwrvrsjgrmzqzvbttscldsnnwzvmlztnnpdjrwvhshpdwgvhmlrnhtfccjnldlnhtfncfjjjztjmhrdqpvhggtqzwjsvwdzhdmwhsmgzjcwzqzlwbrlzsmlwhpjvflnppvrbgrsblmjpnqvgpjbpwbjgjqzwvjbgcplccjgbfwlblzfjqpwszbqbcnlbmfmqpmgspscgfdgfwnmcdzcqnjznndjcvlblszcnpflbjqltpfzhffdbwbshtpnwwlspltpcrvbdtflwbjrfnvrflqpgqtjzqwmmsdvtsmgjtrtbrzchwhpfsznjqcbrjcvwqgrcsqpvfzhrdlmnvvhjzpgpnlrmqfvcnlrlcfjblfcgvngdjfdczsrtnnwjndsfcsdlhdnbtplfnhsmmbldmsjwcblghhgqwbnjvqbqhddrmrtncvwnchsfpddzgrrtzntmwnmdwlrvnjgnzjqvptztnqnqmcjmmrhmtstgdvhffbbmphnbtsdmpmscsfdbnfnchrhhjpsfhhswfszgqfcbdbgnrqhrflpfgfgdcrjvrwbvsfmzzhvzvqzgshcqzlfcljnlgshdlhwdchhhvwlshwdrgjfbnptqqglbpcfgrmqjhqvlbzdwgnzfzlpcpjzqwhbfjljszvjdsrmfzntgnjflhnwhpfrlbpvgzmbqwzlgphmbvbfdqfgqqbhzzvrjftnwjzhlrqccwcfzvntscnbfcsrqqnvlvhszpgwtrzjrqbtslctbhtbczwtmsgwczncbjmzqvnthpwjmsbsjnfpsmghnvtqjjnjfwtnmlthrlcpqhjpnvnbbnwrdjfshwhpdwmsbngfhbhsqphlqspcgzwrgfjmqqtlsfgnvqtdgnhmdvvqzjwlhsnvjczbssrnlhwdmdthmtprjjfttfzbbswfwsvvslfnbcvprzhtcqwdrzjrnjjctqfsjrsddlhzcnstqfppjlqhvcbjbfwndwdtdfvnlwgvdvhzzrqthdhdmddfdwschmpwwrnlgsldzhgjrlmtzrnrrtqfctvbncpcjlsvnwjvhgnbshhwlqhtjghvrctlvngjgjrlgshhwscrdvzjqtfrrbssvqlcjjdljpmlzfqqnqmffpsbvgcqzqdjwczbqwjgfvpdgjglnqdshppcsqcmszhrbcpnhjnczlhwsbnfnzsczjvmftngqcvhgpgwlzbmjnmmdvdjfrcwnjrncvfstrvvqsstphmqdpwjqhzgppmgwlgjhgfwqgmjrlsvqpfqznvbqzgtngvpbpttzvngjwtrjgdnvdggzlnmpgbzhtnfnrhgwvhnpqdwfdvvftzllpqblgdglclwtwbchlvwcmmvtchlntlghztfvgfjczcbqmzgnqmrjcmqvjmjhfpztjcvclblmrctzfmsdfvfpwdcbsglgrsjqcgtcblhbtgcgjlwhhqnwhdnwzlhvphtvmlfnbfmgpnnbzqtdtzqrbhfljlwstlbscnrsvhrbrcthvzcngrttddcjqhtmsfpsgldgtsgjtprsttlssmrrfjmrddqvnqcfmphbnjtdsqvptrdzqbqfjqtnrqtjgdpbrlzrlvwcbcqbcmncfmwcpdhgpjdrdcmrqnflsqbllrqslmhsljwghnwcjwvhchcnlgppmphbqtcdfzjpcqcgsjzvmgfjgfsvmvjfqvtpffbpmhnnnrjmqhhhrhrqfqdwzdvzssslzvqhngdpszztgrvjntcpzhbfmhbpvcndsjbtnwgpmztpbrtjmfqrsvndrspdqmlsbldgghfflncszhnsttfslvwhvfnsmmhbbvjqslsjfqplndndwmbmvgchgvhzclrcnhvgbgmpctrggvqpvqvgvncmdwhpmwhzwhlgsnlnwggfbbvdvqrrsmhwzrrpgrjfshzgzjpfwjhpqmqhbjlwhwsfszlshpzprvgprlprrvlcrmbttjrpqsrdcdfwdrzbcfjpvrlrjjdwhbspqmrblvtldqdhtjtjphpqswgvqfftdgqrtjgsmthlhvlcqrwlqtthwjgrcpwcnsqtssqzpzqptrwjjdfchfmmsrsccnlvqbdmbcdjmhpgvnnlttfhggfphvbwqtcztbnsflztcfpbcpjbcmsplhjdbsmzhgnmfrhscmwmfqbljvhgllvvgqzphzbswdzlhmpcvnntczrcnqvlphhjdjjjnhfzzcjjsdlfccwvswvjfgvmlnpvjvcbpglsgtpj \ No newline at end of file diff --git a/2022/day-06/solution.test.ts b/2022/day-06/solution.test.ts new file mode 100644 index 0000000..8b34043 --- /dev/null +++ b/2022/day-06/solution.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(1647); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(2447); +}) diff --git a/2022/day-06/solution.ts b/2022/day-06/solution.ts new file mode 100644 index 0000000..3ab774a --- /dev/null +++ b/2022/day-06/solution.ts @@ -0,0 +1,30 @@ +const solve = (input: string, uniqueCount: number): number => { + const uniqueCharacters: string[] = []; // sliding window + + for (let i = 0; i < input.length; i++) { + const ch = input[i]; + + if (uniqueCharacters.includes(ch)) { // if exists -> remove all before the one (including it) and continue + const repeatedChIndex = uniqueCharacters.indexOf(ch); + uniqueCharacters.splice(0, repeatedChIndex + 1); + } + + uniqueCharacters.push(ch); + + if (uniqueCharacters.length === uniqueCount) { + return i + 1; + } + } + + throw new Error(`A marker of ${uniqueCount} unique characters not found`); +} + +const solvePart1 = (input: string): number => { + return solve(input, 4); +}; + +const solvePart2 = (input: string): number => { + return solve(input, 14); +}; + +export { solvePart1, solvePart2 }; \ No newline at end of file diff --git a/2022/day-07/input.txt b/2022/day-07/input.txt new file mode 100644 index 0000000..7ca5854 --- /dev/null +++ b/2022/day-07/input.txt @@ -0,0 +1,1010 @@ +$ cd / +$ ls +dir bsnqsfm +dir dtqvbspj +dir hhhtrws +dir ldmsq +307337 pnm.slh +dir pqcndb +dir pwtqzwv +212421 zcrfndg.cms +$ cd bsnqsfm +$ ls +179236 lccnhn +$ cd .. +$ cd dtqvbspj +$ ls +221336 gdjfp.mfp +273114 jjgpvcqv.jlq +$ cd .. +$ cd hhhtrws +$ ls +dir gcbg +dir jjgpvcqv +dir mgvdbtl +1606 mgvdbtl.ztt +dir qhv +27538 wprqtd.wph +$ cd gcbg +$ ls +dir bgcwh +dir bsnqsfm +dir jjgpvcqv +186683 lccnhn +dir rqbnd +32944 zjfs.mdf +$ cd bgcwh +$ ls +211273 nvns +$ cd .. +$ cd bsnqsfm +$ ls +dir bsnqsfm +210022 dtqvbspj +dir gpcpgfh +189603 pnm.slh +199755 rcsffv.gbt +$ cd bsnqsfm +$ ls +292856 bsnqsfm.vww +$ cd .. +$ cd gpcpgfh +$ ls +177703 jrr.jnj +$ cd .. +$ cd .. +$ cd jjgpvcqv +$ ls +233963 bsnqsfm.fnn +127603 gpcpgfh.gtw +dir jjgpvcqv +48213 jrs.bdw +172974 pnm.slh +$ cd jjgpvcqv +$ ls +dir bqnctqvn +dir bsnqsfm +dir gpcpgfh +254570 qpmnqwvl +258040 rrvjrv.zbp +$ cd bqnctqvn +$ ls +106211 bsnqsfm.pql +299973 dtqvbspj +dir nzrst +$ cd nzrst +$ ls +dir whtfvrl +$ cd whtfvrl +$ ls +12412 vzdrqs.rwt +$ cd .. +$ cd .. +$ cd .. +$ cd bsnqsfm +$ ls +293832 bggllqhj.dvb +$ cd .. +$ cd gpcpgfh +$ ls +196159 jrr.jnj +$ cd .. +$ cd .. +$ cd .. +$ cd rqbnd +$ ls +97630 ddjrjp +56378 rsb +$ cd .. +$ cd .. +$ cd jjgpvcqv +$ ls +89238 bsnqsfm.mgf +dir dvsst +dir gpcpgfh +dir jjgpvcqv +dir mhrzj +164176 pnm.slh +dir tmh +dir vmwz +$ cd dvsst +$ ls +286924 dtqvbspj +252366 hcnqdmg.zst +266562 wgfdmgmh.ptw +$ cd .. +$ cd gpcpgfh +$ ls +91199 jrs.bdw +78761 rspd.vmj +dir tbrbw +dir vvm +dir wplf +$ cd tbrbw +$ ls +195696 bjd.csj +56063 lccnhn +193863 pnm.slh +121918 qpd.dtq +209757 rcsffv.gbt +dir rmqlpvq +$ cd rmqlpvq +$ ls +dir gjgfvt +255533 lhdqqbg.fgm +68413 qltvgnrp.gfd +dir wqfcnlzq +$ cd gjgfvt +$ ls +242867 zqbdmpb +$ cd .. +$ cd wqfcnlzq +$ ls +dir vhhscrvb +$ cd vhhscrvb +$ ls +62647 rcsffv.gbt +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd vvm +$ ls +281698 dscllv.qwl +14348 rmgpnprq +$ cd .. +$ cd wplf +$ ls +44465 jjgpvcqv +248434 vpsfbjh.zsj +$ cd .. +$ cd .. +$ cd jjgpvcqv +$ ls +dir dhfcbc +dir jjgpvcqv +dir ltclg +dir ptbsgmlr +$ cd dhfcbc +$ ls +224134 lccnhn +197124 tns +$ cd .. +$ cd jjgpvcqv +$ ls +126322 jrr.jnj +280287 jrs.bdw +$ cd .. +$ cd ltclg +$ ls +dir fdfn +47501 jrr.jnj +dir mgvdbtl +24374 mgvdbtl.gll +227751 pnm.slh +286088 wvsfr +$ cd fdfn +$ ls +32987 hmt +$ cd .. +$ cd mgvdbtl +$ ls +201629 pnm.slh +246591 whtcjvh +$ cd .. +$ cd .. +$ cd ptbsgmlr +$ ls +239257 rcsffv.gbt +$ cd .. +$ cd .. +$ cd mhrzj +$ ls +279222 mgvdbtl.rzf +214102 rvjnddbr +$ cd .. +$ cd tmh +$ ls +152958 rcsffv.gbt +$ cd .. +$ cd vmwz +$ ls +131525 bsnqsfm.djc +122342 jrs.bdw +$ cd .. +$ cd .. +$ cd mgvdbtl +$ ls +24916 tcsltrml +$ cd .. +$ cd qhv +$ ls +dir hncvrlbw +153239 jwdg.wbg +$ cd hncvrlbw +$ ls +178499 clmwn.ztj +297967 jrr.jnj +30359 sntbnf.whh +$ cd .. +$ cd .. +$ cd .. +$ cd ldmsq +$ ls +dir jngnzc +dir psgrjgr +dir rgwp +dir rtsmnzm +dir wsd +$ cd jngnzc +$ ls +dir dzlcq +dir gpcpgfh +dir rlwwwngc +dir swrlvd +$ cd dzlcq +$ ls +70984 lccnhn +$ cd .. +$ cd gpcpgfh +$ ls +288159 hztmtp.fpj +$ cd .. +$ cd rlwwwngc +$ ls +173335 bsnqsfm.rtr +292723 jrr.jnj +175123 lccnhn +$ cd .. +$ cd swrlvd +$ ls +69589 fwrt +$ cd .. +$ cd .. +$ cd psgrjgr +$ ls +283186 dtqvbspj.hjw +dir fcvqsp +104691 jrs.bdw +286657 lccnhn +258194 rcsffv.gbt +$ cd fcvqsp +$ ls +209758 fzqmqlvs.hsc +$ cd .. +$ cd .. +$ cd rgwp +$ ls +11060 nwg.qcg +$ cd .. +$ cd rtsmnzm +$ ls +dir rdv +dir sdwmbsz +dir tjwht +$ cd rdv +$ ls +189234 nngdwngf.jpm +102320 qbq +$ cd .. +$ cd sdwmbsz +$ ls +dir dfzw +dir jbnsvcv +dir jjgpvcqv +140827 jjgpvcqv.cvz +$ cd dfzw +$ ls +168631 dhbfr +$ cd .. +$ cd jbnsvcv +$ ls +dir bsnqsfm +20840 lsgnjrn +83537 lvtbqlh +dir qfmj +$ cd bsnqsfm +$ ls +74345 jrr.jnj +$ cd .. +$ cd qfmj +$ ls +dir bfvwng +dir jjgpvcqv +$ cd bfvwng +$ ls +dir qzdpp +$ cd qzdpp +$ ls +dir jjgpvcqv +$ cd jjgpvcqv +$ ls +207083 rchw.lgb +$ cd .. +$ cd .. +$ cd .. +$ cd jjgpvcqv +$ ls +273755 dqmb +$ cd .. +$ cd .. +$ cd .. +$ cd jjgpvcqv +$ ls +190922 dtqvbspj.rww +59784 lccnhn +293765 mwvpgtzm +dir vtbln +dir wph +$ cd vtbln +$ ls +19558 jrs.bdw +72791 lccnhn +262803 pnm.slh +40575 sbdz +$ cd .. +$ cd wph +$ ls +174151 jrr.jnj +$ cd .. +$ cd .. +$ cd .. +$ cd tjwht +$ ls +dir mgvdbtl +136586 rcsffv.gbt +$ cd mgvdbtl +$ ls +dir gtmbf +$ cd gtmbf +$ ls +61244 jvs.gvw +269474 rcsffv.gbt +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd wsd +$ ls +275247 dtqvbspj.mjl +dir gpcpgfh +dir jdnfsqzd +88516 jrr.jnj +77096 lccnhn +dir lspqh +dir pfcmb +120975 tqzmlsz +215518 zvzhjd.ggw +$ cd gpcpgfh +$ ls +217225 lccnhn +dir qtnqzql +$ cd qtnqzql +$ ls +242800 rzfvcjvh +$ cd .. +$ cd .. +$ cd jdnfsqzd +$ ls +293894 ppdh +310316 rcsffv.gbt +$ cd .. +$ cd lspqh +$ ls +dir pspghgw +$ cd pspghgw +$ ls +105894 gpcpgfh.zht +20657 nccmrdjv.tml +241440 nrb.zrj +$ cd .. +$ cd .. +$ cd pfcmb +$ ls +64751 cfnptz +dir dmlsqf +dir dtqvbspj +288252 nfcdscgz +309178 pnm.slh +$ cd dmlsqf +$ ls +82960 czhbvv.fvc +238189 dtqvbspj.mqp +232175 lccnhn +$ cd .. +$ cd dtqvbspj +$ ls +dir fpq +99045 jrs.bdw +$ cd fpq +$ ls +98034 bnbvjg.nfq +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd pqcndb +$ ls +dir dtqvbspj +dir fvrtmdg +dir gpcpgfh +dir jjgpvcqv +dir mgvdbtl +dir pftswtnl +302354 rcsffv.gbt +dir zwph +$ cd dtqvbspj +$ ls +134541 mgvdbtl.gbr +$ cd .. +$ cd fvrtmdg +$ ls +dir gpcpgfh +231704 gpcpgfh.cgh +304822 jrr.jnj +$ cd gpcpgfh +$ ls +64193 ztqztct.ctr +$ cd .. +$ cd .. +$ cd gpcpgfh +$ ls +dir cmg +129101 hqcjs.fsf +dir jjgpvcqv +dir lmb +dir lzgc +dir nqvzvfb +dir rbh +149226 tzgn.sqv +257657 zbjzcn +$ cd cmg +$ ls +54041 bbrbwdw.mtf +233793 dtqvbspj.hjj +227618 jjgpvcqv.sls +36553 rcsffv.gbt +dir vsjs +$ cd vsjs +$ ls +199262 bsnqsfm +dir dqpqvsfn +dir ghw +73538 jrs.bdw +20726 mtfzjhc +$ cd dqpqvsfn +$ ls +91215 ppfmvz +$ cd .. +$ cd ghw +$ ls +dir bwhn +307330 jrr.jnj +25726 pnm.slh +$ cd bwhn +$ ls +dir gpcpgfh +$ cd gpcpgfh +$ ls +61301 mhchvsnp.lpv +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd jjgpvcqv +$ ls +281936 zjfrwg +$ cd .. +$ cd lmb +$ ls +dir mmqr +$ cd mmqr +$ ls +60362 mbjdfmf.wfh +$ cd .. +$ cd .. +$ cd lzgc +$ ls +211543 rcsffv.gbt +$ cd .. +$ cd nqvzvfb +$ ls +288538 lccnhn +224852 rcsffv.gbt +$ cd .. +$ cd rbh +$ ls +dir cwgc +dir gpcpgfh +dir hdmmgms +dir jwqdv +75165 mgvdbtl.rdd +dir mzt +$ cd cwgc +$ ls +254910 ghsbvcw.wgh +$ cd .. +$ cd gpcpgfh +$ ls +8668 lccnhn +145750 mcpd +265522 rcsffv.gbt +$ cd .. +$ cd hdmmgms +$ ls +dir dtqvbspj +dir gpcpgfh +203642 jrs.bdw +19047 rcsffv.gbt +215131 tbdf +dir tgqbtw +$ cd dtqvbspj +$ ls +46484 hjztnq +14784 tmmf.ggs +$ cd .. +$ cd gpcpgfh +$ ls +123990 jrs.bdw +52381 mgvdbtl +130292 rrqp.pmz +$ cd .. +$ cd tgqbtw +$ ls +dir bsnqsfm +dir nnn +$ cd bsnqsfm +$ ls +279305 mgvdbtl.mhc +$ cd .. +$ cd nnn +$ ls +181320 jjgpvcqv.zcn +$ cd .. +$ cd .. +$ cd .. +$ cd jwqdv +$ ls +306471 jjgpvcqv.jbv +$ cd .. +$ cd mzt +$ ls +159120 wcfjbfsb.vlq +$ cd .. +$ cd .. +$ cd .. +$ cd jjgpvcqv +$ ls +dir drmmqldt +dir jjgpvcqv +235210 jjnbtgh +116214 lccnhn +dir mzj +dir qcclcdd +dir rtnnjct +dir trgbfqb +$ cd drmmqldt +$ ls +dir bsnqsfm +dir gpcpgfh +dir jjgpvcqv +$ cd bsnqsfm +$ ls +200217 gpcpgfh.bmf +$ cd .. +$ cd gpcpgfh +$ ls +183548 jjgpvcqv.cgs +119367 rcsffv.gbt +$ cd .. +$ cd jjgpvcqv +$ ls +dir bzhsjfq +dir lptnp +$ cd bzhsjfq +$ ls +37713 pnm.slh +$ cd .. +$ cd lptnp +$ ls +150154 jjgpvcqv.jpt +$ cd .. +$ cd .. +$ cd .. +$ cd jjgpvcqv +$ ls +dir csvpf +$ cd csvpf +$ ls +96915 bdsqr.ptg +15712 gpcpgfh.hbw +13419 pnm.slh +23191 vhzngpw.bdp +$ cd .. +$ cd .. +$ cd mzj +$ ls +216100 fblqpwgd.rmb +$ cd .. +$ cd qcclcdd +$ ls +67202 bdz.flj +51451 dtqvbspj +dir mgvdbtl +36642 rhc.qtg +252808 slqzl.hgz +$ cd mgvdbtl +$ ls +dir dtqvbspj +$ cd dtqvbspj +$ ls +142184 pnm.slh +$ cd .. +$ cd .. +$ cd .. +$ cd rtnnjct +$ ls +dir bsnqsfm +dir dtqvbspj +dir ftlr +dir grpln +dir wtjfbzjq +$ cd bsnqsfm +$ ls +dir gbp +$ cd gbp +$ ls +dir gpcpgfh +$ cd gpcpgfh +$ ls +157447 msdhpv +$ cd .. +$ cd .. +$ cd .. +$ cd dtqvbspj +$ ls +dir fbpz +dir mgvdbtl +$ cd fbpz +$ ls +118001 zzffss.qdv +$ cd .. +$ cd mgvdbtl +$ ls +dir gtbpnhhm +dir rvjdhdvf +$ cd gtbpnhhm +$ ls +115199 mgvdbtl.zhd +307710 pbqqz.dvg +$ cd .. +$ cd rvjdhdvf +$ ls +192704 lccnhn +49374 qsv.nzw +dir vnlq +$ cd vnlq +$ ls +dir zwtwvdb +$ cd zwtwvdb +$ ls +99356 cqfppfg.cwl +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd ftlr +$ ls +dir fdm +$ cd fdm +$ ls +dir pdzbthz +$ cd pdzbthz +$ ls +dir gmpzrfv +286299 gmvg +32579 jrr.jnj +$ cd gmpzrfv +$ ls +44930 tfwc.sjb +76143 wtwpz +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd grpln +$ ls +dir thsbgczd +dir vdmt +$ cd thsbgczd +$ ls +231385 lccnhn +$ cd .. +$ cd vdmt +$ ls +dir qzwzwlpr +$ cd qzwzwlpr +$ ls +119862 qbpglhp.pmz +$ cd .. +$ cd .. +$ cd .. +$ cd wtjfbzjq +$ ls +308656 cvjrn.mmz +107735 mgvdbtl.pjv +$ cd .. +$ cd .. +$ cd trgbfqb +$ ls +59890 jrr.jnj +dir mhhbp +$ cd mhhbp +$ ls +dir bsnqsfm +dir hvjtmr +$ cd bsnqsfm +$ ls +80555 trsl.zjm +$ cd .. +$ cd hvjtmr +$ ls +78682 cgjqlrw +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd mgvdbtl +$ ls +85693 bsnqsfm.jft +dir gpcpgfh +136814 gvfz +243282 jjgpvcqv.phc +23472 mrq +dir tdnhp +188849 ztrvjzw.gjj +$ cd gpcpgfh +$ ls +dir bfjb +172798 blt +dir dtqvbspj +dir lwtj +$ cd bfjb +$ ls +9385 fhgqhrnq +$ cd .. +$ cd dtqvbspj +$ ls +dir zrtpvzh +$ cd zrtpvzh +$ ls +115949 gjcpswqv.tqg +$ cd .. +$ cd .. +$ cd lwtj +$ ls +269246 dtqvbspj.tmv +106980 jrr.jnj +20735 ldjswqtb.plp +$ cd .. +$ cd .. +$ cd tdnhp +$ ls +25816 lccnhn +$ cd .. +$ cd .. +$ cd pftswtnl +$ ls +60146 blg.vhz +dir cjzl +dir mgvdbtl +165072 mgvdbtl.cvq +dir rdhdqvm +dir swgdh +dir tgwws +101085 wtvlsbbf +139565 zfhlb.fmg +$ cd cjzl +$ ls +51636 hmwmvgg +$ cd .. +$ cd mgvdbtl +$ ls +dir dtlr +118691 pjjfwhwj +74684 rcsffv.gbt +253814 rgmn.csn +$ cd dtlr +$ ls +43065 dtqvbspj +$ cd .. +$ cd .. +$ cd rdhdqvm +$ ls +103093 bsnqsfm.rjd +5514 lccnhn +$ cd .. +$ cd swgdh +$ ls +dir dwznjd +230643 jjgpvcqv +296232 ltnlhbln.bqp +dir mgvdbtl +dir nbpdfrv +199830 rcsffv.gbt +$ cd dwznjd +$ ls +138849 jrs.bdw +240327 mgvdbtl +$ cd .. +$ cd mgvdbtl +$ ls +293382 dgrzgpr +218657 jjgpvcqv.lwt +dir pbw +125455 rcsffv.gbt +$ cd pbw +$ ls +242621 tnt.zbl +$ cd .. +$ cd .. +$ cd nbpdfrv +$ ls +297826 nfqbq.zfg +183227 qvr +148665 rcsffv.gbt +$ cd .. +$ cd .. +$ cd tgwws +$ ls +dir bhr +dir gpcpgfh +$ cd bhr +$ ls +dir wfjfvb +$ cd wfjfvb +$ ls +dir jgfbpwjh +13720 lwnz +38140 wrgb.ntr +$ cd jgfbpwjh +$ ls +207048 cbtdqb +176591 mgvdbtl +311612 nwflw.mmp +92978 pwrrz +273467 rnzzs.wrr +dir vsmgcv +$ cd vsmgcv +$ ls +dir dpdmspz +$ cd dpdmspz +$ ls +dir bsnqsfm +$ cd bsnqsfm +$ ls +197093 wzqlhhpv.lgb +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd gpcpgfh +$ ls +98093 lccnhn +208835 llplrrr.jrp +$ cd .. +$ cd .. +$ cd .. +$ cd zwph +$ ls +dir cmznd +$ cd cmznd +$ ls +dir zhhm +$ cd zhhm +$ ls +204738 rjh.qjf +$ cd .. +$ cd .. +$ cd .. +$ cd .. +$ cd pwtqzwv +$ ls +21382 gbcccm.jdc +dir hthq +dir jcsmcf +dir jjgpvcqv +262556 mgvdbtl.vrm +dir twrjfd +dir zzclqz +$ cd hthq +$ ls +dir dtqvbspj +dir mgvdbtl +dir wgcss +$ cd dtqvbspj +$ ls +35525 gpcpgfh.wpc +4808 jjgpvcqv +dir lrvftwzb +dir nzvbpcwd +$ cd lrvftwzb +$ ls +92705 rcsffv.gbt +33209 wvthcng.qlf +$ cd .. +$ cd nzvbpcwd +$ ls +dir tzvclhw +$ cd tzvclhw +$ ls +251094 gpcpgfh.bpj +$ cd .. +$ cd .. +$ cd .. +$ cd mgvdbtl +$ ls +229319 hvzhcpr.dbc +301679 lrvlp.bnl +157154 pjq +129501 sgqsjl +$ cd .. +$ cd wgcss +$ ls +37019 fpmmqmv +286113 gpcpgfh.mrm +dir jjgpvcqv +132664 lccnhn +194995 pnm.slh +$ cd jjgpvcqv +$ ls +116833 pnm.slh +$ cd .. +$ cd .. +$ cd .. +$ cd jcsmcf +$ ls +146144 jjgpvcqv.jvj +$ cd .. +$ cd jjgpvcqv +$ ls +dir gdrqbn +dir nwbqdd +$ cd gdrqbn +$ ls +149865 bsnqsfm.zjh +1714 jjgpvcqv.lwq +$ cd .. +$ cd nwbqdd +$ ls +14359 bsnqsfm +77969 dpqt.lph +285861 dtqvbspj.svq +dir gpcpgfh +156597 hhsfwctl.hng +15497 mgvdbtl +$ cd gpcpgfh +$ ls +275833 gpcpgfh.hdd +$ cd .. +$ cd .. +$ cd .. +$ cd twrjfd +$ ls +302115 gpcpgfh.zcb +dir gqlqnpvm +20848 rcsffv.gbt +$ cd gqlqnpvm +$ ls +123135 gpcpgfh +57433 gpcpgfh.zfp +$ cd .. +$ cd .. +$ cd zzclqz +$ ls +217719 vcq.flg \ No newline at end of file diff --git a/2022/day-07/solution.test.ts b/2022/day-07/solution.test.ts new file mode 100644 index 0000000..a5a83c9 --- /dev/null +++ b/2022/day-07/solution.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(1517599); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(2481982); +}) diff --git a/2022/day-07/solution.ts b/2022/day-07/solution.ts new file mode 100644 index 0000000..ea60b98 --- /dev/null +++ b/2022/day-07/solution.ts @@ -0,0 +1,191 @@ +// RegExp-s for parsing + +const CD_REGEXP = /^\$ cd (?.+)$/; +const CD_ROOT = '/'; +const CD_MOVE_OUT = '..'; + +const LS_REGEXP = /^\$ ls$/; +const LS_RESULT_DIR_REGEXP = /^dir (?.+)$/; +const LS_RESULT_FILE_REGEXP = /^(?\d+) (?.+)$/; + +// Magic numbers for Part 2 + +const TOTAL_FILE_SYSTEM_SIZE = 70_000_000; +const REQUIRED_TO_UPDATE_SIZE = 30_000_000; + +class FileNode { + public readonly name: string; + public readonly size: number; + + constructor(name: string, size: number) { + this.name = name; + this.size = size; + } +} + +class DirNode { + public readonly name: string; + public readonly dirs: DirNode[]; + public readonly files: FileNode[]; + public readonly parent: DirNode | null; // reference to the parent dir for easier cd .. + + constructor(name: string, parent: DirNode | null = null, dirs: DirNode[] = [], files: FileNode[] = []) { + this.name = name; + this.parent = parent; + this.dirs = dirs; + this.files = files; + } + + public findDir(name: string): DirNode | null { + return this.dirs.find((dir) => dir.name === name) || null; + } + + public addDir(dir: DirNode): void { + this.dirs.push(dir); + } + + public addFile(file: FileNode): void { + this.files.push(file); + } + + public get size(): number { + /** + * It's not efficient to calculate the size like that, as you will see in tree traversal aggregation. + * We could memoize calculated size, and update/invalidate it on dir update (update its own value and + * call parent.invalidateSize(), for example). But for the given input, it's good enough. + */ + + const allFileSize = this.files.reduce((total, file) => { + return total + file.size; + }, 0); + + const allDirsSize = this.dirs.reduce((total, dir) => { + return total + dir.size; + }, 0); + + return allFileSize + allDirsSize; + } +} + +/** + * Parses input and builds a file system tree + */ +const parseInput = (input: string): DirNode => { + const root = new DirNode('/'); + + let currentDir = root; // track which dir we are at + let readingLsResult = false; // track if reading `ls` result + + input.split('\n').forEach((line) => { + if (line[0] === '$') { // if a command + readingLsResult = false; // not reading ls result anymore + + if (CD_REGEXP.test(line)) { // if cd command + const matches = CD_REGEXP.exec(line); + + if (matches === null || !matches.groups?.dirName) { + throw new Error(`Can not parse cd command: ${line}`); + } + + const { dirName } = matches.groups; + + if (dirName === CD_ROOT) { + currentDir = root; + } else if (dirName === CD_MOVE_OUT) { + if (currentDir.parent === null) { + throw new Error(`Can not move out of ${currentDir.name}: ${line}`); + } + + currentDir = currentDir.parent; + } else { + const targetDir = currentDir.findDir(dirName); + + if (targetDir === null) { + throw new Error(`Can not find ${dirName} in ${currentDir.name}: ${line}`); + } + + currentDir = targetDir; + } + } else if (LS_REGEXP.test(line)) { // if ls command + readingLsResult = true; // next lines are reading ls result + } + } else if (readingLsResult) { + if (LS_RESULT_DIR_REGEXP.test(line)) { // new dir + const matches = LS_RESULT_DIR_REGEXP.exec(line); + + if (matches === null || !matches.groups?.dirName) { + throw new Error(`Can not parse ls result line: ${line}`); + } + + const { dirName } = matches.groups; + + const newDir = new DirNode(dirName, currentDir); + + currentDir.addDir(newDir); + } else if (LS_RESULT_FILE_REGEXP.test(line)) { // new file + const matches = LS_RESULT_FILE_REGEXP.exec(line); + + if (matches === null || !matches.groups?.fileName || !matches.groups?.fileSize) { + throw new Error(`Can not parse ls result line: ${line}`); + } + + const { fileSize, fileName } = matches.groups; + + const newFile = new FileNode(fileName, Number(fileSize)); + + currentDir.addFile(newFile); + } + } + }); + + return root; +} + + +const solvePart1 = (input: string): number => { + const root = parseInput(input); + + let totalSize = 0; + + // DFS + + let stack: DirNode[] = [root]; + + while (stack.length !== 0) { + const node = stack.pop()!; // ! because the node is always there + + if (node!.size <= 100000) { + totalSize += node.size; + } + + stack.push(...node.dirs); + } + + return totalSize; +}; + +const solvePart2 = (input: string): number => { + const root = parseInput(input); + + const sizeToFreeUp = REQUIRED_TO_UPDATE_SIZE - (TOTAL_FILE_SYSTEM_SIZE - root.size); + + let smallestToRemove = root.size; // root is the max + + // BFS + + let queue: DirNode[] = [root]; + + while (queue.length !== 0) { + const node = queue.shift()!; // ! because the node is always there + + if (node.size >= sizeToFreeUp) { + smallestToRemove = Math.min(smallestToRemove, node.size) + } + + queue.push(...node.dirs); + } + + return smallestToRemove; +}; + +export { solvePart1, solvePart2 }; \ No newline at end of file diff --git a/2022/day-08/input.txt b/2022/day-08/input.txt new file mode 100644 index 0000000..3001d42 --- /dev/null +++ b/2022/day-08/input.txt @@ -0,0 +1,99 @@ +333430420313204425152200622665264212245045167252605104200413164212660350624632202413410021112040303 +134032100422510245106510040264663362503422541041505357621476703420114122465165643524253354025030130 +210440124144200401002041231025015610061612057522105774716346600327132553305630102152112533024041242 +013233025442442502513652024201322435500523165612141337672674773011016503513304233064521152335042120 +011305252432552501064411033666722407647207507507162465046733615606446206134542053636654320003411012 +243023202214501634062402146610001573103776454700372701707211030076547400104323412251550200540512404 +012253133143312645661144666762653037430267574705006276313562402352550711050455115603136051241513541 +233542100202100442245031231337073750307372173356368622812112644626652722416200145424010111505415531 +113050445521502306510155606560425124341767678204475464563457405544476324177711546422100335421551051 +130312341330642365123453250761202155236155527441423565417554884760031702032102426223145121613433104 +530143503231520461205002652051677511261563711762374740277300428262470663721100666052106105145213354 +151015303344663420237540025132125454561370180385741740506056160664715223770111664734064302411202001 +514034244406063254635323474251671315666526663746817240033573000108656045541344434601625022610052020 +243154262363253554536541354003054186654045878102055585888161073638066213274671743325026010363535544 +154120103402345375743506401360683734777656123267113230466240585461121530607117743057503356131114533 +505455224133247240206564160431257714250053833782497581816130354025606255867122005077143403662520504 +433241563055247633235066320883447875386276657781137827895139991200185503683760166777605024035426130 +303666031235074150733051862308708620362115983146857284227577913250668362434852742536154264141044024 +511222166044117055516803386663311572614519912678966147915185424343732707633260441221576201346435364 +134360166233105100536433310812063681167658735195196145453391339382888328188314274546107317546511612 +523620025403415442506243437017113976271955932743366455248318611782168343828238367826356710005034553 +014143654212533674034560645259292873615816185144293735857682321366761974620115762457417172700305122 +333105652265122475614582321536546127468959745749345269543234433166487289336786316820563170617120623 +121601237502476667431600852195954252478198756563435696885982284312387934896760152481177324330131535 +513446344670703428776508215695735445332247985475848233554657523817331875769331074017245476757301446 +012251345264710602027058214811913234262454325876757887757444777969332385321984700241201345057245460 +332461240272352410086272428238633529256552789239244723226288876562681521623121465728463663000253564 +050241632437771176667281335711828626835432482452477575257825295624648638453256338282617312743052665 +320460534364211482024332384631858292847294377732562824355842225275426886973273352617364252451510462 +266231012324356276581324273442396899956952282898875358753279379896748925691919481576682154760400425 +251566121704323168579128997588889283799488966757983883789954475486796857383783125527355207013547362 +245170254224671131425381468779784773763587376849883899445985425964397253171121657364305543424605521 +343241363651032654076929887424957669374497498475354869687897566288757258268124776805646407142505401 +245235561074546607814525522575333844748378895964779738636436493832747556344467633450422573200613626 +621467001761357111428393119677926772938443995376393853338365997532477292336453235160086048160217366 +023775641054213273228832376568693489696566663398748497398659859837842294529619661172107248203627734 +113467643020563674853798174949656774647946468556996446468936764346927347556233294257603825510225301 +051772112150067612784116555244795748964966494976764476446478663548637694355969461949802873774665326 +331233366625881187249285952947585544548997559569878848947886766655686939429493965123777681254223431 +531573100137313597119916274627286959837544585968649788887976885577683473432893398693858562631240775 +054773273536345576254932477965348359857659449696548949674766533585646392228226613594760535225257520 +634743657825387116635366754892478485999446656868585575764798688597369672379597529612611500237237137 +651102700443476274786872839522556949489444557965565689748499865784355354284683261999963545702441533 +410422511344877258216478752346893586694958864569678896795749775497587467528943274138345032337425341 +673074304265406323296329836734538597845554475567958596678746854759768739593368885149598108068333526 +164263147103304418178278924224955484489949675979877868596747956467863649963887857128138635543007456 +532045787035117465515664676376447636548656879595576977999774677855856735289939791867587713667806712 +140404452768874515592229468574985653794588555889757998699874747589835947525564614257120186050531145 +626535737062375329774963856647668644846998677768989895657468468657744348329253697139398584012102340 +542125001671358961555599377429643566889856477767859887987675655559949868728345434499546123323161001 +762120151054669481822452228565333874958454877687779859759785868573886766599894442765981274505151104 +562471434368683846173563223634735557586587876899579875869878986493584743886292333767594628622775172 +734222626506039543828356435245676596966499685666977779895844487493883497384439766576599302272713402 +267177441831802248969359922326967573465467679688596788687556889843594594235859261867187578441714647 +102117327257157522217556335628537334684966957875575975895695664957459754746968515546793540724822122 +505233476882555673336484437283696496447664879799897577664966999965538753757237631528664630007177613 +172066031365473733492776338746459955449887594496989558546775496577455654236726314131630007341654314 +314412002266354633365762544569746844798457477779477686985845846857578447499935436861745481600772033 +055237658717854148961524344444377964774585475448796459485964778855656967368965165942952602115364653 +101635324187220117445419465884645869853647668548567797785599767597638684836376214415920463048311165 +617323525735135461172377579929749788439689969985978844695495846787466498442754416512973663308107726 +530710323015385832525292779264243858439684558659447696949696563673466249277668864281263486712173314 +002226007723488635329843652368236983569879555555499475484483447567969679832981393855106427002552444 +235757010870250337834974492853239769846747448878894988996873977468347779876273667633884411064437311 +221537334662832777621573374939367297734988578388657548445987535345422574756283382295070667547270175 +521462413004381720189539712492796774975667453383769536485344786668527448878163526268353212024115651 +064167050511487528145433135444328348559358573773345433397876388385483662364771941163658800310756444 +436636405027304747391412742798583342975676858784346378455554898673579853526351275216574538060506774 +566540130441706782811763156886277636247669397646566433399777965674843633877716691920750361127241155 +053372117542772170611448311472432495277284498837535486344595366632773998492323674853732413030542046 +534364447320670867339153474824374957359843939965384798895376292698497378559437674083011730747713713 +216264161444177358545356854382958565667999985377695889365464464565434283664444674351070427062510112 +364206763745554337574296145539342755237347237689765249424576387533835284249337951552318166532717320 +301321356401273810374524947234817483255967848336723823829824987424831571693585243183871374121705463 +013142075522165017716733784396332487689825356344265736822666843742955823165716761855438154413641115 +630515150411425607542463652174216633554978982572463873259338392247874837335324720668014545652155202 +455031465466436525813303414966445845648576498854883558298456269113968383196025720070233635412326555 +513541260473273275035537870749767166583572678469583476276998677949239286734633062745335042001531221 +601365053241646675287550254721413885162954529985825668299219771922524729302706116406630414253264405 +400344346330307036562615004227693316398374195415562381655134627581299617653477441607644245074524600 +210313442047552663082465608147628816371648823764493322559365352994178913344658255573614412766560553 +111352631055464137145152202878508984883298488591213254293969862555144081556414044421631665225522264 +010164431247751037435264713238223247871448917563495625643168725587551433114342107055334272403301466 +525253154605640500025274247121151664615511794958191647464479638471563708865215767367622432614243221 +414144456652451577051364610780083460325111586672621671575123547806751385176766676676633016126156340 +403125420124660622446312308556131072702464323774759977763680287787058873788251453020274036222556015 +010450420461552234703024366261462024624268728424661115870447017746132551326225623245140220643235304 +331053044132010120214026102738858112181065532060281161763064277514475458526554547622102204600502333 +530232021520613242257763671271000321860552177274506581315403280378427012530121320262015343211500552 +513451503556626221314452431160424362623172424403733615107832160275406543265725327322555342222542502 +202051420236066361423130725131562714626884368317212022283380747212427753155731701600356565400542402 +435145215102611325100662266006561366705875616488262665660460450412270343501022642555052262142035502 +334403454455503501622450035064441374653775177026475804121642120210207061757610262641220243402302545 +321311214442661462245102175522241130532337170266155071611254164127776674570166055246211562130500431 +443124503252503622414632304026653173070670661231063766052605435514223357361561150225254553205315111 +232120055124304462512532500502156531032207726437333213051406414333207241265312052356525310410451511 +202002311103141164630106023656017441203731706174163257322311073432575771525344436600220200050051342 +041004212342412120333645230362446732233342662123535575315702023322757200126221443432142400145220443 +420334452105533313552263566256611333163022717266264743363602103371464132116230560501113054442342042 \ No newline at end of file diff --git a/2022/day-08/solution.test.ts b/2022/day-08/solution.test.ts new file mode 100644 index 0000000..3894eac --- /dev/null +++ b/2022/day-08/solution.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(1546); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(519064); +}) diff --git a/2022/day-08/solution.ts b/2022/day-08/solution.ts new file mode 100644 index 0000000..1b9013d --- /dev/null +++ b/2022/day-08/solution.ts @@ -0,0 +1,138 @@ +/** + * Checks if tree (x0, y0) is visible from the outside of the treeMatrix grid (part 1) + */ +const isVisible = (treeMatrix: number[][], H: number, W: number, y0: number, x0: number): boolean => { + // if edges -> visible + + if (y0 === 0 || x0 === 0 || y0 === H - 1 || x0 === W - 1) { + return true; + } + + // check if visible from each side + + let topVisible = true; + let bottomVisible = true; + let leftVisible = true; + let rightVisible = true; + + for (let x = 0; x < x0; x++) { + if (treeMatrix[y0][x] >= treeMatrix[y0][x0]) { + leftVisible = false; + } + } + + for (let x = x0 + 1; x < W; x++) { + if (treeMatrix[y0][x] >= treeMatrix[y0][x0]) { + rightVisible = false; + } + } + + for (let y = 0; y < y0; y++) { + if (treeMatrix[y][x0] >= treeMatrix[y0][x0]) { + topVisible = false; + } + } + + for (let y = y0 + 1; y < H; y++) { + if (treeMatrix[y][x0] >= treeMatrix[y0][x0]) { + bottomVisible = false; + } + } + + // if visible from any side -> visible + + return topVisible || bottomVisible || leftVisible || rightVisible; +} + +/** + * Returns the (x0, y0) tree's scenic score (based on how many trees are visible from it) (part 2) + */ +const countVisibilityScore = (treeMatrix: number[][], H: number, W: number, y0: number, x0: number): number => { + // count how many trees visible to each side + + let topVisible = 0; + let bottomVisible = 0; + let leftVisible = 0; + let rightVisible = 0; + + for (let x = x0 - 1; x >= 0; x--) { + leftVisible++; + + if (treeMatrix[y0][x] >= treeMatrix[y0][x0]) { + break; + } + } + + for (let x = x0 + 1; x < W; x++) { + rightVisible++; + + if (treeMatrix[y0][x] >= treeMatrix[y0][x0]) { + break; + } + } + + for (let y = y0 - 1; y >= 0; y--) { + topVisible++; + + if (treeMatrix[y][x0] >= treeMatrix[y0][x0]) { + break; + } + } + + for (let y = y0 + 1; y < H; y++) { + bottomVisible++ + + if (treeMatrix[y][x0] >= treeMatrix[y0][x0]) { + break; + } + } + + // multiply to get the tree's scenic score + + return topVisible * bottomVisible * leftVisible * rightVisible; +} + +const solve = (input: string): [number, number] => { + // parse input to treeHeight[][] matrix + + const treeMatrix = input.split('\n').map((row) => { + return row.split('').map(Number); + }); + + const W = treeMatrix[0].length; + const H = treeMatrix.length; + + let totalVisibleFromOutside = 0; + let maxVisibilityScenicScore = 0; + + // for each tree, check visibility and count scenic score + + for (let y = 0; y < H; y++) { + for (let x = 0; x < W; x++) { + if (isVisible(treeMatrix, H, W, y, x)) { + totalVisibleFromOutside++; + } + + maxVisibilityScenicScore = Math.max( + maxVisibilityScenicScore, + countVisibilityScore(treeMatrix, H, W, y, x), + ); + } + } + + return [totalVisibleFromOutside, maxVisibilityScenicScore]; +}; + +const solvePart1 = (input: string): number => { + const [totalVisibleFromOutside] = solve(input); + + return totalVisibleFromOutside; +}; + +const solvePart2 = (input: string): number => { + const [_, maxVisibilityScenicScore] = solve(input); + + return maxVisibilityScenicScore; +}; + +export { solvePart1, solvePart2 }; \ No newline at end of file diff --git a/2022/day-09/input.txt b/2022/day-09/input.txt new file mode 100644 index 0000000..71ff282 --- /dev/null +++ b/2022/day-09/input.txt @@ -0,0 +1,2000 @@ +L 2 +U 2 +L 1 +D 1 +U 1 +L 2 +R 2 +D 1 +U 2 +D 1 +R 2 +U 1 +L 2 +D 2 +L 2 +R 2 +L 2 +R 1 +L 2 +D 1 +U 1 +L 2 +U 1 +D 1 +R 2 +L 1 +R 1 +L 2 +U 2 +D 2 +U 1 +D 2 +R 1 +D 1 +R 2 +L 2 +D 1 +L 1 +U 2 +R 2 +L 2 +U 2 +D 1 +U 2 +D 2 +R 1 +U 2 +L 2 +D 2 +U 2 +D 2 +L 2 +R 1 +L 2 +D 2 +U 1 +R 2 +U 2 +L 1 +D 2 +R 2 +L 2 +R 1 +L 2 +D 1 +R 2 +L 2 +R 1 +L 2 +D 1 +U 1 +L 1 +D 1 +R 2 +D 1 +L 1 +D 1 +R 1 +D 1 +U 2 +R 1 +L 1 +U 2 +L 2 +D 2 +L 1 +U 1 +D 1 +L 1 +U 1 +D 1 +U 1 +R 2 +L 2 +U 2 +R 2 +L 2 +D 2 +U 1 +L 1 +R 1 +U 2 +R 1 +D 2 +R 1 +L 2 +R 2 +U 2 +D 2 +R 1 +U 2 +L 2 +R 1 +L 2 +D 3 +L 3 +D 3 +L 3 +U 3 +D 2 +R 2 +D 3 +L 1 +R 2 +D 2 +R 2 +D 3 +U 3 +D 1 +R 2 +D 3 +L 1 +D 1 +L 1 +D 3 +R 2 +U 2 +D 3 +R 2 +U 2 +D 2 +L 2 +U 1 +R 3 +U 2 +D 3 +U 1 +R 2 +D 2 +U 2 +D 1 +R 2 +D 2 +R 3 +L 1 +R 1 +L 1 +D 2 +U 3 +R 2 +U 2 +L 1 +R 1 +U 3 +L 3 +D 2 +R 2 +L 1 +U 2 +R 3 +D 3 +U 2 +D 3 +R 2 +U 2 +D 2 +L 1 +D 3 +U 1 +L 2 +R 2 +L 2 +R 1 +L 1 +R 3 +L 2 +U 1 +D 2 +U 2 +L 2 +U 2 +L 3 +U 2 +D 3 +U 1 +L 3 +D 3 +U 2 +D 2 +L 1 +U 2 +D 2 +L 3 +D 3 +R 2 +L 1 +U 3 +L 3 +D 2 +L 2 +R 2 +D 1 +L 2 +D 1 +R 2 +L 1 +U 3 +R 2 +L 3 +R 1 +L 1 +R 3 +L 2 +R 2 +U 2 +D 4 +L 3 +U 3 +L 4 +U 2 +L 2 +U 3 +R 2 +U 4 +R 1 +U 3 +R 1 +U 4 +L 3 +R 4 +L 4 +U 3 +D 1 +R 2 +D 4 +U 1 +D 3 +R 2 +U 2 +R 1 +L 4 +R 2 +L 3 +U 4 +D 4 +R 4 +U 1 +R 2 +D 3 +U 1 +L 1 +U 3 +L 1 +R 1 +U 2 +R 4 +D 2 +U 1 +D 3 +U 4 +L 1 +U 1 +R 2 +U 4 +L 1 +R 2 +L 1 +D 4 +L 3 +R 1 +L 2 +R 1 +U 3 +R 3 +D 2 +R 2 +L 2 +D 1 +U 4 +R 2 +U 2 +L 1 +R 2 +U 3 +L 2 +D 3 +U 2 +D 3 +U 4 +D 2 +R 3 +U 1 +D 2 +R 1 +D 2 +R 3 +L 1 +D 4 +R 4 +D 4 +R 2 +D 3 +U 1 +R 2 +U 1 +L 4 +D 2 +L 2 +D 4 +L 1 +U 4 +D 3 +L 3 +U 2 +L 2 +D 1 +L 4 +R 4 +D 2 +R 3 +L 1 +U 3 +L 3 +D 5 +U 5 +D 5 +U 1 +D 1 +R 1 +U 2 +L 2 +U 3 +L 5 +D 4 +R 2 +U 2 +L 4 +U 3 +L 2 +U 3 +R 2 +D 3 +R 4 +D 5 +R 1 +D 3 +R 2 +U 2 +R 3 +U 5 +R 2 +D 1 +R 5 +L 1 +D 5 +L 5 +U 2 +D 4 +R 1 +L 3 +R 2 +U 2 +R 1 +U 5 +R 5 +D 2 +U 1 +R 4 +L 4 +D 5 +U 1 +D 1 +L 4 +D 3 +L 3 +D 5 +R 3 +U 3 +L 2 +R 5 +U 5 +R 3 +D 2 +L 2 +D 3 +R 1 +U 5 +L 1 +D 5 +R 2 +L 5 +R 4 +L 3 +D 2 +U 1 +L 4 +U 5 +L 3 +R 1 +U 3 +R 3 +U 5 +L 5 +U 5 +R 5 +L 1 +R 4 +L 2 +D 3 +U 3 +L 1 +U 5 +D 3 +U 4 +L 5 +U 3 +L 3 +D 1 +U 3 +L 4 +D 2 +R 3 +L 3 +D 4 +L 1 +D 4 +U 3 +D 4 +L 5 +R 2 +L 2 +R 4 +L 1 +U 1 +D 1 +U 1 +R 5 +U 1 +R 2 +D 3 +L 4 +D 1 +R 3 +U 3 +D 6 +U 1 +R 3 +D 1 +L 5 +D 3 +R 3 +L 2 +D 5 +R 3 +D 3 +U 5 +D 6 +U 2 +R 2 +U 3 +R 1 +U 6 +L 1 +R 1 +L 5 +R 2 +U 6 +D 3 +R 3 +D 5 +U 1 +L 4 +D 4 +L 1 +R 4 +D 5 +L 3 +R 5 +U 6 +D 4 +U 4 +D 5 +R 1 +U 1 +L 6 +R 3 +D 1 +L 2 +D 1 +L 1 +U 5 +L 4 +R 1 +L 3 +U 6 +L 1 +D 3 +L 6 +D 6 +R 2 +U 5 +D 3 +U 6 +R 5 +L 2 +U 1 +R 3 +L 5 +R 2 +L 6 +R 1 +U 1 +R 1 +D 3 +R 1 +D 1 +L 4 +D 2 +R 3 +U 2 +L 6 +U 5 +R 3 +D 4 +R 4 +D 6 +R 1 +D 5 +L 5 +R 1 +D 1 +L 3 +D 6 +R 3 +U 4 +D 6 +R 2 +L 6 +D 2 +L 1 +D 6 +L 3 +R 2 +U 3 +L 4 +R 6 +U 6 +R 1 +U 6 +D 5 +U 1 +L 6 +R 6 +D 1 +R 5 +L 1 +D 5 +R 6 +U 1 +L 5 +D 3 +R 6 +U 1 +L 3 +U 1 +R 4 +D 1 +R 2 +D 7 +U 5 +D 2 +U 6 +D 3 +U 1 +D 3 +R 4 +D 6 +R 3 +L 1 +U 1 +L 2 +R 4 +U 3 +L 3 +R 1 +D 7 +L 4 +D 2 +R 3 +L 2 +U 2 +L 1 +D 5 +U 4 +L 4 +D 7 +U 4 +D 5 +L 7 +U 6 +L 1 +U 1 +L 1 +R 6 +U 1 +D 5 +R 2 +D 4 +R 3 +D 2 +R 2 +L 5 +U 5 +R 7 +D 6 +R 1 +D 5 +R 1 +L 7 +D 7 +L 6 +D 6 +U 4 +R 3 +U 2 +R 6 +D 4 +R 6 +D 3 +L 5 +U 7 +D 2 +R 5 +D 5 +L 1 +R 1 +D 6 +L 3 +R 3 +L 1 +R 2 +D 5 +R 2 +D 1 +L 6 +D 1 +U 7 +R 6 +D 4 +U 2 +R 5 +L 7 +R 7 +D 3 +L 2 +R 7 +D 1 +R 8 +D 2 +R 3 +L 2 +R 8 +U 7 +L 8 +D 3 +U 6 +D 3 +R 8 +U 4 +L 3 +R 4 +D 5 +U 6 +R 8 +D 5 +U 4 +L 5 +D 2 +U 8 +D 6 +U 4 +L 1 +R 2 +D 4 +U 3 +L 1 +U 6 +R 6 +U 3 +L 7 +U 6 +R 3 +U 5 +R 6 +D 8 +R 6 +U 1 +R 8 +L 5 +R 5 +L 3 +R 5 +L 7 +R 3 +D 6 +R 1 +D 4 +R 5 +U 6 +R 4 +D 3 +R 4 +D 7 +R 5 +U 5 +D 2 +R 6 +U 3 +L 1 +U 4 +R 7 +U 5 +D 2 +R 3 +L 1 +U 2 +R 1 +D 7 +L 4 +R 4 +D 2 +U 8 +D 2 +L 4 +D 7 +R 6 +U 8 +R 7 +D 1 +U 4 +L 8 +D 8 +R 5 +D 2 +L 5 +D 1 +L 1 +U 4 +D 4 +L 7 +D 3 +L 8 +D 1 +R 1 +L 2 +U 7 +R 8 +D 3 +R 7 +D 1 +R 2 +U 8 +R 8 +U 2 +D 6 +U 7 +R 1 +U 8 +R 5 +D 3 +R 4 +L 2 +D 1 +L 6 +D 8 +R 1 +L 4 +U 5 +L 7 +D 5 +U 4 +L 4 +R 9 +L 9 +U 7 +L 3 +R 4 +U 2 +R 5 +D 1 +L 5 +R 7 +D 7 +L 6 +U 2 +L 6 +R 5 +D 2 +U 6 +R 3 +U 7 +D 8 +U 3 +L 3 +U 5 +D 5 +U 1 +D 6 +R 4 +U 3 +R 4 +U 1 +D 3 +R 2 +L 8 +D 6 +L 3 +U 7 +D 2 +R 9 +D 4 +L 5 +R 4 +L 8 +D 7 +R 2 +D 3 +U 5 +D 6 +R 1 +L 1 +D 5 +L 6 +U 4 +D 2 +R 5 +U 2 +R 4 +U 5 +D 7 +R 8 +D 2 +R 6 +D 4 +R 6 +L 8 +U 4 +L 3 +U 4 +L 3 +R 6 +D 4 +L 5 +D 1 +U 8 +L 8 +U 2 +L 9 +R 6 +L 1 +D 5 +L 5 +R 4 +D 3 +R 4 +L 8 +R 9 +D 2 +R 8 +D 6 +L 4 +D 2 +U 3 +R 9 +L 7 +D 9 +R 8 +U 3 +L 10 +D 10 +L 7 +R 8 +L 7 +D 7 +L 7 +D 6 +R 1 +U 10 +R 7 +U 10 +L 1 +D 7 +L 2 +D 1 +U 10 +D 5 +L 1 +U 9 +L 10 +U 6 +L 4 +U 10 +R 7 +L 10 +U 8 +D 6 +L 4 +D 9 +L 7 +R 5 +D 3 +L 2 +R 9 +U 4 +D 2 +L 6 +R 4 +L 3 +R 1 +L 2 +U 8 +L 7 +U 4 +D 8 +R 9 +L 4 +R 1 +U 6 +L 5 +R 10 +D 10 +U 2 +R 8 +U 1 +R 4 +D 10 +R 2 +L 2 +D 3 +U 8 +L 7 +D 9 +L 8 +D 7 +R 9 +L 6 +U 8 +D 7 +U 6 +D 5 +R 3 +L 7 +U 4 +R 7 +D 9 +R 9 +D 5 +L 6 +U 2 +R 7 +U 7 +D 3 +R 10 +L 10 +R 1 +D 10 +U 2 +R 3 +U 2 +L 4 +R 5 +L 1 +U 6 +R 1 +U 6 +R 10 +L 2 +D 8 +U 3 +L 8 +U 4 +L 8 +U 10 +D 7 +R 4 +U 10 +L 3 +D 7 +L 1 +R 5 +L 1 +U 5 +L 1 +D 1 +R 7 +D 3 +L 3 +R 2 +U 7 +L 11 +R 5 +D 8 +R 1 +U 3 +R 1 +L 11 +R 4 +U 1 +D 9 +R 7 +D 8 +R 11 +D 3 +U 1 +L 7 +R 5 +L 5 +R 1 +D 4 +R 6 +D 8 +R 3 +L 10 +R 10 +D 4 +L 7 +R 7 +L 9 +D 11 +L 1 +D 1 +L 10 +U 6 +L 8 +R 11 +D 10 +L 4 +U 5 +D 8 +R 8 +L 3 +U 4 +R 4 +U 7 +R 7 +D 8 +U 6 +R 11 +L 8 +D 10 +R 7 +D 8 +L 11 +U 3 +D 7 +U 2 +R 5 +L 6 +U 10 +R 4 +L 9 +U 7 +D 7 +R 7 +D 6 +R 10 +U 4 +L 3 +D 4 +R 8 +L 4 +R 3 +U 2 +R 4 +U 2 +L 6 +D 5 +R 3 +D 1 +U 4 +L 6 +U 10 +D 9 +L 6 +U 4 +R 3 +L 2 +D 4 +R 1 +L 3 +R 4 +L 2 +R 7 +L 6 +R 7 +U 8 +D 6 +U 2 +L 11 +R 9 +L 10 +R 6 +D 4 +R 7 +L 6 +D 2 +L 10 +D 3 +L 2 +D 9 +L 2 +R 10 +L 8 +U 2 +L 9 +D 12 +U 3 +R 7 +U 6 +L 1 +R 6 +D 9 +U 1 +R 9 +U 5 +L 5 +R 12 +L 5 +U 4 +R 1 +D 1 +R 7 +L 1 +R 1 +D 3 +U 5 +R 9 +D 6 +L 12 +R 2 +U 4 +R 2 +U 2 +R 11 +U 2 +D 3 +U 2 +L 11 +D 11 +R 1 +D 10 +L 5 +D 11 +R 4 +D 4 +R 12 +U 11 +R 2 +U 1 +D 11 +L 3 +D 3 +R 5 +D 6 +R 9 +U 10 +L 9 +D 4 +U 8 +D 5 +R 5 +U 1 +R 2 +U 12 +L 2 +R 9 +D 5 +U 11 +D 8 +R 8 +L 10 +D 10 +U 9 +L 5 +U 2 +R 4 +D 4 +U 11 +R 2 +U 8 +R 5 +U 3 +D 12 +L 10 +U 11 +D 12 +R 3 +L 6 +R 5 +U 6 +R 9 +U 7 +R 9 +D 6 +L 3 +U 3 +L 5 +D 1 +L 9 +U 9 +R 2 +D 9 +R 5 +U 9 +R 7 +D 5 +R 10 +D 7 +U 4 +L 1 +D 6 +U 10 +L 12 +R 7 +U 9 +L 1 +D 5 +U 8 +D 3 +L 6 +D 7 +R 7 +L 13 +D 4 +R 3 +D 8 +L 10 +R 11 +D 2 +R 8 +D 7 +R 8 +L 13 +D 3 +L 2 +D 4 +L 2 +U 5 +R 6 +U 9 +R 7 +L 3 +R 13 +L 11 +R 1 +D 13 +L 10 +D 6 +R 2 +L 12 +D 8 +U 12 +D 5 +R 3 +U 5 +D 6 +U 4 +D 6 +U 7 +D 12 +R 6 +L 1 +U 3 +R 10 +U 7 +L 12 +R 11 +D 1 +L 9 +U 12 +L 5 +D 6 +U 7 +D 11 +L 9 +D 13 +L 7 +D 13 +U 5 +R 9 +U 8 +R 9 +D 9 +L 9 +R 3 +D 11 +U 7 +L 9 +U 6 +L 11 +U 2 +R 6 +U 6 +R 12 +U 1 +L 3 +U 5 +R 9 +U 11 +R 13 +U 11 +D 13 +R 7 +U 11 +L 9 +D 10 +U 1 +L 12 +R 13 +D 3 +U 4 +L 11 +U 3 +D 2 +R 10 +U 9 +D 4 +L 14 +R 2 +D 2 +U 13 +D 3 +U 10 +L 7 +U 6 +D 13 +U 9 +R 1 +D 1 +R 1 +D 5 +L 2 +D 7 +U 10 +R 1 +D 8 +L 13 +R 2 +U 10 +L 6 +D 8 +R 7 +U 9 +D 4 +U 7 +D 6 +R 12 +U 1 +D 13 +U 4 +L 13 +D 7 +R 5 +U 10 +D 12 +U 5 +L 1 +U 12 +D 4 +U 3 +R 3 +D 9 +L 5 +R 2 +D 3 +U 6 +R 14 +L 2 +R 3 +U 11 +R 9 +L 13 +D 1 +U 8 +D 2 +R 12 +D 5 +L 6 +U 14 +R 1 +D 2 +L 6 +R 7 +L 8 +D 6 +U 7 +L 2 +R 2 +D 5 +R 6 +U 1 +D 8 +L 12 +D 7 +L 6 +D 8 +L 4 +U 4 +D 13 +R 11 +D 1 +R 9 +L 6 +D 8 +L 12 +U 11 +D 11 +U 4 +D 12 +R 4 +L 14 +U 6 +D 3 +R 8 +D 7 +L 12 +U 12 +R 10 +U 2 +R 6 +L 1 +R 11 +U 2 +L 4 +U 12 +R 5 +U 8 +L 15 +R 5 +U 4 +R 9 +D 8 +U 15 +D 10 +R 10 +L 9 +R 12 +L 8 +D 14 +R 2 +D 11 +L 14 +D 8 +L 1 +D 15 +U 4 +L 4 +D 9 +R 4 +D 10 +L 1 +U 7 +D 13 +R 15 +U 12 +R 11 +D 12 +R 2 +L 7 +D 15 +L 1 +U 4 +D 14 +L 7 +D 1 +R 9 +U 1 +L 3 +D 2 +L 5 +D 13 +R 3 +L 12 +U 5 +L 13 +U 5 +L 2 +D 9 +L 1 +D 10 +L 14 +D 14 +U 5 +D 14 +U 5 +D 4 +R 12 +U 10 +R 14 +D 1 +L 1 +U 8 +D 7 +L 13 +R 5 +L 7 +D 5 +L 3 +U 15 +R 8 +L 9 +D 14 +R 14 +L 12 +D 7 +L 15 +D 14 +U 12 +L 7 +R 11 +L 10 +D 8 +L 7 +R 14 +L 11 +U 1 +R 9 +U 13 +R 14 +D 6 +U 1 +L 4 +R 12 +L 2 +U 12 +L 12 +D 13 +U 13 +R 12 +U 5 +R 9 +U 4 +D 13 +L 7 +D 4 +U 16 +D 11 +U 16 +R 12 +U 10 +R 14 +L 1 +U 12 +R 4 +U 7 +R 10 +D 14 +R 9 +D 9 +L 8 +R 11 +L 7 +U 5 +R 15 +U 1 +D 12 +U 5 +D 11 +U 5 +D 11 +L 13 +R 6 +D 10 +U 1 +L 5 +U 11 +L 4 +U 14 +L 15 +R 14 +L 4 +D 13 +L 11 +D 1 +U 12 +D 2 +L 13 +D 10 +L 8 +U 15 +R 3 +U 5 +R 13 +L 11 +U 12 +L 14 +R 10 +D 15 +R 2 +U 6 +D 15 +U 11 +D 9 +U 10 +R 16 +U 16 +D 6 +R 2 +L 4 +D 15 +L 8 +U 8 +L 14 +D 8 +U 4 +R 2 +D 4 +U 11 +R 9 +L 15 +U 5 +L 15 +D 12 +R 9 +U 3 +R 7 +D 14 +U 6 +R 11 +L 16 +D 5 +R 15 +D 6 +U 5 +L 13 +U 5 +R 4 +U 11 +R 13 +D 7 +R 7 +U 12 +R 13 +U 1 +L 5 +D 6 +R 8 +U 14 +R 6 +D 16 +R 8 +D 6 +R 5 +U 6 +D 2 +U 4 +R 5 +D 17 +L 3 +D 1 +R 9 +U 6 +R 13 +L 3 +D 15 +L 9 +D 4 +R 6 +D 13 +U 11 +D 2 +U 10 +L 11 +D 4 +U 17 +R 12 +D 12 +R 7 +D 10 +U 7 +R 3 +L 5 +D 5 +R 3 +D 3 +U 6 +D 6 +U 17 +L 16 +D 3 +R 14 +D 5 +U 12 +L 13 +U 7 +D 5 +R 17 +L 7 +D 12 +U 9 +D 15 +L 2 +R 13 +L 14 +D 1 +L 3 +U 17 +R 9 +U 4 +L 14 +R 8 +D 15 +L 11 +U 15 +L 9 +U 4 +L 10 +U 13 +D 12 +U 9 +L 8 +R 12 +U 5 +D 13 +U 10 +R 13 +U 1 +L 14 +D 10 +U 10 +R 3 +D 7 +R 5 +D 10 +R 6 +U 1 +D 1 +R 3 +L 16 +D 4 +U 13 +D 17 +L 5 +R 14 +U 3 +R 12 +U 5 +D 2 +U 9 +R 11 +D 13 +L 6 +U 3 +R 17 +L 11 +R 17 +L 13 +U 2 +R 17 +U 9 +L 3 +R 16 +D 1 +U 13 +D 3 +R 7 +L 9 +R 16 +D 17 +L 3 +U 3 +R 7 +L 15 +U 3 +R 6 +L 11 +R 11 +D 2 +U 1 +L 4 +D 6 +L 15 +R 9 +D 14 +U 1 +L 1 +U 10 +L 18 +D 4 +R 12 +L 14 +R 11 +D 14 +L 15 +U 17 +L 6 +U 11 +D 14 +U 1 +L 9 +D 8 +U 6 +L 18 +R 2 +D 4 +L 1 +D 13 +L 17 +U 6 +L 18 +U 16 +R 1 +U 8 +R 8 +L 17 +D 13 +U 18 +R 5 +U 6 +R 14 +D 4 +U 16 +L 18 +U 6 +R 18 +L 3 +U 12 +R 2 +D 9 +U 6 +R 11 +L 2 +D 11 +U 11 +D 16 +L 17 +U 18 +D 7 +R 12 +D 2 +L 9 +R 4 +L 3 +R 3 +U 17 +L 15 +R 12 +U 16 +L 12 +U 2 +L 8 +D 3 +L 10 +U 11 +L 2 +D 18 +R 1 +D 2 +R 5 +D 9 +L 15 +D 8 +L 18 +D 7 +L 16 +R 2 +U 17 +L 14 +R 11 +D 2 +U 12 +L 5 +D 6 +R 17 +L 7 +U 10 +R 1 +L 17 +R 12 +U 2 +D 4 +U 13 +D 11 +U 16 +L 4 +R 10 +U 3 +R 14 +U 16 +L 15 +U 10 +L 12 +U 19 +L 19 +R 15 +L 3 +U 6 +R 19 +L 14 +R 4 +L 6 +R 5 +L 17 +U 15 +L 6 +D 11 +U 7 +L 2 +R 8 +U 8 +R 16 +L 4 +U 19 +D 9 +L 15 +D 15 +L 16 +D 15 +L 9 +R 5 +L 10 +U 4 +R 15 +U 1 +D 4 +U 18 +R 18 +L 1 +U 18 +R 8 +L 11 +R 12 +U 3 +R 16 +D 17 +R 2 +L 18 +D 9 +R 5 +U 13 +R 12 +U 5 +R 6 +U 18 +R 5 +D 1 +L 8 +D 6 +L 16 +D 19 +L 16 +R 10 +L 9 +U 17 +D 19 +R 6 +D 15 +R 4 +U 19 +D 16 +R 13 +U 5 +R 10 +U 16 +D 4 +U 19 +R 17 +L 11 +U 4 +L 1 +U 9 +R 16 +L 6 +U 12 +D 9 +L 9 +R 3 +U 15 +R 18 +D 4 +U 19 +R 8 +L 3 +U 5 +D 18 +R 18 +D 17 +L 18 +R 15 +U 12 \ No newline at end of file diff --git a/2022/day-09/solution.test.ts b/2022/day-09/solution.test.ts new file mode 100644 index 0000000..3078fd7 --- /dev/null +++ b/2022/day-09/solution.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(6197); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(2562); +}) diff --git a/2022/day-09/solution.ts b/2022/day-09/solution.ts new file mode 100644 index 0000000..37efcb7 --- /dev/null +++ b/2022/day-09/solution.ts @@ -0,0 +1,115 @@ +// Parsing constants + +const LINE_REGEXP = /^(?[RULD]) (?\d+)$/; + +const DIRECTION_DELTAS: Record = { + R: { dx: 1, dy: 0 }, + L: { dx: -1, dy: 0}, + U: { dx: 0, dy: 1 }, + D: { dx: 0, dy: -1}, +} + +// Rope is a linked list of Knot-s + +class Knot { + public x: number; + public y: number; + public next: Knot | null; + + constructor(x: number, y: number) { + this.x = x; + this.y = y; + + this.next = null + } + + public follow(knot: Knot) { + const dHorizontal = knot.x - this.x; + const dVertical = knot.y - this.y; + + // if distance more than 2, the knot needs to move + + if (Math.abs(dHorizontal) >= 2 || Math.abs(dVertical) >= 2) { + this.x += Math.sign(dHorizontal); + this.y += Math.sign(dVertical); + + if (this.next) { // the knot moved, so the next must follow + this.next.follow(this); + } + } + } +} + +// HeadKnot is a Knot that can be pulled + +class HeadKnot extends Knot { + constructor(x: number, y: number) { + super(x, y); + } + + public pull(dx: number, dy: number): void { + this.x += dx; + this.y += dy; + + if (this.next) { + this.next.follow(this); + } + } +} + +const solve = (input: string, ropeLength: number): number => { + // create a rope + + const ropeHead = new HeadKnot(0, 0); + + let curr: Knot = ropeHead; + + for (let i = 0; i < ropeLength - 1; i++) { + curr.next = new Knot(0, 0); + curr = curr.next; + } + + const tail = curr; // last added Knot is a tail + + // keep track of coordinates, visited by a tail (a set of `x, y` strings) + + const visited = new Set(); + + input.split('\n').forEach((line) => { + // parse a line + + const matches = LINE_REGEXP.exec(line); + + if (!matches || !matches?.groups?.direction || !matches?.groups?.distance) { + throw new Error(`Can not parse line: ${line}`); + } + + const direction = matches.groups.direction; + const distance = Number(matches.groups.distance); + + const { dx, dy } = DIRECTION_DELTAS[direction]; + + // pull rope to direction for distance + + for (let i = 0; i < distance; i++) { + ropeHead.pull(dx, dy); + + // after each pull step, record tail visited coordinates, + // `Set` will filter out duplicates automatically + + visited.add(`${tail.x}, ${tail.y}`) + } + }); + + return visited.size; +}; + +const solvePart1 = (input: string): number => { + return solve(input, 2); +}; + +const solvePart2 = (input: string): number => { + return solve(input, 10); +}; + +export { solvePart1, solvePart2 }; \ No newline at end of file diff --git a/2022/day-10/input.txt b/2022/day-10/input.txt new file mode 100644 index 0000000..9aa6cb0 --- /dev/null +++ b/2022/day-10/input.txt @@ -0,0 +1,140 @@ +addx 2 +addx 15 +addx -11 +addx 6 +noop +noop +noop +addx -1 +addx 5 +addx -1 +addx 5 +noop +noop +noop +noop +noop +addx 7 +addx -1 +addx 3 +addx 1 +addx 5 +addx 1 +noop +addx -38 +noop +addx 1 +addx 6 +addx 3 +noop +addx -8 +noop +addx 13 +addx 2 +addx 3 +addx -2 +addx 2 +noop +addx 3 +addx 9 +addx -2 +addx 2 +addx -10 +addx 11 +addx 2 +addx -14 +addx -21 +addx 2 +noop +addx 5 +addx 29 +addx -2 +noop +addx -19 +noop +addx 2 +addx 11 +addx -10 +addx 2 +addx 5 +addx -9 +noop +addx 14 +addx 2 +addx 3 +addx -2 +addx 3 +addx 1 +noop +addx -37 +noop +addx 13 +addx -8 +noop +noop +noop +noop +addx 13 +addx -5 +addx 3 +addx 3 +addx 3 +noop +noop +noop +noop +noop +noop +noop +addx 6 +addx 3 +addx 1 +addx 5 +addx -15 +addx 5 +addx -27 +addx 30 +addx -23 +addx 33 +addx -32 +addx 2 +addx 5 +addx 2 +addx -16 +addx 17 +addx 2 +addx -10 +addx 17 +addx 10 +addx -9 +addx 2 +addx 2 +addx 5 +addx -29 +addx -8 +noop +noop +noop +addx 19 +addx -11 +addx -1 +addx 6 +noop +noop +addx -1 +addx 3 +noop +addx 3 +addx 2 +addx -3 +addx 11 +addx -1 +addx 5 +addx -2 +addx 5 +addx 2 +noop +noop +addx 1 +noop +noop \ No newline at end of file diff --git a/2022/day-10/solution.test.ts b/2022/day-10/solution.test.ts new file mode 100644 index 0000000..801a40a --- /dev/null +++ b/2022/day-10/solution.test.ts @@ -0,0 +1,21 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(12880); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(` +####..##....##..##..###....##.###..####. +#....#..#....#.#..#.#..#....#.#..#.#.... +###..#.......#.#..#.#..#....#.#..#.###.. +#....#.......#.####.###.....#.###..#.... +#....#..#.#..#.#..#.#....#..#.#.#..#.... +#.....##...##..#..#.#.....##..#..#.####. + `.trim()); +}) diff --git a/2022/day-10/solution.ts b/2022/day-10/solution.ts new file mode 100644 index 0000000..c748272 --- /dev/null +++ b/2022/day-10/solution.ts @@ -0,0 +1,152 @@ +// Parse commands RegExp-s + +const NOOP_CMD_REGEXP = /^noop$/; +const ADDX_CMD_REGEXP = /^addx (?-?\d+)$/ + +// Command interfaces + +enum CMD { + NOOP, + ADDX +} + +interface CommandBase { + name: CMD; +} + +interface NoopCmd extends CommandBase { + name: CMD.NOOP; +} + +interface AddxCmd extends CommandBase { + name: CMD.ADDX; + value: number; +} + +type Command = NoopCmd | AddxCmd; + +// CRT + +class CRT { + public readonly width: number; + public readonly height: number; + + private readonly buffer: string[][]; + + private cursor: number; + + constructor(width: number = 40, height: number = 6) { + this.width = width; + this.height = height; + + this.buffer = []; + + for (let i = 0; i < this.height; i++) { + this.buffer.push([]); + } + + this.cursor = 0; + } + + public drawPixel(spriteStart: number, spriteEnd: number): void { + const row = Math.floor(this.cursor / this.width); + const col = this.cursor % this.width; + + if (col >= spriteStart && col <= spriteEnd) { + this.buffer[row][col] = '#'; + } else { + this.buffer[row][col] = '.'; + } + + this.cursor += 1; + } + + public toString(): string { + return this.buffer.map((row) => { + return row.join(''); + }).join('\n'); + } +} + +const solve = (input: string): [number, string] => { + const execQueue: Command[] = []; + + // parse input to execQueue + + input.split('\n').forEach((line) => { + if (NOOP_CMD_REGEXP.test(line)) { + execQueue.push({ name: CMD.NOOP }); + } else if (ADDX_CMD_REGEXP.test(line)) { + const matches = ADDX_CMD_REGEXP.exec(line); + + if (!matches || !matches?.groups?.value) { + throw new Error(`Can not parse addx command: ${line}`); + } + + execQueue.push({ name: CMD.ADDX, value: Number(matches.groups.value) }); + } else { + throw new Error(`Unrecognized command: ${line}`); + } + }); + + // set up for execution + + let cycle = 1; + let registerX = 1; + let signalStrength = 0; + + const crt = new CRT(); + const execImmediate: Command[] = []; + + // execute execQueue + + while (execQueue.length !== 0) { + // if cycle of interest -> add signal strength + + if ([20, 60, 100, 140, 180, 220].includes(cycle)) { + signalStrength += cycle * registerX; + } + + crt.drawPixel(registerX - 1, registerX + 1); + + // check execImmediate stack and execute + + const immediateCmd = execImmediate.pop(); + + if (immediateCmd !== undefined) { + switch (immediateCmd.name) { + case CMD.ADDX: + registerX += immediateCmd.value; + break + default: + throw new Error(`Unrecognized immediate command: ${immediateCmd}`); + } + } else { + const queueCmd = execQueue.shift()!; + + switch (queueCmd.name) { + case CMD.NOOP: // do nothing + break; + case CMD.ADDX: // push to execImmediate stack to be executed during the next cycle + execImmediate.push(queueCmd); + } + } + + cycle += 1; + } + + return [signalStrength, crt.toString()]; +}; + +const solvePart1 = (input: string): number => { + const [signalStrength] = solve(input); + return signalStrength; +}; + + +const solvePart2 = (input: string): string => { + const [_, crtPicture] = solve(input); + return crtPicture; +}; + +export { solvePart1, solvePart2 }; \ No newline at end of file diff --git a/2022/day-11/input.txt b/2022/day-11/input.txt new file mode 100644 index 0000000..3e7b0eb --- /dev/null +++ b/2022/day-11/input.txt @@ -0,0 +1,55 @@ +Monkey 0: + Starting items: 54, 53 + Operation: new = old * 3 + Test: divisible by 2 + If true: throw to monkey 2 + If false: throw to monkey 6 + +Monkey 1: + Starting items: 95, 88, 75, 81, 91, 67, 65, 84 + Operation: new = old * 11 + Test: divisible by 7 + If true: throw to monkey 3 + If false: throw to monkey 4 + +Monkey 2: + Starting items: 76, 81, 50, 93, 96, 81, 83 + Operation: new = old + 6 + Test: divisible by 3 + If true: throw to monkey 5 + If false: throw to monkey 1 + +Monkey 3: + Starting items: 83, 85, 85, 63 + Operation: new = old + 4 + Test: divisible by 11 + If true: throw to monkey 7 + If false: throw to monkey 4 + +Monkey 4: + Starting items: 85, 52, 64 + Operation: new = old + 8 + Test: divisible by 17 + If true: throw to monkey 0 + If false: throw to monkey 7 + +Monkey 5: + Starting items: 57 + Operation: new = old + 2 + Test: divisible by 5 + If true: throw to monkey 1 + If false: throw to monkey 3 + +Monkey 6: + Starting items: 60, 95, 76, 66, 91 + Operation: new = old * old + Test: divisible by 13 + If true: throw to monkey 2 + If false: throw to monkey 5 + +Monkey 7: + Starting items: 65, 84, 76, 72, 79, 65 + Operation: new = old + 5 + Test: divisible by 19 + If true: throw to monkey 6 + If false: throw to monkey 0 \ No newline at end of file diff --git a/2022/day-11/solution.test.ts b/2022/day-11/solution.test.ts new file mode 100644 index 0000000..9e15de2 --- /dev/null +++ b/2022/day-11/solution.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(111210); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(15447387620); +}) diff --git a/2022/day-11/solution.ts b/2022/day-11/solution.ts new file mode 100644 index 0000000..3e64131 --- /dev/null +++ b/2022/day-11/solution.ts @@ -0,0 +1,217 @@ +// RegExp-s to parse + +const MONKEY_INDEX_REGEXP = /^Monkey (?\d+):$/; +const STARTING_ITEMS_REGEXP = /^ +Starting items: (?[\d, ?]+)$/; +const OPERATION_REGEXP = /^ +Operation: new = (?.*)$/; +const CONDITION_REGEXP = /^ +Test: divisible by (?\d+)$/; +const IF_TRUE_REGEXP = /^ +If true: throw to monkey (?\d+)$/; +const IF_FALSE_REGEXP = /^ +If false: throw to monkey (?\d+)$/; + +// Worry level adjustment for each Part + +const WORRY_LEVEL_ADJUSTMENT_1 = 1 / 3; +const WORRY_LEVEL_ADJUSTMENT_2 = 1; // very worried during the Part 2 + + +/** + * Calculates a base divider (a product of all dividers which are all prime). + * We are going to store item % baseDivider instead of actual item value -> it allows us + * to avoid dealing with huge numbers to get correct `% divider` operations results + */ +const calculateBaseDivider = (monkeys: Map): number => { + let baseDivider = 1; + + for (const monkey of monkeys.values()) { + baseDivider *= monkey.inspectionOptions.divider; + } + + return baseDivider; +} + +/** + * Counts a business level of monkeys (a product of 2 most active monkeys' inspectionCount-s) + */ +const countMonkeyBusinessLevel = (monkeys: Map): number => { + let mostActive1 = 1; + let mostActive2 = 1; + + for (const [_, monkey] of monkeys) { + if (mostActive1 <= monkey.inspectionCount) { + mostActive2 = mostActive1; + mostActive1 = monkey.inspectionCount; + } else if (mostActive2 <= monkey.inspectionCount) { + mostActive2 = monkey.inspectionCount; + } + } + + return mostActive1 * mostActive2; +} + +/** + * Monkey + */ + +interface MonkeyInspectionOptions { + operation: string; + divider: number; + ifTrueMonkeyId: number; + ifFalseMonkeyId: number; +} + +class Monkey { + public inspectionCount: number; + public readonly items: number[]; + public readonly inspectionOptions: MonkeyInspectionOptions; + + constructor(startingItems: number[], inspectionOptions: MonkeyInspectionOptions) { + this.items = startingItems; + this.inspectionOptions = inspectionOptions; + this.inspectionCount = 0; + } + + catchItem(item: number): void { + this.items.push(item); + } + + inspectAndThrow(item: number, baseDivider: number, worryLevelAdjustment: number): [number, number] { + const { operation, divider, ifTrueMonkeyId, ifFalseMonkeyId } = this.inspectionOptions; + + this.inspectionCount += 1; + + // noinspection JSUnusedLocalSymbols – used in eval + const old = item; + + // instead of storing actual item values, we store item % baseDivider + // in this case, we always get correct `% divider` calculations and do not need to store huge numbers + + const newItem = Math.floor(eval(operation) * worryLevelAdjustment) % baseDivider; + const throwToId = newItem % divider === 0 ? ifTrueMonkeyId : ifFalseMonkeyId; + + return [newItem, throwToId]; + } +} + +const parseInput = (input: string): [Map, number] => { + const monkeys = new Map(); + + input.split('\n\n').forEach((monkeyInput) => { + const [ + indexLine, + startingItemsLine, + operationLine, + conditionLine, + ifTrueLine, + ifFalseLine, + ] = monkeyInput.split('\n'); + + // parse monkey id + + const indexLineMatches = MONKEY_INDEX_REGEXP.exec(indexLine); + + if (!indexLineMatches || !indexLineMatches.groups?.monkeyId) { + throw new Error(`Can not parse monkey index line: ${indexLine}`); + } + + const monkeyId = Number(indexLineMatches.groups.monkeyId); + + // parse starting items + + const startingItemsLineMatches = STARTING_ITEMS_REGEXP.exec(startingItemsLine); + + if (!startingItemsLineMatches || !startingItemsLineMatches.groups?.itemsStr) { + throw new Error(`Can not parse monkey starting items line: ${startingItemsLine}`); + } + + const startingItems = startingItemsLineMatches.groups.itemsStr.split(', ').map(Number); + + // parse operation + + const operationLineMatches = OPERATION_REGEXP.exec(operationLine); + + if (!operationLineMatches || !operationLineMatches.groups?.operationStr) { + throw new Error(`Can not parse monkey operation line: ${operationLine}`); + } + + const operation = operationLineMatches.groups.operationStr; + + // parse divider + + const conditionLineMatches = CONDITION_REGEXP.exec(conditionLine); + + if (!conditionLineMatches || !conditionLineMatches.groups?.divider) { + throw new Error(`Can not parse monkey condition line: ${conditionLine}`); + } + + const divider = Number(conditionLineMatches.groups.divider); + + // parse if true + + const ifTrueLineMatches = IF_TRUE_REGEXP.exec(ifTrueLine); + + if (!ifTrueLineMatches || !ifTrueLineMatches.groups?.monkeyId) { + throw new Error(`Can not parse monkey if true line: ${ifTrueLine}`); + } + + const ifTrueMonkeyId = Number(ifTrueLineMatches.groups.monkeyId); + + // parse if false + + const ifFalseLineMatches = IF_FALSE_REGEXP.exec(ifFalseLine); + + if (!ifFalseLineMatches || !ifFalseLineMatches.groups?.monkeyId) { + throw new Error(`Can not parse monkey if false line: ${ifFalseLine}`); + } + + const ifFalseMonkeyId = Number(ifFalseLineMatches.groups.monkeyId); + + // create a Monkey + // we don't have baseDivider until we parse all monkeys, so startingItems are actual values, + // but it does not really matter + + const monkey = new Monkey(startingItems, { + operation, divider, ifTrueMonkeyId, ifFalseMonkeyId, + }); + + monkeys.set(monkeyId, monkey); + }); + + return [monkeys, calculateBaseDivider(monkeys)]; +} + +const solvePart1 = (input: string): number => { + const [monkeys, baseDivider] = parseInput(input); + + for (let i = 0; i < 20; i++) { + for (const monkey of monkeys.values()) { + while (monkey.items.length > 0) { + const item = monkey.items.shift()!; + + const [newItem, throwToId] = monkey.inspectAndThrow(item, baseDivider, WORRY_LEVEL_ADJUSTMENT_1); + + monkeys.get(throwToId)!.catchItem(newItem); + } + } + } + + return countMonkeyBusinessLevel(monkeys); +}; + +const solvePart2 = (input: string): number => { + const [monkeys, baseDivider] = parseInput(input); + + for (let i = 0; i < 10000; i++) { + for (const monkey of monkeys.values()) { + while (monkey.items.length > 0) { + const item = monkey.items.shift()!; + + const [newItem, throwToId] = monkey.inspectAndThrow(item, baseDivider, WORRY_LEVEL_ADJUSTMENT_2); + + monkeys.get(throwToId)!.catchItem(newItem); + } + } + } + + return countMonkeyBusinessLevel(monkeys); +}; + +export { solvePart1, solvePart2 }; \ No newline at end of file diff --git a/2022/day-12/input.txt b/2022/day-12/input.txt new file mode 100644 index 0000000..cc285fe --- /dev/null +++ b/2022/day-12/input.txt @@ -0,0 +1,41 @@ +abacccaaaacccccccccccaaaaaacccccaaaaaaccccaaacccccccccccccccccccccccccccccccccccccccccccaaaaa +abaaccaaaacccccccccccaaaaaaccccccaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccccccaaaaa +abaaccaaaacccccccccccaaaaacccccaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccccccaaaaa +abccccccccccccccccccccaaaaacccaaaaaaaaaaaaaaaacccccccccccccccccccccccccccaaaccccccccccccaaaaa +abccccccccccccccccccccaacaacccaaaaaaaaccaaaaaccccccccccccccccccccccccccccaaaccccccccccccaccaa +abcccccccccccccaacccaaaccccccaaaaaaaaaccaaaaaccccccccccccccccccccccccccccccacccccccccccccccca +abcccccccccccaaaaaaccaaaccacccccaaaaaaacccccccccccccccccccccccccciiiicccccccddddddccccccccccc +abcccccccccccaaaaaaccaaaaaaaccccaaaaaacccccaacccccccaaaccccccccciiiiiiiicccdddddddddacaaccccc +abccccccccccccaaaaaaaaaaaaacccccaaaaaaacaaaacccccccaaaacccccccchhiiiiiiiiicddddddddddaaaccccc +abcccccccccccaaaaaaaaaaaaaacccccccaaacccaaaaaacccccaaaaccccccchhhipppppiiiijjjjjjjddddaaccccc +abcccccccccccaaaaaaaaaaaaaaccccccccccccccaaaaaccccccaaaccccccchhhpppppppiijjjjjjjjjddeeaccccc +abcccccccccccccccccaaaaaaaacccccccccccccaaaaaccccccccccccccccchhppppppppppjjqqqjjjjjeeeaacccc +abccccccccccccccccccaaaaaaaacccccccccccccccaacccccccccccccccchhhpppuuuupppqqqqqqqjjjeeeaacccc +abcccccccccccccccccccaacccacccccccccccccccccccccccccccccccccchhhopuuuuuuppqqqqqqqjjjeeecccccc +abacccccccccccccaaacaaaccccccccccccccccccccccccccccaaccccccchhhhoouuuuuuuqvvvvvqqqjkeeecccccc +abaccccccccccccaaaaaacccccaaccccccccccccccccccccccaaaccccccchhhooouuuxxxuvvvvvvqqqkkeeecccccc +abaccccccccccccaaaaaacccaaaaaaccccccccccccccccccaaaaaaaaccchhhhooouuxxxxuvyyyvvqqqkkeeecccccc +abcccccccccccccaaaaacccaaaaaaaccccccccccccccccccaaaaaaaaccjjhooooouuxxxxyyyyyvvqqqkkeeecccccc +abccccccccccccccaaaaaacaaaaaaaccccccccaaaccccccccaaaaaaccjjjooootuuuxxxxyyyyyvvqqkkkeeecccccc +abccccccccccccccaaaaaaaaaaaaacccccccccaaaacccccccaaaaaacjjjooootttuxxxxxyyyyvvrrrkkkeeecccccc +SbccccccccccccccccccaaaaaaaaacccccccccaaaacccccccaaaaaacjjjoootttxxxEzzzzyyvvvrrrkkkfffcccccc +abcccccccccccaaacccccaaaaaaacaaaccccccaaaccccccccaaccaacjjjoootttxxxxxyyyyyyvvvrrkkkfffcccccc +abcccccccccaaaaaacccaaaaaacccaaacacccaacccccccccccccccccjjjoootttxxxxyxyyyyyywvvrrkkkfffccccc +abcccccccccaaaaaacccaaaaaaaaaaaaaaaccaaacaaacccccaacccccjjjnnnttttxxxxyyyyyyywwwrrkkkfffccccc +abcaacacccccaaaaacccaaacaaaaaaaaaaaccaaaaaaacccccaacaaacjjjnnnntttttxxyywwwwwwwwrrrlkfffccccc +abcaaaaccccaaaaacccccccccaacaaaaaaccccaaaaaacccccaaaaacccjjjnnnnnttttwwywwwwwwwrrrrllfffccccc +abaaaaaccccaaaaaccccccaaaaaccaaaaacaaaaaaaaccccaaaaaaccccjjjjinnnntttwwwwwsssrrrrrllllffccccc +abaaaaaaccccccccccccccaaaaacaaaaaacaaaaaaaaacccaaaaaaacccciiiiinnnntswwwwssssrrrrrlllfffccccc +abacaaaaccccccccccccccaaaaaacaaccccaaaaaaaaaaccccaaaaaaccccciiiinnnssswwsssssllllllllfffccccc +abccaaccccccccccccccccaaaaaaccccccccccaaacaaaccccaaccaacccccciiiinnsssssssmmllllllllfffaacccc +abccccccccccccccccccccaaaaaaccccccccccaaaccccccccaaccccccccccciiinnmsssssmmmmlllllgggffaacccc +abcccccccccccccccaccccccaaacccccccccccaaccccccccccccccccccccccciiimmmsssmmmmmgggggggggaaacccc +abcccccccccaaaaaaaaccccccccccccccccccccccccccccaaaaaccccccccccciiimmmmmmmmmgggggggggaaacccccc +abccccccccccaaaaaaccccccccccccccccccaacccccccccaaaaacccccccccccciiimmmmmmmhhggggcaaaaaaaccccc +abccccccccccaaaaaacccccccccccccccccaacccccccccaaaaaacccccccccccciihhmmmmhhhhgccccccccaacccccc +abccccaacaaaaaaaaaaccccccccccccccccaaaccccccccaaaaaaccccccccccccchhhhhhhhhhhaaccccccccccccccc +abccccaaaaaaaaaaaaaaccccccccccaaccaaaaccccccccaaaaaacccaaacccccccchhhhhhhhaaaaccccccccccccccc +abcccaaaaaaaaaaaaaaaccccccccaaaaaacaaaacacaccccaaaccccaaaacccccccccchhhhccccaaccccccccccaaaca +abcccaaaaaacacaaacccccccccccaaaaaaaaaaaaaaacccccccccccaaaacccccccccccaaaccccccccccccccccaaaaa +abcccccaaaacccaaaccccccccccaaaaaaaaaaaaaaaaccccccccccccaaacccccccccccaaacccccccccccccccccaaaa +abcccccaacccccaacccccccccccaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccccccccccccaaaaa \ No newline at end of file diff --git a/2022/day-12/solution.test.ts b/2022/day-12/solution.test.ts new file mode 100644 index 0000000..95b8c21 --- /dev/null +++ b/2022/day-12/solution.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(412); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(402); +}) diff --git a/2022/day-12/solution.ts b/2022/day-12/solution.ts new file mode 100644 index 0000000..0b15155 --- /dev/null +++ b/2022/day-12/solution.ts @@ -0,0 +1,194 @@ +const ELEVATIONS = 'abcdefghijklmnopqrstuvwxyz'; + +const CURRENT_POSITION = 'S'; +const BEST_SIGNAL_POSITION = 'E'; + +const getElevation = (position: string): number => { + if (position === CURRENT_POSITION) { + return ELEVATIONS.indexOf('a'); + } else if (position === BEST_SIGNAL_POSITION) { + return ELEVATIONS.indexOf('z'); + } else { + return ELEVATIONS.indexOf(position); + } +} + +const findSmallestUnvisited = (unvisited: Set, distances: number[]): number => { + let smallestDistance = Infinity; + let smallestDistanceIndex = -1; + + for (let v = 0; v < distances.length; v++) { + if (smallestDistance > distances[v] && unvisited.has(v)) { + smallestDistance = distances[v]; + smallestDistanceIndex = v; + } + } + + return smallestDistanceIndex; +} + +// Dijkstra (based on https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm#Algorithm) +// Could be more optimal with heap-based priority queue +const dijkstra = (startingNode: number, adjacencySets: Map>): number[] => { + // Keep track of unvisited node + + const unvisited = new Set(adjacencySets.keys()); + + // Tentative distance values for each node (0 – if startingNode, Infinity – if any other node) + + const distances: number[] = []; + + // Fill in initial `unvisited` and `distances` + + for (const i of adjacencySets.keys()) { + unvisited.add(i); // all are unvisited + distances.push(i === startingNode ? 0 : Infinity); // 0 – if startingNode, Infinity – if any other node + } + + while (unvisited.size > 0) { + // Pick the smallest distance unvisited node (will be CURRENT_POSITION for the first iteration) + + let curr = findSmallestUnvisited(unvisited, distances); + + if (curr === -1) { // If no reachable nodes (distance = Infinity), the algorithm is finished + break; + } + + // Calculate all neighbors distances, filtering out visited + + for (const u of adjacencySets.get(curr)!) { + if (unvisited.has(u)) { + distances[u] = Math.min(distances[u], distances[curr] + 1); + } + } + + // Mark the current node as visited + + unvisited.delete(curr); + } + + return distances; +} + +const solvePart1 = (input: string): number => { + const heightmap = input.split('\n').map((line) => line.split('')); + + const H = heightmap.length; + const W = heightmap[0].length; + + // Build adjacency list (no need to store anything except node indexes) + + const adjacencySets: Map> = new Map(); // nodeIndex => Set + + let startingNode = -1; // CURRENT_POSITION index in adjacencySets + + for (let y = 0; y < H; y++) { + for (let x = 0; x < W; x++) { // for each height + const i = y * W + x; + const set = new Set(); + + // check all 4 siblings + + if (x + 1 < W && (getElevation(heightmap[y][x + 1]) - getElevation(heightmap[y][x]) <= 1)) { + set.add(y * W + x + 1); + } + + if (x - 1 >= 0 && (getElevation(heightmap[y][x - 1]) - getElevation(heightmap[y][x]) <= 1)) { + set.add(y * W + x - 1); + } + + if (y + 1 < H && (getElevation(heightmap[y + 1][x]) - getElevation(heightmap[y][x]) <= 1)) { + set.add((y + 1) * W + x); + } + + if (y - 1 >= 0 && (getElevation(heightmap[y - 1][x]) - getElevation(heightmap[y][x]) <= 1)) { + set.add((y - 1) * W + x); + } + + if (heightmap[y][x] === CURRENT_POSITION) { + startingNode = i; + } + + adjacencySets.set(i, set); + } + } + + // Count all shortest distances + + const distances = dijkstra(startingNode, adjacencySets); + + // Find distance to BEST_SIGNAL_POSITION + + return distances.find((distance, i) => { + const x = i % W; + const y = Math.floor(i / W); + + return heightmap[y][x] === BEST_SIGNAL_POSITION; + })!; +}; + +const solvePart2 = (input: string): number => { + const heightmap = input.split('\n').map((line) => line.split('')); + + const H = heightmap.length; + const W = heightmap[0].length; + + // Build adjacency list + + const adjacencySets: Map> = new Map(); // nodeIndex => Set + + let startingNode = -1; // BEST_SIGNAL_POSITION index in adjacencySets + + for (let y = 0; y < H; y++) { + for (let x = 0; x < W; x++) { + const i = y * W + x; + const set = new Set(); + + // check all 4 siblings + // this time we will be traversing in reverse, so we compare elevations vise-versa too + + if (x + 1 < W && (getElevation(heightmap[y][x]) - getElevation(heightmap[y][x + 1]) <= 1)) { + set.add(y * W + x + 1); + } + + if (x - 1 >= 0 && (getElevation(heightmap[y][x]) - getElevation(heightmap[y][x - 1]) <= 1)) { + set.add(y * W + x - 1); + } + + if (y + 1 < H && (getElevation(heightmap[y][x]) - getElevation(heightmap[y + 1][x]) <= 1)) { + set.add((y + 1) * W + x); + } + + if (y - 1 >= 0 && (getElevation(heightmap[y][x]) - getElevation(heightmap[y - 1][x]) <= 1)) { + set.add((y - 1) * W + x); + } + + if (heightmap[y][x] === BEST_SIGNAL_POSITION) { + startingNode = i; + } + + adjacencySets.set(i, set); + } + } + + // Count all shortest distances + + const distances = dijkstra(startingNode, adjacencySets); + + // Find the closest `a` + + let minDistance = Number.MAX_SAFE_INTEGER; + + for (let i = 0; i < distances.length; i++) { + const x = i % W; + const y = Math.floor(i / W); + + if (heightmap[y][x] === 'a' && distances[i] < minDistance) { + minDistance = distances[i]; + } + } + + return minDistance; +}; + +export { solvePart1, solvePart2 }; \ No newline at end of file diff --git a/2022/day-13/input.txt b/2022/day-13/input.txt new file mode 100644 index 0000000..e40383b --- /dev/null +++ b/2022/day-13/input.txt @@ -0,0 +1,449 @@ +[[[5,[10,6],5,1,6],4],[[9,[7,4,7],6,[],7],[[9,6,0,10],7,[8,5,5,2,7],[7,10,5,6]]]] +[[[[10,8,4,6],7,2,[8],0],7,8],[[4,[0],[10,0,9],[1,10],4],[[6,6,1,10],4,6,[],[9,1]],[[4],[7,6,4,10,6],1,[2,2,5,3,2]],[[10,9,5],[1,1,1]],[[3,4,3],[3,10,0,8],[0,7,8,9],2,4]]] + +[[],[1,[[6,9,6,9,7],[9,2,3]],[[9],6,[2,9]],[2,6,2,4]],[[[10,3,1,4],[6,5,5,5,1]],[4,[9,3,6],7,2],7,8],[],[6,6,[8],2,1]] +[[9,[[1,9,9,4],6,9,[4,10,5],[0,9]],8],[],[10,[[2,10,3,10],[]],2,[10]],[3,[8,[],3,8]]] + +[[2,[[8,4,1,10,4],[0,8,3,6,4],[6,9,8,9],7,6],[6,[3,3,3,1]]]] +[[[6],8,[[1]]],[[[0,0],2,[0,9],[6,1],[7,1,4]],[7,[9,5],[10],[],2],8],[1,8],[],[1,[[7],[10,6],[],4,8],[10,[4,9,9,5],7,[8,10,3,0,2]],0]] + +[[[3,8,9],[],[[4]],[]],[],[[9],5,10,3,[3,[],3,[6,8,4],8]],[],[8,7,[],0]] +[[],[[[10],5,0,6],5,7,1,[[5,5]]],[8]] + +[[9,8,4,[2,4,6,[4,9]]]] +[[[9]],[9,[[4,7,8],[4,4],[5,10,0,7,9],2]]] + +[[[],[8],[[9,4,1,6],[4,10,9,5],[],[5,8,2,7,3]],6,4],[[[3,0]],5],[2],[0,[],[2]]] +[[[6],[1,[5,9,10,7,6],10],8,6],[[2],[[],[1,7],[10,2,0],[4,4]],[[8,4,10,10,9]],3,[5,[],5]],[]] + +[[[],5,9,2,8],[7,10,0],[2,0],[[9,[3],[],2,[0,2,0,9]],4,[]]] +[[[[],[7,0,0]],1,9,[[2]]]] + +[[[],[[]],4,4,[0]],[],[[[9]]]] +[[8,[],10],[[2],9,[2,3,[],[0],[0,3,0]],9]] + +[[6,6,[[],[0]],1],[9,5,8]] +[[3,0],[10,5,8,2,[0,6,[1,8,1]]],[9,10]] + +[[[2,[4,2,10,4]],4,10,1,[5]],[[[4,1,5],4],6],[7]] +[[3,[[1,2,5,7,7],[9,8,5,8,7],7],[10,9],0],[10,[],5,[6,[],[0,6,6,4,4],[6,1,1,6,0],[]],[4]],[[7,[4,10,0],9,[9]],[[0]]]] + +[[[6,1,[]]],[3],[]] +[[[8,[10,8,6],8],4,[4,7,10,1]],[0,[[],8,[9],5],[[9,8,8,1]]],[[[9,5,4],[7,8,10,7,10],[]],[[],[10,10],[],8,[8]],[],[5,[3,7,6,1]]],[[[5,5],[10,7]],1,[5],[],[[4,5],2,10,[]]],[[],8,10,9,[10,6,[6,3]]]] + +[[[[],[7,1],[7,0,10,0,6],8],[],7,[[],2,4,4],[]]] +[[],[4,1,[[3,5,8,3],10,0],[4,[],[0,8,4,1],[5,9],1],10],[[[2,5,4,10,6],[2,8],8],1,[[]],[0,[],2,2,2]],[],[]] + +[[[[],8,8,9]]] +[[10],[[[3,6],3],[[1,6,2],[6,10,2],7]],[],[]] + +[[[10,6,[3,3]],[[5],9,[10],10,6],[5,0,2,[10,8,10],[8]]],[4,6,6,[10,[0,9],8,6,[0,5,5]],5],[7,[[]],3,9],[[9,1,[8,0,7,3,2],[8,1,7,4],[6,9,4,7,5]],[[5],0],1,[1,7,[]],[5]]] +[[],[6,1],[[7,2],[5,[6,6,6],[9,1,2,5],[9,1,8],9],2,7,[[],[4,1,4,9,1],[4,4]]],[0]] + +[[],[10,7,1,4,2],[9,8,4,[[3,7,9,8],2,9,[6],[6,9,0]]],[[[6,5,7,7,0]],[7],4]] +[[3,[[7,10]],9]] + +[[0]] +[] + +[[4,2,6],[10,[],3],[2,[2,8,3,[],[9,10,5,2,7]],9,7,9],[[],[],10,[[5]]]] +[[3,[[1],4,4,[1,7,3,2,9]],9,7,[[]]],[[4,[5,5,1,0,7]]],[4],[8,[8,9,1],[[],[10],3]]] + +[[7,10,3],[[5]],[]] +[[[[6,0,6,1,6],5,[10,2,9,2,8]],[],[2,[3,5,5,0,6],10,2],1],[[]],[[[3,0],[],7,7,1],[[8,4,8,9,2],1,[10,3,5,5],5,2],5,6,[[0,8,0,2],[5]]],[3,10,[1],[[2,10,2,9,8],[6,10,4],[]],[9,[3,2],[8,8,5],9]]] + +[[[[2],[8,7,8,4,10]],8,1,8,10]] +[[[1],0,[[9,3,4,0]],9,[0,3,1,7,[4,2,7,3,10]]],[6,3,[[9],1,7],1],[],[[7,5,1,1,[2,5,2]],6,4,0,[[2,7,0,8,1],[7,4,7],[3,0,1,6],[7,9,0,1,1],[9]]],[[0,5],1,2,[4,2,7]]] + +[[4],[[1,2,[8,10],[2,8]],10,0]] +[[3,4],[2,[[1,8]],[10,[1,0,8],[1],[4]],[0,4,8]],[6,[[8,10,7],6,2]]] + +[[[1,[6,9,9],[8,6,0]],4,[6,[2,1,10],4],7,[2,[2,9],1]]] +[[],[5,3,[8,[],9]],[8]] + +[[[3,[8,2,1,4,0],[9,5,7,7,8]],[[5,5,2,2,9],[10],8],1,3]] +[[0,1,[],5],[[8,4],[10],6,7,0],[2],[[7,[3,2]],7,[],2,[0,[5,8,7,1,2],[0],1]],[[[4,4,4,10,8],0,2,10],[[9,8,6],3,[9,2,4,3,8],5,1]]] + +[[4,[[]]],[10,[[2,7],8]],[[[6,7],10,10,5],1,2,[[],2,10]],[[2,5,1,0,8],[[5,8,10]],6]] +[[8,[[4,5,6,2],5,[7],8,9]],[],[[],3,[],4],[[0],5,1]] + +[[3],[0,[],[3,1,4,10],2,[5]],[2,6,[],[[1,5],1]],[[],7,8,[]]] +[[[[],9,10],[[6,10,6,7]],7],[]] + +[[[4,[10]],9,[9,[9,8,5,9,1],[10],[3]]]] +[[3],[2,[10],[[4,2,7,2]],[[],[8],[7,5]]],[[[5,3]],3],[[7,[9,9,5,2,3],10,5],8,6],[4,[[3,1],[10,4,6,8],[8,0,8,2,5]],[[1,6,10,2],[2,10,5],6],1,[9,2]]] + +[[],[[[4,2,4],8,[8,9,3]],9,[]],[],[[[3]]]] +[[],[5,[[2,8,5,1],[0,10,6],[],2],[[1],[2,1,6],7,[1,5,1]],7],[0,9,7,5,0],[[[0,2,10,8],4,[6,6,5,4],[10,8,0]],0,4]] + +[[[]],[1,8,0,[[1,1,1,1],9,7,[],9]],[6],[6,[[0,4,9]],[[10,0],3,[0,10,4,6,1],[4,6,6,10,5],[]],[4,3],[8,3]],[2,5]] +[[[6,10,7,1]],[7,[[0,6,5]],[[10,8,9]],[[]]]] + +[[4,[[2,7,2,9,4],[8,8,3,2,1]]]] +[[[[],0,7,1],[[]],0,[6,[2,10,4,2]],[7,8]],[8,[[8,0],[10,0],10],1,4,[[10,9,3,8,0],7,[10,3,1,1],3]],[],[[1,10,[7],[4,8,1,2,10],4],[[],6]],[[1,[7,10,10,0],[],[],[2]],[[2,0],8,[7],[2,2,10],3]]] + +[[4,[[2,7],10,3,10,[1]]],[0,1,[[],[],1],[[8],2,6,[],4],[7]],[],[2,6,[[3],[1,1,4,9,0],0,[8,3,0,9],1],0],[2,8]] +[[9,1,9,[4,[8,4]]]] + +[[[0,[6],6,9,[2,2,3,2,5]],[9],[7,3,[1,7]],[[0,5,10,3],[],[5],0]]] +[[[[0],9,0,9],[[4,3,9,3],[],2,0,[3,9,5]],[3,10,5,[9,3]]],[9,[5,8,8,[]]],[[[6,5,8,5,8],[4,7,5,6,1]],9,6],[8,7]] + +[[5],[],[8,4,[],[[3,7,0]],3]] +[[[[1,6,9,6,4],8,[]],10,[10,[0,3,7,2,4]]],[[6],[7,10],[[],6,[7,8]],7],[4,[5,[2,6],5],3,5]] + +[[],[[]],[],[10,8],[[5,9,[5],[],[]],[[6],[5,8,3],[2,8,7,10,2]]]] +[[],[[]],[[[10,5,9]]],[8,6,[0,8],0,[4,[8],7]]] + +[[[],[],[],0],[5,[[],0,[10,3,6,1,8],[7]],0,[[],8,[],[9,9,6,1]],[[6,3],10]],[[[1,8,5,1],[4,1,10,2,9]]],[7],[[],[7,2,[3,1,8],10,[8,5]],2]] +[[],[[[2],1,10,6,[0,7,7,10]],7,0,[[0,8,9,6,9],[7,10,9,4,9],9,5],[[9,10,0],[],5,[10]]],[],[[[0,7,5,4],[10,7,7,4],9]],[2]] + +[7,6,8,6,7] +[7,6,8,6] + +[[[[]],[[],[7,5,3,9,4],[4,4,5],[5],[10,0,9,1]],[10]],[[],[[4],0,1,10,[]],[[],3,0,[2,7,8,10,3],10],0,7],[[],[5],[],[[],8,3,2],[[4,7]]],[]] +[[[[4,3,6,1]],3,[3,5,[6],8,3],[[4],[]]]] + +[[[],[8,[2,7],10,9,6],7],[[],[[2,4,1,4,3],[6,0,8,1],[7,3,8,1],[0,6,5],3],9,[[8,0,2,9,1]],2],[5,1,8,3,[[2,9,5,3],9]]] +[[0,[[10,6,0],10],[],4,5]] + +[[9,[9,[7,7,4]]]] +[[],[[]],[0,7,[[10],[3],[2,6,1,4]]]] + +[[[[4,6,1],8,4,3],7,[[10,5,0]],0],[7,[],10,[9,[3],[7,3,3],[8,10,9,6],2]],[1,5]] +[[[5,[9,2],[6],10,[5,8,6,8,3]],[[2,0,8]],6,[2,4,[10],1],[1,[6,9,10,2],0,[4,9],[9,6,2]]],[[[3,4,3,5],[4,3,7,8],[5,5,1,10],4],[6,[],[9,9],[8,2,5],1],[[],[2],[5,0,9],7,0],[7,9],7],[1,5]] + +[[7,[[3],[0,2,5,10],9,10,4],1,7,6]] +[[1,[8],[6,3,3,[6,3,1],[9,5]],10,[9,[3,3],3,0]],[[8,3],7,5,[9,4]],[10,[2,5,9],10,[4,3,[1],[8,8],0]],[],[]] + +[[[[1,1,3,9]],[[6,10],2],[[8,0,7,3],[0,8,4,8],0]]] +[[],[9,[[10,8],0,[1,5,5],10,4],[0,2,9,[0,4,6]]],[[[9,0],[10,0,9],[9],[10,9,10,4,2],[1]],3,[],[[],3,[0,5,6,1],[]]]] + +[[10,[[3,7],2,5,[0]],[4,[3,6,9]],3],[6,8]] +[[1],[8,10,3],[1],[1,3],[3,[6,[4,2],4,[2,9,0],[8,7,1,10]]]] + +[[[[],6,5,0,10],4,0]] +[[5,[[1],6,3],9]] + +[[7,[[],[],[2,6,10],[0,6,4,2]]]] +[[],[4,1,[[0,3,2,10]],[]],[[7,2,7],[[2,10,6,1],[10,6]],[4,3,8,[9,8,0,2,6]],7,[]]] + +[[4,0,[[3,6,1,2,1],[10,9,6,7,10]],[2,[6,9,3,10],[6,2,9,5,6]],[]],[[5,[9],10,[10,1,0,10,2]],2,[7,10]],[],[8,8],[1,8,[],[[7],9]]] +[[],[5,[9,2,[7,9],[9,3,3,0,3]],[[4,0],[1,7],[9,2,8]]],[[[1,8,10],[],[]]],[[[8,5,9,2,10]],[],[[0],2,[4],[5,1]],10,7],[3,7,[[8,3,1,6,9],1,[],6,[9,3]],5]] + +[[],[4,[2],6,8]] +[[[5,[7,3]],8],[[[4,3,1],4,2,2],[10,4,[3,0],[8,7,8]]],[],[[[7,0]],8,4,2,[5,0,4,[5,10,1,1],[0,9]]],[[[10,6,2],3,[2,6,4]],3]] + +[[8,[[8,1,0,0],9],5,7,[7,[8,6]]],[[[7,10,5,10,7],[8,8,1,10],7,[2,10,4]],5,7],[4,2,1,[[0,3,4,7],[9,0,1,8],6,9]]] +[[8,[3,[],[3,3,10]],[10,[4],[10,5,2,4,5],4,[]]],[[3,0,3,9,2]],[[[]]],[8,6]] + +[[[]],[[8,[1,0,0],[6],2,[8,4,3,3,10]],5,[[3,1,3],[2,6],[9,2]]],[[]]] +[[7],[[9,1],10,5,8,[7,[3,2],[7,0,2,1,1]]],[5,1,0,[1,[8,0,2,9],10,1],6]] + +[[5,2,[]]] +[[[[10,10,2,4],10],0,7,[2,[10,8,3,0,8],[8],[4]]],[],[2,[]]] + +[[[3],[],[]],[],[[[5],[9,2,4,8,10]],[[3,6]],5,[[],[4,6,1,4],1],0],[3,[7],[[],7,[],4]],[[],[[9,3,3,8],4,9,5]]] +[[[],[0,3],[1,6,7]],[[]],[],[8,6],[4,[[5]]]] + +[[],[[0,[8,0,5,6,2],[6,8,4],[8,2],2],[],[1,[6]],9],[1,[7]]] +[[[[0]],[[0,10,4,8,7]],8,0],[2,9,[[9,8,2],8,[7,10,7,5]],[[],[],3],7]] + +[[8,8,[6],6,[8,0]]] +[[4,5,[1,1],8,[]],[10,[[4],7]],[[[3],9],0,[3,8,8,[7,8],[]],0],[[],[5,[5,2,0]]]] + +[[[],8],[[],4,7,[],7],[5,[],[],[[6,7,0,5,4]]]] +[[[5,[2,1,3,0,3],[6,3],[6,5,4,1,4]],[[2],[]],7,10,1],[],[[[],[9,9,2,5],[1,9,7,10,5],4,[1,0,10,7]]]] + +[[7,8]] +[[6,[[9,5],[2,10],4],9,[[10,0,8,6],5,[4],8]],[],[[[3,3,1,2],7],6,8,[[]]],[]] + +[[2,[]],[4],[],[],[[2,8,7,[8,8,0]]]] +[[0,3,4,[2,3,2,0,[7,7,9]],[[2,0,9],[1,6,1,0,3]]],[3,[[3,2,5,3],6,[2,2,3,7],[10,7,4],3],10,[3,4]],[1,5,1,1,[[3,8,6],[0,1],[2],[]]],[9,4,8,7,10],[0,[3,[9,4,3]]]] + +[[[[0],9,[6,3,5,9]],[[1],8,[4,2,1,7,10],[1,6,3,7,8]],[[9,2,0,8,7],6]],[7,9,[[7,9],[],[5,9]],0,1]] +[[7,[[],[4,2,0,3]]],[[8,9,3,8],3,[[]]],[10,5,[8,[6,10],0,1,7],5,4]] + +[[[1,5],7,9]] +[[10,[[4,9]],[[5]],7],[[],[[1,4,7]],[[1,9,0,0],[2,10,5,2,1]]]] + +[[],[[6],[[6,6]],9,[[5,3],9,2,[8,1,6],8]],[],[[[3],[6],[0,3,0],[4,0],[1,8,8,3,1]],0,[[],[10]]],[2,[7,[6,10],5,0,8],[1,[5,1,1]],1]] +[[9]] + +[[6,3],[4,4,3,6,[4]]] +[[],[3,10,0,10]] + +[[8,[4],[[8]]],[6,[]],[],[2],[0,3,10]] +[[[0,[6,2,1,3],2,4,[3]]],[[],0,1,[7,[1,9,4,3]],1],[[[10],[7,10,2,8],6]]] + +[[7,[[3,8,1,7,10]],6,[9,0,[9]],8],[[9,7,4],[[2]]],[[[2,5,7,7],2]]] +[[[[8,0,8],0],[0],[[0,8,5],[8,10,6,2,2],7,[9,0]],0],[[[0,2,9,0],10,[0,3],[1,1,7],0],5]] + +[[],[[5],[],[]]] +[[],[[[6,2,4],10,[8]],1,2,6],[[[3,2,2],8],[]]] + +[[[[],[10],10,7]],[],[6,6]] +[[8,4]] + +[[7,4,[1,[3,5,3,0,7],4]],[4,[4,8,[]],[[2,6]]]] +[[],[4,1,0,4],[]] + +[[10,[6,[9,9]]]] +[[2,6,9,10]] + +[[9,8,[[7,2,8,6],[7],[5,1]],4,[5,1,[5,8,10],[7,5]]],[1,3,[[1,7],10,2,6]]] +[[9,2,[6,2]],[[[2,10,7,7,3],[7],[7,6,5,8,1],[2,0],[6]],[[0]],0]] + +[[],[],[9,[[6,4,0],[4,9,0,2],[0,8,5,0,0]]]] +[[1,[[0],10,6,2,[7,5,5,5,0]]],[7],[]] + +[[[6,6],6],[[3,[3],[]],[1],[3,2,2,6,[10]]]] +[[[[],4,4,10],[[9,4,6],4,[1,2,4,6,4],5,[]],2,[[6,1,9,1,7],9,8,[5,0],[8,3,7,6]],[[8,10,0,5],9,10,10,4]],[[[4,2,6],9,7],9,0,7,9]] + +[[9,10],[9,3],[],[9,[[2]]],[[[],1,[1,9,3,8],[7,2],10]]] +[[[[10,0],9,4],[6],[[5],8,[2,10,8,1,8]],[[10],0,[8,1]],[8,[10],[2,4,5,10,8],[1],[8,6]]],[3]] + +[[2],[[6],0,[8]]] +[[[[10,1,0],[4]],1,[[7,4],[10,7,5,5]]],[9,[[10,8],[1],6,7],3,[[4,8],[],10]],[[2]],[6],[0,3,2,[7,[3,9,8],6,4]]] + +[[[[10,4]],[6,[],1,5,5],[8,8,3],3,[0,[6],[],2]],[7,[9],2],[[[0,4,1]],3,[7,[3,5,2,7,5],3],9,4],[2,3,7,7,9],[2,5,[4,[8,2,4,4],[9],[2,3],[6,7,10,0]],[[9,8,6],[6,1,2,0,1],[7,1,5],[5,0,9,7],2],3]] +[[0,[[8,4,7,3,6],2,[8,10,8]],[3,2,1,[5,3,1,4,1],1],[[4,2,8,1],[10,0,3],[5,7],5]],[5,4,1,2],[[[10,0,2]],[[3,10],4],0]] + +[[[3],[[10,4]]],[0,[[4,2],6,6,10],[[9,6,4],[6,8,4],[10,7,10,4],2],2,5],[7]] +[[5,[[0,9,4]],7,5,[[0,10,3,8,10],[7,2,1]]],[9,[1,[9,2,10,1,1],[1,0]],2,[[9,4],3],2]] + +[[[],8,1,7],[[1]],[8,2],[5,[[],[4],[4,9,2,4],[10,3,0,9],[9,3]],[[4,3,4,1,6],[2]],[[6,6],10,5,[6,8,9]]]] +[[10,[],[[],[1,5,4,10,3],[2,4,5,6],[7,8],[]],[5,[6,1]]],[],[3,[7,[6,0,2,1]],8,[10,[8,9],4,9,7]],[[[],1],[[10,6,9,2],10,[6,1],1,1],9,0,[[9,10,4],9,0,[9],1]],[[[6,0,6],[6,9,0,1,2]]]] + +[[1],[3,9,6,[[5],[],0,5,10]],[[9,[],[3,1,8]],0,[[6,8],6],[[],10],[4]],[[4,[5,6,4,1,5],3,[1,6,5,7]],[[8],2,2],6]] +[[7,5,9,[4],[[],[8,1],5]],[7,3,1,8],[[8,3,0],9],[],[[[1],8,5]]] + +[[6,9,[2,[4,9,3],[7,6,10,7],2,7],8],[[4,10,8],2],[[[8,1,7],8],3],[[[6]],[3],[[],8]],[2,0,8,[8,5]]] +[[4,[9,9],2,[[],[1]]],[[],7,6,1,[]],[]] + +[[[[5,2,4,9],[9,10,8],[]],0],[[8]]] +[[],[9,[[10,4,10],[1,7,10,7],[]],[],7],[[9,5],[[2,2]],0,[[3,4]],[[10,9,1,9,6],[3,0,5,4]]]] + +[[[10,10,[5]],[10],7,[]],[3,5,3],[],[],[[],[7,[9,8,9],[4,2,9,9,2],[]],0,0,7]] +[[[[],1,6,9,[]],0,[0,[0,0],[10,0,0,1,2],0],[[1,7,7],3,[],[9,4],6]],[],[1,6,[5,2],[1,5,[7,2,8]],[[5,9,6,4],[0,10],[6,9,3],[3,8,0]]],[7]] + +[[0,[2],10],[2,10,7,[[9]]]] +[[2,0,2],[10,2,[9,8,9,2,4]]] + +[[2],[2,[10,[4,1,3],10],7,[[7,7,3],[7,8],[0,7,6,3,8],3]],[[[9,0,3],[],[1,3,10,0,8]]]] +[[[[1,3,8,5],10,[4],2],10],[0,9,7,[[0,4,10,0,6],[]],7],[[[0],1,9,[3],[6,9]],4,9],[[5],6],[1]] + +[[[3,[5,3,2,7,9]],10,[]]] +[[[5,7,5],[[9,1,6,7],9,[2,6,5],[6,6,1],[0,6]],[[]],[],9],[[1,[3],[3,10,0],4],2,[],[[2,1,1,5,9],6,8],[]],[],[[],6,[[5,2],2,[8]]],[]] + +[[],[],[1,[[2,0]]]] +[[7,2,2,[],[[8,7,3,6],4,2,2,[]]]] + +[[6,9,8],[[],3,8,[],2],[3,9],[[[],10],[[9,3,9,8]],2,7]] +[[2,[8,[]],[7,8,5,5,5],2,1],[],[[[6,1,9,2,9],7,4],[3,[3,8,1,6]],[[4,6,5],[3,10,8,5,6],[1],8,[5,0,4,0,6]],1]] + +[[],[],[2,1,[4,7,[1]],[9,[7],0,6]]] +[[3],[0,[[6,6,9,6],[4,7,10,1,8],[4,0,10],1,[10]]],[0,[6,5,[8,9,3,9,6],[],[4]]],[[],[[]],4]] + +[[1,8,10,[]],[9,[],[[8]],[[9,6,3,2],[3,8,10],[],3],[1,9,[0]]],[],[5,[1,[],[4,5,7,10,9]],[[10,6,0,1]],9,[0]]] +[[0,3,[9,9]]] + +[[4,0,3],[],[],[[[]],[[5,3,1],8,[],1,[1,8,3,7]],[6]]] +[[[]],[[[8,0,3,2,2],[3],[1,6,8],10,4],[6,4,7,[1,2]],[8,[3],[10,9],[4,0,10,8],[1]]],[[],[1,2,6,8],5],[3,9,7],[[6,6],0]] + +[[7,[],[0],5],[7,[7]]] +[[0,[8,[3,3,8],10,7],5,[[1,7],[0,0],[5,2,0],1],2],[7,8]] + +[[4,[2,2,2,9],[[6,6,1,10,4],[]],5,10],[],[6,[[5,3,7,9,2],[4,2,4,9,7],[1,4,9,7,1]],2,[],[]],[[[7,0],7,[9,4,0]],9,[1,[1,0,1],[9,3,3],[9,2,10,5,10],10],7,[[9,0,8,1,8],8,[7,7,10,2]]],[]] +[[[3,7,[]],[9,7],0],[[[9,9,3,5,2],1],7,[10],[[10],2,[6,1],[1,10,3,1]],8],[3,9],[7,7,2,[2,[8,7,6],10]],[1]] + +[[[7,[10,1],[2,9],[3,4,6,9]],2,[],3],[[],6,3,[],[[4,7]]]] +[[],[[6,[],[],[0,10,2,6],1],1,3,[3,[10,2,7,1,4],[6,3,0],[1,3,6,3],[4]],[0,[8,10,0,8,5],3,2,6]],[],[]] + +[[5,[[4,0],[1,3,4],7,2],0,8,[]]] +[[],[[[],10,[10,9,6,0,1],[]],[[8],4,6,4,[0,2,8]]],[4]] + +[[],[],[],[[[],[8,6],[],[2,7,7,4]],[],1,[9,9,[1,3,4],0,[5,2]],[[4,4,5,6,10],[5,1,3,3],0]]] +[[10,[[6,4],[3,1,1,8,4]],9,[[3]]],[9,2,6,8,1]] + +[[],[1],[[[4],[5,1,6]],[]]] +[[10,[[]],[[8,10],8],[1,[5,3,7,8,7]]],[],[],[[[7]],[[2],6],[[0,8,1,3,10],[],2,0]],[[7,8,[]],2,1,[[8,7,4],1,[4],[],2],7]] + +[[[[3,5],[]],[7,0,5],[[],1,[7,2,7,10,1],3],[[4,1,5,5,6],[3,4],[6,1,3,9,2],8],[8]]] +[[10,10,[6],[4]]] + +[[[]],[8,4],[4,7,8,3,[[8,4,2],6,0]],[[1,[4,6,4],[],1]]] +[[[5],[[4,4,9,2,0]]],[9,[[7]],[[6,2],[0,3,1,1,7],5,4],[0]]] + +[[[3,[1,0,10,7],[8,8,8,10]],[10,[0,3],8,[9,5]],6],[[10,[3],[9,10,0,2]],[7,4],[0,7,4,6,[3,5]],[],[10,[5,4,6,1],5,4]],[[[0],0],5],[4],[8,[[9,4,5],3],[9,[0,7,2]],[],[]]] +[[5,3,9,0],[7,[6,[8,1,0,1,8],3,[9,2],5],[[1,0,0,6,4]],[6,[2,4],5,[2,10]]],[],[3,9]] + +[[[1,[4,0,10,6,8]],1],[],[[[]]]] +[[],[],[[9,[9,7],7,[9,4,3],0],9,6],[2,[[6,8]],2,[9,7,[4,6,10,4,2],[]]]] + +[[2,10,[4,9,[],[7,10,0],1],[[1,8,5,4,6],5]],[[[]],[[10,2,1]],[[]]]] +[[9,9,[10,[1,5,1,2]],[9],3],[8,8],[4,[5,[6],10],[[0,5],[7,10],2],6,[[2,9,8],[5,4,7,5]]],[1],[[10,8,4,[1,7,8,9],8]]] + +[[3,[]]] +[[10],[[3,[7,10,7],[2,6,6,1,1],5],8],[1],[4,[9,1,[2]],7]] + +[[],[[[3,2,0],[3,4,5,10,8],[3,3,3,0,3],[8,3],9],[[5,0,7,8],[],[1,1]],[[10],[2,7,4,4],[],6],2],[[1,[3],[7,4],[8,1,9],3],0,7]] +[[0,8]] + +[[[],[]],[3],[1,9,10,[[4,3,2],[3,10,0,6,4],7,7,10],[6,[10],[9,8,0]]],[]] +[[[5,0,[0],[9,10,7],[1,0]],5],[],[5,3,0,3],[[[3,8,9],[],[2,2,6,6,10],[]]]] + +[[[[9,1,6]],3,[[2,0,8,1,0]]]] +[[3,[[2,1],[8],10,6]],[10,2,3,6,[]],[0,10,0,[[4,7,9],[],3],3],[[[4,2,5],[8]],9,6,[3,[],7,[0,4,8,0]]],[[[6],10,[10,9]],2,[7,[3],[2,0],[6,5,5,7,0]]]] + +[[1,5],[8,[5,1,10,[0,4,9,4,1]],6],[],[7,[3,3,5,10,4]]] +[[],[10,[7]]] + +[5,8,1,2] +[5,8,1,2,1] + +[[0,[],[],[[6,6,7,7],10,3],1],[[6,7,[8,1,4,4,7],[6,6],2]],[[[],7,[],4,2],[[5,5,5,0,7],6,[8,9,7]],[[6,3,3,8,9],1,[6,9,8,5],3],3,[[9,9],[],7,[8,2,8,10],8]]] +[[[9,[2],[],[4,6],[10,2]],5]] + +[[[9],3,[7,2,10]]] +[[2],[9,1,7,[9]]] + +[[],[]] +[[5,[],7],[[[6,0],[7,5,9,7],2]],[[],[[5,2,8],[]],[[5,4,1,10],[3,5,2,2,10],[0,6],10]],[[2],0,8],[]] + +[[[9,10,[4],7,0],1,1,[[],5]]] +[[[[9,8,8,3,1],[10,7,2,10,5]],4,3],[9,[5],[[],[5],10,[10],[10,3,4]]]] + +[[10,[[2],[7,7,3,3,3]],[1,[],[10,4,4]]]] +[[[[1],[1,2,5,7]],[6,3,[2,1,7]],8],[4,5]] + +[[[3,[1,6,1,4,4],[4,5,5,0]],8,8,9],[[],[],[6,[4,10],[],[4,9,2]],6]] +[[0,5,7,8],[]] + +[[2,[[0,5,9],[10,8],[2,1],[5,6,5],[7,9]]],[7,1,[10,3,[2,4],[9,10,1,9,10],0],0],[0,[[2,10,4,0],4],[6]]] +[[[[9,10,9],[8,7,5,7,8]],0,0,[[2,3],8,0,[2,5,10,9,8]],6]] + +[[2,[9,4,5,[2,0]],1,7],[9,[6,[9,5,1]]]] +[[],[[],4,[[4,10,5,8],10,[0,3,6],8],[6]],[[9]],[3,9,9,[],[9,[7,9,5],8]],[[2,1,9,[2,0,9,7,4],[9,10,10]],[8,[9,2,3],2,[6,9,3,8]],[10,7,[],10],2]] + +[[5],[],[],[9],[[[7,8,8],5],[1,[7,4,10],[9,1],2,[]],[],[4,5,1,10,10]]] +[[[10,[10,3,4,0,8],4,5,1],[10,7],[[9,6,6],[5,6,3,7],[5,9,2,0,8],3],[[]],[[1,10,7,1,3],8,4,3]],[[[]],[9],2]] + +[[6,[[1],[7],[]],5,6,8],[6,[2],[[]]]] +[[[7,[10],[7,8,8,7,1]]],[3,10,3,[[6],7,[0,9,7,7],1,[9,9,1,2,2]],3],[6,[6,[2,9]],[[],[2,1,3,2,9],[3,7,9,6],5],[[1]],[6,[9,6,1,3]]],[[2,[2],[5,0,2],5],0,4,5,1]] + +[[[9,0],4,[[7]],4],[9,7],[[1,[0],[1,0,7,1,3],[8],[4,2,0]],9,[[0,5],0,7],6,[[],10]],[]] +[[[[5,10],[4,4,5,3],[9,8,9],[],[5,2]],10,9],[],[[[],[]],5]] + +[[],[],[[],7,7,[2,[8,9]],[0,[7,3],[3,6,1,10,5]]],[3]] +[[[[0,9,7,10]],5],[[],[]],[[[0,2,10],[10,0,5,3,9],9,[],5]]] + +[[8]] +[[[2,[1,6]],[[9,6,6,4,10],[],9,6],[],[]],[],[[1,1,6],4,[[],[4,3,2,9,2]],3]] + +[[5,8,10,4,3],[0,9,[2,9,[4],[6,9,8,0],[9]],6,[]]] +[[],[7,5,[5,[6,5,1,1],4],[[4,10,0,4,10],[10,9],[0,9,1]],6],[[],[[0,9],2],[0,[2,7,9],[],10],[[7,1,9,5,0],[4,3,1,8,1],3,[8,8]],9],[[10,3,5,[5,4,9,10,6]],7],[[1,[],1],[[0,4],6,1,[10,10,8,6,9]],[],6]] + +[[],[1,[2,2,[2,9],4,[]],2],[],[4,10,[],7,[8,[],[]]],[6,8,10,3]] +[[[3,0],4],[[8,[1,10,5]],[[1,7,0,3],[7,3,5]],[10,8,[0],2,[9,2,1]]],[[],[10],[[9,0]],[8,0,4],[[8,0],3]]] + +[[10],[6],[[6,[5,2,7,10,1],[1,6,6],[9,6,10,8],10],2,9,[[0,3,7],0]],[[[3,2],2,9,[]],10,7],[3,1,[6],[9,10,[]]]] +[[[],[[]],6],[[],[],[7],[]],[3,0,8,5]] + +[[],[3,[10],8],[[[9]],[],[[4,5,0,9,2],[],[8],[0,6,9]]],[],[8]] +[[7],[[8,9,4,8],[]],[],[3,8,[[8],[],[6,4,4],3]],[[[10,6]],[[],[],9,[2,3,7,1],10]]] + +[[9,[9,3]],[[7,7,7,7,3],1],[7,[[],[6,10,1],[4,5,3,8]]]] +[[8,4],[[4,1,[1,3,3],0,[0,10]],[[0,6,8],0,[7,5,4],6,[7,2,5,7]],10,2,9]] + +[[],[6],[[[1,4,4,1],[]],2],[1,1,[[0],[6,6]],2]] +[[6,[[0,7],0,[6],3],9,[[8],3,[1,5,0,8,6],[]]],[0,8,2,2,10]] + +[[3,[[7],[10,6,9,3,0],[3],4,4],8],[[0,7,[7,8,8],1,[0,4]]]] +[[[10,9,[],[5,2,8,3]],[8,[8,1],9,[]],10],[6,8,[9,[7],9,[5,8,8,10,1]]],[4],[[[4,9,6],5,9],4,4]] + +[[],[],[[0,[5,5,5,1,3],1,[],0]],[[5,1,[2,10],[1]],9,2,[8,9,[10,10]]]] +[[[3,1]]] + +[[[8,3,[4,2,1,2]],[10],9],[[0,5],[2],3,1],[0,[[1,7,7,9]],1,[8,[7,6,8],5]],[[8,[8,8]],[10,3,[3],[10,9,1]],[]]] +[[[[2,0,2]],[0,2,9]],[8,5,[0],[8,6],10],[10,[[5,1,4],3],10],[[5,[],0,3,[2,4,7,8]]]] + +[[],[[],[6,[5,7,5,5],[8,4,3],6,8],10,[[8,5,6,1,7],[9,8,9,2],[5,2,4,10]],[[8]]],[[5,5,[2,4,4,4,9],9],2,6,[[7,5,7,4,4],3,[],[9]],[[3,9,5]]]] +[[9,6],[[[0]]],[0,8,[[9,7],4,[8,0,0]]],[]] + +[[1,1],[4,1,[5,[0,7,3,5,0],[7,8,9],[4,0,0,8],2],1,[9,[1,9],[],[3,4,8,4,1]]],[[5,0,[4,2,0,9,4],[]],0],[3]] +[[0,7,[[6,0,8],0,[]]]] + +[[],[[],[6],1],[7,[6,3,5],[]]] +[[],[[7,[6],[3,2,2],[10]],[[],[6],[7,9,9]],[[8],[2,10,5],[1,9,5,6,4],3],8],[[],[[9],[2],[0,8,10,6],[3,7]],[5,[1,3,9],2,10,7],[7]]] + +[[[[]],[[1,5,5,3,3]]],[],[1,[8,8,[3,9,6]]]] +[[[],7,2,6,[9,[5,10,0],[9,6,6,5,5],1]],[]] + +[[1,5,[4,0,[8]]],[[[5],8,[7,6,5],3,0],[],4,6],[2,[[2],[0,2,5,3,3],1],4,7,6]] +[[2,[[10,10,1,0,9]]],[[],9,1],[[3,4]],[[[10,2,3],[9,3,7],[10,1,6,1]],7]] + +[[0,[],[[],10,7,[7,8,8]]],[],[0,[[7,2,2,7],4,1,7,[7,8,0,6,6]],[[8,8,6]]]] +[[9],[[[4,7,5],[1,5,8,2],[3,2,8,6,0],[7,5]],[[7,9,6],[]],[0,3,8]],[[4]],[[],[2,5,[]],0]] + +[[8,[[2],0,[]],[5,9],[]],[[2,6],[]]] +[[[]],[0,3,9,4,0],[[[2,4],[6],[4,2,1],[]]],[[1,0,[0,0],7,6],1,5,7,[2]]] + +[[[[4,10,7],0],[[1,1,7,4,5],[1],8,5,9],[[9,9],3,[],[7,6,2]],[[3,0],[3],3],[2,[3,6,3,2],[10,2,6],[],4]]] +[[[10,9,3,0],8]] + +[[[[4,10,7],7,[4,8,5,2,4]],8,4],[[[],5],[],7,[2,3]]] +[[[9],[1,0,[],2,[0]],[[0,1],[10,8],[10]]]] + +[[[[10,1,3,6,3],[3,0],2],[],6],[9,9,[4,[10],4,5,[5,0,4]]],[9,9]] +[[10,10,8]] + +[[[[3,6]],8,[],6,[0,2,8,[1,0],8]]] +[[6,6,6,7,1],[],[],[],[[[6],[6,3]],[4,0],3,3,[[],[10,4,9,8]]]] + +[[1,[[2,1,2,10],5,[],[8,4,2],1],[7,9,[4,5]],[3,[6,6]],5],[]] +[[]] + +[[[3,10],[8,9,9],2,9],[8,[],10,10]] +[[[[],[0]],3,6]] + +[[3,4,[]],[4],[3,9,[5,[1],[],[10,7],[9,0,2,9]],[2,2,9],4],[[[2,2,6]]]] +[[],[4,6,[[],[],[3,7,5],9,7]],[],[[8,5,7],8,1,3,8]] + +[[],[[0,2],0,7,[],[[6]]],[[],[8],[3,[],3],[7,[5,0,4],7],5],[1,1,[[]]],[[[0,10,7,10],2,0,[3,7,1,1]],9]] +[[[8,[7,6,6]],9],[10,8,9,6],[[[],[1,7,3]],[[5,5,5,1],[],0,[7,7,9,8],7],[10,[],[3,9,7,4,3],10],[[8,7],10]],[[2],[5],4,[[2,6],[7,7,10,7,0],[3,8,3],3,6],10],[9,10,[[6,2]],5]] + +[[4,2],[[9,5,7,7,[]]]] +[[[1,[4,8,7,2,4],4,[4,6,5,6,4]],[8,[6]],8],[3]] + +[[3,2,1,8]] +[[[10,6,[2],2],10],[[],3,10,[[],[],[4],6,8],[[8,5,10],[],5]]] + +[[[6,[5,5,0]],5],[[],7,1,[],7]] +[[3,4,1,6,[[],[4],9]],[[[3,4,5]],[],4]] + +[[4,[5,4],[[0,10,9,1,5]],5,5]] +[[3]] + +[[0,[8],9],[3,[[5,7]],8],[[5,7,1,10,4]]] +[[6,[3,6,3,[9,2,9,2,9]],[[3,4,1,9,5],7,4,10,[5,0,4,4,2]]],[0],[[0,1,[7],[],0],[5,4,[9,3]],9,1,[[6,0],[7,4]]],[[5,8],2]] + +[[6,[],[[4],[3,5]],6],[8,[7,5,3]],[5,[[],2,[1,1]],[6,4],[],[[0],9,[0,8,10,4],0]]] +[[[[10,5,10,4],[9,1,7,6,10],[0]],9,[1,2,3,5],[0,[5,7,4,7],[9,10,7],1,7]],[[[],0],7,[8,[10,1,10,7,8]],[4,1,[4,3,10],[],1],5],[8,9],[[7,10,2,[4],2],[[3],[8,8,0,6],6,4]]] + +[[[[7,8,2,2],[8,2,3,0],[4,3,8,0,8]],5,[[9,7,1],[],[1,0],[1,2,6]],9,[[5,1,7],3,[],5]]] +[[[0,[8,3,5],[5],1],[8],[[4,10,10,8]],0],[[0]],[[[7,2],[8,9],[]],[[],[1,9,7],[9,4,6],[5]],[[5,8,7,2]]]] + +[[[],2,[1,[6,6,2,2,5]],8]] +[[0,[[2,7,6,0]]]] + +[[],[10,1],[6,[2,[],8,0,[5,1,7,9,4]],9,4,9],[[[8,5,9,4,1],6],3,[],9,3],[[2],[],[[9,3,7],8,[0,1],[1,2,1,9,1],[]],[[6,7],[5],2,9],[[]]]] +[[[8,6]],[0],[],[10]] + +[[],[9],[],[[[],[2],[9]]],[6,7,10,[8,[],[6,3],0]]] +[[7],[9,8,[[2,5],[6]],[[3,10,5,5,4],[1,8,3],0,9,[0,2,5]]]] + +[[6,[],[[6,6,0,3],[10,0,6,5,0],9]]] +[[],[[10,[7]],8],[7,7],[[5,1,[10],[8,1,6,0,10],3]],[4,[0,6]]] + +[[3],[[6,9]]] +[[[[5,10],8],10,[[9,1,10,4,4],[10,3],4,[9,9,9,9,5]]]] \ No newline at end of file diff --git a/2022/day-13/solution.test.ts b/2022/day-13/solution.test.ts new file mode 100644 index 0000000..c4f0e65 --- /dev/null +++ b/2022/day-13/solution.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(6076); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(24805); +}) diff --git a/2022/day-13/solution.ts b/2022/day-13/solution.ts new file mode 100644 index 0000000..a72846f --- /dev/null +++ b/2022/day-13/solution.ts @@ -0,0 +1,93 @@ +type Packets = (number | Packets)[]; + +/** + * Compares 2 packets, returns `null` if can't determine +*/ +const areInRightOrder = (packets1: Packets, packets2: Packets): boolean | null => { + // iterate over all packets + + for (let i = 0; i < Math.min(packets1.length, packets2.length); i++) { + const packet1 = packets1[i]; + const packet2 = packets2[i]; + + // if a number, compare and return if decisive + + if (typeof packet1 === 'number' && typeof packet2 === 'number') { + if (packet1 < packet2) { + return true; + } else if (packet1 > packet2) { + return false; + } else { + continue; + } + } + + // if any of those not a number -> convert to list, then compare lists + + const result = areInRightOrder( + Array.isArray(packet1) ? packet1 : [packet1] as Packets, + Array.isArray(packet2) ? packet2 : [packet2] as Packets, + ); + + // if result determined, return + + if (result !== null) { + return result; + } + } + + // if result was not determined by this point, compare lengths + + if (packets1.length < packets2.length) { + return true; + } else if (packets1.length > packets2.length) { + return false; + } else { + return null; + } +} + +const solvePart1 = (input: string): number => { + let rightOrderPairsCount = 0; + + input.split('\n\n').forEach((pairs, index) => { + const [packets1Str, packets2Str] = pairs.split('\n'); + + const packets1: Packets = JSON.parse(packets1Str); // apparently, packets string is a JS array :) + const packets2: Packets = JSON.parse(packets2Str); + + if (areInRightOrder(packets1, packets2)) { + rightOrderPairsCount += index + 1; + } + }); + + return rightOrderPairsCount; +}; + +const DIVIDER_PACKET_1: Packets = [[2]]; +const DIVIDER_PACKET_2: Packets = [[6]]; + +const solvePart2 = (input: string): number => { + // in part 2, we don't care about pairs, so we just parse everything in the array + + const pairs: Packets[] = input.split('\n') + .filter((line) => line.trim() !== '') // filtering out empty lines + .map((line) => JSON.parse(line)); + + // add divider packets + + pairs.push(DIVIDER_PACKET_1, DIVIDER_PACKET_2); + + // sort pairs based on the order using native Array.sort + + pairs.sort((a, b) => areInRightOrder(a, b) ? -1 : 1); + + // find dividers indexes + + let dividerPacket1Index = pairs.findIndex((packets) => packets.toString() === DIVIDER_PACKET_1.toString()) + 1; + let dividerPacket2Index = pairs.findIndex((packets) => packets.toString() === DIVIDER_PACKET_2.toString()) + 1; + + return dividerPacket1Index * dividerPacket2Index; +}; + +export { solvePart1, solvePart2 }; \ No newline at end of file diff --git a/2022/day-14/input.txt b/2022/day-14/input.txt new file mode 100644 index 0000000..6d90a55 --- /dev/null +++ b/2022/day-14/input.txt @@ -0,0 +1,137 @@ +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76 +498,13 -> 502,13 +525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120 +504,21 -> 508,21 +492,17 -> 496,17 +534,137 -> 538,137 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +469,37 -> 469,38 -> 487,38 -> 487,37 +548,160 -> 548,161 -> 561,161 -> 561,160 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +469,37 -> 469,38 -> 487,38 -> 487,37 +537,139 -> 537,140 -> 548,140 -> 548,139 +523,117 -> 527,117 +501,15 -> 505,15 +514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110 +497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76 +514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110 +545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +492,21 -> 496,21 +548,160 -> 548,161 -> 561,161 -> 561,160 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120 +469,37 -> 469,38 -> 487,38 -> 487,37 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120 +481,45 -> 486,45 +495,15 -> 499,15 +525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110 +547,143 -> 552,143 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146 +511,117 -> 515,117 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +484,43 -> 489,43 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +498,17 -> 502,17 +489,19 -> 493,19 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76 +525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120 +545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +537,139 -> 537,140 -> 548,140 -> 548,139 +537,139 -> 537,140 -> 548,140 -> 548,139 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76 +498,21 -> 502,21 +514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110 +545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146 +517,113 -> 521,113 +534,133 -> 538,133 +545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +507,19 -> 511,19 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +517,117 -> 521,117 +504,17 -> 508,17 +514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110 +487,41 -> 492,41 +507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89 +478,47 -> 483,47 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +492,47 -> 497,47 +545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146 +488,45 -> 493,45 +525,120 -> 525,122 -> 522,122 -> 522,130 -> 535,130 -> 535,122 -> 531,122 -> 531,120 +491,43 -> 496,43 +514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110 +507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89 +486,21 -> 490,21 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +537,135 -> 541,135 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +531,135 -> 535,135 +497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76 +507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89 +499,47 -> 504,47 +507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89 +514,110 -> 514,103 -> 514,110 -> 516,110 -> 516,101 -> 516,110 -> 518,110 -> 518,105 -> 518,110 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +497,76 -> 497,80 -> 494,80 -> 494,86 -> 508,86 -> 508,80 -> 503,80 -> 503,76 +501,19 -> 505,19 +495,45 -> 500,45 +540,137 -> 544,137 +520,115 -> 524,115 +510,21 -> 514,21 +485,47 -> 490,47 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89 +491,73 -> 491,63 -> 491,73 -> 493,73 -> 493,65 -> 493,73 -> 495,73 -> 495,68 -> 495,73 -> 497,73 -> 497,67 -> 497,73 -> 499,73 -> 499,68 -> 499,73 +548,160 -> 548,161 -> 561,161 -> 561,160 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +495,19 -> 499,19 +514,115 -> 518,115 +507,89 -> 507,93 -> 499,93 -> 499,97 -> 516,97 -> 516,93 -> 510,93 -> 510,89 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +479,34 -> 479,32 -> 479,34 -> 481,34 -> 481,30 -> 481,34 -> 483,34 -> 483,26 -> 483,34 -> 485,34 -> 485,25 -> 485,34 -> 487,34 -> 487,26 -> 487,34 -> 489,34 -> 489,32 -> 489,34 +497,60 -> 497,59 -> 497,60 -> 499,60 -> 499,55 -> 499,60 -> 501,60 -> 501,54 -> 501,60 -> 503,60 -> 503,53 -> 503,60 -> 505,60 -> 505,53 -> 505,60 -> 507,60 -> 507,52 -> 507,60 -> 509,60 -> 509,53 -> 509,60 -> 511,60 -> 511,58 -> 511,60 +528,137 -> 532,137 +545,146 -> 545,150 -> 537,150 -> 537,156 -> 551,156 -> 551,150 -> 548,150 -> 548,146 \ No newline at end of file diff --git a/2022/day-14/solution.test.ts b/2022/day-14/solution.test.ts new file mode 100644 index 0000000..67ae86b --- /dev/null +++ b/2022/day-14/solution.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(873); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(24812); +}) diff --git a/2022/day-14/solution.ts b/2022/day-14/solution.ts new file mode 100644 index 0000000..1290b4c --- /dev/null +++ b/2022/day-14/solution.ts @@ -0,0 +1,153 @@ +/** + * Cave is an object that stores the state of the cave. + * It keeps track of all occupied coordinates in there (by rocks or by sand). + */ +class Cave { + /** + * I think, the most optimal data structure could be 2-dimensional binary tree aka point quadtree. + * + * Current implementation is Map (lookups should be sublinear). It's quite fast comparing to just a Set, + * and consumes way less space comparing to a 2D array of the cave. + */ + private occupiedCoordinates: Map>; + public yBottom: number; + + constructor() { + this.occupiedCoordinates = new Map(); + this.yBottom = 0; + } + + /** + * Marks (x, y) as occupied + */ + public addEntity(x: number, y: number): void { + if (y > this.yBottom) { + this.yBottom = y; + } + + if (!this.occupiedCoordinates.has(x)) { + this.occupiedCoordinates.set(x, new Set()); + } + + this.occupiedCoordinates.get(x)!.add(y); + } + + /** + * Checks if (x, y) is occupied + */ + public hasEntity(x: number, y: number): boolean { + return !!this.occupiedCoordinates.get(x)?.has(y); + } +} + +/** + * Parses input to a Cave + */ +const parseInputToSpace = (input: string): Cave => { + const cave = new Cave(); + + input.split('\n').forEach((rockPathStr) => { + // we store previous rock coordinates to fill in the path to the next one + + let prevRockCoords: [number, number] | null = null; + + rockPathStr.split(' -> ').forEach((rockPathCoords) => { + const [x, y] = rockPathCoords.split(',').map(Number); + + // if prevCoordinates, then fill the entire path + + if (prevRockCoords !== null) { + const [prevX, prevY] = prevRockCoords; + + const dx = Math.sign(x - prevX); + const dy = Math.sign(y - prevY); + + let x0 = prevX; + let y0 = prevY; + + while (x0 != x) { + cave.addEntity(x0, y); + x0 += dx; + } + + while (y0 != y) { + cave.addEntity(x, y0); + y0 += dy; + } + } + + cave.addEntity(x, y); + + prevRockCoords = [x, y]; + }); + }); + + return cave; +} + +/** + * Simulates dropping a sand and occupies its final position in a cave. + * @param firmBottomAt – y coordinate of a firm bottom (if exists) + * @returns true – if sand landed, false – if can not drop or nowhere to land + */ +const dropSand = (cave: Cave, x0: number, y0 :number, firmBottomAt?: number): boolean => { + let x = x0; + let y = y0; + + // simulating sand falling, one level at a time + + while (y < (firmBottomAt ?? cave.yBottom)) { // stop if bottom reached + if (!cave.hasEntity(x, y + 1)) { + y += 1; + } else if (!cave.hasEntity(x - 1, y + 1)) { + y += 1; + x -= 1 + } else if (!cave.hasEntity(x + 1, y + 1)) { + x += 1; + y += 1; + } else { // nowhere to go => landed successfully + cave.addEntity(x, y); + + if (x === x0 && y === y0) { // if starting coordinates, stop + return false; + } + + return true; + } + } + + if (firmBottomAt) { // if firm bottom, then landed successfully + cave.addEntity(x, y); + return true; + } + + return false; +} + +const solvePart1 = (input: string): number => { + const cave = parseInputToSpace(input); + + let countDropped = 0; + + while (dropSand(cave,500, 0)) { + countDropped++; + } + + return countDropped; +}; + +const solvePart2 = (input: string): number => { + const cave = parseInputToSpace(input); + + let countDropped = 0; + + const firmBottomAt = cave.yBottom + 1; + + while (dropSand(cave,500, 0, firmBottomAt)) { + countDropped++; + } + + return countDropped; +}; + +export { solvePart1, solvePart2 }; \ No newline at end of file diff --git a/2022/day-15/input.txt b/2022/day-15/input.txt new file mode 100644 index 0000000..b9320de --- /dev/null +++ b/2022/day-15/input.txt @@ -0,0 +1,34 @@ +Sensor at x=1363026, y=2928920: closest beacon is at x=1571469, y=3023534 +Sensor at x=2744178, y=3005943: closest beacon is at x=3091714, y=3106683 +Sensor at x=223983, y=2437431: closest beacon is at x=-278961, y=3326224 +Sensor at x=2454616, y=2576344: closest beacon is at x=2885998, y=2387754 +Sensor at x=1551436, y=29248: closest beacon is at x=1865296, y=-1279130 +Sensor at x=2997120, y=2493979: closest beacon is at x=2885998, y=2387754 +Sensor at x=1588355, y=3153332: closest beacon is at x=1571469, y=3023534 +Sensor at x=3539081, y=3302128: closest beacon is at x=3309042, y=3583067 +Sensor at x=3973905, y=60392: closest beacon is at x=3515381, y=-806927 +Sensor at x=3305001, y=3120691: closest beacon is at x=3091714, y=3106683 +Sensor at x=3859262, y=2668840: closest beacon is at x=3574747, y=2000000 +Sensor at x=2475557, y=3997856: closest beacon is at x=2364210, y=4052453 +Sensor at x=2775306, y=3668540: closest beacon is at x=3309042, y=3583067 +Sensor at x=3018235, y=2285225: closest beacon is at x=2885998, y=2387754 +Sensor at x=3033163, y=3294719: closest beacon is at x=3091714, y=3106683 +Sensor at x=3079956, y=3215569: closest beacon is at x=3091714, y=3106683 +Sensor at x=3994355, y=1831842: closest beacon is at x=3574747, y=2000000 +Sensor at x=1741021, y=3231978: closest beacon is at x=1571469, y=3023534 +Sensor at x=1873455, y=3917294: closest beacon is at x=2364210, y=4052453 +Sensor at x=3128140, y=2938277: closest beacon is at x=3091714, y=3106683 +Sensor at x=732217, y=3603298: closest beacon is at x=-278961, y=3326224 +Sensor at x=3884431, y=3834735: closest beacon is at x=3309042, y=3583067 +Sensor at x=3679358, y=1029949: closest beacon is at x=3574747, y=2000000 +Sensor at x=2260133, y=3563353: closest beacon is at x=2364210, y=4052453 +Sensor at x=60149, y=3320681: closest beacon is at x=-278961, y=3326224 +Sensor at x=3132535, y=2405693: closest beacon is at x=2885998, y=2387754 +Sensor at x=3028313, y=2829410: closest beacon is at x=3091714, y=3106683 +Sensor at x=3142423, y=3921417: closest beacon is at x=3309042, y=3583067 +Sensor at x=2636416, y=939525: closest beacon is at x=2885998, y=2387754 +Sensor at x=524530, y=681397: closest beacon is at x=-1031499, y=681463 +Sensor at x=3155000, y=1666362: closest beacon is at x=3574747, y=2000000 +Sensor at x=2169350, y=3040469: closest beacon is at x=1571469, y=3023534 +Sensor at x=1663350, y=1595182: closest beacon is at x=1571469, y=3023534 +Sensor at x=3311582, y=3386773: closest beacon is at x=3309042, y=3583067 \ No newline at end of file diff --git a/2022/day-15/solution.test.ts b/2022/day-15/solution.test.ts new file mode 100644 index 0000000..aca27a1 --- /dev/null +++ b/2022/day-15/solution.test.ts @@ -0,0 +1,14 @@ +import { test, expect } from 'bun:test'; + +import { solvePart1, solvePart2 } from './solution.ts'; + +const inputFile = Bun.file(import.meta.dir + '/input.txt'); +const input = await inputFile.text(); + +test('part 1', () => { + expect(solvePart1(input)).toEqual(5144286); +}) + +test('part 2', () => { + expect(solvePart2(input)).toEqual(10229191267339); +}) diff --git a/2022/day-15/solution.ts b/2022/day-15/solution.ts new file mode 100644 index 0000000..5381e71 --- /dev/null +++ b/2022/day-15/solution.ts @@ -0,0 +1,144 @@ +const ROW_TO_CHECK_Y = 2000000; + +const SENSOR_LINE_REGEXP = /Sensor at x=(?-?\d+), y=(?-?\d+): closest beacon is at x=(?-?\d+), y=(?-?\d+)/; + +/** + * Calculates manhattan distance between (x0, y0) and (x1, y1) + */ +const manhattanDistance = (x0: number, y0: number, x1: number, y1: number): number => { + return Math.abs(x0 - x1) + Math.abs(y0 - y1); +}; + +/** + * Details of each sensor and its beacon + */ +interface SensorDetails { + sensorX: number; + sensorY: number; + beaconX: number; + beaconY: number; + distanceToBeacon: number; +} + +/** + * Parses input to an array of SensorDetails + */ +const parseInput = (input: string): SensorDetails[] => { + const sensors: SensorDetails[] = []; + + input.split('\n').forEach((line) => { + const matches = SENSOR_LINE_REGEXP.exec(line); + + if (!matches || !matches.groups) { + throw new Error(`Can not parse sensor line: ${line}`); + } + + const sensorX = Number(matches.groups.sensorX); + const sensorY = Number(matches.groups.sensorY); + const beaconX = Number(matches.groups.beaconX); + const beaconY = Number(matches.groups.beaconY); + + const distanceToBeacon = manhattanDistance(sensorX, sensorY, beaconX, beaconY); + + sensors.push({ sensorX, sensorY, beaconX, beaconY, distanceToBeacon }); + }); + + return sensors; +}; + +const solvePart1 = (input: string): number => { + const sensors = parseInput(input); + + /** + * A Set of X unavailable coordinates at ROW_TO_CHECK_Y (the ROW_TO_CHECK_Y is fixed, so we don't store it). + * We need to remember already found unavailable locations to avoid duplicates + */ + let unavailableLocations = new Set(); + + // check if each sensor's unavailable area cross ROW_TO_CHECK_Y + + sensors.forEach(({ sensorX, sensorY, beaconX, beaconY, distanceToBeacon }) => { + /** + * starting from (sensorX, ROW_TO_CHECK_Y) we're going left and right simultaneously, 1 point at a time + * until distance <= sensorToBeacon distance + */ + + let dx = 0; + let distance = manhattanDistance(sensorX, sensorY, sensorX, ROW_TO_CHECK_Y); + + while (distance <= distanceToBeacon) { + if (beaconY !== ROW_TO_CHECK_Y || sensorX - dx !== beaconX) { // make sure to skip the actual beacon's location + unavailableLocations.add(sensorX - dx); + } + + if (beaconY !== ROW_TO_CHECK_Y || sensorX + dx !== beaconX) { + unavailableLocations.add(sensorX + dx); + } + + dx++; + distance += 1; + } + }); + + return unavailableLocations.size; +}; + +const solvePart2 = (input: string): number => { + const sensors = parseInput(input); + + /** + * Checks if new beacon can be placed at (x, y) + */ + const canBePlaced = (x: number, y: number): boolean => { + return sensors.every(({ sensorX, sensorY, distanceToBeacon }) => { + return distanceToBeacon < manhattanDistance(sensorX, sensorY, x, y); + }); + }; + + /** + * It's trivial that if a single available location exists, it must be located on the border of + * existing sensors unavailable areas. Therefore, we don't need to check all possible locations (4000000 * 4000000), + * but we can rather just walk over each of the sensors. + */ + + for (let i = 0; i < sensors.length; i++) { + const { sensorX, sensorY, beaconX, beaconY, distanceToBeacon } = sensors[i]; + + // walk over the sensor unavailable area clockwise from top-most + 1 point + + let y0 = sensorY - distanceToBeacon - 1; + let x0 = sensorX; + + let y = y0; + let x = x0; + + let dy = 1; + let dx = 1; + + do { + if (x === sensorX + distanceToBeacon + 1) { + dx = -dx; + } else if (x === sensorX - distanceToBeacon - 1) { + dx = 1; + } + + if (y === sensorY - distanceToBeacon - 1) { + dy = 1; + } else if (y === sensorY + distanceToBeacon + 1) { + dy = -1; + } + + // if coordinates are within boundaries and the new beacon can be placed -> a single locaiton found + if (x >= 0 && x <= 4000000 && y >= 0 && y <= 4000000 && canBePlaced(x, y)) { + return x * 4000000 + y; // return the "tuning frequency" + } + + x += dx; + y += dy; + } while (y !== y0 || x !== x0); + } + + throw new Error(`Can not find a place suitable for a beacon`); +}; + +export { solvePart1, solvePart2 }; \ No newline at end of file