day 5 part 1
This commit is contained in:
parent
4b0072f574
commit
4437121bb0
2 changed files with 401 additions and 0 deletions
156
src/bin/day5.rs
Normal file
156
src/bin/day5.rs
Normal file
|
@ -0,0 +1,156 @@
|
|||
#![allow(clippy::let_and_return)]
|
||||
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
|
||||
|
||||
use aoc23::read;
|
||||
use chumsky::{prelude::*, text::int};
|
||||
|
||||
struct Range {
|
||||
source_start: usize,
|
||||
target_start: usize,
|
||||
len: usize
|
||||
}
|
||||
|
||||
struct Map {
|
||||
ranges: Vec<Range>
|
||||
}
|
||||
|
||||
impl Map {
|
||||
fn get(&self, source: usize) -> usize {
|
||||
for r in &self.ranges {
|
||||
let Some(offset) = source.checked_sub(r.source_start) else {
|
||||
continue;
|
||||
};
|
||||
if offset < r.len {
|
||||
return r.target_start + offset;
|
||||
}
|
||||
}
|
||||
|
||||
source
|
||||
}
|
||||
|
||||
fn parser() -> impl Parser<char, Self, Error = Simple<char>> {
|
||||
int(10)
|
||||
.separated_by(just(" "))
|
||||
.exactly(3)
|
||||
.then_ignore(just("\n"))
|
||||
.repeated()
|
||||
.map(|ranges| Self {
|
||||
ranges: ranges
|
||||
.into_iter()
|
||||
.map(|ints: Vec<String>| Range {
|
||||
source_start: ints[1].parse().unwrap(),
|
||||
target_start: ints[0].parse().unwrap(),
|
||||
len: ints[2].parse().unwrap()
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct Almanac {
|
||||
seeds: Vec<usize>,
|
||||
seed_to_soil: Map,
|
||||
soil_to_fertilizer: Map,
|
||||
fertilizer_to_water: Map,
|
||||
water_to_light: Map,
|
||||
light_to_temperature: Map,
|
||||
temperature_to_humidity: Map,
|
||||
humidity_to_location: Map
|
||||
}
|
||||
|
||||
impl Almanac {
|
||||
fn parser() -> impl Parser<char, Self, Error = Simple<char>> {
|
||||
fn parse_another_map<'a, P, T>(
|
||||
parser: P,
|
||||
name: &'a str
|
||||
) -> impl Parser<char, (T, Map), Error = Simple<char>> + 'a
|
||||
where
|
||||
P: Parser<char, T, Error = Simple<char>> + 'a,
|
||||
T: 'a
|
||||
{
|
||||
parser
|
||||
.then_ignore(just(name))
|
||||
.then_ignore(just(" map:\n"))
|
||||
.then(Map::parser())
|
||||
}
|
||||
|
||||
let parser = just("seeds: ")
|
||||
.ignore_then(int(10).separated_by(just(" ")))
|
||||
.map(|ints: Vec<String>| {
|
||||
ints.into_iter()
|
||||
.map(|int| int.parse().unwrap())
|
||||
.collect::<Vec<usize>>()
|
||||
})
|
||||
.then_ignore(just("\n\n"));
|
||||
let parser = parse_another_map(parser, "seed-to-soil").then_ignore(just("\n"));
|
||||
let parser =
|
||||
parse_another_map(parser, "soil-to-fertilizer").then_ignore(just("\n"));
|
||||
let parser =
|
||||
parse_another_map(parser, "fertilizer-to-water").then_ignore(just("\n"));
|
||||
let parser = parse_another_map(parser, "water-to-light").then_ignore(just("\n"));
|
||||
let parser =
|
||||
parse_another_map(parser, "light-to-temperature").then_ignore(just("\n"));
|
||||
let parser =
|
||||
parse_another_map(parser, "temperature-to-humidity").then_ignore(just("\n"));
|
||||
let parser = parse_another_map(parser, "humidity-to-location");
|
||||
|
||||
parser.map(
|
||||
|(
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
((seeds, seed_to_soil), soil_to_fertilizer),
|
||||
fertilizer_to_water
|
||||
),
|
||||
water_to_light
|
||||
),
|
||||
light_to_temperature
|
||||
),
|
||||
temperature_to_humidity
|
||||
),
|
||||
humidity_to_location
|
||||
)| {
|
||||
Almanac {
|
||||
seeds,
|
||||
seed_to_soil,
|
||||
soil_to_fertilizer,
|
||||
fertilizer_to_water,
|
||||
water_to_light,
|
||||
light_to_temperature,
|
||||
temperature_to_humidity,
|
||||
humidity_to_location
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn parser() -> impl Parser<char, Almanac, Error = Simple<char>> {
|
||||
Almanac::parser().then_ignore(end())
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let almanac = read("inputs/day5.txt", parser())?;
|
||||
|
||||
let min_loc = almanac
|
||||
.seeds
|
||||
.iter()
|
||||
.copied()
|
||||
.map(|seed| {
|
||||
let soil = almanac.seed_to_soil.get(seed);
|
||||
let fertilizer = almanac.soil_to_fertilizer.get(soil);
|
||||
let water = almanac.fertilizer_to_water.get(fertilizer);
|
||||
let light = almanac.water_to_light.get(water);
|
||||
let temperature = almanac.light_to_temperature.get(light);
|
||||
let humidity = almanac.temperature_to_humidity.get(temperature);
|
||||
let location = almanac.humidity_to_location.get(humidity);
|
||||
// eprintln!("{seed}, {soil}, {fertilizer}, {water}, {light}, {temperature}, {humidity}, {location}");
|
||||
location
|
||||
})
|
||||
.min()
|
||||
.unwrap();
|
||||
println!("{min_loc}");
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue