From 7f2cf1cb021ed5fef11119b03e9656ad90be3955 Mon Sep 17 00:00:00 2001 From: Anthony Oteri Date: Mon, 18 Dec 2023 16:31:45 -0500 Subject: [PATCH] Day 18 - Part 1 Signed-off-by: Anthony Oteri --- day-18/Cargo.toml | 29 ++ day-18/benches/benchmark.rs | 15 + day-18/input.txt | 630 ++++++++++++++++++++++++++++++++++++ day-18/src/bin/part1.rs | 21 ++ day-18/src/bin/part2.rs | 21 ++ day-18/src/error.rs | 9 + day-18/src/lib.rs | 4 + day-18/src/part1.rs | 186 +++++++++++ day-18/src/part2.rs | 18 ++ day-18/test-input.txt | 14 + output.txt | 334 +++++++++++++++++++ 11 files changed, 1281 insertions(+) create mode 100644 day-18/Cargo.toml create mode 100644 day-18/benches/benchmark.rs create mode 100644 day-18/input.txt create mode 100644 day-18/src/bin/part1.rs create mode 100644 day-18/src/bin/part2.rs create mode 100644 day-18/src/error.rs create mode 100644 day-18/src/lib.rs create mode 100644 day-18/src/part1.rs create mode 100644 day-18/src/part2.rs create mode 100644 day-18/test-input.txt create mode 100644 output.txt diff --git a/day-18/Cargo.toml b/day-18/Cargo.toml new file mode 100644 index 0000000..01a602e --- /dev/null +++ b/day-18/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "day-18" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +itertools = { workspace = true } +nom = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } +miette = { workspace = true } +thiserror = { workspace = true } +dhat = { workspace = true } +glam = { workspace = true } + +[dev-dependencies] +divan = { workspace = true } +env_logger = { workspace = true } +test-log = { workspace = true } + +[[bench]] +name = "day-18" +path = "benches/benchmark.rs" +harness = false + +[features] +dhat-heap = [] diff --git a/day-18/benches/benchmark.rs b/day-18/benches/benchmark.rs new file mode 100644 index 0000000..849555b --- /dev/null +++ b/day-18/benches/benchmark.rs @@ -0,0 +1,15 @@ +use day_18::*; + +fn main() { + divan::main(); +} + +#[divan::bench] +fn part1() { + part1::process(divan::black_box(include_str!("../input.txt"))).unwrap(); +} + +#[divan::bench] +fn part2() { + part2::process(divan::black_box(include_str!("../input.txt"))).unwrap(); +} diff --git a/day-18/input.txt b/day-18/input.txt new file mode 100644 index 0000000..92969a0 --- /dev/null +++ b/day-18/input.txt @@ -0,0 +1,630 @@ +L 7 (#080f92) +U 8 (#6345a3) +L 9 (#8646f2) +U 6 (#34e153) +L 4 (#0f1112) +D 15 (#441d83) +L 5 (#259752) +U 9 (#1a63b3) +L 2 (#7d6642) +U 6 (#471dc3) +L 15 (#0b2432) +U 4 (#179b23) +L 3 (#4f3500) +U 5 (#7166d3) +L 11 (#36b9b0) +U 8 (#2a4fb3) +R 11 (#2a9d40) +U 4 (#7776d3) +L 4 (#1f5af0) +U 3 (#610911) +R 6 (#513130) +U 5 (#38d451) +R 6 (#25d420) +U 6 (#07e921) +L 12 (#049d20) +U 3 (#579443) +L 5 (#2cfd52) +U 8 (#67b1d3) +L 5 (#0fc502) +U 5 (#1aac63) +L 7 (#7dd532) +D 9 (#0183c1) +L 7 (#3647a2) +D 4 (#35f4f1) +L 8 (#714d12) +U 6 (#27e461) +L 2 (#227ba2) +U 3 (#688731) +L 12 (#3d6ba2) +U 2 (#594ea3) +L 8 (#326992) +U 13 (#399cc3) +R 8 (#48d190) +U 3 (#6515e3) +R 5 (#48d192) +U 3 (#37a513) +R 6 (#1ecf82) +U 10 (#342493) +R 5 (#6df562) +U 13 (#39bae3) +L 7 (#116512) +U 13 (#49af63) +R 7 (#1b61d2) +U 6 (#437ed3) +R 14 (#703f32) +U 8 (#250693) +R 4 (#30dce2) +D 11 (#2e4181) +L 6 (#446470) +D 3 (#822d51) +L 8 (#331170) +D 8 (#082d21) +R 14 (#1af7d2) +D 7 (#584861) +R 11 (#1af7d0) +D 11 (#5656c1) +R 8 (#6c6962) +U 6 (#81b131) +R 5 (#0b0c82) +U 13 (#0871a1) +L 5 (#6171a2) +U 4 (#0e40f1) +L 12 (#3e21f2) +U 3 (#501bb1) +R 11 (#12af92) +U 7 (#04a483) +R 13 (#4d2822) +U 9 (#5ebfa3) +L 13 (#4d2820) +U 5 (#62fc63) +L 11 (#2328f2) +U 4 (#0183c3) +L 7 (#077c92) +D 6 (#815a33) +L 4 (#440a12) +U 6 (#0fd693) +L 10 (#2813a2) +U 6 (#13bea3) +L 4 (#688d32) +D 6 (#54f993) +L 6 (#688d30) +D 12 (#3d6313) +L 9 (#2813a0) +U 4 (#1694b3) +L 10 (#440a10) +U 4 (#5e3943) +L 5 (#2a8f52) +U 7 (#34c963) +R 15 (#2a8f50) +U 3 (#3705a3) +L 9 (#00b952) +U 9 (#6e5ef3) +R 5 (#63c4d2) +U 4 (#405243) +R 5 (#80f640) +U 4 (#4dd323) +R 11 (#05e080) +D 8 (#1ea993) +R 3 (#86d6c2) +D 5 (#0f1583) +R 12 (#4f5302) +U 5 (#06d053) +R 12 (#69d392) +U 4 (#645c53) +R 8 (#59a5e2) +U 6 (#317593) +R 5 (#600892) +U 7 (#2e9d33) +R 8 (#452812) +U 6 (#415bc3) +R 9 (#03d492) +D 4 (#50e883) +R 2 (#1f1412) +D 6 (#1674b3) +R 11 (#482570) +U 10 (#64c201) +R 12 (#15ece0) +U 10 (#3e4b71) +R 11 (#20a590) +D 5 (#42fcb3) +R 9 (#5ef040) +D 4 (#6010c3) +R 8 (#38b750) +D 6 (#205343) +L 7 (#82eac0) +D 2 (#371d03) +L 10 (#7cf2c2) +D 6 (#4c6dc3) +R 8 (#7cf2c0) +D 11 (#56ce93) +R 8 (#046250) +D 4 (#12ef83) +R 6 (#501950) +U 4 (#214f01) +R 5 (#54d0d0) +U 5 (#1a5851) +L 6 (#969010) +U 5 (#41da71) +R 6 (#14c1f0) +U 7 (#3aed41) +L 5 (#376ac2) +U 4 (#34b961) +R 3 (#529e22) +U 15 (#34b963) +R 7 (#214922) +D 10 (#34d9d1) +R 10 (#673ec0) +D 7 (#6430f1) +R 7 (#6c3120) +D 5 (#0f0d01) +R 4 (#17a740) +D 8 (#5aefa1) +R 7 (#178970) +D 10 (#3990f1) +R 12 (#2fbc90) +D 7 (#2e35f1) +R 8 (#8b7710) +D 4 (#492861) +R 4 (#8b7712) +D 8 (#2d6701) +R 10 (#5875b0) +U 12 (#1d44a1) +R 5 (#47de12) +D 3 (#5397b1) +R 15 (#47de10) +D 5 (#532ac1) +R 6 (#5875b2) +U 8 (#512811) +R 3 (#364932) +D 8 (#407bc1) +R 8 (#364930) +D 4 (#30a4e1) +L 5 (#739de0) +D 5 (#76d5b3) +L 10 (#315880) +D 11 (#480321) +R 10 (#42c7a0) +D 3 (#4e5751) +R 5 (#42c7a2) +D 10 (#3749e1) +R 12 (#89fcf0) +D 6 (#02f443) +R 9 (#0ee550) +D 4 (#320553) +R 5 (#89da30) +D 9 (#369de3) +L 10 (#03c382) +D 11 (#49d2b3) +L 4 (#94fc02) +D 3 (#183a33) +R 7 (#33a150) +D 6 (#669da3) +R 7 (#546cc2) +D 3 (#0ad4c1) +R 13 (#973832) +U 6 (#0ad4c3) +R 11 (#0351d2) +U 8 (#35d693) +R 6 (#06e6e0) +U 5 (#098233) +R 6 (#5277e0) +U 6 (#959b53) +R 10 (#3917c0) +U 4 (#89bb93) +R 9 (#469ac0) +U 10 (#1bee63) +L 6 (#0bd950) +D 4 (#2e0b41) +L 14 (#1e8690) +U 4 (#4f1003) +L 5 (#4de430) +U 4 (#4f1001) +L 8 (#3cbf60) +U 11 (#2e0b43) +L 9 (#038de0) +U 8 (#156883) +R 4 (#149080) +U 3 (#64d193) +R 10 (#12e500) +U 5 (#608833) +L 8 (#46ec10) +U 3 (#56ecc3) +L 2 (#1f7430) +U 11 (#49b923) +L 7 (#1f7432) +U 6 (#1de083) +L 3 (#66b490) +U 4 (#16e561) +L 14 (#40c420) +U 3 (#5ec471) +R 7 (#40c422) +U 11 (#48dc91) +R 3 (#1c26f0) +U 6 (#2e4273) +R 2 (#3f5c80) +U 5 (#634373) +R 10 (#4b6580) +U 2 (#46bd43) +R 12 (#7d0f50) +U 7 (#3a3233) +R 5 (#1034d0) +D 13 (#3208f3) +L 8 (#081450) +D 4 (#6079d1) +L 12 (#3eb490) +U 4 (#2cbf81) +L 4 (#754540) +D 8 (#4d48e1) +R 8 (#346ce0) +D 9 (#56bf41) +R 11 (#68b710) +U 9 (#320161) +R 5 (#489950) +D 7 (#620d21) +R 7 (#546180) +D 6 (#301f93) +R 4 (#663820) +D 10 (#2fa3d3) +R 7 (#2131a0) +D 2 (#59e5d3) +R 9 (#4a92e0) +D 8 (#464c61) +R 11 (#4a90b2) +D 3 (#39d451) +L 9 (#4a90b0) +D 2 (#27c3b1) +L 6 (#24b1f0) +D 7 (#11c4d1) +L 5 (#3563c0) +D 7 (#620d23) +R 8 (#2118e0) +D 2 (#6392e1) +R 12 (#43f1d2) +D 3 (#3d4f21) +R 6 (#246e22) +U 15 (#29db11) +R 6 (#6edaa0) +U 12 (#484b61) +L 6 (#6edaa2) +U 8 (#493501) +R 7 (#5d18a2) +U 3 (#4a17b1) +L 9 (#1f9eb2) +U 4 (#4fe283) +L 7 (#7217e2) +U 4 (#4fe281) +R 7 (#2867c2) +U 8 (#46de21) +R 4 (#5961e2) +D 8 (#394411) +R 5 (#326882) +U 7 (#414e51) +R 10 (#33a9a2) +U 9 (#08dc51) +R 11 (#483f12) +U 5 (#376f01) +R 4 (#50bac0) +U 8 (#6e8c21) +R 10 (#167092) +U 8 (#404293) +R 7 (#953a82) +U 12 (#404291) +L 7 (#5c7582) +U 3 (#326d61) +R 10 (#7960c0) +D 11 (#66a8c1) +R 12 (#75f300) +D 2 (#66a8c3) +L 12 (#18ccd0) +D 10 (#2231e1) +R 9 (#8f76a0) +D 5 (#585591) +L 11 (#384890) +D 7 (#22c7b1) +L 7 (#8a1050) +D 5 (#096291) +L 4 (#66e550) +D 10 (#216c01) +L 9 (#6cf190) +D 10 (#7683c1) +L 9 (#05ecc0) +U 10 (#459413) +L 7 (#1a43a0) +D 2 (#557593) +L 2 (#47fe80) +D 13 (#4db093) +R 4 (#3af720) +D 5 (#06b261) +R 6 (#7e1f60) +D 4 (#709101) +R 7 (#7e1f62) +D 2 (#2bbbd1) +R 5 (#2050d0) +U 14 (#8e50b1) +R 5 (#55efb0) +U 6 (#147081) +R 6 (#137320) +D 4 (#1047d1) +R 5 (#33a880) +D 6 (#8f2f93) +L 12 (#186b70) +D 4 (#860693) +R 12 (#08ae40) +D 6 (#101663) +R 7 (#597790) +D 4 (#2ac7f3) +L 3 (#18cb10) +D 4 (#43a413) +L 7 (#18cb12) +U 4 (#3d18d3) +L 6 (#3f9040) +D 7 (#448fb1) +R 6 (#6ae4d0) +D 4 (#2ade11) +R 10 (#6ae4d2) +D 4 (#3c1711) +R 4 (#2a27c0) +D 3 (#30bbb3) +R 8 (#84bff0) +U 9 (#1c12d1) +R 11 (#0c24a0) +U 6 (#626c31) +R 3 (#618320) +U 9 (#380fe1) +R 14 (#462210) +U 3 (#0cb7b1) +R 5 (#3fbcf2) +U 7 (#855e61) +L 6 (#36b5e2) +U 4 (#855e63) +L 9 (#3d5702) +U 3 (#2573a1) +L 7 (#3c2f20) +U 9 (#60cb91) +R 7 (#311920) +D 3 (#45c451) +R 8 (#4067f0) +U 12 (#4c5b81) +R 9 (#973f00) +D 12 (#016101) +R 3 (#696210) +D 10 (#3dd841) +R 5 (#58ad20) +U 5 (#33ca01) +R 14 (#0356a2) +D 5 (#55c131) +R 6 (#0356a0) +D 2 (#2eec71) +R 7 (#58ad22) +D 9 (#73b831) +L 11 (#696212) +D 12 (#562f41) +L 3 (#0fb450) +D 5 (#2306a1) +L 4 (#90ab20) +U 15 (#151451) +L 7 (#13bcd0) +U 2 (#357ed1) +L 7 (#11a1c2) +D 12 (#51acd1) +L 11 (#7e5122) +D 4 (#651b41) +L 9 (#4e5bd2) +D 13 (#79eca1) +L 4 (#326342) +D 4 (#7f54e1) +L 6 (#303812) +D 7 (#1f1641) +L 11 (#557572) +D 6 (#64b501) +L 9 (#3dbc92) +U 3 (#628813) +L 5 (#40df92) +U 10 (#41f863) +L 5 (#308632) +D 5 (#1f97d3) +L 12 (#116cb0) +D 6 (#7a90c3) +R 12 (#116cb2) +D 9 (#47fba3) +R 9 (#8a7e22) +D 6 (#592b83) +R 13 (#1577e2) +D 7 (#162c53) +L 10 (#59e022) +D 11 (#73c3e1) +R 10 (#08ac70) +D 3 (#7c67b1) +R 11 (#0e45f2) +D 4 (#604fc3) +R 7 (#31bd92) +D 7 (#3bd893) +L 3 (#5e6ec2) +D 10 (#5852b3) +R 7 (#18f192) +D 5 (#1b1f41) +R 9 (#7624c2) +U 5 (#35a501) +R 5 (#3c8190) +D 12 (#5d1861) +L 8 (#3c8192) +D 5 (#469e61) +L 7 (#303d42) +U 5 (#7595c1) +L 6 (#6d6c80) +D 4 (#4a7691) +L 12 (#2c9180) +D 4 (#981bf3) +L 14 (#3b5170) +D 3 (#981bf1) +R 7 (#3dc980) +D 5 (#4a7693) +R 12 (#4aace0) +D 7 (#726771) +L 14 (#08ac72) +D 5 (#0660b1) +L 5 (#7e4992) +D 6 (#177301) +L 4 (#32bea2) +D 11 (#23a031) +L 8 (#6f00b2) +D 6 (#23a033) +L 14 (#1f58f2) +U 6 (#49ae81) +L 7 (#4f02b0) +U 7 (#592bf1) +L 6 (#561ba0) +U 6 (#0b3711) +L 2 (#4ddd40) +U 8 (#6fe7c3) +L 11 (#4cf840) +U 5 (#012ca3) +R 4 (#18bc90) +U 6 (#012ca1) +R 9 (#4e18e0) +U 8 (#6fe7c1) +R 10 (#09a1e0) +D 5 (#79e5e1) +R 4 (#531062) +U 5 (#0840f3) +R 10 (#26a220) +D 8 (#3d1503) +R 5 (#0407b2) +U 6 (#241033) +R 6 (#0407b0) +U 6 (#4cf003) +L 6 (#26a222) +U 6 (#151513) +L 6 (#63a0b2) +U 10 (#5984e1) +L 4 (#169992) +U 5 (#063cb3) +L 9 (#67a882) +U 6 (#063cb1) +L 7 (#33c942) +D 14 (#41bc51) +L 5 (#1d7ca0) +D 3 (#08e773) +L 5 (#838e70) +D 4 (#08e771) +L 6 (#110040) +U 7 (#302a01) +R 5 (#549bc2) +U 7 (#898301) +L 5 (#5f4dd0) +U 3 (#180e51) +L 3 (#235670) +D 8 (#44d421) +L 10 (#7a58a0) +D 8 (#44d423) +L 5 (#330430) +D 4 (#0a3701) +L 9 (#840820) +D 11 (#0dc433) +L 2 (#1e1620) +D 4 (#092f53) +L 4 (#0b85b2) +D 4 (#848813) +L 10 (#0b85b0) +D 11 (#0e2ed3) +L 7 (#13c660) +D 7 (#58b303) +L 3 (#523600) +D 11 (#1587b1) +L 6 (#23c730) +D 5 (#6fb511) +L 6 (#23c732) +D 10 (#19e711) +L 10 (#3ed9a0) +D 6 (#633991) +L 5 (#845760) +D 4 (#11a581) +L 8 (#79ed52) +D 6 (#13eaa1) +L 6 (#0cc702) +D 9 (#5933b1) +L 10 (#501220) +D 8 (#18b601) +R 10 (#24abb0) +D 7 (#659331) +R 4 (#0f5f80) +D 4 (#0ca3f1) +R 10 (#841d52) +D 6 (#026d01) +L 7 (#0cc700) +D 14 (#1e2f71) +L 7 (#247a02) +U 14 (#703553) +L 7 (#5d2812) +D 7 (#105e43) +L 8 (#327d12) +U 9 (#1cc023) +L 6 (#45f0c2) +D 11 (#5e68b3) +L 9 (#786dd0) +D 14 (#1ceb83) +R 9 (#75c2b2) +D 9 (#150751) +L 5 (#4f6762) +D 5 (#267841) +L 8 (#250ed2) +U 3 (#6b17c1) +L 10 (#583a82) +U 3 (#3bef71) +L 5 (#68e0f2) +U 11 (#4fdf61) +L 12 (#485b32) +U 4 (#0dfe11) +R 4 (#614b92) +U 6 (#8b2c33) +R 10 (#58dab2) +D 6 (#349073) +R 3 (#5d7782) +U 4 (#248903) +R 10 (#19ee82) +U 6 (#6c1543) +L 6 (#6a8212) +U 8 (#2c7ee3) +L 5 (#22ab82) +U 3 (#8a9d43) +L 11 (#217212) +U 4 (#385233) +L 2 (#10d002) +U 9 (#4d36b1) +L 9 (#19ace2) +U 5 (#6f27d1) +L 4 (#7d9e82) +U 11 (#241d03) +L 9 (#0e0cc2) +U 5 (#1e5093) +L 4 (#8a9a32) +U 6 (#414ef3) +R 12 (#8a9a30) +U 2 (#38a203) +L 12 (#3456f2) +U 3 (#156dd3) +L 3 (#267ac2) +U 10 (#3b5203) +L 2 (#4912d2) +U 5 (#750db3) +L 11 (#4912d0) +U 8 (#15f963) +L 3 (#5897d2) +U 3 (#401cc3) +L 9 (#32ffc2) +U 7 (#78bde3) +L 6 (#3fc702) +D 6 (#4fd523) +L 12 (#5be3d2) +D 2 (#401483) +L 3 (#4eb542) +D 13 (#0cf9c3) +L 3 (#4b3d42) +U 14 (#6716d3) +L 6 (#12d372) +U 7 (#69f8a3) +L 9 (#7210b2) +D 7 (#1740b3) +L 5 (#083fe2) +U 9 (#515bc3) \ No newline at end of file diff --git a/day-18/src/bin/part1.rs b/day-18/src/bin/part1.rs new file mode 100644 index 0000000..bc93cf7 --- /dev/null +++ b/day-18/src/bin/part1.rs @@ -0,0 +1,21 @@ +use day_18::part1::process; +use miette::Context; + +#[cfg(feature = "dhat-heap")] +#[global_allocator] +static ALLOC: dhat::Alloc = dhat::Alloc; + +#[tracing::instrument] +fn main() -> miette::Result<()> { + #[cfg(feature = "dhat-heap")] + let _profiler = dhat::Profiler::new_heap(); + + #[cfg(not(feature = "dhat-heap"))] + tracing_subscriber::fmt::init(); + + let file = include_str!("../../input.txt"); + let result = process(file).context("process part 1")?; + + println!("{}", result); + Ok(()) +} diff --git a/day-18/src/bin/part2.rs b/day-18/src/bin/part2.rs new file mode 100644 index 0000000..537ab88 --- /dev/null +++ b/day-18/src/bin/part2.rs @@ -0,0 +1,21 @@ +use day_18::part2::process; +use miette::Context; + +#[cfg(feature = "dhat-heap")] +#[global_allocator] +static ALLOC: dhat::Alloc = dhat::Alloc; + +#[tracing::instrument] +fn main() -> miette::Result<()> { + #[cfg(feature = "dhat-heap")] + let _profiler = dhat::Profiler::new_heap(); + + #[cfg(not(feature = "dhat-heap"))] + tracing_subscriber::fmt::init(); + + let file = include_str!("../../input.txt"); + let result = process(file).context("process part 1")?; + + println!("{}", result); + Ok(()) +} diff --git a/day-18/src/error.rs b/day-18/src/error.rs new file mode 100644 index 0000000..e08a17f --- /dev/null +++ b/day-18/src/error.rs @@ -0,0 +1,9 @@ +use miette::Diagnostic; +use thiserror::Error; + +#[derive(Error, Diagnostic, Debug)] +pub enum AocError { + #[error(transparent)] + #[diagnostic(code(aoc::io_error))] + IoError(#[from] std::io::Error), +} diff --git a/day-18/src/lib.rs b/day-18/src/lib.rs new file mode 100644 index 0000000..681e54b --- /dev/null +++ b/day-18/src/lib.rs @@ -0,0 +1,4 @@ +pub mod error; + +pub mod part1; +pub mod part2; diff --git a/day-18/src/part1.rs b/day-18/src/part1.rs new file mode 100644 index 0000000..2e74339 --- /dev/null +++ b/day-18/src/part1.rs @@ -0,0 +1,186 @@ +use std::collections::{HashMap}; + +use crate::error::AocError; +use glam::IVec2; +use nom::{ + branch::alt, + bytes::complete::{tag, take_while_m_n}, + character::complete::{self, digit1, line_ending, space1}, + combinator::{map, map_res}, + multi::separated_list1, + sequence::tuple, + IResult, +}; + +#[derive(Debug, Clone)] +enum Direction { + North, + South, + East, + West, +} + +#[derive(Debug, Clone, Default)] +struct Color { + red: u8, + green: u8, + blue: u8, +} + +#[derive(Debug, Clone)] +struct Instruction { + direction: Direction, + distance: u32, + color: Color, +} + +fn hex_primary(input: &str) -> IResult<&str, u8> { + map_res(take_while_m_n(2, 2, |c: char| c.is_ascii_hexdigit()), |v| { + u8::from_str_radix(v, 16) + })(input) +} + +fn hex_color(input: &str) -> IResult<&str, Color> { + let (input, _) = tag("#")(input)?; + let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(input)?; + + Ok((input, Color { red, green, blue })) +} + +fn parse_line(input: &str) -> IResult<&str, (Direction, u32, Color)> { + let (input, direction) = alt(( + map(complete::char('R'), |_| Direction::East), + map(complete::char('L'), |_| Direction::West), + map(complete::char('U'), |_| Direction::North), + map(complete::char('D'), |_| Direction::South), + ))(input)?; + let (input, _) = space1(input)?; + let (input, distance) = map(digit1, |s: &str| s.parse::().unwrap())(input)?; + let (input, _) = space1(input)?; + let (input, _) = tag("(")(input)?; + let (input, color) = hex_color(input)?; + let (input, _) = tag(")")(input)?; + + Ok((input, (direction, distance, color))) +} + +fn parse(input: &str) -> IResult<&str, Vec> { + let (input, lines) = separated_list1(line_ending, parse_line)(input)?; + + Ok(( + input, + lines + .iter() + .map(|(direction, distance, color)| Instruction { + direction: direction.clone(), + distance: *distance, + color: color.clone(), + }) + .collect(), + )) +} + +fn normalize(grid: &HashMap) -> HashMap { + let min_x = grid.keys().map(|v| v.x).min().unwrap(); + let min_y = grid.keys().map(|v| v.y).min().unwrap(); + + let origin = IVec2::new(min_x, min_y); + + let mut normalized = HashMap::new(); + for (pos, color) in grid.iter() { + normalized.insert(*pos + origin.abs(), color.clone()); + } + + normalized +} + +#[cfg(test)] +fn visualize(grid: &HashMap) { + let min_x = grid.keys().map(|v| v.x).min().unwrap(); + let min_y = grid.keys().map(|v| v.y).min().unwrap(); + let max_x = grid.keys().map(|v| v.x).max().unwrap(); + let max_y = grid.keys().map(|v| v.y).max().unwrap(); + + for y in (min_y..=max_y).rev() { + for x in min_x..=max_x { + let pos = IVec2::new(x, y); + if let Some(color) = grid.get(&pos) { + print!( + "\x1b[48;2;{};{};{}m \x1b[0m", + color.red, color.green, color.blue + ); + } else { + print!(" "); + } + } + println!(); + } +} + +fn flood_fill(grid: &HashMap) -> HashMap { + let min_x = grid.keys().map(|v| v.x).min().unwrap(); + let min_y = grid.keys().map(|v| v.y).min().unwrap(); + let max_x = grid.keys().map(|v| v.x).max().unwrap(); + let max_y = grid.keys().map(|v| v.y).max().unwrap(); + + let mut filled = grid.clone(); + for y in min_y..max_y { + let mut is_inside = false; + for x in min_x..=max_x { + if grid.contains_key(&IVec2::new(x, y)) && grid.contains_key(&IVec2::new(x, y + 1)) { + is_inside = !is_inside + } else if is_inside { + filled.insert( + IVec2::new(x, y), + Color { + red: 128, + green: 128, + blue: 128, + }, + ); + } + } + } + filled +} + +#[tracing::instrument] +pub fn process(input: &str) -> miette::Result { + let (input, instructions) = parse(input).unwrap(); + + debug_assert!(input.is_empty()); + + let mut grid: HashMap = HashMap::new(); + let mut current = IVec2::splat(0); + instructions.into_iter().for_each(|instruction| { + (0..instruction.distance).for_each(|_| { + match instruction.direction { + Direction::North => current.y += 1, + Direction::South => current.y -= 1, + Direction::East => current.x += 1, + Direction::West => current.x -= 1, + }; + grid.insert(current, instruction.color.clone()); + }); + }); + + let normalized = normalize(&grid); + let filled = flood_fill(&normalized); + + #[cfg(test)] + visualize(&filled); + + Ok(filled.len() as u64) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test_log::test] + fn test_process() -> miette::Result<()> { + let input = include_str!("../test-input.txt"); + assert_eq!(62, process(input)?); + Ok(()) + } +} diff --git a/day-18/src/part2.rs b/day-18/src/part2.rs new file mode 100644 index 0000000..1ff3976 --- /dev/null +++ b/day-18/src/part2.rs @@ -0,0 +1,18 @@ +use crate::error::AocError; + +#[tracing::instrument] +pub fn process(input: &str) -> miette::Result { + Ok(0) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test_log::test] + fn test_process() -> miette::Result<()> { + let input = include_str!("../test-input.txt"); + assert_eq!(0, process(input)?); + Ok(()) + } +} diff --git a/day-18/test-input.txt b/day-18/test-input.txt new file mode 100644 index 0000000..0ad754b --- /dev/null +++ b/day-18/test-input.txt @@ -0,0 +1,14 @@ +R 6 (#70c710) +D 5 (#0dc571) +L 2 (#5713f0) +D 2 (#d2c081) +R 2 (#59c680) +D 2 (#411b91) +L 5 (#8ceee2) +U 2 (#caa173) +L 1 (#1b58a2) +U 2 (#caa171) +R 2 (#7807d2) +U 3 (#a77fa3) +L 2 (#015232) +U 2 (#7a21e3) \ No newline at end of file diff --git a/output.txt b/output.txt new file mode 100644 index 0000000..fda04e5 --- /dev/null +++ b/output.txt @@ -0,0 +1,334 @@ +             +     +     +            +     +     +     +     +     +     +     +                 +     +                 +     +            +     +     +              +         +                             +                 +                 +                                    +                 +                          +                 +                             +                                      +                                   +                                        +                         +                     +                                      +                             +                                              +                                            +                                                  +                     +                                +                                             +                                    +                         +                                      +                                     +                                                    +                                 +                                 +                                                        +                                                        +                                                                +                                                     +                                             +                                                 +                                                            +                             +                                                            +                                            +                                                                  +                             +                                                           +                                  +                                         +                                       +                                             +                                                               +                                                     +                                +                                                                        +                                        +                                                      +                                               +                                                                        +                                                     +                                                                              +                                   +                                                     +                                                                +                                 +                                     +                                               +                             +                                       +                                                +                                                +                         +                                               +                                             +                                  +                                      +                           +                               +                     +                                                                 +                              +                                     +                                      +                     +                               +             +                  +                               +             +             +             +                                  +                                    +                 +                            +                              +                                 +                     +                                         +                                      +                 +                      +                                  +                 +                        +                                 +         +         +         +                   +         +                            +         +         +         +                     +         +                      +              +         +               +                 +             +         +                   +                +         +         +                    +         +         +                +                  +             +                                +                   +                     +              +                    +           +         +                +                +         +         +                             +         +         +                     +                 +             +                      +                  +             +                   +             +                 +                       +             +                                           +                 +                 +                          +                 +                        +                  +                                  +         +         +                  +         +                         +                   +             +                        +                         +                                          +                 +                       +                                  +                   +                   +                    +                                  +                                 +             +             +                         +                       +                        +                 +             +             +             +                           +                        +             +                    +                +                                        +                 +                 +                 +                   +                 +                                 +                                      +                +             +                      +             +             +             +             +             +             +                            +                              +             +             +              +         +                             +     +     +     +     +     +     +     +     +     +                  +     +     +                 +     +                 +          +     +     +     +             +         +     +     +     +     +                    +     +     +     +     +     +     +     +     +               +     +         +     +     +     +     +              +               +     +     +     +     +     +     +         +       +     +     +               +                +     +     +                  +         +                         +             +             +             +             +             +                   +                   +         +                  +                     +             +                       +             +                  +         +              +     +     +     +                 +     +     +              +     +     +     +     +     +     +     +          +          +     +               +     +     +