generated from janezicmatej/aoc-template
solution: day5 ranges
Squashed commit of the following:
commit 000001603e10102f634c2f4ca7eb310ec72f1863
Author: Matej Janežič <janezic.mj@gmail.com>
Date: Wed Dec 6 20:47:26 2023 +0100
day(5): ranges
commit 0000015049
Author: Matej Janežič <janezic.mj@gmail.com>
Date: Wed Dec 6 18:58:58 2023 +0100
wip: solve with range type
This commit is contained in:
parent
00000140d3
commit
0000015082
|
@ -1,17 +1,33 @@
|
||||||
use std::{
|
use std::{
|
||||||
cmp::{max, min},
|
cmp::{max, min},
|
||||||
|
fmt::Debug,
|
||||||
|
ops::RangeInclusive,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
use aoc::parsers::to_vec;
|
use aoc::parsers::to_vec;
|
||||||
|
|
||||||
type PairRange = (u64, u64);
|
trait RangeInclusiveExt {
|
||||||
|
fn overlaps(&self, other: &Self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> RangeInclusiveExt for RangeInclusive<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) -> RangeInclusive<u64> {
|
||||||
|
start..=(start + range - 1)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Mapping {
|
struct Mapping {
|
||||||
destination: u64,
|
pub source: RangeInclusive<u64>,
|
||||||
source: u64,
|
pub destination: RangeInclusive<u64>,
|
||||||
range: u64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ParseMappingError;
|
struct ParseMappingError;
|
||||||
|
@ -22,49 +38,43 @@ 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[0], nums[2]),
|
||||||
source: nums[1],
|
source: build_range(nums[1], nums[2]),
|
||||||
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 map_range(&self, r: RangeInclusive<u64>) -> RangeInclusive<u64> {
|
||||||
|
self.map(*r.start())..=(self.map(*r.end()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn split_range(&self, r: RangeInclusive<u64>) -> [Option<RangeInclusive<u64>>; 3] {
|
||||||
let mut fences = [
|
let mut fences = [
|
||||||
s,
|
*r.start(),
|
||||||
s + r,
|
*r.end() + 1,
|
||||||
max(self.source, s),
|
max(*self.source.start(), *r.start()),
|
||||||
min(self.source + self.range, s + r),
|
min(*self.source.end() + 1, *r.end() + 1),
|
||||||
];
|
];
|
||||||
|
|
||||||
fences.sort();
|
fences.sort();
|
||||||
|
|
||||||
let mut v = Vec::new();
|
const ARRAY_REPEAT_VALUE: Option<RangeInclusive<u64>> = None;
|
||||||
|
let mut v = [ARRAY_REPEAT_VALUE; 3];
|
||||||
|
|
||||||
for i in 0..3 {
|
for i in 0..3 {
|
||||||
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[i] = Some(f..=(nf - 1))
|
||||||
} else {
|
|
||||||
v.push(None)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
v
|
||||||
v[..3].try_into().unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +105,7 @@ pub fn part_one(input: &str) -> Option<u64> {
|
||||||
let mut s = *seed;
|
let mut s = *seed;
|
||||||
'maps: for map in maps.iter() {
|
'maps: for map in maps.iter() {
|
||||||
for inner in map.iter() {
|
for inner in map.iter() {
|
||||||
if inner.contains(s) {
|
if inner.source.contains(&s) {
|
||||||
s = inner.map(s);
|
s = inner.map(s);
|
||||||
continue 'maps;
|
continue 'maps;
|
||||||
}
|
}
|
||||||
|
@ -111,22 +121,19 @@ pub fn part_one(input: &str) -> Option<u64> {
|
||||||
pub fn part_two(input: &str) -> Option<u64> {
|
pub fn part_two(input: &str) -> Option<u64> {
|
||||||
let (first, rest) = input.split_once("\n\n").unwrap();
|
let (first, rest) = input.split_once("\n\n").unwrap();
|
||||||
let maps = parse_map(rest);
|
let maps = parse_map(rest);
|
||||||
let seeds = to_vec::<u64, _>(first.strip_prefix("seeds: ").unwrap(), ' ');
|
let mut seeds_ranges: Vec<_> = to_vec::<u64, _>(first.strip_prefix("seeds: ").unwrap(), ' ')
|
||||||
let mut seeds_ranges: Vec<_> = Vec::new();
|
.chunks(2)
|
||||||
for s in seeds.chunks(2) {
|
.map(|x| build_range(x[0], x[1]))
|
||||||
seeds_ranges.push((s[0], s[1]))
|
.collect();
|
||||||
}
|
|
||||||
|
|
||||||
for mapping in maps.iter() {
|
for mapping in maps.iter() {
|
||||||
let mut new_ranges = Vec::new();
|
let mut new_ranges = Vec::new();
|
||||||
|
|
||||||
'queue: while let Some((s, r)) = seeds_ranges.pop() {
|
'queue: while let Some(rng) = seeds_ranges.pop() {
|
||||||
for map in mapping {
|
for map in mapping {
|
||||||
if map.contains_any((s, r)) {
|
if map.source.overlaps(&rng) {
|
||||||
let [pre, to_map, post] = map.split_range((s, r));
|
let [pre, to_map, post] = map.split_range(rng);
|
||||||
let to_map = to_map.unwrap();
|
new_ranges.push(map.map_range(to_map.unwrap()));
|
||||||
let mapped = (map.map(to_map.0), to_map.1);
|
|
||||||
new_ranges.push(mapped);
|
|
||||||
for r in [pre, post].into_iter().flatten() {
|
for r in [pre, post].into_iter().flatten() {
|
||||||
seeds_ranges.push(r);
|
seeds_ranges.push(r);
|
||||||
}
|
}
|
||||||
|
@ -134,13 +141,17 @@ pub fn part_two(input: &str) -> Option<u64> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new_ranges.push((s, r));
|
new_ranges.push(rng);
|
||||||
}
|
}
|
||||||
|
|
||||||
seeds_ranges = new_ranges;
|
seeds_ranges = new_ranges;
|
||||||
}
|
}
|
||||||
|
|
||||||
seeds_ranges.iter().map(|(x, _)| *x).min()
|
seeds_ranges
|
||||||
|
.iter()
|
||||||
|
.map(RangeInclusive::start)
|
||||||
|
.min()
|
||||||
|
.copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
aoc::solution!(5);
|
aoc::solution!(5);
|
||||||
|
|
Loading…
Reference in New Issue