This commit is contained in:
BlackDemonFire 2023-12-05 13:38:04 +01:00
parent cec5519273
commit a53b8d78d7
Signed by: lucy
SSH key fingerprint: SHA256:5NG0Um+vQQHuWkYn+Vd84YFm10edFBJiOIpOuHjl8UE
8 changed files with 312 additions and 0 deletions

8
Cargo.lock generated
View file

@ -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"

View file

@ -10,4 +10,6 @@ members = [
"d03t2",
"d04t1",
"d04t2",
"d05t1",
"d05t2",
]

8
d05t1/Cargo.toml Normal file
View 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
View 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
View 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
View 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
View 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
View 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);
}
}