Part 1 day 5
This commit is contained in:
parent
97e5ab4bed
commit
6b7afc5a93
|
|
@ -0,0 +1,152 @@
|
|||
use std::collections::HashMap;
|
||||
use regex::Regex;
|
||||
|
||||
use log::{debug, info};
|
||||
|
||||
use super::utils::Part;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Range {
|
||||
range_start: u64,
|
||||
src_range_start: u64,
|
||||
length: u64
|
||||
}
|
||||
|
||||
impl Range {
|
||||
fn map(&self, n: u64) -> Option<u64> {
|
||||
if (self.src_range_start..(self.src_range_start+self.length)).contains(&n) {
|
||||
debug!("matching range {} -> {} [{:?}]", n, self.range_start + n - self.src_range_start, self);
|
||||
return Some(self.range_start + n - self.src_range_start )
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
#[derive(Default)]
|
||||
struct Map {
|
||||
start_domain: String,
|
||||
target_domain: String,
|
||||
ranges: Vec<Range>
|
||||
}
|
||||
impl Map {
|
||||
fn new() -> Self {
|
||||
Map { ..Default::default() }
|
||||
}
|
||||
|
||||
fn map(&self, n: u64) -> u64 {
|
||||
for range in &self.ranges {
|
||||
if let Some(value) = range.map(n) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Dataset {
|
||||
seeds: Vec<u64>,
|
||||
maps: HashMap<String, Map>
|
||||
}
|
||||
|
||||
impl Dataset {
|
||||
fn new() -> Self {
|
||||
Dataset { ..Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn solve(lines: Vec<String>, part: Part) -> u64 {
|
||||
let parts : Vec<String> = lines.into_iter()
|
||||
.filter(|l| !l.is_empty())
|
||||
.collect();
|
||||
|
||||
let mut dataset = Dataset::new();
|
||||
debug!("{:?}", parts);
|
||||
|
||||
let (seeds_line, other_lines) = parts.split_at(1);
|
||||
dataset.seeds = seeds_line.first().unwrap().split(' ').skip(1).map(|e| e.parse().unwrap()).collect();
|
||||
debug!("Seeds : {:?}", dataset.seeds);
|
||||
|
||||
let mut current_map : Map = Map::new();
|
||||
let regex_map_header = Regex::new(r"^(\w*)-to-(\w*)").unwrap();
|
||||
for line in other_lines {
|
||||
if let Some(captures) = regex_map_header.captures(line) {
|
||||
if !current_map.ranges.is_empty() {
|
||||
debug!("New mapping detected, saving the last one");
|
||||
dataset.maps.insert(current_map.start_domain.to_owned(), current_map);
|
||||
current_map = Map::new();
|
||||
}
|
||||
current_map.start_domain = captures[1].to_owned();
|
||||
current_map.target_domain = captures[2].to_owned();
|
||||
}else{
|
||||
let components : [u64; 3] = line.split(' ').map(|e| e.parse().unwrap()).collect::<Vec<_>>().try_into().unwrap();
|
||||
debug!("new range: {:?}", components);
|
||||
current_map.ranges.push(
|
||||
Range {
|
||||
range_start: components[0],
|
||||
src_range_start: components[1],
|
||||
length: components[2]
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
dataset.maps.insert(current_map.start_domain.to_owned(), current_map);
|
||||
|
||||
|
||||
info!("Loaded {} mapping categories", dataset.maps.len());
|
||||
for (src, map) in &dataset.maps {
|
||||
info!("{} -> {} with {} ranges", src, map.target_domain, map.ranges.len());
|
||||
}
|
||||
|
||||
match part {
|
||||
Part::One => {
|
||||
let mut min_location = u64::MAX;
|
||||
for seed in dataset.seeds {
|
||||
let mut stage = "seed";
|
||||
let mut value = seed;
|
||||
while let Some(map) = dataset.maps.get(stage) {
|
||||
debug!("Stage {} -> {}", stage, map.target_domain);
|
||||
value = map.map(value);
|
||||
stage = &map.target_domain;
|
||||
}
|
||||
min_location = min_location.min(value);
|
||||
info!("Final stage seed {} -> location {}", seed, value);
|
||||
}
|
||||
|
||||
min_location
|
||||
},
|
||||
Part::Two => todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_range_mapping() {
|
||||
let mut map = Map::new();
|
||||
map.start_domain = "seed".to_owned();
|
||||
map.target_domain = "soil".to_owned();
|
||||
|
||||
map.ranges.push(Range {
|
||||
range_start: 50,
|
||||
src_range_start: 98,
|
||||
length: 2
|
||||
});
|
||||
|
||||
map.ranges.push(Range {
|
||||
range_start: 52,
|
||||
src_range_start: 50,
|
||||
length: 48
|
||||
});
|
||||
|
||||
assert_eq!(map.map(1), 1);
|
||||
assert_eq!(map.map(99), 51);
|
||||
assert_eq!(map.map(51), 53);
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part2(){
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue