1
0
Fork 0

day(05): add solution

“brute-force me up inside”

Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
Matej Focko 2023-12-05 08:34:27 +01:00
parent e58483770f
commit 715904ca2b
Signed by: mfocko
GPG key ID: 7C47D46246790496
2 changed files with 162 additions and 0 deletions

33
samples/day05.txt Normal file
View 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
View 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);