This commit is contained in:
Christian
2023-12-06 19:13:33 +01:00
parent 488b518f08
commit 7c30d11783
2 changed files with 389 additions and 0 deletions

150
src/bin/day05.rs Normal file
View File

@@ -0,0 +1,150 @@
use std::env;
use std::fs;
use anyhow::{Context, Result};
#[derive(Clone)]
struct Range {
start: i64,
end: i64,
}
impl Range {
fn new(start: i64, end: i64) -> Range {
Range {
start: start.min(end),
end: end.max(start),
}
}
fn from_start_size(start: i64, size: i64) -> Range {
Range {
start,
end: start + size,
}
}
fn intersects(&self, other: &Range) -> bool {
!(self.end <= other.start || other.end <= self.start)
}
fn intersect(&self, other: &Range) -> Option<Range> {
if self.intersects(other) {
Some(Range::new(
self.start.max(other.start),
self.end.min(other.end),
))
} else {
None
}
}
fn contains(&self, value: i64) -> bool {
self.start <= value && value <= self.end
}
}
struct Entry {
offset: i64,
range: Range,
}
impl Entry {
fn new(dest: i64, start: i64, size: i64) -> Entry {
Entry {
offset: dest - start,
range: Range::from_start_size(start, size),
}
}
fn translate(&self, value: i64) -> Option<i64> {
if self.range.contains(value) {
Some(value + self.offset)
} else {
None
}
}
}
fn main() -> Result<()> {
let filename = env::args()
.nth(1)
.context("./day03 <path to puzzle input>")?;
let input = fs::read_to_string(filename)?;
let mut sections = input.split("\n\n");
let seeds = sections
.next()
.unwrap()
.split(' ')
.skip(1)
.map(|w| w.parse::<i64>().unwrap())
.collect::<Vec<_>>();
let maps = sections
.map(|mp| {
mp.lines()
.skip(1)
.map(|line| {
let mut l = line.split(' ').map(|v| v.parse::<i64>().unwrap());
let dest = l.next().unwrap();
let start = l.next().unwrap();
let size = l.next().unwrap();
Entry::new(dest, start, size)
})
.collect()
})
.collect::<Vec<Vec<_>>>();
let convert =
|value, map: &Vec<Entry>| map.iter().find_map(|m| m.translate(value)).unwrap_or(value);
let find_location = |&seed| maps.iter().fold(seed, convert);
let part1 = seeds.iter().map(find_location).min().unwrap();
let mut inputs = Vec::new();
let mut outputs = Vec::new();
let mut rests = Vec::new();
let mut chunked = seeds.chunks(2);
while let Some(&[start, size]) = chunked.next() {
inputs.push(Range::from_start_size(start, size));
}
for map in maps.iter() {
for map_section in map.iter() {
for range in inputs.iter() {
if let Some(intersection) = map_section.range.intersect(&range) {
outputs.push(Range::new(
intersection.start + map_section.offset,
intersection.end + map_section.offset,
));
if range.start < map_section.range.start {
rests.push(Range::new(range.start, map_section.range.start));
}
if map_section.range.end < range.end {
rests.push(Range::new(map_section.range.end, range.end))
}
} else {
rests.push(range.clone());
}
}
inputs.clear();
inputs.append(&mut rests);
}
inputs.append(&mut outputs);
}
let part2 = inputs.into_iter().map(|range| range.start).min().unwrap();
println!("1) {}", part1);
println!("2) {}", part2);
Ok(())
}