Fuck day6p2 lol
This commit is contained in:
parent
aecb2f2278
commit
c1e46e9f0d
1 changed files with 105 additions and 0 deletions
|
|
@ -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) {
|
||||
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());
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue