From 9208ba29376afeb11da71511822cfc3a645233dc Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 6 Dec 2023 17:34:50 +0200 Subject: [PATCH] finished day 05 part 2 --- 2023/Cargo.lock | 133 +++++++++++++++++++ 2023/Cargo.toml | 3 + 2023/day-05/Cargo.toml | 3 + 2023/day-05/input2.txt | 237 ++++++++++++++++++++++++++++++++++ 2023/day-05/src/part1.rs | 2 +- 2023/day-05/src/part2-slow.rs | 160 +++++++++++++++++++++++ 2023/day-05/src/part2.rs | 113 +++++++++++++++- 7 files changed, 644 insertions(+), 7 deletions(-) create mode 100644 2023/day-05/src/part2-slow.rs diff --git a/2023/Cargo.lock b/2023/Cargo.lock index e4705ba..fb4d5ce 100644 --- a/2023/Cargo.lock +++ b/2023/Cargo.lock @@ -17,6 +17,18 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "backtrace" version = "0.3.69" @@ -32,6 +44,15 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "brownstone" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5839ee4f953e811bfdcf223f509cb2c6a3e1447959b0bff459405575bc17f22" +dependencies = [ + "arrayvec", +] + [[package]] name = "cc" version = "1.0.83" @@ -74,6 +95,39 @@ dependencies = [ "tracing-error", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + [[package]] name = "day-01" version = "0.1.0" @@ -109,6 +163,9 @@ version = "0.1.0" dependencies = [ "color-eyre", "itertools", + "nom", + "nom-supreme", + "rayon", ] [[package]] @@ -133,6 +190,12 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "indent_write" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cfe9645a18782869361d9c8732246be7b410ad4e919d3609ebabdac00ba12c3" + [[package]] name = "indenter" version = "0.3.3" @@ -148,6 +211,12 @@ dependencies = [ "either", ] +[[package]] +name = "joinery" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72167d68f5fce3b8655487b8038691a3c9984ee769590f93f2a631f4ad64e4f5" + [[package]] name = "lazy_static" version = "1.4.0" @@ -166,6 +235,21 @@ version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -175,6 +259,29 @@ dependencies = [ "adler", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom-supreme" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd3ae6c901f1959588759ff51c95d24b491ecb9ff91aa9c2ef4acc5b1dcab27" +dependencies = [ + "brownstone", + "indent_write", + "joinery", + "memchr", + "nom", +] + [[package]] name = "object" version = "0.32.1" @@ -202,12 +309,38 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "rustc-demangle" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "sharded-slab" version = "0.1.7" diff --git a/2023/Cargo.toml b/2023/Cargo.toml index 6a3943e..f6f1257 100644 --- a/2023/Cargo.toml +++ b/2023/Cargo.toml @@ -6,3 +6,6 @@ members = ["day-*"] [workspace.dependencies] color-eyre = "0.6.2" itertools = "0.12.0" +nom = "7.1.3" +nom-supreme = "0.8.0" +rayon = "1.8.0" diff --git a/2023/day-05/Cargo.toml b/2023/day-05/Cargo.toml index 8cda5f9..58822c6 100644 --- a/2023/day-05/Cargo.toml +++ b/2023/day-05/Cargo.toml @@ -8,3 +8,6 @@ edition = "2021" [dependencies] color-eyre = { workspace = true } itertools = { workspace = true } +nom = { workspace = true } +nom-supreme = { workspace = true } +rayon = { workspace = true } diff --git a/2023/day-05/input2.txt b/2023/day-05/input2.txt index e69de29..352db90 100644 --- a/2023/day-05/input2.txt +++ b/2023/day-05/input2.txt @@ -0,0 +1,237 @@ +seeds: 4188359137 37519573 3736161691 172346126 2590035450 66446591 209124047 106578880 1404892542 30069991 3014689843 117426545 2169439765 226325492 1511958436 177344330 1822605035 51025110 382778843 823998526 + +seed-to-soil map: +1014943420 3864598346 36796924 +3481858860 1134944893 176050938 +1463359964 377309295 172917932 +1909673912 2511534001 114785858 +3472030089 1310995831 9828771 +188280292 3055921442 55776498 +352078282 1410745074 662865138 +1436499332 3759669547 26860632 +281816159 550227227 70262123 +2940933503 180112079 197197216 +3314718477 977633281 157311612 +3269652387 3354932755 45066090 +3138688421 4164003330 130963966 +3689427547 3407181792 70304018 +2673867052 3901395270 21291616 +3881132258 2371714487 139819514 +180112079 3751501334 8168213 +2471524173 3399998845 7182947 +244056790 3826838977 37759369 +2330362750 620489350 141161423 +1730119344 3786530179 40308798 +1770428142 4040990485 122455143 +1892883285 4024199858 16790627 +3657909798 2340196738 31517749 +1365072738 2268770144 71426594 +1636277896 3930358410 93841448 +1173574466 2626319859 183826748 +3871069976 3233532062 10062282 +3138130719 4163445628 557702 +3759731565 3243594344 111338411 +1357401214 3922686886 7671524 +2478707120 2073610212 195159932 +2695158668 2810146607 245774835 +1051740344 3111697940 121834122 +2024459770 761650773 215982508 +2240442278 1320824602 89920472 +4020951772 3477485810 274015524 + +soil-to-fertilizer map: +3211509025 2411974869 518394 +3778955089 2412493263 120143427 +1387254723 3589309701 265617279 +3899098516 3906385182 120055953 +1714049028 3209939839 261248850 +3687768172 2393589437 18385432 +554325135 488411873 327969675 +2579624415 1520719313 60457941 +4019154469 1244906486 275812827 +65913262 0 488411873 +1244906486 2362023384 31566053 +2251369843 4026441135 268526161 +0 826989738 65913262 +3737515035 2233559302 41440054 +1975297878 2563998121 276071965 +3606812793 2152603923 80955379 +3706153604 2532636690 31361431 +1327930741 2336176382 25847002 +3262441387 2840070086 276664362 +1353777743 3176462859 33476980 +1007455475 962102883 213088648 +3212027419 3538895733 50413968 +2519896004 3116734448 59728411 +938255592 892903000 69199883 +3539105749 3471188689 67707044 +2640082356 1581177254 571426669 +927647402 816381548 10608190 +882294810 1175191531 45352592 +1652872002 2274999356 61177026 +1276472539 3854926980 51458202 + +fertilizer-to-water map: +3919934952 4034286493 116558226 +3104838986 886102234 15848522 +151486725 1109841455 112301087 +38656834 2035810690 62773281 +1106567462 3087125934 135164894 +1010741746 2114463748 17027276 +1428501666 0 69192244 +1241732356 699332924 186769310 +728534624 1829633882 45432965 +465497393 318840419 263037231 +263787812 69192244 201709581 +1750247416 2131491024 226195640 +3103410010 1396336613 1428976 +1541007057 2541565636 209240359 +2557596892 1222142542 146760701 +3810606692 4150844719 109328260 +1497693910 2098583971 15879777 +2027240691 1925694260 110116430 +3120687508 1664856712 30800728 +2919531038 2357686664 183878972 +2271333563 2800862605 286263329 +0 660676090 38656834 +121820432 2771196312 29666293 +773967589 1428082555 236774157 +2137357121 1695657440 133976442 +2704357593 270901825 47938594 +2782613153 952748391 136917885 +4200808114 3619712494 94159182 +1513573687 1368903243 27433370 +3151488236 1875066847 50627413 +4036493178 4260172979 34794317 +1027769022 581877650 78798440 +3202115649 1089666276 20175179 +4071287495 3713871676 33593925 +1976443056 901950756 50797635 +2752296187 1397765589 30316966 +101430115 2750805995 20390317 +4104881420 3523785800 95926694 +3523785800 3747465601 286820892 + +water-to-light map: +3408155249 2527370950 73535457 +1697763259 1358503385 195569028 +4146691798 4150439777 2978835 +1667104621 3141702962 30658638 +3109198454 2600906407 225322957 +2896907826 3481425874 212290628 +3568598531 1256359145 28510402 +1021594560 3172361600 54292616 +2709047387 0 23043868 +634713149 1912815102 64867237 +2732091255 3693716502 115595269 +4005143114 4153418612 141548684 +1341220299 1554072413 325884322 +3514549073 2826229364 54049458 +1113545862 2299696513 227674437 +3481690706 1879956735 32858367 +379941491 3226654216 254771658 +4149670633 4005143114 145296663 +699580386 1977682339 322014174 +2847686524 2880278822 49221302 +1075887176 23043868 37658686 +3334521411 1284869547 73633838 +3597108933 2929500124 212202838 +1893332287 440644045 815715100 +0 60702554 379941491 + +light-to-temperature map: +3239555722 2588818955 376881377 +413170934 1615450109 438931580 +1386539780 3880234113 95792562 +3901352290 2965700332 122376625 +2415511159 396206595 236868242 +396206595 3092807515 16964339 +2652379401 633074837 587176321 +1998109231 1220251158 178061188 +2176170419 3109771854 239340740 +852102514 2054381689 534437266 +1806003521 3349112594 192105710 +1487062900 3976026675 318940621 +1482332342 3088076957 4730558 +3616437099 3687776838 138356657 +3754793756 3541218304 146558534 +4077829533 1398312346 217137763 +4023728915 3826133495 54100618 + +temperature-to-humidity map: +2477444013 1065021126 6182773 +845330217 1308005650 445611689 +1290941906 3378900568 76961272 +2975821403 1792935684 125881029 +2161173272 2394771508 172817491 +2483626786 3710234886 492194617 +3447920062 2383111679 11659829 +4033768577 1918816713 94002198 +3319210784 3455861840 27565379 +1373852246 1071203899 92358857 +3101702432 845330217 174648768 +2026258159 2567588999 134915113 +1799450492 3483427219 226807667 +3552117684 3041692569 337207999 +3889325683 1163562756 144442894 +3346776163 2047917336 101143899 +3459579891 4202429503 92537793 +0 348737431 60744241 +1367903178 2829658946 5949068 +1466211103 2702504112 127154834 +1764704299 2835608014 34746193 +60744241 322208375 20457270 +1593365937 2870354207 171338362 +81201511 342665645 6071786 +4255648951 1753617339 39318345 +2442345588 2012818911 35098425 +2333990763 2231897270 108354825 +87273297 0 322208375 +4210606810 1019978985 45042141 +3276351200 2340252095 42859584 +4127770775 2149061235 82836035 + +humidity-to-location map: +4164635022 1854717524 130332274 +1293632444 529805154 119897086 +2886189584 4227662016 67305280 +2977935483 447338344 82466810 +1796689277 771172820 2500486 +3592167651 2376391709 149158288 +85140393 196642481 8447522 +1799189763 1985049798 97611367 +93587915 82281848 114360633 +1191989560 4020597507 76356570 +2953494864 3996156888 24440619 +2292169251 649702240 113196341 +3741325939 3311723608 237145571 +3978471510 3948521384 47635504 +2457376544 762898581 6077326 +1413529530 768975907 2196913 +1268346130 3923235070 25286314 +4064092089 3749326886 100542933 +2463453870 3849869819 73365251 +2858545 0 82281848 +4026107014 4166840403 37985075 +3060402293 223340676 11429685 +0 205090003 2858545 +3071831978 1031969734 125782276 +895745297 2082661165 83676280 +513318799 1318499280 382426498 +2536819121 3548869179 86842399 +2405365592 1157752010 52010952 +2086131564 3105685921 206037687 +1972516256 3635711578 113615308 +3197614254 2921186788 184499133 +3382113387 2166337445 210054264 +383000830 933333460 37595105 +2777453266 1209762962 108736318 +443432473 4096954077 69886326 +1461500584 2540223954 335188693 +1415726443 2875412647 45774141 +420595935 4204825478 22836538 +979421577 234770361 212567983 +223340676 773673306 159660154 +1911475087 970928565 61041169 +1896801130 2525549997 14673957 +2623661520 1700925778 153791746 diff --git a/2023/day-05/src/part1.rs b/2023/day-05/src/part1.rs index 13d0e23..70284b4 100644 --- a/2023/day-05/src/part1.rs +++ b/2023/day-05/src/part1.rs @@ -1,4 +1,4 @@ -use color_eyre::{eyre::anyhow, Result}; +use color_eyre::Result; use std::str::FromStr; #[derive(Debug, Clone)] diff --git a/2023/day-05/src/part2-slow.rs b/2023/day-05/src/part2-slow.rs new file mode 100644 index 0000000..8406c85 --- /dev/null +++ b/2023/day-05/src/part2-slow.rs @@ -0,0 +1,160 @@ +use color_eyre::Result; +use std::str::FromStr; + +#[derive(Debug, Clone)] +struct Seeds(Vec); + +impl FromStr for Seeds { + type Err = &'static str; + fn from_str(s: &str) -> std::prelude::v1::Result { + let nums = s.split(':').last().map(|nums| { + nums.split_whitespace() + .map(|num| { + num.parse::() + .map_err(|_| "Seed should be a number") + .unwrap() + }) + .collect::>() + }); + let seeds = nums + .ok_or("No seeds found")? + .chunks(2) + .flat_map(|chunk| { + let start = chunk[0]; + let end = start + chunk[1]; + (start..=end).collect::>() + }) + .collect(); + + Ok(Self(seeds)) + } +} + +#[derive(Debug, Clone)] +struct SeedMap { + dest_range: Vec, + source_range: Vec, + range_len: Vec, +} + +impl SeedMap { + fn iter(&self) -> impl Iterator { + itertools::izip!(&self.dest_range, &self.source_range, &self.range_len) + } +} + +impl From> for SeedMap { + fn from(value: Vec) -> Self { + let mut dest_range = Vec::new(); + let mut source_range = Vec::new(); + let mut range_len = Vec::new(); + + for chunk in value.chunks(3) { + if let [dest, source, range] = chunk { + dest_range.push(*dest); + source_range.push(*source); + range_len.push(*range); + } + } + + Self { + dest_range, + source_range, + range_len, + } + } +} + +pub fn process(input: &str) -> Result { + let mut lines: Vec<_> = input.lines().collect(); + lines.push(""); + let seeds = Seeds::from_str(lines.remove(0)).unwrap(); + + let mut nums: Vec = Vec::new(); + + let maps: Vec<_> = lines + .iter() + .map(|line| { + if !line.contains(':') && !line.is_empty() { + line.split_whitespace().for_each(|num_str| { + if let Ok(num) = num_str.parse::() { + nums.push(num); + } + }); + } + + if line.is_empty() && !nums.is_empty() { + let map = SeedMap::from(nums.clone()); + nums.clear(); + Some(map) + } else { + None + } + }) + .filter_map(|map_option| map_option) + .collect(); + + let mut step = seeds.0; + let mut next_step = Vec::new(); + + for map in &maps { + for (&dest_range, &source_range, &range_len) in map.iter() { + for num in step.clone() { + if (source_range..=source_range + range_len).contains(&num) { + step.retain(|&x| x != num); + let dest = num + dest_range - source_range; + next_step.push(dest); + } + } + } + next_step.append(&mut step); + step = next_step.clone(); + next_step.clear(); + } + + Ok(*step.iter().min().unwrap_or(&0)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_process() -> Result<()> { + let input = "seeds: 79 14 55 13 + +seed-to-soil map: +50 98 2 +52 50 48 + +soil-to-fertilizer map: +0 15 37 +37 52 2 +39 0 15 + +fertilizer-to-water map: +49 53 8 +0 11 42 +42 0 7 +57 7 4 + +water-to-light map: +88 18 7 +18 25 70 + +light-to-temperature map: +45 77 23 +81 45 19 +68 64 13 + +temperature-to-humidity map: +0 69 1 +1 0 69 + +humidity-to-location map: +60 56 37 +56 93 4"; + assert_eq!(46, process(input)?); + Ok(()) + } +} diff --git a/2023/day-05/src/part2.rs b/2023/day-05/src/part2.rs index b2f0774..3fe32ec 100644 --- a/2023/day-05/src/part2.rs +++ b/2023/day-05/src/part2.rs @@ -1,8 +1,78 @@ use color_eyre::Result; +use rayon::iter::{IntoParallelIterator, ParallelIterator}; +use std::ops::Range; -pub fn process(input: &str) -> Result { - todo!("day xx - part 2"); - Ok(0) +use nom::{ + bytes::complete::take_until, + character::complete::{self, line_ending, space1}, + multi::{many1, separated_list1}, + sequence::{separated_pair, tuple}, + IResult, Parser, +}; +use nom_supreme::{tag::complete::tag, ParserExt}; + +#[derive(Debug)] +struct SeedMap { + mappings: Vec<(Range, Range)>, +} + +impl SeedMap { + fn translate(&self, source: u64) -> u64 { + let valid_mapping = self + .mappings + .iter() + .find(|(source_range, _)| source_range.contains(&source)); + let Some((source_range, destination_range)) = valid_mapping else { + return source; + }; + let offset = source - source_range.start; + destination_range.start + offset + } +} + +fn line(input: &str) -> IResult<&str, (Range, Range)> { + let (input, (destination, source, num)) = tuple(( + complete::u64, + complete::u64.preceded_by(tag(" ")), + complete::u64.preceded_by(tag(" ")), + ))(input)?; + Ok(( + input, + (source..(source + num), destination..(destination + num)), + )) +} + +fn seed_map(input: &str) -> IResult<&str, SeedMap> { + take_until("map:") + .precedes(tag("map:")) + .precedes(many1(line_ending.precedes(line)).map(|mappings| SeedMap { mappings })) + .parse(input) +} + +fn parse_seedmaps(input: &str) -> IResult<&str, (Vec>, Vec)> { + let (input, seeds) = tag("seeds: ") + .precedes(separated_list1( + space1, + separated_pair(complete::u64, tag(" "), complete::u64) + .map(|(start, offset)| start..(start + offset)), + )) + .parse(input)?; + + let (input, maps) = many1(seed_map)(input)?; + + Ok((input, (seeds, maps))) +} + +pub fn process(input: &str) -> Result { + let (_, (seeds, maps)) = parse_seedmaps(input).expect("A valid prarse"); + + let minimum_location = seeds + .into_par_iter() + .flat_map(|range| range.clone()) + .map(|seed| maps.iter().fold(seed, |seed, map| map.translate(seed))) + .min(); + + Ok(minimum_location.expect("Should ha a minimum value")) } #[cfg(test)] @@ -11,9 +81,40 @@ mod tests { #[test] fn test_process() -> Result<()> { - let input = ""; - todo!("haven't built test yet"); - assert_eq!(0, process(input)?); + let input = "seeds: 79 14 55 13 + +seed-to-soil map: +50 98 2 +52 50 48 + +soil-to-fertilizer map: +0 15 37 +37 52 2 +39 0 15 + +fertilizer-to-water map: +49 53 8 +0 11 42 +42 0 7 +57 7 4 + +water-to-light map: +88 18 7 +18 25 70 + +light-to-temperature map: +45 77 23 +81 45 19 +68 64 13 + +temperature-to-humidity map: +0 69 1 +1 0 69 + +humidity-to-location map: +60 56 37 +56 93 4"; + assert_eq!(46, process(input)?); Ok(()) } }