add 2023/05/2
This commit is contained in:
parent
2e5602388d
commit
b27523103a
|
@ -1,4 +1,4 @@
|
|||
#![feature(test)]
|
||||
#![feature(test, iter_array_chunks)]
|
||||
extern crate test;
|
||||
use std::ops::Range;
|
||||
|
||||
|
@ -7,7 +7,7 @@ use itertools::Itertools;
|
|||
|
||||
const DAY: usize = 5;
|
||||
type I = i64;
|
||||
type Mapping = Vec<(Range<I>, I)>;
|
||||
type Mapping = Vec<(Range<I>, Range<I>, I)>;
|
||||
type Parsed = (Vec<I>, Vec<Mapping>);
|
||||
|
||||
fn parse_input(raw: &str) -> Parsed {
|
||||
|
@ -18,7 +18,8 @@ fn parse_input(raw: &str) -> Parsed {
|
|||
g.lines()
|
||||
.skip(1)
|
||||
.map(|l| l.split(' ').map(parse_num).collect_tuple().unwrap())
|
||||
.map(|(dst, src, len)| (src..src + len, dst - src))
|
||||
// We swap the order of dst and src here because it just makes much more sense to me this way.
|
||||
.map(|(dst, src, len)| (src..src + len, dst..dst + len, dst - src))
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
|
@ -26,15 +27,40 @@ fn parse_input(raw: &str) -> Parsed {
|
|||
}
|
||||
|
||||
fn resolve(start: I, mappings: &Vec<Mapping>) -> I {
|
||||
mappings.iter().fold(start, |i, map| map.iter().find_map(|(range, offset)| range.contains(&i).then_some(i + offset)).unwrap_or(i))
|
||||
mappings.iter().fold(start, |i, map| map.iter().find_map(|(range, _, offset)| range.contains(&i).then_some(i + offset)).unwrap_or(i))
|
||||
}
|
||||
|
||||
fn part1((seeds, mappings): &Parsed) -> I {
|
||||
seeds.iter().map(|&s| resolve(s, mappings)).min().unwrap()
|
||||
}
|
||||
|
||||
fn part2(parsed: &Parsed) -> I {
|
||||
unimplemented!()
|
||||
fn resolve_backwards(start: I, mappings: &Vec<Mapping>) -> I {
|
||||
mappings.iter().fold(start, |i, map| map.iter().find_map(|(_, range, offset)| range.contains(&i).then_some(i - offset)).unwrap_or(i))
|
||||
}
|
||||
|
||||
fn part2((seeds, mappings): &Parsed) -> I {
|
||||
let seed_ranges = seeds.iter().array_chunks().map(|[&a, &b]| a..a + b).collect_vec();
|
||||
let mut mappings = mappings.clone();
|
||||
// let smallest_range = mappings.iter().flatten().map(|(r, _, _)| r.try_len().unwrap()).min().unwrap();
|
||||
|
||||
let mut destinations = mappings.remove(mappings.len() - 1);
|
||||
destinations.sort_by_key(|(_, range, _)| range.start);
|
||||
mappings.reverse();
|
||||
|
||||
let mut ranges = Vec::<(Range<I>, I)>::new();
|
||||
for (_, range, offset) in destinations {
|
||||
ranges.push((ranges.last().map(|(r, _)| r.end).unwrap_or(1)..range.start, 0));
|
||||
ranges.push((range, offset));
|
||||
}
|
||||
ranges.into_iter().find_map(|(range, offset)| starting_seed(range, offset, &seed_ranges, &mappings, 1)).unwrap()
|
||||
}
|
||||
|
||||
fn starting_seed(range: Range<I>, offset: i64, seed_ranges: &Vec<Range<I>>, mappings: &Vec<Mapping>, step: usize) -> Option<i64> {
|
||||
range.step_by(step).find(|&s| {
|
||||
let seed = resolve_backwards(s - offset, &mappings);
|
||||
// If seed == s, the entire resolution didn’t hit a single mapping, so we don’t need to check seeds.
|
||||
seed != s && seed_ranges.iter().any(|r| r.contains(&seed))
|
||||
})
|
||||
}
|
||||
|
||||
boilerplate! {
|
||||
|
@ -73,9 +99,9 @@ humidity-to-location map:
|
|||
56 93 4",
|
||||
tests: {
|
||||
part1: { TEST_INPUT => 35 },
|
||||
part2: { TEST_INPUT => 0 },
|
||||
part2: { TEST_INPUT => 46 },
|
||||
},
|
||||
bench1 == 462648396,
|
||||
bench2 == 0,
|
||||
bench2 == 2520479,
|
||||
bench_parse: |(v1, v2): &Parsed| (v1.len(), v2.len()) => (20, 7),
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user