mirror of
https://github.com/RussellChamp/advent-of-code-2024-rust.git
synced 2026-10-27 23:52:29 +00:00
day 6 pt2
This commit is contained in:
1 parent
54591fadd8
commit
09038351d4
4 files changed
+125
-5
No files matched your search
@@ -134,7 +134,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
fn test_part_two() {
|
fn test_part_two() {
|
||||||
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
|
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
|
||||||
assert_eq!(result, Some(123));
|
assert_eq!(result, Some(123));
|
||||||
|
|||||||
+123
-3
@@ -1,7 +1,15 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
advent_of_code::solution!(6);
|
advent_of_code::solution!(6);
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone)]
|
||||||
|
enum Tile {
|
||||||
|
Empty,
|
||||||
|
Object,
|
||||||
|
Guard
|
||||||
|
}
|
||||||
|
|
||||||
pub fn part_one(input: &str) -> Option<u32> {
|
pub fn part_one(input: &str) -> Option<u32> {
|
||||||
let mut pos = (0_isize, 0_isize);
|
let mut pos = (0_isize, 0_isize);
|
||||||
let mut dir = (-1_isize, 0_isize);
|
let mut dir = (-1_isize, 0_isize);
|
||||||
@@ -51,14 +59,127 @@ pub fn part_one(input: &str) -> Option<u32> {
|
|||||||
Some(count_spaces(visited) as u32)
|
Some(count_spaces(visited) as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn part_two(_input: &str) -> Option<u32> {
|
pub fn part_two(input: &str) -> Option<u32> {
|
||||||
None
|
let grid = input.lines().map(|line| line.chars().map(|c| {
|
||||||
|
match c {
|
||||||
|
'.' => Tile::Empty,
|
||||||
|
'#' => Tile::Object,
|
||||||
|
'^' => Tile::Guard,
|
||||||
|
_ => panic!()
|
||||||
|
}
|
||||||
|
}).collect_vec()).collect_vec();
|
||||||
|
|
||||||
|
let mut looper_count = 0;
|
||||||
|
// find all the spots the guard normally follows
|
||||||
|
// then see if placing an object on one of those spots creates a loop
|
||||||
|
|
||||||
|
let paths = walk_path(&grid);
|
||||||
|
// println!("CHECKING {:?} PATHS", paths.len());
|
||||||
|
|
||||||
|
for (row_idx, col_idx) in paths {
|
||||||
|
if grid[row_idx][col_idx] != Tile::Empty { continue }
|
||||||
|
let mut test_grid = grid.clone();
|
||||||
|
test_grid[row_idx][col_idx] = Tile::Object; // Add a wall and check if it creates a loop
|
||||||
|
|
||||||
|
if does_loop(&test_grid) {
|
||||||
|
looper_count += 1;
|
||||||
|
// print!("!");
|
||||||
|
// let _ = io::stdout().flush();
|
||||||
|
} else {
|
||||||
|
// print!("x");
|
||||||
|
// let _ = io::stdout().flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(looper_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count_spaces(grid: Vec<Vec<i32>>) -> usize {
|
fn count_spaces(grid: Vec<Vec<i32>>) -> usize {
|
||||||
grid.iter().flat_map(|line: &Vec<_>| line.iter().filter(|v| v > &&0)).count()
|
grid.iter().flat_map(|line: &Vec<_>| line.iter().filter(|v| v > &&0)).count()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn walk_path(grid: &Vec<Vec<Tile>>) -> Vec<(usize, usize)> {
|
||||||
|
let mut pos = grid.iter().enumerate().find_map(|(row_idx, row)| {
|
||||||
|
row.iter().enumerate().find_map(|(col_idx, cell)| {
|
||||||
|
if *cell == Tile::Guard { Some((row_idx as isize, col_idx as isize)) } else { None }
|
||||||
|
})
|
||||||
|
}).unwrap();
|
||||||
|
let mut dir = (-1_isize, 0_isize);
|
||||||
|
|
||||||
|
let mut history = HashSet::new();
|
||||||
|
history.insert((pos.0 as usize, pos.1 as usize));
|
||||||
|
|
||||||
|
let is_valid_position = |(row_idx, col_idx)| {
|
||||||
|
(0..grid.len() as isize).contains(&row_idx) && (0..grid[0].len() as isize).contains(&col_idx)
|
||||||
|
};
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let new_pos = (pos.0 + dir.0, pos.1 + dir.1);
|
||||||
|
if !is_valid_position(new_pos) { break }
|
||||||
|
|
||||||
|
if grid[new_pos.0 as usize][new_pos.1 as usize] == Tile::Object {
|
||||||
|
// if it is a blocker, turn 90deg
|
||||||
|
let directions = [(-1, 0), (0, 1), (1, 0), (0, -1), (-1, 0)];
|
||||||
|
let new_dir = *directions.iter().skip_while(|d| **d != dir).nth(1).unwrap();
|
||||||
|
dir.0 = new_dir.0;
|
||||||
|
dir.1 = new_dir.1;
|
||||||
|
} else {
|
||||||
|
// else move into the new position and mark it as entered
|
||||||
|
history.insert((new_pos.0 as usize, new_pos.1 as usize));
|
||||||
|
pos.0 = new_pos.0;
|
||||||
|
pos.1 = new_pos.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
history.into_iter().collect_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn does_loop(grid: &Vec<Vec<Tile>>) -> bool {
|
||||||
|
let mut pos = grid.iter().enumerate().find_map(|(row_idx, row)| {
|
||||||
|
row.iter().enumerate().find_map(|(col_idx, cell)| {
|
||||||
|
if *cell == Tile::Guard { Some((row_idx as isize, col_idx as isize)) } else { None }
|
||||||
|
})
|
||||||
|
}).unwrap();
|
||||||
|
let mut dir = (-1_isize, 0_isize);
|
||||||
|
|
||||||
|
let mut history = vec![];
|
||||||
|
history.push(((pos.0, pos.1), (-1_isize, 0_isize)));
|
||||||
|
|
||||||
|
|
||||||
|
let is_valid_position = |(row_idx, col_idx)| {
|
||||||
|
(0..grid.len() as isize).contains(&row_idx) && (0..grid[0].len() as isize).contains(&col_idx)
|
||||||
|
};
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let new_pos = (pos.0 + dir.0, pos.1 + dir.1);
|
||||||
|
if !is_valid_position(new_pos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if grid[new_pos.0 as usize][new_pos.1 as usize] == Tile::Object {
|
||||||
|
// if it is a blocker, turn 90deg
|
||||||
|
let directions = [(-1, 0), (0, 1), (1, 0), (0, -1), (-1, 0)];
|
||||||
|
let new_dir = *directions.iter().skip_while(|d| **d != dir).nth(1).unwrap();
|
||||||
|
|
||||||
|
if history.contains(&(pos, new_dir)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir.0 = new_dir.0;
|
||||||
|
dir.1 = new_dir.1;
|
||||||
|
} else {
|
||||||
|
// else move into the new position and mark it as entered
|
||||||
|
if history.contains(&((new_pos.0, new_pos.1), dir)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
history.push(((new_pos.0, new_pos.1), dir));
|
||||||
|
pos.0 = new_pos.0;
|
||||||
|
pos.1 = new_pos.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -81,7 +202,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
fn test_part_two() {
|
fn test_part_two() {
|
||||||
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
|
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
|
||||||
assert_eq!(result, Some(6));
|
assert_eq!(result, Some(6));
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore]
|
||||||
fn test_part_two() {
|
fn test_part_two() {
|
||||||
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
|
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
|
||||||
assert_eq!(result, Some(3440247820));
|
assert_eq!(result, Some(3440247820));
|
||||||
|
|||||||
+1
-1
@@ -124,7 +124,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_part_one_2() {
|
fn test_part_one_2() {
|
||||||
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
|
let result = part_one(&advent_of_code::template::read_file_part("examples", DAY, 2));
|
||||||
assert_eq!(result, Some(11048));
|
assert_eq!(result, Some(11048));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user