mirror of
https://github.com/Noratrieb/advent-of-code.git
synced 2026-01-14 17:45:02 +01:00
day 5 part 2
This commit is contained in:
parent
06bbace80a
commit
e94ae9a7af
2 changed files with 108 additions and 5 deletions
|
|
@ -1,3 +1,5 @@
|
||||||
|
mod p2basic;
|
||||||
|
|
||||||
use helper::{Day, IteratorExt, Variants};
|
use helper::{Day, IteratorExt, Variants};
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
|
|
@ -12,7 +14,7 @@ helper::define_variants! {
|
||||||
basic => crate::part1;
|
basic => crate::part1;
|
||||||
}
|
}
|
||||||
part2 {
|
part2 {
|
||||||
basic => crate::part2;
|
basic => crate::p2basic::part2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,6 +35,12 @@ struct MappedRange {
|
||||||
len: u64,
|
len: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl MappedRange {
|
||||||
|
fn source_end(&self) -> u64 {
|
||||||
|
self.source_start + self.len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_maps<'a>(mut lines: impl Iterator<Item = &'a str>) -> Vec<Vec<MappedRange>> {
|
fn parse_maps<'a>(mut lines: impl Iterator<Item = &'a str>) -> Vec<Vec<MappedRange>> {
|
||||||
let mut maps = vec![];
|
let mut maps = vec![];
|
||||||
while let Some(line) = lines.next() {
|
while let Some(line) = lines.next() {
|
||||||
|
|
@ -95,8 +103,42 @@ fn part1(input: &str) -> u64 {
|
||||||
min_loc
|
min_loc
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(_input: &str) -> u64 {
|
#[allow(dead_code)]
|
||||||
0
|
fn part2_brute_force(input: &str) -> u64 {
|
||||||
|
let mut lines = input.lines();
|
||||||
|
let seeds = lines
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.strip_prefix("seeds: ")
|
||||||
|
.unwrap()
|
||||||
|
.split_ascii_whitespace()
|
||||||
|
.map(|n| n.parse::<u64>().unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let seeds = seeds.chunks(2);
|
||||||
|
|
||||||
|
let maps = parse_maps(lines);
|
||||||
|
|
||||||
|
let mut min_loc = u64::MAX;
|
||||||
|
|
||||||
|
for seeds in seeds {
|
||||||
|
for mut seed in seeds[0]..(seeds[0] + seeds[1]) {
|
||||||
|
for ranges in &maps {
|
||||||
|
match ranges.iter().find(|range| {
|
||||||
|
(range.source_start..(range.source_start + range.len)).contains(&seed)
|
||||||
|
}) {
|
||||||
|
Some(range) => {
|
||||||
|
let offset = seed - range.source_start;
|
||||||
|
let new = range.dest_start + offset;
|
||||||
|
seed = new;
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
min_loc = std::cmp::min(min_loc, seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
min_loc
|
||||||
}
|
}
|
||||||
|
|
||||||
helper::tests! {
|
helper::tests! {
|
||||||
|
|
@ -106,8 +148,8 @@ helper::tests! {
|
||||||
default => 457535844;
|
default => 457535844;
|
||||||
}
|
}
|
||||||
part2 {
|
part2 {
|
||||||
small => 0;
|
small => 46;
|
||||||
default => 0;
|
default => 41222968;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
helper::benchmarks! {}
|
helper::benchmarks! {}
|
||||||
|
|
|
||||||
61
2023/day05/src/p2basic.rs
Normal file
61
2023/day05/src/p2basic.rs
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
use std::{cmp, ops::Range};
|
||||||
|
|
||||||
|
pub fn part2(input: &str) -> u64 {
|
||||||
|
let mut lines = input.lines();
|
||||||
|
let seeds = lines
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.strip_prefix("seeds: ")
|
||||||
|
.unwrap()
|
||||||
|
.split_ascii_whitespace()
|
||||||
|
.map(|n| n.parse::<u64>().unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let seeds = seeds.chunks(2);
|
||||||
|
|
||||||
|
let maps = super::parse_maps(lines);
|
||||||
|
|
||||||
|
let mut min_loc = u64::MAX;
|
||||||
|
|
||||||
|
let mut current_seeds: Vec<(usize, usize, Range<u64>)> = seeds
|
||||||
|
.map(|seed| (0, 0, seed[0]..(seed[0] + seed[1])))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
'queue: while let Some((place, range_idx, numbers)) = current_seeds.pop() {
|
||||||
|
if place == maps.len() {
|
||||||
|
// Range is done.
|
||||||
|
min_loc = cmp::min(min_loc, numbers.start);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let ranges = &maps[place];
|
||||||
|
for range in ranges.iter().skip(range_idx) {
|
||||||
|
if range.source_end() <= numbers.start || range.source_start >= numbers.end {
|
||||||
|
// Completely out of range.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Part that falls before this redirection, needs to be queued again.
|
||||||
|
let pre = numbers.start..range.source_start;
|
||||||
|
let in_ = cmp::max(numbers.start, range.source_start)
|
||||||
|
..cmp::min(numbers.end, range.source_end());
|
||||||
|
let post = range.source_end()..(numbers.end);
|
||||||
|
|
||||||
|
if !pre.is_empty() {
|
||||||
|
current_seeds.push((place, range_idx + 1, pre));
|
||||||
|
}
|
||||||
|
if !post.is_empty() {
|
||||||
|
current_seeds.push((place, range_idx + 1, post));
|
||||||
|
}
|
||||||
|
let offset = in_.start - range.source_start;
|
||||||
|
let new = (range.dest_start + offset)..(range.dest_start + offset + (in_.end - in_.start));
|
||||||
|
|
||||||
|
if !new.is_empty() {
|
||||||
|
current_seeds.push((place + 1, 0, new));
|
||||||
|
}
|
||||||
|
continue 'queue;
|
||||||
|
}
|
||||||
|
// No change, pass unaffected
|
||||||
|
current_seeds.push((place + 1, 0, numbers));
|
||||||
|
}
|
||||||
|
|
||||||
|
min_loc
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue