Complete 2023 Day 5 Part 1
This commit is contained in:
parent
36320e90bc
commit
ba4e489cdb
@ -1,9 +1,8 @@
|
|||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use crate::DataType::Soil;
|
use DataType::*;
|
||||||
|
|
||||||
const FILE_STR: &'static str = include_str!("input.txt");
|
const FILE_STR: &'static str = include_str!("input.txt");
|
||||||
const EXAMPLE_FILE_STR: &'static str = include_str!("example-input.txt");
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
||||||
enum DataType {
|
enum DataType {
|
||||||
@ -20,14 +19,14 @@ enum DataType {
|
|||||||
impl DataType {
|
impl DataType {
|
||||||
fn try_from(s: &str) -> Option<Self> {
|
fn try_from(s: &str) -> Option<Self> {
|
||||||
match s {
|
match s {
|
||||||
"seed" => Some(Self::Seed),
|
"seed" => Some(Seed),
|
||||||
"soil" => Some(Self::Soil),
|
"soil" => Some(Soil),
|
||||||
"fertilizer" => Some(Self::Fertilizer),
|
"fertilizer" => Some(Fertilizer),
|
||||||
"water" => Some(Self::Water),
|
"water" => Some(Water),
|
||||||
"light" => Some(Self::Light),
|
"light" => Some(Light),
|
||||||
"temperature" => Some(Self::Temperature),
|
"temperature" => Some(Temperature),
|
||||||
"humidity" => Some(Self::Humidity),
|
"humidity" => Some(Humidity),
|
||||||
"location" => Some(Self::Location),
|
"location" => Some(Location),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,32 +49,16 @@ impl DataMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_dest_idx(&self, src_value: u64) -> u64 {
|
fn get_dest_idx(&self, src_value: u64) -> Option<u64> {
|
||||||
let src_index = src_value.checked_sub(self.to_range.start);
|
if let Some(idx) = src_value.checked_sub(self.to_range.start) {
|
||||||
let dest_index = if let Some(idx) = src_index {
|
if let Some(new_idx) = self.from_range.start.checked_add(idx) {
|
||||||
self.from_range.start.checked_add(idx)
|
if new_idx < self.from_range.end {
|
||||||
} else {
|
return Some(new_idx);
|
||||||
Some(src_value)
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
match dest_index {
|
|
||||||
Some(n) => n,
|
|
||||||
None => src_value,
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn get_src_idx(&self, dest_value: u64) -> u64 {
|
None
|
||||||
let dest_index = dest_value.checked_sub(self.from_range.start);
|
|
||||||
let src_index = if let Some(idx) = dest_index {
|
|
||||||
self.to_range.start.checked_add(idx)
|
|
||||||
} else {
|
|
||||||
Some(dest_value)
|
|
||||||
};
|
|
||||||
|
|
||||||
match src_index {
|
|
||||||
Some(n) => n,
|
|
||||||
None => dest_value,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +98,7 @@ impl Almanac {
|
|||||||
let (from, to) = (types[0], types[1]);
|
let (from, to) = (types[0], types[1]);
|
||||||
let mappings: Vec<DataMap> = lines
|
let mappings: Vec<DataMap> = lines
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
.filter(|l| l.len() > 0)
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
line.split_whitespace()
|
line.split_whitespace()
|
||||||
.map(|s| s.trim())
|
.map(|s| s.trim())
|
||||||
@ -133,8 +117,21 @@ impl Almanac {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn x_from_y(&self, x: DataType, y: DataType, search: u64) -> u64 {
|
fn x_from_y(&self, x: DataType, y: DataType, search: u64) -> u64 {
|
||||||
let maps = self.maps.get(&(y, x)).expect(&format!("Missing mapping from {:?} to {:?}", x, y));
|
let maps = self
|
||||||
todo!();
|
.maps
|
||||||
|
.get(&(y, x))
|
||||||
|
.expect(&format!("Missing mapping from {:?} to {:?}", x, y));
|
||||||
|
let mut mapped_value: Vec<Option<u64>> = maps
|
||||||
|
.into_iter()
|
||||||
|
.map(|dm| dm.get_dest_idx(search))
|
||||||
|
.filter(|r| r.is_some())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if mapped_value.is_empty() {
|
||||||
|
return search;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapped_value.pop().unwrap().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn soil_from_seed(&self, seed: u64) -> u64 {
|
fn soil_from_seed(&self, seed: u64) -> u64 {
|
||||||
@ -142,17 +139,73 @@ impl Almanac {
|
|||||||
|
|
||||||
self.x_from_y(Soil, Seed, seed)
|
self.x_from_y(Soil, Seed, seed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fertilizer_from_soil(&self, soil: u64) -> u64 {
|
||||||
|
self.x_from_y(Fertilizer, Soil, soil)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn location_from_seed(&self, seed: u64) -> u64 {
|
||||||
|
let soil = self.soil_from_seed(seed);
|
||||||
|
let fert = self.fertilizer_from_soil(soil);
|
||||||
|
let water = self.x_from_y(Water, Fertilizer, fert);
|
||||||
|
let light = self.x_from_y(Light, Water, water);
|
||||||
|
let temp = self.x_from_y(Temperature, Light, light);
|
||||||
|
let humid = self.x_from_y(Humidity, Temperature, temp);
|
||||||
|
|
||||||
|
self.x_from_y(Location, Humidity, humid)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn locations_from_seeds(&self) -> HashMap<u64, u64> {
|
||||||
|
self.seeds
|
||||||
|
.iter()
|
||||||
|
.map(|s| (*s, self.location_from_seed(*s)))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lowest_seed_location(&self) -> u64 {
|
||||||
|
self.locations_from_seeds()
|
||||||
|
.iter()
|
||||||
|
.map(|(_, l)| *l)
|
||||||
|
.min()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn part_one() {
|
||||||
|
let almanac = Almanac::parse(FILE_STR);
|
||||||
|
println!("Part 1: Lowest seed location: {}", almanac.lowest_seed_location());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let almanac = Almanac::parse(EXAMPLE_FILE_STR);
|
part_one();
|
||||||
let soil = almanac.soil_from_seed(79);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::Almanac;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
const EXAMPLE_FILE_STR: &'static str = include_str!("example-input.txt");
|
const EXAMPLE_FILE_STR: &'static str = include_str!("example-input.txt");
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse() {}
|
fn test_location_from_seed() {
|
||||||
|
let almanac = Almanac::parse(EXAMPLE_FILE_STR);
|
||||||
|
assert_eq!(82, almanac.location_from_seed(79));
|
||||||
|
assert_eq!(43, almanac.location_from_seed(14));
|
||||||
|
assert_eq!(86, almanac.location_from_seed(55));
|
||||||
|
assert_eq!(35, almanac.location_from_seed(13));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_locations_from_seeds() {
|
||||||
|
let almanac = Almanac::parse(EXAMPLE_FILE_STR);
|
||||||
|
let expected = HashMap::from([(79, 82), (14, 43), (55, 86), (13, 35)]);
|
||||||
|
assert_eq!(expected, almanac.locations_from_seeds());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lowest_seed_location() {
|
||||||
|
let almanac = Almanac::parse(EXAMPLE_FILE_STR);
|
||||||
|
assert_eq!(35, almanac.lowest_seed_location());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user