Compare commits

...

2 Commits

Author SHA1 Message Date
Matej Janezic 0000015049
wip: solve with range type 2023-12-06 19:40:56 +01:00
Matej Janezic 00000140d3
solution: day 6 clean 2023-12-06 19:39:39 +01:00
2 changed files with 54 additions and 43 deletions

View File

@ -1,17 +1,32 @@
use std::{ use std::{
cmp::{max, min}, cmp::{max, min},
ops::Range,
str::FromStr, str::FromStr,
}; };
use aoc::parsers::to_vec; use aoc::parsers::to_vec;
type PairRange = (u64, u64); trait RangeExt {
fn overlaps(&self, other: &Self) -> bool;
}
impl<T> RangeExt for Range<T>
where
T: PartialOrd,
{
fn overlaps(&self, other: &Self) -> bool {
self.contains(&other.start) || self.contains(&other.end)
}
}
fn build_range(start: u64, range: u64) -> Range<u64> {
start..(start + range)
}
#[derive(Debug)] #[derive(Debug)]
struct Mapping { struct Mapping {
destination: u64, destination: Range<u64>,
source: u64, source: Range<u64>,
range: u64,
} }
struct ParseMappingError; struct ParseMappingError;
@ -22,34 +37,26 @@ impl FromStr for Mapping {
let nums: Vec<u64> = to_vec(s, ' '); let nums: Vec<u64> = to_vec(s, ' ');
Ok(Self { Ok(Self {
destination: nums[0], destination: build_range(nums[2], nums[0]),
source: nums[1], source: build_range(nums[1], nums[0]),
range: nums[2],
}) })
} }
} }
impl Mapping { impl Mapping {
fn contains(&self, n: u64) -> bool {
n >= self.source && n < self.source + self.range
}
fn contains_any(&self, (s, r): PairRange) -> bool {
s < self.source + self.range && s + r > self.source
}
fn map(&self, n: u64) -> u64 { fn map(&self, n: u64) -> u64 {
let shift = n - self.source; let shift = n - self.source.start;
self.destination + shift self.destination.start + shift
} }
fn split_range(&self, (s, r): PairRange) -> [Option<PairRange>; 3] { fn split_range(&self, r: Range<u64>) -> [Option<Range<u64>>; 3] {
let mut fences = [ let mut fences = [
s, r.start,
s + r, r.end,
max(self.source, s), max(self.source.start, r.start),
min(self.source + self.range, s + r), min(self.source.end, r.end),
]; ];
fences.sort(); fences.sort();
let mut v = Vec::new(); let mut v = Vec::new();
@ -58,13 +65,13 @@ impl Mapping {
let f = fences[i]; let f = fences[i];
let nf = fences[i + 1]; let nf = fences[i + 1];
if f != nf { if f != nf {
v.push(Some((f, nf - f))) v.push(Some(f..(nf - f)))
} else { } else {
v.push(None) v.push(None)
} }
} }
v[..3].try_into().unwrap() [v[0], v[1], v[2]]
} }
} }

View File

@ -1,5 +1,3 @@
use aoc::parsers::to_vec;
fn win_options((time, distance): (u64, u64)) -> u64 { fn win_options((time, distance): (u64, u64)) -> u64 {
let discriminant = ((time.pow(2) - 4 * distance) as f64).sqrt(); let discriminant = ((time.pow(2) - 4 * distance) as f64).sqrt();
@ -14,28 +12,34 @@ fn win_options((time, distance): (u64, u64)) -> u64 {
} }
pub fn part_one(input: &str) -> Option<u64> { pub fn part_one(input: &str) -> Option<u64> {
let (upt, upd) = input.split_once('\n')?; let [time, distance] = input
let time: Vec<u64> = to_vec(upt.strip_prefix("Time: ")?, ' '); .lines()
let distance: Vec<u64> = to_vec(upd.strip_prefix("Distance: ")?, ' '); .map(|l| {
l.split_whitespace()
.skip(1)
.filter_map(|n| n.parse().ok())
.collect::<Vec<u64>>()
})
.collect::<Vec<_>>()
.try_into()
.ok()?;
Some(time.into_iter().zip(distance).map(win_options).product()) Some(time.into_iter().zip(distance).map(win_options).product())
} }
pub fn part_two(input: &str) -> Option<u64> { pub fn part_two(input: &str) -> Option<u64> {
let (upt, upd) = input.split_once('\n')?; let [time, distance] = input
let time: u64 = upt .lines()
.strip_prefix("Time: ")? .filter_map(|l| {
.split(' ') l.split_whitespace()
.flat_map(|x| x.chars()) .skip(1)
.collect::<String>()
.parse()
.ok()?;
let distance: u64 = upd
.strip_prefix("Distance: ")?
.split(' ')
.flat_map(|x| x.chars()) .flat_map(|x| x.chars())
.collect::<String>() .collect::<String>()
.parse() .parse()
.ok()
})
.collect::<Vec<_>>()
.try_into()
.ok()?; .ok()?;
Some(win_options((time, distance))) Some(win_options((time, distance)))