Skip to content

Instantly share code, notes, and snippets.

@typester
Created December 5, 2023 16:20
Show Gist options
  • Save typester/6c7f52c9d8c49ed57515308ad365768a to your computer and use it in GitHub Desktop.
Save typester/6c7f52c9d8c49ed57515308ad365768a to your computer and use it in GitHub Desktop.
2023 Advent of Code Day 5
use lazy_static::lazy_static;
use regex::Regex;
const INPUT: &str = "..snip..";
lazy_static! {
static ref RE_NUM: Regex = Regex::new(r"(\d+)").unwrap();
}
#[derive(Debug)]
struct Info {
seeds: Vec<u64>,
seed_to_soil: Vec<Map>,
soil_to_fertilizer: Vec<Map>,
fertilizer_to_water: Vec<Map>,
water_to_light: Vec<Map>,
light_to_temperature: Vec<Map>,
temperature_to_humidity: Vec<Map>,
humidity_to_location: Vec<Map>,
}
impl Info {
fn part2_seeds(&self) -> Vec<(u64, u64)> {
let mut r: Vec<(u64, u64)> = vec![];
let mut iter = self.seeds.iter();
while let Some(n1) = iter.next() {
match iter.next() {
Some(n2) => r.push((*n1, *n2)),
None => break,
}
}
r
}
}
#[derive(Debug)]
struct Map {
dest: u64,
source: u64,
len: u64,
}
impl Map {
fn match_dest(&self, source: u64) -> Option<u64> {
if self.source <= source && source < self.source + self.len {
Some(self.dest + (source - self.source))
} else {
None
}
}
}
fn main() {
let info = parse_input(INPUT);
let min_location = info.seeds.iter()
.map(|seed| find_location(*seed, &info))
.min();
println!("part1: {}", min_location.unwrap());
let min_location = info.part2_seeds().iter()
.flat_map(|seed| {
let mut loc: Vec<u64> = vec![];
println!("process: {:?}", seed);
for s in seed.0..(seed.0+seed.1) {
loc.push(find_location(s, &info));
}
loc
})
.min();
println!("part2: {}", min_location.unwrap());
}
fn parse_input(input: &str) -> Info {
let mut iter = input.lines();
let seeds: Vec<u64> = RE_NUM.captures_iter(iter.next().unwrap())
.map(|c| c.get(1).map(|m| m.as_str()).unwrap_or("0").parse::<u64>().unwrap())
.collect();
iter.next();
let mut seed_to_soil: Vec<Map> = vec![];
while let Some(line) = iter.next() {
if line == "" { break }
if let Some(map) = parse_map(line) {
seed_to_soil.push(map);
}
}
let mut soil_to_fertilizer: Vec<Map> = vec![];
while let Some(line) = iter.next() {
if line == "" { break }
if let Some(map) = parse_map(line) {
soil_to_fertilizer.push(map);
}
}
let mut fertilizer_to_water: Vec<Map> = vec![];
while let Some(line) = iter.next() {
if line == "" { break }
if let Some(map) = parse_map(line) {
fertilizer_to_water.push(map);
}
}
let mut water_to_light: Vec<Map> = vec![];
while let Some(line) = iter.next() {
if line == "" { break }
if let Some(map) = parse_map(line) {
water_to_light.push(map);
}
}
let mut light_to_temperature: Vec<Map> = vec![];
while let Some(line) = iter.next() {
if line == "" { break }
if let Some(map) = parse_map(line) {
light_to_temperature.push(map);
}
}
let mut temperature_to_humidity: Vec<Map> = vec![];
while let Some(line) = iter.next() {
if line == "" { break }
if let Some(map) = parse_map(line) {
temperature_to_humidity.push(map);
}
}
let mut humidity_to_location: Vec<Map> = vec![];
while let Some(line) = iter.next() {
if line == "" { break }
if let Some(map) = parse_map(line) {
humidity_to_location.push(map);
}
}
Info {
seeds,
seed_to_soil,
soil_to_fertilizer,
fertilizer_to_water,
water_to_light,
light_to_temperature,
temperature_to_humidity,
humidity_to_location,
}
}
fn parse_map(input: &str) -> Option<Map> {
let nums: Vec<u64> = RE_NUM.captures_iter(input)
.map(|c| c.get(1).unwrap().as_str().parse::<u64>().unwrap())
.collect();
if nums.len() == 3 {
let dest = nums[0];
let source = nums[1];
let len = nums[2];
Some(Map {
dest,
source,
len,
})
} else {
None
}
}
fn find_location(seed: u64, info: &Info) -> u64 {
let soil = info.seed_to_soil.iter().filter_map(|m| m.match_dest(seed)).next().unwrap_or(seed);
let fertilizer = info.soil_to_fertilizer.iter().filter_map(|m| m.match_dest(soil)).next().unwrap_or(soil);
let water = info.fertilizer_to_water.iter().filter_map(|m| m.match_dest(fertilizer)).next().unwrap_or(fertilizer);
let light = info.water_to_light.iter().filter_map(|m| m.match_dest(water)).next().unwrap_or(water);
let temperature = info.light_to_temperature.iter().filter_map(|m| m.match_dest(light)).next().unwrap_or(light);
let humidity = info.temperature_to_humidity.iter().filter_map(|m| m.match_dest(temperature)).next().unwrap_or(temperature);
let location = info.humidity_to_location.iter().filter_map(|m| m.match_dest(humidity)).next().unwrap_or(humidity);
location
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment