From c1aa86d7e23c4a7d5781e58dbc9cef70d679d67c Mon Sep 17 00:00:00 2001 From: merrywhether Date: Tue, 17 Dec 2024 22:54:52 -0800 Subject: [PATCH] day 14 --- src/14/enput.txt | 2 + src/14/input.test.ts | 14 ++++++ src/14/main.ts | 116 +++++++++++++++++++++++++++++++++++++++++++ src/14/sample.txt | 12 +++++ src/14/test.ts | 9 ++++ 5 files changed, 153 insertions(+) create mode 100644 src/14/enput.txt create mode 100644 src/14/input.test.ts create mode 100644 src/14/main.ts create mode 100644 src/14/sample.txt create mode 100644 src/14/test.ts diff --git a/src/14/enput.txt b/src/14/enput.txt new file mode 100644 index 0000000..382b39d --- /dev/null +++ b/src/14/enput.txt @@ -0,0 +1,2 @@ +109,243,0,139,25,166,200,95,96,181,184,171 +9bd534b89150fb3c0f1dbd171a0bbd4ca63767fb3f13aba85ecdd3b6e0f55a70423f63ffe5013485ad110f6958bcee79292198424feb4a4e0c97c3db352664638c5d0417305235e3421dcdd04bb2576beb9c94c7425fb9ca5259a3226be61963c54e1e71e39fddfc2d6a068d0bbe7eb537f6386f397091a0710bc83f2826da3ff7e4e877708bc608ee921a70300ac7bd86fd8a16a65cc867559a31f5ae41bb398826bb0da2ccc97840bb061d9e853d9a9cf0737cee57f9b5f9b1e6fcebc5b7842ff059211d820a8c73a5a79605ead789bf4efe29ff0e504559b40bc60c1a17472543ddfc2d2984d0e1b9e715f008a8933df56635d54082d78bcbd5f16b8aede02b454bff7510c7e853cdb863dda9a450a73904af4a1d335583aefaa0132007e93abbe2a04e70005d134bf3b013d4dc0d6eb0311c5b7877e29dbbf86fce98621ba2b05e63741c91b758a212b07990679da565b63ff53853617011b2ca0a095c3cdce2b71027f29331a2fab31b152204d170d3f92fc3de48dbb11090add969aa3e3463cce3e372fd5af504ded394ef6da9a3bc65574d6bd3429a31a35e3b483a98312dee038fd9bd4d2e393a6e5decce06aaf76cac1b8b9bdc57641f941be851c198fa64b537bb7264c24bca22a0e4e38d91a21ff9d297980b25664b03e5a34e5368d2572dd4c13e7ec3bd2e3e5f32a2c893c09320c72708be6ebc35e5f69f5ae24e014d2815d573041bfb4e392b74993b2122dcfe4e52171ae02529dd31a9fe3f53c61cb7931a35efbef8fa35e6dc3a35e8aeb48f814fde72f5f05799ec8549640a8ab89d125925bebb8dd365ef8edc0cd6c8e468e0059e48451406a159f5bb2beaabce125572402be3abc37f9832ab178d91d1eb3dfde3325ecf2bdfa9903eadca7a62d2d5c6357605f3112c545ed30a50dbca4aa0c7872e616704ada66b33c165cb87668c6549e7f4f77f216593b6835862876f685e697b7165942c708c7a23fa2610488e89b3fe21bd6a9a10ed42ea97e8c3b01c19fb1b55f89df3f1eea742b713e0e71d9578d24520c38edd49b81d6dc9a5d3d06f333b13a9ff110ebb0a6fb13ea66430b21d5fd4f1b5fc8410531cfa7baf61dbf5559f81c72d321b8dd9256e5e87c7712cb4d731651e7a1abd318bd9ea5085dc12f13ccc9b63dd5dcc1cd696ce22a013c52c29f8be35eed3a9fbfb75498735f024aae0d0237939041998a736963aa108c7ae9dede01207db30b69f85098b754e9015a5c51556f84fac0105fdd9c2bb28cea253a75e4ab7d8f0b94e90ec6f75ffa1043986bae9187f74f8e1c9069bab2304d52f13ceb48998c6f0afa1f7a65fb5b2b4b935bdb86ca407b9c5eeb296be8c32505a7a0b9d34d4410626adb7bcc1a589750ef3423e0d26a0d51f7d48777d7b6f6d53738a9e0c3dd4f2e649d64d139a90574becef56cdb57ffdd69a6a563c24df75a53860b913a85cb12bcfc0e326d08502ed7bc973f9a35ae391f4cd022452e7764e794dff87781eb84ed783aac87c6b467a305d7f4f5e1d64a52903ba99410989d8311abaeabd8150d86a69ec2f0551ab0afd500e0cad6c0bd36ae43675c2e5b667d5abe972e0d8fdced13b6c39a6d30af4d4de74821bb2f21068b43913cee64a1ab5015673eba92ae60b070be2b21948c5f60217b4f8653226ed5841557fcd404bdfaf118ce189a927ad4e873ee17ee88a6cc0a61600e9392ea54fc6f2bc6c6782bd58f0d910bb220b975c5780409db797faa668d0d00b0f2b0094b037077f169962a0c83c141f5a490df2e9a99ba0945891c0dc63b7474752d882887018e12e1262e8c22aa28b76b51e30df003fb0e400ef3ab967853f96048ff0b5ef25d4e38a75242ab21d634ecd68cd649b831f7854692b911d9bedda1cbb8956999e47a3a38cb0d1d1db43a232477725b9be3b58f175261f29dbf046fdb39853a0a6e151a6e76e7e577dcb0cdb3fb778417b0b64570caae77ca006040562e4be2ca701d8c5e1327e6386a290bbc83a4e4fd54325e1efb279fc5ef0c921d80c76bed3599d6548ec723673247ab6007f9147a56a970b3da72aba03fd9f13e72a1acdf73bb7c0ea9b714d22aeb05170dc3a214dfe9fe1465f545ae50e9d4bee140b0e22a4e0237cb6ca5cb35c2dd12a202e4aca7f93614909a80d8edc6cbc4f339375b6c24afad4c4fc81853e6e6acd5e75157a0afb1993af51b9c7dd7f40f2a748eaba91ddc30965530ba1cd5dcd5ec3558432318d3cde606f736e9c047a3e725890cc5de43b788ee72557abac49a3c47c57a722be4d0e4d4b321d3948f9010b1c078d98782a52e563cc850d6b13c2c70a1d44a360ac1335e619af1191e782e0fe75c39d9d7a307bf6799d73003f91de0de76ca6f31b17b9a429ea01942beb6554b968a1243dbb9143a1f9a003e4ab49280961ac96981165ee5ed109969a440cffe9c523cbd32141c507994eb9affda4c593c89c38df66f14fe004fe9d72ad363c8e626d765b55132d630f04bb936e8c6bdca150382fac6726e428c8a26c3b7a14815409bd3fe84e1c41304cb990e1f5285d4196a51a65c33e30f725d5c62b491fe429368abb2e4da7c2c99edb777684359f1f78cb73c2001fed025534da095327f82fe50a8ed1a1be90118384968aba87a22ce687b309f22368be937d53546ed2fd4db4cd970161fb436b31fda318122073a9dab1b606226325b0b4d5e53cc6b844fcc1d368ad6d496256d5fbe521a3d59357169b6324e156cf6deffbace97b90c4f5bdcc326963d9336ccd0ad08197bbab9eb203de9d462b87c1d164f16d4fee2fa23663687c82b5567248f661cc7e06e3d75259b5c0d40e3251454f288a7db03acefd2502d7c0733432629cca250cb1387a40f6c83235926c7a8e9e4fc81ae87482e8a148e59c560ab4805a247f4546534417e3f797eab7dcf2bc74d0ff55959a990b358e89e970622dbea9d23db3c17505429fe91baae073016bc039929fb311b87fbddf57c5c4563f74c4ee6964c5749748d542dec260c8117402ad65f1a538c4408b9c7da1654b83a5d5ff5b2dae7189f432d5787c572aa887b6514b799c0e449b1c9c0301f836adb1ce26d03bbcdee9421579d041930f28813510d230221708d8749b478af8253a1bd86803dd75ea793203999d6877e2995f2e8a23b060cc2ac329d24f4d58e81f5d263da763bed3a9fb4c4e47e2af6a09a76e8847f7f907d556be6759079a85b1f486ad48fe24a1fc4cad13ae5af80c570eeec0450e1ed78faafde62ee875556900c57d14d1b719c88c586dd9686ea964b4e9676a6f97f8fb854a13a49cb3ef162b3359c778e0663526d787afabbd5c2d05a7291b40d637b42d952624886a1cd11c371198bfb781a5e62e396a282117f6da8e3eeefa46361df23422657118a12662ab58a0c646ecd1e7ea89e64dc7980b4f4d75420988ebec56bc91c23c7a7fcd76ba497fc4eaaf387f993e8a18471fdaa3412df162a5ab6fd31302dbc851a993f9c9509106b1447ae50bb1cee7fe23af6ae434ff3726b7e6989b73fe564ebfa5f03ebe4d84e14390b65dc2e0f07e2617ae86ebcc643dd779647aa5166920d72e5d7e8e25834c50853c75d64582a46ddd1c682e0ac83c646cbab48ed424954c93e3a82822c74e2cd7cabf510a5ddbec6e0f9de8961900ff69ead90278df57197fe12c62be81fcec27e374c7e21bee8db1185fbea3b85adc54848bfa22e7a7d742882c82c0a7953548808aed7c8554120066478ab685e11ce223668c265b834f6d2c93c56bff9c374c224c3b3a35fa1aaab15620b80fa65432cf539379d28590ec707a326922a1f89ce9260208bda787d2bf92932d04dec558ce61c5807e2436a2b0f52a6da10342250e55573f703f7f07dbf03a7c53a8e9f642fce406faeec31983d35208a09d66f9f314b69a96b28d448af812867db1955d08bad3846814bb052f0fda13521e691c68f444d85e6d9d95e3c5d59b6f81aafbcad29946d40434699b9fa93c4e12dc55a1c21efa6db2ee37e12ef37b750c82cca358ed917bb64c592a6cd3497fc07fc35f16f3f21880e87fbae0db7b51534b8e1c1b13914fc42167ee1662ff8d4d3aaa40ce8aa74d55e8cb741b3fee000a93d1ae86c3394d0eca5cdeef9cf5a64a7262db231fd777998f8a4f4bc717af321aabbb92235cf55add4a529bbd95e241a117659930e95926d47485a9db1ca87bd12a30e21bda450a4cb5d40da15d31c7b1c1498c9e05c357156c0e192513b3498fb5b69c777d47b6908145b50af6444cc3c650f450a4754c0b7bffb545f3dd8e03484f5cc146f41cd3458a82889fd10bb815bf66ef7c0367f6b3a59f30856fabf15f00a832423fa7d8f9a7ce1aa2b348137ae1f2283545bf9db4e9f086c3ff1dc55840b8ff21ca7957f87edd1a008b38db16797e4dc4604e76e399e8404751fcbb1c4aca5412b6d82edd216d1396e561d3e4f3b2f435f91785d65c55f5ce5e047e0b21ceec4ccdb0db136d41e2885fae0119ca33e4d18382cfdfc3fe9b09d67009b715bb2bb5dbc2f2812fea8fadf83318a12b9f743b266811ee44053d73ec17391ab623a7f40df9e44e6bbbc74b05a167ea89007e3a7df38af99a4a0f7bdbf5757bc19a1bea59ff5cbfce04bdf008a152cd6dd44807ce90a9d5361a6f8c0a4b1edfdcf4af733afbccec3cba4acf20b98990a386e91a7aaae627069ca8c10ad96b59717b26242fcd1cc7dde0953f8aeb48a1ff9d8dd59cf6496b8c07a029f9dcadc97672f58890ba67d89af6d8626a021e0e07c9045618d365ec2c3041893a02d1a9ed1fa0dea0adc1c38d2a30a63491afa1961d727715092619ad17c1784bcff43b2c4812c1a04e9a1f1f91976dd659dbc83f6c9aeb2dafebe06ad59448104a3dbaab93b6ee08a9cbb143f64f50262a10f48ec38eae80ab7ae5afa169faa73b1de6700970f566eef51835980a15ba4dc9f19a4f4c34c84a932ca8462da66d13329764a62230fa2cf79df09fb1be60107d9dd8b1e4210055c685316b7060cb54a71ff837aacb35b386dc79327bd22d7b7742940aba630e1c1ee24d665e9cd064f0789965b14378f7d29024d90a3493737cfc72368aa18d031557c6165baaf59f0d4f811da770e0c95ad0f683db4f42b7efa74200f1bbdc9798a9dbdd93df0d9c5c1ef449f80d3773f8b58123496ec7641ce8e0554a36d947a412c52f8c0f943d45e4b29c29d4f066e480784745e43cde8e594871e92d1b3530e6ddc91ea81e172b4c4a86a0ed6838d315b146e5e6c50fc7164450b4d2d7ed1e2efd22044c70191ef37c49aeb1c1c2ab760d0771a68be786f33817d739cb733d73f01fe05b22bc32631657f9c2fc2d99650dae897d0725c6ac179b3a4753085f53ac071c94adb383021e849497be7c8f6cc5a4fddef4bb8b5745384fc3db2a6059d88ca782d4fce008f35f263a41863e9ad76b0000f64bb7533f7a4b29f324d8635a10fa8a0f0caf9137f87e23fe0207a54b10f9b8ddb472b233ffe2c350e3b0ccd69364daf3508b78b2b778599e5dec9e64302d1e65fb80e487aeefc13726da4b15a5d8e375c82ef2da8acad6dbf6c04c12257b5d511a26222bd005272e4f75d9c502ed1c0c04db4496a9c5cc97cbc20429a7c0d4e8d196445d728b8a4bf80ca134c68930e6a2cb1889b61f7ee822e58b29443eeca6e12d855e775f43425b57c33bcb1070174ceec3af1f29ea6c6f9261a5a17e7fcf30b58f897cef43921b124a2e056ac03d5e72d0e9db07dd71e72419a19a2695d6882fffcfeaf2a2eaa8564965442d71f6703ab1df4755aaac4b9eb80b0c2304876817afed9fe4d68d9a4fe8168cd9757a5e496070ab489559bafbfc838c441e6f00123bc04312cd6828d758a2a0ea7882c294a61a3c47af105221e30aba117873370c3f76a496bb4ebe6780f46e48f2cd053acc11ad7beef36ac68122bfc7a1557cc83a738afd5df489bd4c912413fe917b2d30957bfdf4b4765b2854741d65f3b4d1088440ac990ef8348fea5ac6be6796114ecf5fc8a917d145f524e0e5b30f427bcbdfeaf34334b7a57089c1da2996c60c06215c82e4eb627e164091644569d50b349e985c40dd2811fff28e2ae9fb02beef4cd906bc22510ca11689ac835fabf8ad9c9d9366d2096d7211a387a0c3bb154f05edf043cbfd125ba8bfbe2c30989a1c5a438abe7be4b48459efa2a4baee6ede812e1e10b79bdd2100671a05afbf3595a98c5265b54de3bdc9b8143a70288c7c43d65b2884dac03599e4581d64eb9d6bc1d84924e06c4f610396680b7f7fb12ceccff2dd73cf8d4c93c8255596904b84fda35372e9a581309672e9b7a2707440ab72b5eab0b5d27f399ff2d190690767f0129e0f835faf96831fe075206fed155ab377594b3de47f03f64fb72e16ea6a67039452693778c53883269d700082e21f52385b3b903127ddb95928a0be9a63055471f7a7db7a98eb3a9bea3c6dec567b22084e67764fbb6e715d2bec166536c43d8f716aae48b8304556c845eba3ebd1207fe6964593d8df41854cf3c2d6b1e35f1c46ebb661b22794d1b3a00238b6ff89cab8c23f3c2d430b438e2f777af5b400387c65cbe15429cf72503c1edd2c9af0b05a6b3a0d1e78c70115bc96c5ee08cb1ecf2bb5e2b2a1a24bd2903dbc4215a90ed8ff09bce1fd14a66ce21634f2e14f31bfdcfa65e30b8ff575f42783fffc1c4ed20831827e50be7b6c401bc1445c5a8001dcd51dbaa12e71c8a8c69a9b4c28374e2371ef2dc021a841a0f40c4f461a57bd2d6c52cfc1a326b490873f77f24725351da083e56ca26ae237455ab60477a0bb16f54f9733aeb8c90d7d068740e7d19d9a0902c8114ef373b836d5b4e09aa594a4115cf2fffbce82a64aa6e92d337769a69143f6b76633dcebf912f429edfa7c9a0a47f8ca1a5fc9ba73c525378d1cfde32bf2cbd758a5cabf994721977a502220cadf2bab4927d5b6509d5fd1841942ab8cea3032907b0c6ae5b08fd75c9d45ee0c74ac8960784218c860ad188c4828775cf1d6718ed4c69d4a70aca3e2a20a5e322d7b77362c60132a6443658f61e5f7954ffda684dfdbc8bd316278cbadf3315926c385c65363d0061458cb9a445600537cd12539b70f4ad34b1ad6cce229b7fef72577bbf09646f3aa70e5ec65207b52eeebfca9064cdb40f7cdb8826944936af898b34e85e8461e5e452089abf45fe5899a6ca85a1fb3956fd23b9874744af15f85a49e94ac62f1936345aca2f8ff42622143a729d6b7ee2db9bfcf7561b31e9bd195eb16b1cec347f0ee98c8ed800e8381fa8235137e86d4469fcc53db103509a404a471b98d4ab6e3562d32ee37f40795b48dc38c33df5ae372d4688c56631623045fecd984bd5d827ae82f2e49874e84433a8ff5a21670b65745168da2ff0795ecf0f1728e0f9cec291ad70a2fee009105b4891d36cc903e2fbb97238d1d61ebcdf94377f5980579bad7afd43d008cdee2bee3b616d4a3ee1a014a77bcc15b94f69d7de4124ba46cfbd22b0ce5f4e312f4b1691fe3fb6c1b1aee3577eb0128b5b53947c2cf2110e87ff67a94576c66e9d76efeaa6e3061b411ef6f33d583d6593b27a938c90b18146babc155d05e0d6312904a21da73b6cd3d7bcf84f13e8d39b37c52268c8cb795fdc18533e2e4d03bdc6f0390273854751b3dd58fdae79c996d29a4c143808279c2c506f77c8e951fd356dd61ba9b6b18c5026eed9bc3d08acefc95511fa322e85dcf2a67d8e323eca180b0ddd05578414d9c4816b46d096dd64c7ac33a5a8ee33bdee977b6e1d3e17f51fd669c786420eb0e430a2843e53325dd0fa8f3aec187613879f9caf8a71f09ab379280e96a23792eca38d583ec2928a976a003af43e9f158f14ccdd3b1dc570678020c972d9b09dd3d4738aee876d52427a8ef5348ea447a9ef650310fd69ab26dea8f12d277b1b1dcfb145811a4346f5d1b5d28c3be9e47952e8dd6e59a27f2b110d8253fb130d1acec7d4fbf9226d778959c1b0abcce8ac2e011ba56451cb6062464f31f9f25d3766ae4b45444315aa7670818baca6dfeb2f66ecbeec37f1577c7bd07a66e9d9a9d00b02631a87efca259c9beefbaf2c4eb7aa49c1fd895ff052916406f30f0fcd5b03d48ffc051c0c5c8109d2a97c6fe8f0be4a3cef75f087bda3c7dfb4f1ea06c58bec17c09f9460ea5d36c0b25aaf9ff2669aebddb177707b37b3f1a0c090b6d9967753f8e1b70545059a4d036d775b0fa4dc6b8092be7f167185b3854a66e87f8cb8acc5bc9db50a3e969d4f45dc9d3c0e01202c4dc6f01b92f3ddb10066a15d79f66f9c91709966769be2fa50e9ee4567dd79353b381adc0633dea50fb5019a8dcee17eef6e4675be530b45b68eb8bdc98fa11cce6ab11fe9e9a4477ccf2ae6a163edc0a5a323bd63df5b99c2519ed86e7351762fce3aab77500900bd04b433aa60ac59dd4df823c51782565eac88d6ff34a6e76371234ee8bb59aae96eaf36fc9366b9ea803e4f4419a77a2a779659d648a458938e676721183163b106cc7f0bdd29063f3f9af6ed194ffd56e8dcd88d1d115a543dcee702bca118ab2cdde2085046c22be0391695334b741fa504b2974f131a116f1291212f95afbf3405a3ea5a7ce3696e4bbe6ce3bdad589759281b9c643535d8dccb53905ae1454fe284871208bf8086f7a0df09e82fd340a2eaaaa52b50495b9e1f37dd02c22892799ea0c486bbe795e723d67db76326de1fa8b5f4ca468a617d5dfb68a77a862951be8d954d48ff92fe16a708e13fe319d6ed1d893efbecd08b897706ed14c87dfb027f60444a2c8ca20dbe6a77d1e0220368268f0b7dc6abf3b09396abdfbc6f0230f2b420acda8ca9c86a97b524840ecf619bc7a8c044eaa4c0e3511511b59207ebaee8f5f5cc1b2a17957ede34ee95aff72569d7ad7cfd2b8b05ea4b1aee5be19dc422a70772515275d6cc648fe502fc13918d7899709adf5aa3d4f84b84fd8b5e2ea9f61d38de1660c5401cd10ea878ece5348015ca0a6c884b15e7408a3fb8e32205a9db822fb0ec2c3c7104799cd254ea6c5eaa4557ae7df08a72a34d87ba6cae7956ff6e6a93484ba5924bd780fb241e223704aaa4ff7ffff95d05a5bf8dd0c84b4bfafe02cb08879d0a6ff42b0c2a1596e1c2e6b91cab00a23c9971546af516e53128076234082aed75c873deebef4dc0fc15e67716b15aa68af84a9a45948f2891346d6b1d69da3b78ee29aaa30ed516979e91c54585f607a5b660c599bea95315020d55b9725664ed7f4bf3dca94c1676bc5e3efe0a312413c6ca59396e5e9fb225854621d649275e05c57bf63583371bc37ccf7130ab0201e434542b55b4d38f8fdb7db0f1409d33251111b40386e690483b357fe1a66af5d94cc0ff5604c7d98690dfb46352031fd334d39e7d3b48d9f1b5513296aece114217149cff0d6f478f0949ac01d1cabc244882599dbe7d6ce8392b96c49fd8a4a4834b8a3a5646c124985f98ac7e2a63d36b363be964adc7ff1c38af79293834d03c77a21f1b0a96c1731174a04781ca78afc91211a299109ae3c44b2c6adfed1d761f9170d1ac16154fff3470e11185887fb12859d77e9afff994a10735f86e14db0680c85f4dce8b1b59d6b0e8bf1c8b14c4514003a74c7f3d9742425d5831ac4ee9a3a9dd88b06be9b6affc4916f577625926873417d3fc418c587b7f11d36744dcead14a428bacad1992141610366451dd8ab7c2c1db7502ceb42b915780d8e809396dc16bdd396143a47d84f772a9098c6f4c7bc3c11b9a188154906139944f175e8d046eb66be23be522f71a732215a56f4774b1d6f8addf77d23010f841e0bac2c0e57902c52d07c9b72fea04d4a9e14d700a8aa96cdf79351b4054d3411dcefd2de1178d543dd80987e748939ddd8977c4a9268f0abb43f211b4872f4f6967177124803d6db39e5b729f836a936bf1f9a811cb04f2a37a0368c8209ccc2c380f380d4b1ac380b67f247cdf4d69fc14c7990d29d23b132fea6fd33ab065ae04717cb8f011c96d59e84444292fc06091f259ee06f2b9b45247fa3ef0a782324296b95708bd83e9df202991c698e58951df69d9b14edd0963acd69ac5ddb5bc1329acc593b6e3b5bc3951c029dba5fde39d37b9243feea16eb8a252e4518e67aa81151e23ad93d856838a829377a5d6b49d1473c792cf930944cb309c94bb63d261327484e7b402bcdbe373a3591f5af2dd8599824d0ecfcce987b2e07b0df82c3df65c01dade76277f8f0156e8b9eb7e38beff495975035bc7d52fdfad8bb6e43d2010f4983cd52379f31299bf1414f1c2769146436182af8a903efbe66b750ed931e10e925edbd80aa1adb878a1daefa1e4e9dd9cfb49f73b47fb3d6bd36159e97a2a7986ba84a176a356d3891a1a8d07a3b297c18432313900db8e6be25331aa8fcce09b0e84071b0912717e064014351fbd17fdb6651fbdadc446b1cc796fb290b68be06abe34fdf2295cfc838aaba1893cb7ab5deefeb324e356a720986b1f432b112240b46c0efdafb7ca6ae5b28a757447556e98dec2d515eb1b7ca7c53e46e7dc9daed255578e16f2e2ab7256c92f99da928c5050198bc8dd80c307c915c45aab77364f1e41f5c1cbaf105d6ba3bd845e50bea69ea413210872bc36b18290eef44796de0ea2c302d36442bd18bec3b6cc947510e9ce22809d5bca1a6dc1310ed62bfbb424d3e1ee16f28811a31a7e7c3bfaf23935200e5a9c8d6d98f8c2e6cec431cf51c343185a039734a34bfbc210e98f05860a0464a9fc20942f26f34abe4b29bc22268124bae2b57df3af826a8d1746e5da36829d5821b847e2aa124087e788adb0824028a116ea90f1999951e0f4c21bdbb0e98a3e50a52a9f9858599d682515ed4a6ac2311bd18a57433a9834eb5e6db1e044bc01a9545f3b12bbd815a6f56390b3a1365817cfd4ebb2fc03eb7defdb8e50f741c6b8a1a84d29bf8212a9165c4494f5a1b5292e19c4a0a17f084d739b59363acc231611132c3b4f986ebd40a04c50554da9a423a7048d4bb02b9f64c5fbe06cd0c29922d0d0782620b8fd93e756ba8f2103205f3013bb9a9c346e59cf5ecde80d1399d100dbc17bb9ed3c2778af97b3aace4057f0fb873631b843daf5a57aac151d5ac09dd2bd36ce5f4530a566ba83666b2b81b07e48d71ac6cee5d87d6d2e67527c687b2b3e6ac0ddf40f7a401a8a616b9d04cb93b6cab186c40c1366649514d90bccdadc394b0ebe2d83bc7eb284f52355871cc763ce1a7fa19725cf73b0f584b83dd70fc81bc55329e93e960647f690e6b0d3215577e18d1bcf9894042fdfca807f0a812e9ec1d3762127de37fd18cde29e773d6f027178edbe9f39eb5532576ef4c3d8122e2ead7f46869254cad21a721ad53ea0467b7802d80aac62d95a4cca0dd34c932c3797ca2be154f9d1f7cf57f7244fd4d8e12fdedc6258d7fce2197b65626831eb70ab958e92be7dece0be1ef1dad7b93d0f8e381b039f262920e4f76c70f63b745a86ad36f582f5947e94c0a25310e9a428e4f83008f26f71dc9449c0ede6b8383df9adf2e7314bf92ef80937afe7b4bdb08aafca83d1e6250ba94bdc8f9a8c69446fef83cf828da4e70cf3869a3682e3cf6b190ce3141d80088c2d9d5c67c98252b919a6ed5af4d1c1f303bcba95a7d98a677abfef4eb354a26d701267969a3b4e9a72d4931af1d4ad9fed0523647efff3354965e1079278121866eff2e3d2e3f11b24d9b8bd4d17b0670e24ec2fe10651b4be25389a98b8c6abf4c9692e734a3add8b725f68e329f8ba7e3f8b8cd6e2281fb5c1602468b00759d677b00f30085a8b72bd15fff8ef537e3b006bd29cbe9b2 \ No newline at end of file diff --git a/src/14/input.test.ts b/src/14/input.test.ts new file mode 100644 index 0000000..2053378 --- /dev/null +++ b/src/14/input.test.ts @@ -0,0 +1,14 @@ +import { assertEquals } from "@std/assert"; +import { main } from "./main.ts"; + +const target = "input"; + +Deno.test(`correct safety factor for ${target}`, async () => { + const result = await main(target); + assertEquals(result.safetyFactor, 224438715); +}); + +Deno.test(`correct time to tree for ${target}`, async () => { + const result = await main(target); + assertEquals(result.timeToTree, 7603); +}); diff --git a/src/14/main.ts b/src/14/main.ts new file mode 100644 index 0000000..8b30bc1 --- /dev/null +++ b/src/14/main.ts @@ -0,0 +1,116 @@ +// { safetyFactor: 224438715, timeToTree: 7603 } +// Elapsed: 341ms + +interface Robot { + x: number; + y: number; + vX: number; + vY: number; +} + +type Quadrent = "upperLeft" | "upperRight" | "lowerLeft" | "lowerRight"; + +type QuadrentData = { [Q in Quadrent]: number }; + +function getQuadrentForRobot( + x: number, + y: number, + halfWidth: number, + halfHeight: number, +): Quadrent | undefined { + if (x < halfWidth) { + if (y < halfHeight) { + return "upperLeft"; + } else if (y > halfHeight) { + return "lowerLeft"; + } + } else if (x > halfWidth) { + if (y < halfHeight) { + return "upperRight"; + } else if (y > halfHeight) { + return "lowerRight"; + } + } +} + +function getSafetyFactor(quadrents: QuadrentData) { + return Object.values(quadrents).reduce((agg, quadrent) => agg * quadrent); +} + +export async function main(target = "input") { + const [width, height] = target === "input" ? [101, 103] : [11, 7]; + const halfWidth = (width - 1) / 2; + const halfHeight = (height - 1) / 2; + const maxRounds = height * width; + const targetRounds = 100; + + const dirpath = new URL(".", import.meta.url).pathname; + const text = await Deno.readTextFile(`${dirpath}${target}.txt`); + + const { robots, ...quadrents } = text.split("\n").reduce((agg, line) => { + const match = line.match(/^p=(\d+),(\d+) v=(-?\d+),(-?\d+)$/); + if (match) { + const [_, iX, iY, vX, vY] = match.map(Number); + + const fX = (((iX + targetRounds * vX) % width) + width) % width; + const fY = (((iY + targetRounds * vY) % height) + height) % height; + const quadrent = getQuadrentForRobot(fX, fY, halfWidth, halfHeight); + if (quadrent) { + agg[quadrent]++; + } + + agg.robots.push({ + x: iX, + y: iY, + vX, + vY, + }); + } + return agg; + }, { + robots: [] as Robot[], + upperLeft: 0, + upperRight: 0, + lowerLeft: 0, + lowerRight: 0, + }); + + let round = 1; + let minSafetyFactor = [Infinity, Infinity]; + while (round <= maxRounds) { + robots.forEach((robot) => { + robot.x = (((robot.x + robot.vX) % width) + width) % width; + robot.y = (((robot.y + robot.vY) % height) + height) % height; + }); + + const safetyFactor = getSafetyFactor(robots.reduce((agg, { x, y }) => { + const quadrent = getQuadrentForRobot(x, y, halfWidth, halfHeight); + if (quadrent) { + agg[quadrent]++; + } + return agg; + }, { + upperLeft: 0, + upperRight: 0, + lowerLeft: 0, + lowerRight: 0, + })); + + if (safetyFactor < minSafetyFactor[0]) { + minSafetyFactor = [safetyFactor, round]; + } + + round++; + } + + return { + safetyFactor: getSafetyFactor(quadrents), + timeToTree: minSafetyFactor[1], + }; +} + +if (import.meta.main) { + const startTime = performance.now(); + console.log(await main()); + console.log(`Elapsed: ${Math.round(performance.now() - startTime)}ms`); +} diff --git a/src/14/sample.txt b/src/14/sample.txt new file mode 100644 index 0000000..2455da4 --- /dev/null +++ b/src/14/sample.txt @@ -0,0 +1,12 @@ +p=0,4 v=3,-3 +p=6,3 v=-1,-3 +p=10,3 v=-1,2 +p=2,0 v=2,-1 +p=0,0 v=1,3 +p=3,0 v=-2,-2 +p=7,6 v=-1,-3 +p=3,0 v=-1,-2 +p=9,3 v=2,3 +p=7,3 v=-1,2 +p=2,4 v=2,-3 +p=9,5 v=-3,-3 diff --git a/src/14/test.ts b/src/14/test.ts new file mode 100644 index 0000000..6a9ae2c --- /dev/null +++ b/src/14/test.ts @@ -0,0 +1,9 @@ +import { assertEquals } from "@std/assert"; +import { main } from "./main.ts"; + +const target = "sample"; + +Deno.test(`correct safety factor for ${target}`, async () => { + const result = await main(target); + assertEquals(result.safetyFactor, 12); +});