Fuck day6p2 lol

This commit is contained in:
Jos van Goor 2024-12-14 15:46:48 +01:00
parent aecb2f2278
commit c1e46e9f0d

View file

@ -1,4 +1,109 @@
use std::collections::{HashMap, HashSet};
const DIRECTIONS: [(i64, i64); 4] = [(0, -1), (1, 0), (0, 1), (-1, 0)]; // up right down left
fn find_start(grid: &[Vec<u8>]) -> (i64, i64) {
for (ypos, row) in grid.iter().enumerate() {
let Some(xpos) = row.iter().position(|ch| *ch == b'^') else {
continue;
};
return (xpos as i64, ypos as i64);
}
panic!("No starting position found");
}
fn detect_loop(grid: &[Vec<u8>], start_pos: (i64, i64), start_dir: usize) -> (bool, HashSet<(i64, i64, usize)>) {
let width = grid[0].len() as i64;
let height = grid.len() as i64;
let mut position = start_pos;
let mut direction = start_dir;
let mut tensors: HashSet<(i64, i64, usize)> = HashSet::new();
loop {
tensors.insert((position.0, position.1, direction));
let new_position = (position.0 + DIRECTIONS[direction].0, position.1 + DIRECTIONS[direction].1);
if new_position.0 < 0 || new_position.0 >= width || new_position.1 < 0 || new_position.1 >= height {
return (false, Default::default()); // new position is off the map, so no loop
}
let new_direction = if grid[new_position.1 as usize][new_position.0 as usize] == b'#' {
(direction + 1) % DIRECTIONS.len()
} else {
direction
};
if tensors.contains(&(new_position.0, new_position.1, new_direction)) {
// we are at the exact same position again, so we are in a loop
return (true, tensors);
}
let next_step = grid[new_position.1 as usize][new_position.0 as usize];
if next_step == b'#' || next_step == b'@' {
direction = (direction + 1) % DIRECTIONS.len();
} else {
position = new_position;
}
}
}
pub fn draw_walked_grid(grid: &[Vec<u8>], steps: &HashSet<(i64, i64, usize)>) {
let steps = steps.iter().map(|tup| ((tup.0, tup.1), tup.2)).collect::<HashMap<_, _>>();
for (ypos, line) in grid.iter().enumerate() {
for (xpos, step) in line.iter().enumerate() {
if *step == b'.' {
let pos = &(xpos as i64, ypos as i64);
if steps.contains_key(pos) {
let char = if steps.get(pos).unwrap() % 2 == 0 { "|" } else { "-" };
print!("{}", char);
} else {
print!(".");
}
} else {
print!("{}", *step as char);
}
}
println!();
}
}
pub fn solve(input: &str) { pub fn solve(input: &str) {
let grid = input.lines().map(|line| line.as_bytes().to_vec()).collect::<Vec<_>>();
let width = grid[0].len() as i64;
let height = grid.len() as i64;
let start = find_start(&grid);
let start_dir = 0;
let mut position = start;
let mut direction = 0;
let mut looping_blockades = HashSet::new();
loop {
let new_position = (position.0 + DIRECTIONS[direction].0, position.1 + DIRECTIONS[direction].1);
if new_position.0 < 0 || new_position.0 >= width || new_position.1 < 0 || new_position.1 >= height {
break; // we're off the map
}
if new_position != start {
let mut test_grid = grid.clone();
test_grid[new_position.1 as usize][new_position.0 as usize] = b'@';
let (looped, steps) = detect_loop(&test_grid, start, start_dir);
if looped {
looping_blockades.insert(new_position);
}
}
if grid[new_position.1 as usize][new_position.0 as usize] == b'#' {
direction = (direction + 1) % DIRECTIONS.len();
} else {
position = new_position;
}
}
println!("Number of possible obstacles: {}", looping_blockades.len());
} }