Day 19
This commit is contained in:
parent
187e3c8b07
commit
31c9a768ec
|
@ -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
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
|
@ -34,10 +34,12 @@ mod day15;
|
||||||
mod day16;
|
mod day16;
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
mod day17;
|
mod day17;
|
||||||
|
#[allow(dead_code)]
|
||||||
mod day18;
|
mod day18;
|
||||||
|
mod day19;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
day18::day18();
|
day19::day19();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn input(day: u8) -> String {
|
pub fn input(day: u8) -> String {
|
||||||
|
|
Loading…
Reference in New Issue