feat(day6): init

This commit is contained in:
uku 2024-12-07 21:55:11 +01:00
parent 6394c75524
commit 8ee1f29eed
Signed by: uku
SSH key fingerprint: SHA256:4P0aN6M8ajKukNi6aPOaX0LacanGYtlfjmN+m/sHY/o
2 changed files with 167 additions and 0 deletions

165
src/solutions/day_06.rs Normal file
View file

@ -0,0 +1,165 @@
use std::collections::HashSet;
use crate::common::{Answer, Solution};
pub struct Day06;
impl Solution for Day06 {
fn name(&self) -> &'static str {
"Guard Gallivant"
}
fn part_a(&self, input: &str) -> Answer {
let grid = input
.lines()
.map(|l| l.chars().collect::<Vec<_>>())
.collect::<Vec<_>>();
let guard_pos = input
.lines()
.enumerate()
.filter_map(|(x, l)| l.find('^').map(|y| (x, y)))
.next()
.unwrap();
let guard = Guard {
coords: guard_pos,
direction: Direction::Up,
};
Answer::Number(get_positions(&grid, guard).len() as u64)
}
fn part_b(&self, input: &str) -> Answer {
let grid = input
.lines()
.map(|l| l.chars().collect::<Vec<_>>())
.collect::<Vec<_>>();
let guard_pos = input
.lines()
.enumerate()
.filter_map(|(x, l)| l.find('^').map(|y| (x, y)))
.next()
.unwrap();
let guard = Guard {
coords: guard_pos,
direction: Direction::Up,
};
let count = get_positions(&grid, guard)
.iter()
.filter(|&&coords| {
let tmp_guard = Guard {
coords: guard_pos,
direction: Direction::Up,
};
is_infinite_loop(&grid, tmp_guard, coords)
})
.count();
Answer::Number(count as u64)
}
}
fn get_positions(grid: &[Vec<char>], mut guard: Guard) -> HashSet<(usize, usize)> {
let max_coords = (grid.len() - 1, grid[0].len() - 1);
let mut positions = HashSet::new();
while let Some(next) = guard.next_coords(&max_coords) {
if grid[next.0][next.1] == '#' {
guard.turn_right();
} else {
positions.insert(next);
guard.coords = next;
}
}
positions
}
fn is_infinite_loop(grid: &[Vec<char>], mut guard: Guard, block_coords: (usize, usize)) -> bool {
let max_coords = (grid.len() - 1, grid[0].len() - 1);
let mut positions = HashSet::new();
while let Some(next) = guard.next_coords(&max_coords) {
if positions.contains(&guard) {
return true;
} else if grid[next.0][next.1] == '#' || next == block_coords {
guard.turn_right();
} else {
positions.insert(guard);
guard.coords = next;
}
}
false
}
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
enum Direction {
Up,
Down,
Left,
Right,
}
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
struct Guard {
coords: (usize, usize),
direction: Direction,
}
impl Guard {
fn turn_right(&mut self) {
self.direction = match self.direction {
Direction::Up => Direction::Right,
Direction::Down => Direction::Left,
Direction::Left => Direction::Up,
Direction::Right => Direction::Down,
}
}
/// Assumes (0,0) is top left, .0 is the line and .1 the column.
fn next_coords(&self, max: &(usize, usize)) -> Option<(usize, usize)> {
match self.direction {
Direction::Up => self.coords.0.checked_sub(1).map(|n| (n, self.coords.1)),
Direction::Down => (self.coords.0 < max.0).then(|| (self.coords.0 + 1, self.coords.1)),
Direction::Left => self.coords.1.checked_sub(1).map(|n| (self.coords.0, n)),
Direction::Right => (self.coords.1 < max.1).then(|| (self.coords.0, self.coords.1 + 1)),
}
}
}
#[cfg(test)]
mod test {
use super::Day06;
use crate::common::Solution;
use indoc::indoc;
const INPUT: &str = indoc! {"
....#.....
.........#
..........
..#.......
.......#..
..........
.#..^.....
........#.
#.........
......#...
"};
#[test]
fn part_a() {
assert_eq!(Day06.part_a(INPUT), 41.into());
}
#[test]
fn part_b() {
assert_eq!(Day06.part_b(INPUT), 6.into());
}
}

View file

@ -5,6 +5,7 @@ mod day_02;
mod day_03; mod day_03;
mod day_04; mod day_04;
mod day_05; mod day_05;
mod day_06;
pub const SOLUTIONS: &[&dyn Solution] = &[ pub const SOLUTIONS: &[&dyn Solution] = &[
&day_01::Day01, &day_01::Day01,
@ -12,4 +13,5 @@ pub const SOLUTIONS: &[&dyn Solution] = &[
&day_03::Day03, &day_03::Day03,
&day_04::Day04, &day_04::Day04,
&day_05::Day05, &day_05::Day05,
&day_06::Day06,
]; ];