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]]
|
[[package]]
|
||||||
name = "d04t2"
|
name = "d04t2"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "d05t1"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "d05t2"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
|
@ -10,4 +10,6 @@ members = [
|
||||||
"d03t2",
|
"d03t2",
|
||||||
"d04t1",
|
"d04t1",
|
||||||
"d04t2",
|
"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