Skip to content

Instantly share code, notes, and snippets.

@anden3
Last active December 5, 2023 20:02
Show Gist options
  • Select an option

  • Save anden3/a4582a3fffae8042593ffcbf11c83076 to your computer and use it in GitHub Desktop.

Select an option

Save anden3/a4582a3fffae8042593ffcbf11c83076 to your computer and use it in GitHub Desktop.
use std::ops::Range;
use rangemap::RangeSet;
trait RangeExt {
fn add(&self, offset: i64) -> Self;
}
impl RangeExt for Range<i64> {
fn add(&self, offset: i64) -> Self {
(self.start + offset)..(self.end + offset)
}
}
pub fn part2(input: &str) -> i64 {
let mut seeds = RangeSet::<i64>::new();
for section in input.split("\n\n") {
let (label, values) = section.split_once(':').unwrap();
if label == "seeds" {
let seed_vec = values
.trim()
.split_ascii_whitespace()
.map(|v| v.parse::<i64>().unwrap())
.collect::<Vec<_>>();
for pair in seed_vec.chunks_exact(2) {
let (start, length) = (pair[0], pair[1]);
seeds.insert(start..(start + length));
}
continue;
}
let mut next_seeds = RangeSet::<i64>::new();
for line in values.trim().lines() {
let mut line_values = line.split_ascii_whitespace().map(|v| v.parse().unwrap());
let [dest, source, length]: [i64; 3] =
std::array::from_fn(|_| line_values.next().unwrap());
let diff = dest - source;
let source_range = source..(source + length);
let mut to_remove = Vec::new();
for overlapping in seeds.overlapping(&source_range) {
let range = match (
source_range.contains(&overlapping.start),
source_range.contains(&overlapping.end),
) {
(true, true) => {
overlapping.clone()
}
(true, false) => {
overlapping.start..source_range.end
}
(false, true) => {
source_range.start..overlapping.end
}
(false, false) => {
source_range.clone()
}
};
next_seeds.insert(range.add(diff));
to_remove.push(range);
}
for range in to_remove {
seeds.remove(range);
}
}
next_seeds.extend(seeds);
seeds = next_seeds;
}
seeds.into_iter().next().unwrap().start
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment