day(05): add solution
“brute-force me up inside” Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
parent
e58483770f
commit
715904ca2b
2 changed files with 162 additions and 0 deletions
33
samples/day05.txt
Normal file
33
samples/day05.txt
Normal file
|
@ -0,0 +1,33 @@
|
|||
seeds: 79 14 55 13
|
||||
|
||||
seed-to-soil map:
|
||||
50 98 2
|
||||
52 50 48
|
||||
|
||||
soil-to-fertilizer map:
|
||||
0 15 37
|
||||
37 52 2
|
||||
39 0 15
|
||||
|
||||
fertilizer-to-water map:
|
||||
49 53 8
|
||||
0 11 42
|
||||
42 0 7
|
||||
57 7 4
|
||||
|
||||
water-to-light map:
|
||||
88 18 7
|
||||
18 25 70
|
||||
|
||||
light-to-temperature map:
|
||||
45 77 23
|
||||
81 45 19
|
||||
68 64 13
|
||||
|
||||
temperature-to-humidity map:
|
||||
0 69 1
|
||||
1 0 69
|
||||
|
||||
humidity-to-location map:
|
||||
60 56 37
|
||||
56 93 4
|
129
src/bin/day05.rs
Normal file
129
src/bin/day05.rs
Normal file
|
@ -0,0 +1,129 @@
|
|||
use rayon::prelude::*;
|
||||
use std::str::FromStr;
|
||||
|
||||
use aoc_2023::*;
|
||||
|
||||
type Output1 = i64;
|
||||
type Output2 = Output1;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct AlmanacRange {
|
||||
destination: i64,
|
||||
source: i64,
|
||||
length: i64,
|
||||
}
|
||||
|
||||
impl FromStr for AlmanacRange {
|
||||
type Err = &'static str;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let nums: Vec<i64> = parse_ws_separated(s);
|
||||
Ok(AlmanacRange {
|
||||
destination: nums[0],
|
||||
source: nums[1],
|
||||
length: nums[2],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl AlmanacRange {
|
||||
fn upper_bound(&self) -> i64 {
|
||||
self.source + self.length
|
||||
}
|
||||
|
||||
fn has(&self, key: i64) -> bool {
|
||||
key >= self.source && key < self.upper_bound()
|
||||
}
|
||||
|
||||
fn map(&self, key: i64) -> Option<i64> {
|
||||
if !self.has(key) {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(self.destination + (key - self.source))
|
||||
}
|
||||
|
||||
fn maps_to(&self) -> (i64, i64) {
|
||||
(self.destination, self.destination + self.length)
|
||||
}
|
||||
|
||||
fn overlaps(&self, start: i64, length: i64) -> bool {
|
||||
(start < self.source || self.has(start))
|
||||
&& (start + length >= self.upper_bound() || self.has(start + length))
|
||||
}
|
||||
}
|
||||
|
||||
struct Mapping {
|
||||
ranges: Vec<AlmanacRange>,
|
||||
}
|
||||
|
||||
impl FromStr for Mapping {
|
||||
type Err = &'static str;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let lines = s.lines().skip(1);
|
||||
let ranges = lines.map(|l| l.parse().unwrap()).collect();
|
||||
Ok(Mapping { ranges })
|
||||
}
|
||||
}
|
||||
|
||||
impl Mapping {
|
||||
fn map(&self, key: i64) -> i64 {
|
||||
self.ranges
|
||||
.iter()
|
||||
.find(|r| r.has(key))
|
||||
.and_then(|r| r.map(key))
|
||||
.unwrap_or(key)
|
||||
}
|
||||
}
|
||||
|
||||
struct Day05 {
|
||||
seeds: Vec<i64>,
|
||||
mappings: Vec<Mapping>,
|
||||
}
|
||||
impl Solution<Output1, Output2> for Day05 {
|
||||
fn new<P: AsRef<Path>>(pathname: P) -> Self {
|
||||
let lines = file_to_string(pathname);
|
||||
let mut segments = lines.split("\n\n");
|
||||
|
||||
let seeds = parse_ws_separated(segments.next().unwrap().split(':').nth(1).unwrap());
|
||||
|
||||
let mappings = segments.map(|m| m.parse().unwrap()).collect();
|
||||
|
||||
Self { seeds, mappings }
|
||||
}
|
||||
|
||||
fn part_1(&mut self) -> Output1 {
|
||||
self.seeds
|
||||
.iter()
|
||||
.map(|s| self.mappings.iter().fold(*s, |key, m| m.map(key)))
|
||||
.min()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn part_2(&mut self) -> Output2 {
|
||||
let indices = (0..self.seeds.len())
|
||||
.map(|i| 2 * i)
|
||||
.take_while(|i| *i < self.seeds.len() - 1)
|
||||
.collect_vec();
|
||||
|
||||
indices
|
||||
.par_iter()
|
||||
.flat_map(|i| {
|
||||
let start = self.seeds[*i];
|
||||
let length = self.seeds[i + 1];
|
||||
|
||||
(start..start + length)
|
||||
.into_par_iter()
|
||||
.map(|j| self.mappings.iter().fold(j, |key, m| m.map(key)))
|
||||
})
|
||||
.min()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
Day05::main()
|
||||
}
|
||||
|
||||
test_sample!(day_05, Day05, 35, 46);
|
Loading…
Reference in a new issue