This commit is contained in:
sepia 2024-12-19 14:32:51 -06:00
parent 187e3c8b07
commit 31c9a768ec
3 changed files with 122 additions and 1 deletions

71
src/day18.rs Normal file
View File

@ -0,0 +1,71 @@
use itertools::Itertools;
use crate::util::maps::World;
pub fn day18() {
let bytes: Vec<(usize, usize)> = crate::input(18)
.lines()
.map(|line| {
line.split(",")
.map(|b| b.parse::<usize>().unwrap())
.collect_tuple()
.unwrap()
})
.collect();
let world_with_bytes = |b| {
let mut world = World::from_2d_vec(vec![vec![false; 71]; 71]);
for &(x, y) in bytes.iter().take(b) {
world.set(x, y, true);
}
world
};
let mut low_bound = 0;
let mut high_bound = bytes.len();
loop {
if high_bound - low_bound <= 1 {
break;
}
let i = low_bound + (high_bound - low_bound) / 2;
let world = (world_with_bytes)(i);
let path_length = path_costs(&world, 0, 0).get(70, 70).unwrap();
if path_length == u64::MAX {
high_bound = i;
} else {
low_bound = i;
}
}
let (last_byte_x, last_byte_y) = bytes[high_bound - 1];
println!("After a byte falls at ({last_byte_x}, {last_byte_y}), there is no way out! The researchers perish!");
}
fn path_costs(world: &World<bool>, x: usize, y: usize) -> World<u64> {
fn calculate_path_costs(
world: &World<bool>,
x: usize,
y: usize,
cost_so_far: u64,
costs: &mut World<u64>,
) {
let adjacents = world
.adjacent_locations(x, y)
.into_iter()
.filter(|&(nx, ny)| !world.get(nx, ny).unwrap());
for (nx, ny) in adjacents {
let cost = cost_so_far + 1;
let old_cost = costs.get(nx, ny).unwrap();
if cost < old_cost {
costs.set(nx, ny, cost);
calculate_path_costs(world, nx, ny, cost, costs)
}
}
}
let mut costs = World::from_dimensions(world.width(), world.height(), u64::MAX);
calculate_path_costs(world, x, y, 0, &mut costs);
costs
}

48
src/day19.rs Normal file
View File

@ -0,0 +1,48 @@
use itertools::Itertools;
use rayon::prelude::*;
use std::collections::HashMap;
pub fn day19() {
let input = crate::input(19);
let (towels_input, designs_input) = input.split("\n\n").collect_tuple().unwrap();
let towels: Vec<&str> = towels_input.split(", ").collect();
let designs: Vec<&str> = designs_input.lines().collect();
let ways_to_make_designs: Vec<u64> = designs
.par_iter()
.map(|design| make_pattern_from_towels(design, &towels))
.collect();
let possible_designs_count = ways_to_make_designs
.iter()
.filter(|&&ways| ways != 0)
.count();
println!("{possible_designs_count} designs are possible to make.");
let total_ways: u64 = ways_to_make_designs.iter().sum();
println!("{total_ways} ways to make a design are possible.");
}
fn make_pattern_from_towels(design: &str, towels: &Vec<&str>) -> u64 {
fn make_pattern(design: &str, towels: &Vec<&str>, memo: &mut HashMap<String, u64>) -> u64 {
if let Some(&ways) = memo.get(design) {
return ways;
}
if design.is_empty() {
return 1;
}
let ways = towels
.iter()
.map(|towel| match design.strip_prefix(towel) {
Some(subdesign) => make_pattern(subdesign, towels, memo),
None => 0,
})
.sum();
memo.insert(design.into(), ways);
ways
}
let mut memo: HashMap<String, u64> = HashMap::new();
make_pattern(design, towels, &mut memo)
}

View File

@ -34,10 +34,12 @@ mod day15;
mod day16;
#[allow(dead_code)]
mod day17;
#[allow(dead_code)]
mod day18;
mod day19;
fn main() {
day18::day18();
day19::day19();
}
pub fn input(day: u8) -> String {