summaryrefslogtreecommitdiffstats
path: root/2023/rs/code/five/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to '2023/rs/code/five/src/main.rs')
-rw-r--r--2023/rs/code/five/src/main.rs82
1 files changed, 82 insertions, 0 deletions
diff --git a/2023/rs/code/five/src/main.rs b/2023/rs/code/five/src/main.rs
new file mode 100644
index 0000000..79ba943
--- /dev/null
+++ b/2023/rs/code/five/src/main.rs
@@ -0,0 +1,82 @@
+#![feature(iter_array_chunks)]
+
+use nom::{Parser, IResult, Finish};
+use nom::character::complete::*;
+use nom::bytes::complete::*;
+use nom::sequence::*;
+use nom::multi::*;
+
+use std::io::Write;
+
+static INPUT: &str = include_str!("input.txt");
+
+#[derive(Debug, Copy, Clone)]
+struct Entry {
+ source_start: u32,
+ dest_start: u32,
+ len: u32
+}
+
+fn parse(i: &str) -> IResult<&str, (Vec<u32>, Vec<Vec<Entry>>)> {
+ let (i, (_, seeds, mut entries)) = tuple((
+ tag("seeds: "),
+ separated_list1(tag(" "), digit1.map(|s: &str| s.parse().unwrap())),
+ many1(preceded(
+ tuple((line_ending, line_ending, not_line_ending, line_ending)),
+ separated_list1(
+ line_ending,
+ tuple((
+ digit1,
+ tag(" "),
+ digit1,
+ tag(" "),
+ digit1))
+ .map(|(a, _, b, _, c): (&str, _, &str, _, &str)|
+ Entry { dest_start: a.parse().unwrap(), source_start: b.parse().unwrap(), len: c.parse().unwrap() }))))))
+ (i)?;
+
+ for entry in &mut entries {
+ entry.sort_by_key(|e| e.source_start);
+ }
+
+ Ok((i, (seeds, entries)))
+}
+
+fn main() {
+ let (seeds, entries) = parse(INPUT).finish().unwrap().1;
+
+ let map_seed = |s: u32|
+ entries.iter().fold(
+ s,
+ |s, el| {
+ let entry = el.iter().cloned().find(
+ |i| i.source_start <= s && s - i.source_start < i.len)
+ .unwrap_or(Entry { source_start: 0, dest_start: 0, len: u32::MAX });
+ s - entry.source_start + entry.dest_start
+ });
+
+
+ let min_loc = seeds.iter().cloned().map(map_seed).min().unwrap();
+ println!("Minimum `location`: {min_loc}");
+
+ // [12:48 AM] got p1
+ // [12:48 AM] oh this sucks
+ // [12:50 AM] do i just
+ // [12:50 AM] brute force it
+ // [12:50 AM] i could like
+ // [12:50 AM] write something clever here
+ // [12:51 AM] like i think i could do something like lifting the mapping between the layers and creating one final mapping, and then just checking against that
+ // [12:51 AM] and just finding the lowest start number within the bounds of all the seed ranges
+ // [12:51 AM] but i dont feel like doing that
+
+ #[cfg(debug_assertions)]
+ eprintln!("Warning: Debug build detected! This next bit takes a while, so I'd suggest compiling `--release`.");
+
+ let min_loc_ranged = seeds.iter().array_chunks::<2>()
+ .inspect(|[a, b]| { print!("\x1B[2KChecking {} => {}...\r", *a, *a + *b); std::io::stdout().flush().unwrap(); })
+ .flat_map(|[a, b]| *a..(*a+*b))
+ .map(map_seed)
+ .min().unwrap();
+
+ println!("Minimum `location` within ranges: {min_loc_ranged}");
+}