1
0
Fork 0

naive day5 solution

main
Andrew Coleman 2023-12-05 13:01:42 -05:00
parent 45481154d1
commit b750d99261
2 changed files with 171 additions and 0 deletions

170
2023/src/day05.rs Normal file
View File

@ -0,0 +1,170 @@
use aoc_runner_derive::{aoc, aoc_generator};
use std::ops::RangeInclusive;
use std::str::Lines;
struct RangeMap {
source: RangeInclusive<u64>,
destination: RangeInclusive<u64>,
}
struct Almanac {
seeds: Vec<u64>,
seed_to_soil: Vec<RangeMap>,
soil_to_fertilizer: Vec<RangeMap>,
fertilizer_to_water: Vec<RangeMap>,
water_to_light: Vec<RangeMap>,
light_to_temperature: Vec<RangeMap>,
temperature_to_humidity: Vec<RangeMap>,
humidity_to_location: Vec<RangeMap>,
}
fn line_to_triple(input: &str) -> [u64; 3] {
let mut vals: [u64; 3] = [0; 3];
for (index, i) in input.split(" ").enumerate() {
vals[index] = i.parse::<u64>().unwrap();
}
vals
}
fn next_rangemap(lines: &mut Lines) -> Vec<RangeMap> {
let mut rm: Vec<RangeMap> = vec![];
while let Some(line) = lines.next() {
if line.is_empty() {
break;
}
let triple = line_to_triple(&line);
rm.push(RangeMap {
source: triple[1]..=(triple[1] + triple[2]),
destination: triple[0]..=(triple[0] + triple[2]),
});
}
rm
}
#[aoc_generator(day5)]
fn parse(input: &str) -> Almanac {
let mut lines = input.lines();
let seeds = lines.next().unwrap().split(": ").collect::<Vec<&str>>()[1]
.split(" ")
.map(|s| s.parse::<u64>().unwrap())
.collect();
lines.next();
lines.next();
let seed_to_soil = next_rangemap(&mut lines);
lines.next();
let soil_to_fertilizer = next_rangemap(&mut lines);
lines.next();
let fertilizer_to_water = next_rangemap(&mut lines);
lines.next();
let water_to_light = next_rangemap(&mut lines);
lines.next();
let light_to_temperature = next_rangemap(&mut lines);
lines.next();
let temperature_to_humidity = next_rangemap(&mut lines);
lines.next();
let humidity_to_location = next_rangemap(&mut lines);
Almanac {
seeds,
seed_to_soil,
soil_to_fertilizer,
fertilizer_to_water,
water_to_light,
light_to_temperature,
temperature_to_humidity,
humidity_to_location,
}
}
fn match_to(s: u64, maps: &Vec<RangeMap>) -> u64 {
if let Some(rm) = maps.iter().find(|m| m.source.contains(&s)) {
let offset = s - rm.source.start();
rm.destination.start() + offset
} else {
s
}
}
fn min_location(seeds: &Vec<u64>, input: &Almanac) -> u64 {
let locations = seeds
.iter()
.map(|s| match_to(*s, &input.seed_to_soil))
.map(|s| match_to(s, &input.soil_to_fertilizer))
.map(|s| match_to(s, &input.fertilizer_to_water))
.map(|s| match_to(s, &input.water_to_light))
.map(|s| match_to(s, &input.light_to_temperature))
.map(|s| match_to(s, &input.temperature_to_humidity))
.map(|s| match_to(s, &input.humidity_to_location))
.collect::<Vec<u64>>();
*locations.iter().min().unwrap()
}
#[aoc(day5, part1)]
fn part1(input: &Almanac) -> u64 {
min_location(&input.seeds, input)
}
#[aoc(day5, part2, bf)]
fn part2(input: &Almanac) -> u64 {
let mut seeds: Vec<u64> = vec![];
let mut index = 0;
while index < input.seeds.len() {
let start = input.seeds[index];
let count = input.seeds[index + 1];
index += 2;
for n in start..(start + count) {
seeds.push(n);
}
}
min_location(&seeds, input)
}
#[cfg(test)]
mod tests {
use super::*;
const SAMPLE_DATA: &'static str = r#"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
"#;
#[test]
fn sample_data() {
let maps = parse(&SAMPLE_DATA);
assert_eq!(part1(&maps), 35);
assert_eq!(part2(&maps), 46);
}
}

View File

@ -4,5 +4,6 @@ mod day01;
mod day02;
mod day03;
mod day04;
mod day05;
aoc_lib! { year = 2023 }