mirror of
https://github.com/Rhelvetican/aoc2024.git
synced 2024-12-22 22:51:38 +00:00
day 6
This commit is contained in:
parent
1e68c2ac05
commit
d5910b8bbd
6 changed files with 17117 additions and 4 deletions
|
@ -2,10 +2,7 @@ use ansi_term::enable_ansi_support;
|
|||
use aoc2024::{
|
||||
cli::AocCli,
|
||||
map_solution,
|
||||
solutions::{
|
||||
AocDayFiveSolution, AocDayFourSolution, AocDayOneSolution, AocDayThreeSolution,
|
||||
AocDayTwoSolution, AocSolution,
|
||||
},
|
||||
solutions::*,
|
||||
utils::{Error, Result},
|
||||
};
|
||||
use clap::Parser;
|
||||
|
@ -30,6 +27,7 @@ fn main() -> Result<()> {
|
|||
3 => AocDayThreeSolution,
|
||||
4 => AocDayFourSolution,
|
||||
5 => AocDayFiveSolution,
|
||||
6 => AocDaySixSolution,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1 +1,109 @@
|
|||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
fs::read_to_string,
|
||||
path::Path,
|
||||
};
|
||||
|
||||
use super::AocSolution;
|
||||
use crate::utils::{coord::Coord, direction::Direction, Result};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Guard {
|
||||
dir: Direction,
|
||||
cur: Coord,
|
||||
grid: HashMap<Coord, bool>,
|
||||
}
|
||||
|
||||
impl Guard {
|
||||
fn new(src: &str) -> Self {
|
||||
let (grid, cur) = src
|
||||
.lines()
|
||||
.zip(0..)
|
||||
.flat_map(|(l, y)| {
|
||||
l.chars()
|
||||
.zip(0..)
|
||||
.map(move |(ch, x)| (Coord::new(x, y), ch))
|
||||
})
|
||||
.fold(
|
||||
(HashMap::new(), Coord::new(0, 0)),
|
||||
|(mut map, coord), (crd, obs)| {
|
||||
map.insert(crd, obs == '#');
|
||||
let coord = if obs == '^' { crd } else { coord };
|
||||
(map, coord)
|
||||
},
|
||||
);
|
||||
|
||||
Self {
|
||||
dir: Direction::default(),
|
||||
cur,
|
||||
grid,
|
||||
}
|
||||
}
|
||||
|
||||
fn patrol(&mut self) -> (usize, bool) {
|
||||
let mut repetition = 0u16;
|
||||
let mut flag = false;
|
||||
let mut patrolled = HashSet::new();
|
||||
|
||||
loop {
|
||||
if repetition == 65535 {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
|
||||
let lookahead = self.cur + self.dir;
|
||||
if let Some(&obs) = self.grid.get(&lookahead) {
|
||||
if obs {
|
||||
self.dir.turn_right();
|
||||
} else {
|
||||
if !patrolled.insert(self.cur) {
|
||||
repetition += 1;
|
||||
};
|
||||
self.cur = lookahead;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
(patrolled.len() + 1, flag)
|
||||
}
|
||||
|
||||
fn loop_prank(&mut self) -> u64 {
|
||||
let mut total = 0;
|
||||
for &key in self.grid.keys() {
|
||||
let mut tmp = self.clone();
|
||||
if tmp.grid.get(&key).is_some_and(|cond| !*cond) {
|
||||
tmp.grid.insert(key, true);
|
||||
if tmp.patrol().1 {
|
||||
total += 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
total
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct AocDaySixSolution;
|
||||
|
||||
impl AocSolution for AocDaySixSolution {
|
||||
type Output = u64;
|
||||
fn get_input(&self, path: Option<&Path>) -> Result<String> {
|
||||
match path {
|
||||
Some(p) => Ok(read_to_string(p)?),
|
||||
None => Ok(read_to_string("./input/day_6.txt")?),
|
||||
}
|
||||
}
|
||||
|
||||
fn part_one(&self, input: &str) -> Result<Self::Output> {
|
||||
let mut g = Guard::new(input);
|
||||
Ok(g.patrol().0 as Self::Output)
|
||||
}
|
||||
|
||||
fn part_two(&self, input: &str) -> Result<Self::Output> {
|
||||
let mut g = Guard::new(input);
|
||||
Ok(g.loop_prank())
|
||||
}
|
||||
}
|
||||
|
|
32
src/utils/coord.rs
Normal file
32
src/utils/coord.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use std::ops::Add;
|
||||
|
||||
use super::direction::Direction;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Coord {
|
||||
pub x: i16,
|
||||
pub y: i16,
|
||||
}
|
||||
|
||||
impl Coord {
|
||||
pub fn new(x: i16, y: i16) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Coord {
|
||||
type Output = Coord;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self::new(self.x + rhs.x, self.y + rhs.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<Direction> for Coord {
|
||||
type Output = Coord;
|
||||
|
||||
fn add(self, rhs: Direction) -> Self::Output {
|
||||
let tmp = rhs.lookahead();
|
||||
self + tmp
|
||||
}
|
||||
}
|
66
src/utils/direction.rs
Normal file
66
src/utils/direction.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use std::ops::{Neg, Not};
|
||||
|
||||
use super::coord::Coord;
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Direction {
|
||||
#[default]
|
||||
Up,
|
||||
Right,
|
||||
Left,
|
||||
Down,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
pub fn turn_right(&mut self) {
|
||||
match self {
|
||||
Self::Up => *self = Self::Right,
|
||||
Self::Right => *self = Self::Down,
|
||||
Self::Down => *self = Self::Left,
|
||||
Self::Left => *self = Self::Up,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn turn_left(&mut self) {
|
||||
match self {
|
||||
Self::Up => *self = Self::Left,
|
||||
Self::Left => *self = Self::Down,
|
||||
Self::Down => *self = Self::Right,
|
||||
Self::Right => *self = Self::Up,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn turn_back(&mut self) {
|
||||
*self = !*self
|
||||
}
|
||||
|
||||
pub fn lookahead(&self) -> Coord {
|
||||
match self {
|
||||
Self::Up => Coord::new(0, -1),
|
||||
Self::Right => Coord::new(1, 0),
|
||||
Self::Down => Coord::new(0, 1),
|
||||
Self::Left => Coord::new(-1, 0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Not for Direction {
|
||||
type Output = Self;
|
||||
|
||||
fn not(self) -> Self::Output {
|
||||
match self {
|
||||
Self::Up => Self::Down,
|
||||
Self::Left => Self::Right,
|
||||
Self::Down => Self::Up,
|
||||
Self::Right => Self::Left,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Direction {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
!self
|
||||
}
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
#[macro_use]
|
||||
pub mod macros;
|
||||
|
||||
pub mod coord;
|
||||
pub mod direction;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
|
|
Loading…
Reference in a new issue