mirror of
https://github.com/Rhelvetican/aoc2024.git
synced 2024-12-23 06:51:40 +00:00
Compare commits
2 commits
1e68c2ac05
...
c38b6b6087
Author | SHA1 | Date | |
---|---|---|---|
|
c38b6b6087 | ||
|
d5910b8bbd |
5 changed files with 211 additions and 4 deletions
|
@ -2,10 +2,7 @@ use ansi_term::enable_ansi_support;
|
||||||
use aoc2024::{
|
use aoc2024::{
|
||||||
cli::AocCli,
|
cli::AocCli,
|
||||||
map_solution,
|
map_solution,
|
||||||
solutions::{
|
solutions::*,
|
||||||
AocDayFiveSolution, AocDayFourSolution, AocDayOneSolution, AocDayThreeSolution,
|
|
||||||
AocDayTwoSolution, AocSolution,
|
|
||||||
},
|
|
||||||
utils::{Error, Result},
|
utils::{Error, Result},
|
||||||
};
|
};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
@ -30,6 +27,7 @@ fn main() -> Result<()> {
|
||||||
3 => AocDayThreeSolution,
|
3 => AocDayThreeSolution,
|
||||||
4 => AocDayFourSolution,
|
4 => AocDayFourSolution,
|
||||||
5 => AocDayFiveSolution,
|
5 => AocDayFiveSolution,
|
||||||
|
6 => AocDaySixSolution,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
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;
|
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]
|
#[macro_use]
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
|
|
||||||
|
pub mod coord;
|
||||||
|
pub mod direction;
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
|
Loading…
Reference in a new issue