From aca21ec452d8c95da2ea0838960a3b881ddaa50f Mon Sep 17 00:00:00 2001 From: merrywhether Date: Sun, 8 Dec 2024 00:02:39 -0800 Subject: [PATCH] day 08 --- src/08/enput.txt | 2 + src/08/input.test.ts | 14 ++++++ src/08/main.ts | 100 +++++++++++++++++++++++++++++++++++++++++++ src/08/sample.txt | 12 ++++++ src/08/test.ts | 14 ++++++ 5 files changed, 142 insertions(+) create mode 100644 src/08/enput.txt create mode 100644 src/08/input.test.ts create mode 100644 src/08/main.ts create mode 100644 src/08/sample.txt create mode 100644 src/08/test.ts diff --git a/src/08/enput.txt b/src/08/enput.txt new file mode 100644 index 0000000..7f56a05 --- /dev/null +++ b/src/08/enput.txt @@ -0,0 +1,2 @@ +130,55,35,233,201,27,219,42,236,23,204,136 +3f4b8597a75b94a3774ef1775ea2dce7f62b24d302d9275e03e5886123315907ff0cf0b030a9dbcc65f4ebcdcca62dbc0cea4a240b210a5c8e0b4e5b443b4ec30cf52f823c00e47671176928ab81871daf477652acba17a983953baed73bda64a17f486c2a389574d9653fc49393aaec480c28393514a88726cb4b760ab140a23c1b0211e988741673d21bfc571171da56dbb27d8efbdbe7e5da785c151c15865136efd33db8aac4d2a6262406f45919706fecd784f2eb958248d3faa29694725b3f8ba5fbdc6d3c9a6550459857bffc537e583feaa1d89b8b558e2bae685253ce8203dbc172813bffd8eacfc713d1c741d014aba70c632f6991dce90ba10bfdda5cb76faebfd645986edc53112a6fa856efdf6aaafec45958b758b413891bfd02966862799b89272e1bdece9133bc2f0ae82de33ba7b74695637a26fbb33d7bbac2571b721ccd4ebad66f92a09fc8afd6512abe27aa29f9c66ee5eda020bafc751f5959f1b69e4a0226b189a9d7c8da1e10ad517363332d2cc5aa745adcb339abfbdc63a2d764556d9796f8d48e0f03d1eb6d26f2990f6ccfb0e3a267e43c672be0f2beb33715e46d10eda99ade9938ead842ba68350524fba0111ff88b0b84748a42f23459513a93bf7682c903c4f6da5b6736a30f17e2c687dc999e394db3edc2fa73a9e3bfb406d39967787d6e67c471a8fd32056cdc36c86808355ae163f2a39a3f569bd55e3f9c0dcd3473537768bab7d4c48cf287aa5d28e987f4ef8277c112ec24cf9c904dd5375a06398d65f61feb04f1dc4bc444c88c6b4fd3521631974953c6a0d437c434fb315a2262ea0567c57383100075d4cf110a2f0acabc52516ce1f3ed546535778729fe70b7c1e320e25898a9402486717ef82634f8c82cff3a50b73544b1cccce937a1008e3f43a7f318281876d06f1659872d96c53d4c04ec2fdddacd07586dcf2853d40f65765e49cc72f2e28b90f7e072802a49ea78ffb639bfa9250a1953865145e42dd3f09900cb854bf1a1e8230e09054b4edfc1ee7b37f2be8e814c4739813ded9bf659fdefafe735d301e1f1700e77af7a6078d6d6f991e25b2bd45ffcd78fccbb513ac125db94ccf16f6d701de5793b6c0b9f1f51d060c2f985475ac0f7a26bca3074e6b6752dca9f12d2c36bd373eea29824d3f8eaeaa541dc67fa382e44562459e9a79d9339951fb97a4d99270eabba8bfde35c44d68c07bd3342e6dd6ff37016206345e56b1814e3529da52e8ae89e6bf5e63e537ca8ca338d30a60fa4a792a9173ddedeb62cc7992aad505c902f066e9f40efbe74406051259497447d373e96a17ae793fd44768c50c0e7aa12313173f3cb6344ba7b7a6227211d38b9e87e93fd07c5b9426d487db478d4539b1f9fce9ae7d8b82a6bfed184a514a1f4cbdb80b7091122fe71c58367131087ae34354ab8de8bbb29d23dfa432223fb8555dfa71adbfc4e394694b9753b466f4a1ae26df91961de8a1f57aa7c66114dd3dc2f60bd75ca31949a3f8a3254ab4bdf1bce5f9d53654caa340b50297ce3034bfaea1c96e80a363d4f3cb1f8036035482b8b7ec9fdeed4764955b32e447d85a2a6afdc368707acbd599e59a63896745b24d38411d48adee41218fdc4677d0f59762fb0acb681934cff271b9257950011d64b961a007781a3e58d6d0baa8ab8ee42db45e897999781550c71a90172201ae4ee9dcaf3f9c840dfd37b0d8125d7addd9c4b7c1efe6e18f8b8777b42462c0333c4683d5889da86a8b51f6a53774949e39ab95c79b2a944d1a9767db7086b0c3b95c160046048d39fdd7b7f39c6768c298d206c49fd5d4dd1407c65adf5242a78eb3c0c99d859326469fad0f4b20014a86da830288d9cb23e373bc7ed7a3de88d2c533a45406d0aa23b811970f16876a3d30872f05bc58c765f3803faf02bfc0e7735161568da1ead080664d029c67a0d232264f5ca2bdcd84adfe90ab6cd04a56865e48184f4d48344339bd0d6731a9ccc854a5a858a4614e451778e46e9bc98bda560e4917621034ee544c5680d6c517a772786adcea868f99567932b63e1c48f3b592a5023530bf807a88c5aaf43810d12cd2d6ecf45339ea79e0529731cbb76c8c09eaf681aeeb695ee8bc61352606dbb8f1492c149a2f0aafe9de79bf7877e39c163c52126c499eab0b2adbe77f1d4cc6a6d27030e008d4febc23c10ab76ee9bd03ee8576438c6b46d77f04a5b0f49c2c13251065b16f2418e5f855fbdf69bb64a37058a0a1bb58e445355f63b5db467779c54c6500d0a19e450fa8ed79e656c724201e146c35e0b68440ba82fc3c0465d4555f096db0453ade722b9db45408355f7b9a0e226ae2335a87e6159fee84c3347793a2f389a840031184b36720a23bd59b262e98805a39fba1be66dcb31f9cdf03c60278d272a168cf7103f78dcd4a91b44a2423e3f75e248dff06b1c5cd53735b2df5df270322313cf911f75e39b96402211d105a6a2a2bb12376d90b9cd26e4cba4f1d1fea02e5b418df450b4e667ddffa52252945f56af7741cb8a0027213a37e2d03db54c6ddec596bfe1033051dcaebf4966ccad5914fae70ee1787513ea9272a1311599ff6ced75f2ad1eccb33b2337ab733b3b0be8599204ba8b9b4d7b1b42c340a7810e89a55ef8e9377a5316bbd3fb54c03db307fa06afc2ac8612593f0b88ea4949adf92d323fe5e029e982d6c2489dd2556d37c1252ab9939c9d646736da66d7ea195543aa198c5e4faefae933b608c171b31bb226bcf96b12008eba30e559be18dee5a68ed13ff2c3eb9fece73481d7c8b24dbe5a33694074a77b2c4850c3b6642039a8a47f5ee75a4be7eeb29dc6765793711d25182906ba800567d45fc3fa635b506aa54380bdb3286750fa05963ba3309c3c9debc63836d5d1684fb04c0791358eb97503247150f90fbb74b8a1b5f9babe71b391f885d0c5acd0c13c5f70bf4bcdb847aa8b40b61e050fc801ad3d6b2077cf3f281fe35258d156c8434be35398033bf073e3ef90c3318707b7bfa890748c3695b2bae711cc74063bd6c1030a9de6527f39dea30563642c82c5f0c11940103610fa48e56d6f8f6dd9794971a7abb63fa9b0ed1a1c9452e3b59ed335424bbfba1fda8b96605d1951ea1a5e77db4f978a8db4e61e872e95e8c1d16e76977e3e068814d7ffdabd4c5cb8359c2a8cd18c76304a1ef0bce62f0e434e406a319868b5da46c8045503c302154f63ad19e57d1f8d221308bfacbf578403d603c2bbf3b824d9a85daceb5ad46b520befdc57247b5818315d8bd7499456b7869d3fb20388fba748ab22cf7ac78f34a4454108aa08039912937f11d7ee1de5bd3b7290426a9bcca3d42233225884690039157c2a16d35f57e3377fb9e9d25b91d75fbc2f01690945bc1a778cc56d9c78fddabf2f46ec2d9e8b583da156cf2e65744741dfbef820db03fe70f39dd95ebfd67c08ffa63f6f970dbd5b07d452008a76f248bf62d2fa068a1fb64888a833d862ee5c94be237e5de6425823f071a43afd274156d9fc90547eb9a3aa79fb8c95270b703ca61f911fff3ea5039c279d814304380b5df0fbebe9076facbee2132c3739d4c64bf6b88dce3adb018e006810 \ No newline at end of file diff --git a/src/08/input.test.ts b/src/08/input.test.ts new file mode 100644 index 0000000..34fe3c9 --- /dev/null +++ b/src/08/input.test.ts @@ -0,0 +1,14 @@ +import { assertEquals } from "@std/assert"; +import { main } from "./main.ts"; + +const target = "input"; + +Deno.test(`correct antinode count for ${target}`, async () => { + const result = await main(target); + assertEquals(result.antinodeCount, 413); +}); + +Deno.test(`correct resonant antinode count for ${target}`, async () => { + const result = await main(target); + assertEquals(result.resonantAntinodeCount, 1417); +}); diff --git a/src/08/main.ts b/src/08/main.ts new file mode 100644 index 0000000..e19d459 --- /dev/null +++ b/src/08/main.ts @@ -0,0 +1,100 @@ +// { antinodeCount: 413, resonantAntinodeCount: 1417 } +// Elapsed: 2ms + +type Position = [x: number, y: number]; + +export async function main(target = "input") { + const dirpath = new URL(".", import.meta.url).pathname; + const text = await Deno.readTextFile(`${dirpath}${target}.txt`); + + const { antennaGroups, map } = text.split("\n").reduce((agg, line, y) => { + if (line) { + const row = line.split(""); + row.forEach((char, x) => { + if (char !== ".") { + agg.antennaGroups[char] ??= []; + agg.antennaGroups[char].push([x, y]); + } + }); + agg.map.push(row); + } + return agg; + }, { + antennaGroups: {} as Record, + map: [] as string[][], + }); + + const { antinodes, resonantAntinodes } = Object.values(antennaGroups).reduce( + (agg, antennas) => { + if (antennas.length <= 1) { + return agg; + } + + while (antennas.length > 1) { + const baseAntenna = antennas.shift()!; + agg.resonantAntinodes[baseAntenna[1]].add(baseAntenna[0]); + + antennas.forEach((antenna) => { + const dX = antenna[0] - baseAntenna[0]; + const dY = antenna[1] - baseAntenna[1]; + let ascendingMultiple = 1; + while ( + antenna[1] + dY * ascendingMultiple >= 0 && + antenna[1] + dY * ascendingMultiple < map.length && + antenna[0] + dX * ascendingMultiple >= 0 && + antenna[0] + dX * ascendingMultiple < map[0].length + ) { + agg.resonantAntinodes[antenna[1] + dY * ascendingMultiple].add( + antenna[0] + dX * ascendingMultiple, + ); + if (ascendingMultiple === 1) { + agg.antinodes[antenna[1] + dY * ascendingMultiple].add( + antenna[0] + dX * ascendingMultiple, + ); + } + ascendingMultiple++; + } + + let descendingMultiple = 1; + while ( + baseAntenna[1] - dY * descendingMultiple >= 0 && + baseAntenna[1] - dY * descendingMultiple < map.length && + baseAntenna[0] - dX * descendingMultiple >= 0 && + baseAntenna[0] - dX * descendingMultiple < map[0].length + ) { + agg.resonantAntinodes[baseAntenna[1] - dY * descendingMultiple].add( + baseAntenna[0] - dX * descendingMultiple, + ); + if (descendingMultiple === 1) { + agg.antinodes[baseAntenna[1] - dY * descendingMultiple].add( + baseAntenna[0] - dX * descendingMultiple, + ); + } + descendingMultiple++; + } + }); + } + agg.resonantAntinodes[antennas[0][1]].add(antennas[0][0]); + + return agg; + }, + { + antinodes: Array.from(map, () => new Set()), + resonantAntinodes: Array.from(map, () => new Set()), + }, + ); + + return { + antinodeCount: antinodes.reduce((agg, st) => agg + st.size, 0), + resonantAntinodeCount: resonantAntinodes.reduce( + (agg, st) => agg + st.size, + 0, + ), + }; +} + +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/08/sample.txt b/src/08/sample.txt new file mode 100644 index 0000000..78a1e91 --- /dev/null +++ b/src/08/sample.txt @@ -0,0 +1,12 @@ +............ +........0... +.....0...... +.......0.... +....0....... +......A..... +............ +............ +........A... +.........A.. +............ +............ diff --git a/src/08/test.ts b/src/08/test.ts new file mode 100644 index 0000000..cc2177d --- /dev/null +++ b/src/08/test.ts @@ -0,0 +1,14 @@ +import { assertEquals } from "@std/assert"; +import { main } from "./main.ts"; + +const target = "sample"; + +Deno.test(`correct antinode count for ${target}`, async () => { + const result = await main(target); + assertEquals(result.antinodeCount, 14); +}); + +Deno.test(`correct resonant antinode count for ${target}`, async () => { + const result = await main(target); + assertEquals(result.resonantAntinodeCount, 34); +});