|
|
|
@ -8,6 +8,7 @@
|
|
|
|
* @brief Advent of Code 2024 day 6 problems
|
|
|
|
* @brief Advent of Code 2024 day 6 problems
|
|
|
|
******************************************************************************/
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use nalgebra_glm::I32Vec2;
|
|
|
|
use ::solver_base::solver_base::{Solver, DataSet, RunMode};
|
|
|
|
use ::solver_base::solver_base::{Solver, DataSet, RunMode};
|
|
|
|
use utils::utils;
|
|
|
|
use utils::utils;
|
|
|
|
|
|
|
|
|
|
|
|
@ -20,7 +21,9 @@ pub struct Day6
|
|
|
|
do_debug_prints: bool,
|
|
|
|
do_debug_prints: bool,
|
|
|
|
|
|
|
|
|
|
|
|
map: Map,
|
|
|
|
map: Map,
|
|
|
|
guard_history: Vec<Vec<bool>>,
|
|
|
|
guard_heatmap: Vec<Vec<bool>>,
|
|
|
|
|
|
|
|
guard_position_history: Vec<I32Vec2>,
|
|
|
|
|
|
|
|
step_iterations: i32,
|
|
|
|
pub final_result: i32,
|
|
|
|
pub final_result: i32,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -32,16 +35,23 @@ impl Day6
|
|
|
|
pub fn new() -> Day6
|
|
|
|
pub fn new() -> Day6
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Day6 { data_set: DataSet::Test, run_mode: RunMode::FirstCase, do_debug_prints: false,
|
|
|
|
Day6 { data_set: DataSet::Test, run_mode: RunMode::FirstCase, do_debug_prints: false,
|
|
|
|
map: Map::new(), guard_history: vec![], final_result: 0 }
|
|
|
|
map: Map::new(), guard_heatmap: vec![], guard_position_history: vec![], step_iterations: 0, final_result: 0 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn solve_first_case(self: &mut Self) -> String
|
|
|
|
fn solve_first_case(self: &mut Self) -> String
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
self.step_iterations = 0;
|
|
|
|
while self.map.guard_is_on_map()
|
|
|
|
while self.map.guard_is_on_map()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
let pos = I32Vec2::new(self.map.guard_position().x, self.map.guard_position().y);
|
|
|
|
|
|
|
|
if !self.guard_position_history.contains(&pos)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
self.guard_position_history.push(pos);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
self.guard_history[self.map.guard_position().x as usize][self.map.guard_position().y as usize] = true;
|
|
|
|
self.guard_heatmap[self.map.guard_position().x as usize][self.map.guard_position().y as usize] = true;
|
|
|
|
self.map.step_guard();
|
|
|
|
self.map.step_guard();
|
|
|
|
|
|
|
|
self.step_iterations += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if self.do_debug_prints
|
|
|
|
if self.do_debug_prints
|
|
|
|
@ -52,7 +62,7 @@ impl Day6
|
|
|
|
|
|
|
|
|
|
|
|
let mut num_locations = 0;
|
|
|
|
let mut num_locations = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for row in &self.guard_history
|
|
|
|
for row in &self.guard_heatmap
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for b in row
|
|
|
|
for b in row
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -69,10 +79,66 @@ impl Day6
|
|
|
|
|
|
|
|
|
|
|
|
fn solve_second_case(self: &mut Self) -> String
|
|
|
|
fn solve_second_case(self: &mut Self) -> String
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
// Need the normal path the guard will take without modifying the map first so just....
|
|
|
|
|
|
|
|
self.solve_first_case();
|
|
|
|
|
|
|
|
println!("Step Iterations: {}", self.step_iterations);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Should only need to check the spots the guard visits normally for potential locations for new blockers
|
|
|
|
|
|
|
|
// So the self.guard_history vector should now contain all potential locations for new blockers.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// first attempt: I guess just try brute force with upper-limit for step iterations to guess that it's stuck
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The normal path is 5532 step iterations so maybe 10,000 is enough to determine it is stuck?
|
|
|
|
|
|
|
|
let stuck_limit = 10000; // 100,000 to double check -- 10,000 works! 1995 is the correct answer
|
|
|
|
|
|
|
|
let mut found_locations: Vec<I32Vec2> = vec![];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
println!("Positions to test: {}", self.guard_position_history.len());
|
|
|
|
|
|
|
|
println!("0%");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i, pos) in self.guard_position_history.iter().enumerate()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if i == self.guard_position_history.len() / 4
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
println!("25%");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if i == self.guard_position_history.len() / 2
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
println!("50%");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.map.reset_guard();
|
|
|
|
|
|
|
|
self.map.clear_visited();
|
|
|
|
|
|
|
|
let mut iterations = 0;
|
|
|
|
|
|
|
|
let mut possibly_stuck = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut map_clone = self.map.clone();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
map_clone.add_blocker_at(&pos);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while map_clone.guard_is_on_map()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
map_clone.step_guard();
|
|
|
|
|
|
|
|
iterations += 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if iterations >= stuck_limit
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
possibly_stuck = true;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if possibly_stuck
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
found_locations.push(*pos);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.final_result = found_locations.len() as i32;
|
|
|
|
self.final_result.to_string()
|
|
|
|
self.final_result.to_string()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
@ -109,7 +175,7 @@ impl Solver for Day6
|
|
|
|
self.map.print();
|
|
|
|
self.map.print();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
self.guard_history = vec![vec![false; self.map.width() as usize]; self.map.height() as usize];
|
|
|
|
self.guard_heatmap = vec![vec![false; self.map.width() as usize]; self.map.height() as usize];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn solve(self: &mut Self) -> String
|
|
|
|
fn solve(self: &mut Self) -> String
|
|
|
|
|