Day 5
This commit is contained in:
parent
cec5519273
commit
a53b8d78d7
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -33,3 +33,11 @@ version = "0.1.0"
|
|||
[[package]]
|
||||
name = "d04t2"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "d05t1"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "d05t2"
|
||||
version = "0.1.0"
|
||||
|
|
|
@ -10,4 +10,6 @@ members = [
|
|||
"d03t2",
|
||||
"d04t1",
|
||||
"d04t2",
|
||||
"d05t1",
|
||||
"d05t2",
|
||||
]
|
||||
|
|
8
d05t1/Cargo.toml
Normal file
8
d05t1/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "d05t1"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
33
d05t1/demo_input.txt
Normal file
33
d05t1/demo_input.txt
Normal file
|
@ -0,0 +1,33 @@
|
|||
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
|
123
d05t1/src/main.rs
Normal file
123
d05t1/src/main.rs
Normal file
|
@ -0,0 +1,123 @@
|
|||
fn main() {
|
||||
let input = include_str!("../input.txt");
|
||||
println!("d05t1: {}", d05t1(input));
|
||||
}
|
||||
|
||||
pub fn d05t1(input: &str) -> usize {
|
||||
let mut groups = input.split("\n\n");
|
||||
let seeds = groups.next().unwrap().replace("seeds: ", "");
|
||||
let seeds = seeds
|
||||
.split_whitespace()
|
||||
.map(str::parse::<usize>)
|
||||
.map(Result::unwrap)
|
||||
.collect::<Vec<_>>();
|
||||
let seed_to_spoil_map = parse_maps(groups.next().unwrap(), "seed-to-soil map:");
|
||||
let soil_to_fertilizer_map = parse_maps(groups.next().unwrap(), "soil-to-fertilizer map:");
|
||||
let fertilizer_to_water_map = parse_maps(groups.next().unwrap(), "fertilizer-to-water map:");
|
||||
let water_to_light_map = parse_maps(groups.next().unwrap(), "water-to-light map:");
|
||||
let light_to_temperature_map = parse_maps(groups.next().unwrap(), "light-to-temperature map:");
|
||||
let temperature_to_humidity_map =
|
||||
parse_maps(groups.next().unwrap(), "temperature-to-humidity map:");
|
||||
let humidity_to_location_map = parse_maps(groups.next().unwrap(), "humidity-to-location map:");
|
||||
assert!(groups.next().is_none());
|
||||
let soils = seeds.solve(&seed_to_spoil_map);
|
||||
let fertilizers = soils.solve(&soil_to_fertilizer_map);
|
||||
let waters = fertilizers.solve(&fertilizer_to_water_map);
|
||||
let lights = waters.solve(&water_to_light_map);
|
||||
let temperatures = lights.solve(&light_to_temperature_map);
|
||||
let humidities = temperatures.solve(&temperature_to_humidity_map);
|
||||
let locations = humidities.solve(&humidity_to_location_map);
|
||||
locations.into_iter().min().unwrap()
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TranslationMap {
|
||||
dest_range_start: usize,
|
||||
source_range_start: usize,
|
||||
range_length: usize,
|
||||
}
|
||||
|
||||
trait SolveLayer {
|
||||
fn solve(&self, translation_maps: &Vec<TranslationMap>) -> Self;
|
||||
}
|
||||
|
||||
impl SolveLayer for Vec<usize> {
|
||||
fn solve(&self, translation_maps: &Vec<TranslationMap>) -> Self {
|
||||
self.into_iter()
|
||||
.map(|l| translation_maps.translate(*l))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
|
||||
trait Translate {
|
||||
fn translate(&self, input: usize) -> usize;
|
||||
}
|
||||
|
||||
trait Fold<T, U> {
|
||||
fn fold(self) -> U;
|
||||
}
|
||||
|
||||
impl<T> Fold<T, Option<T>> for Option<Option<T>> {
|
||||
fn fold(self) -> Option<T> {
|
||||
if let Some(o) = self {
|
||||
o
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> Fold<T, Vec<T>> for Vec<Vec<T>> {
|
||||
fn fold(self) -> Vec<T> {
|
||||
let mut ret = Vec::new();
|
||||
for inner in self {
|
||||
for value in inner {
|
||||
ret.push(value)
|
||||
}
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
impl Translate for Vec<TranslationMap> {
|
||||
fn translate(&self, input: usize) -> usize {
|
||||
self.iter()
|
||||
.map(|m| m.translate(input))
|
||||
.filter(Option::is_some)
|
||||
.map(Option::unwrap)
|
||||
.next()
|
||||
.unwrap_or(input)
|
||||
}
|
||||
}
|
||||
impl TranslationMap {
|
||||
fn translate(&self, input: usize) -> Option<usize> {
|
||||
if input >= self.source_range_start && input < self.source_range_start + self.range_length {
|
||||
Some(self.dest_range_start + (input - self.source_range_start))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_maps(input: &str, title: &str) -> Vec<TranslationMap> {
|
||||
let mut lines = input.lines();
|
||||
assert_eq!(lines.next().unwrap(), title);
|
||||
lines.map(parse_map).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn parse_map(input: &str) -> TranslationMap {
|
||||
let mut elems = input.split_whitespace();
|
||||
TranslationMap {
|
||||
dest_range_start: elems.next().unwrap().parse().unwrap(),
|
||||
source_range_start: elems.next().unwrap().parse().unwrap(),
|
||||
range_length: elems.next().unwrap().parse().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_d05t1() {
|
||||
let input = include_str!("../demo_input.txt");
|
||||
assert_eq!(d05t1(input), 35);
|
||||
}
|
||||
}
|
8
d05t2/Cargo.toml
Normal file
8
d05t2/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "d05t2"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
33
d05t2/demo_input.txt
Normal file
33
d05t2/demo_input.txt
Normal file
|
@ -0,0 +1,33 @@
|
|||
seeds: 82 1
|
||||
|
||||
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
|
97
d05t2/src/main.rs
Normal file
97
d05t2/src/main.rs
Normal file
|
@ -0,0 +1,97 @@
|
|||
fn main() {
|
||||
let input = include_str!("../input.txt");
|
||||
println!("d05t2: {}", d05t2(input));
|
||||
}
|
||||
|
||||
pub fn d05t2(input: &str) -> usize {
|
||||
let mut groups = input.split("\n\n");
|
||||
let seeds = groups.next().unwrap().replace("seeds: ", "");
|
||||
let seeds = seeds
|
||||
.split_whitespace()
|
||||
.map(str::parse::<usize>)
|
||||
.map(Result::unwrap)
|
||||
.collect::<Vec<_>>();
|
||||
let seeds = seeds
|
||||
.chunks(2)
|
||||
.map(|chunk| {
|
||||
let start = chunk[0];
|
||||
let range = chunk[1];
|
||||
(start..(start + range)).collect::<Vec<_>>()
|
||||
})
|
||||
.flatten();
|
||||
let seed_to_spoil_map = parse_maps(groups.next().unwrap(), "seed-to-soil map:");
|
||||
let soil_to_fertilizer_map = parse_maps(groups.next().unwrap(), "soil-to-fertilizer map:");
|
||||
let fertilizer_to_water_map = parse_maps(groups.next().unwrap(), "fertilizer-to-water map:");
|
||||
let water_to_light_map = parse_maps(groups.next().unwrap(), "water-to-light map:");
|
||||
let light_to_temperature_map = parse_maps(groups.next().unwrap(), "light-to-temperature map:");
|
||||
let temperature_to_humidity_map =
|
||||
parse_maps(groups.next().unwrap(), "temperature-to-humidity map:");
|
||||
let humidity_to_location_map = parse_maps(groups.next().unwrap(), "humidity-to-location map:");
|
||||
assert!(groups.next().is_none());
|
||||
seeds
|
||||
.map(|s| seed_to_spoil_map.translate(s))
|
||||
.map(|s| soil_to_fertilizer_map.translate(s))
|
||||
.map(|f| fertilizer_to_water_map.translate(f))
|
||||
.map(|w| water_to_light_map.translate(w))
|
||||
.map(|l| light_to_temperature_map.translate(l))
|
||||
.map(|t| temperature_to_humidity_map.translate(t))
|
||||
.map(|h| humidity_to_location_map.translate(h))
|
||||
.min()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TranslationMap {
|
||||
dest_range_start: usize,
|
||||
source_range_start: usize,
|
||||
range_length: usize,
|
||||
}
|
||||
|
||||
trait Translate {
|
||||
fn translate(&self, input: usize) -> usize;
|
||||
}
|
||||
|
||||
impl Translate for Vec<TranslationMap> {
|
||||
fn translate(&self, input: usize) -> usize {
|
||||
self.iter()
|
||||
.map(|m| m.translate(input))
|
||||
.filter(Option::is_some)
|
||||
.map(Option::unwrap)
|
||||
.next()
|
||||
.unwrap_or(input)
|
||||
}
|
||||
}
|
||||
impl TranslationMap {
|
||||
fn translate(&self, input: usize) -> Option<usize> {
|
||||
if input >= self.source_range_start && input < self.source_range_start + self.range_length {
|
||||
Some(self.dest_range_start + (input - self.source_range_start))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_maps(input: &str, title: &str) -> Vec<TranslationMap> {
|
||||
let mut lines = input.lines();
|
||||
assert_eq!(lines.next().unwrap(), title);
|
||||
lines.map(parse_map).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn parse_map(input: &str) -> TranslationMap {
|
||||
let mut elems = input.split_whitespace();
|
||||
TranslationMap {
|
||||
dest_range_start: elems.next().unwrap().parse().unwrap(),
|
||||
source_range_start: elems.next().unwrap().parse().unwrap(),
|
||||
range_length: elems.next().unwrap().parse().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_d05t2() {
|
||||
let input = include_str!("../demo_input.txt");
|
||||
assert_eq!(d05t2(input), 46);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue