added day 6 (incomplete)
Dieser Commit ist enthalten in:
Ursprung
ed43974f0f
Commit
194e904ccc
2 geänderte Dateien mit 278 neuen und 7 gelöschten Zeilen
173
src/bin/2024/06.rs
Normale Datei
173
src/bin/2024/06.rs
Normale Datei
|
@ -0,0 +1,173 @@
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use advent_of_code::{
|
||||||
|
include_data, include_example,
|
||||||
|
strings::{convert_to_array, line_to_char},
|
||||||
|
KartesianDirection,
|
||||||
|
};
|
||||||
|
use advent_of_code::{Kartesian, Table};
|
||||||
|
use log::debug;
|
||||||
|
use num::Integer;
|
||||||
|
|
||||||
|
include_data!(DATA 2024 06);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
struct DirectionalKartesian<T: Integer> {
|
||||||
|
x: T,
|
||||||
|
y: T,
|
||||||
|
dir: KartesianDirection,
|
||||||
|
}
|
||||||
|
impl<T: Integer> From<(Kartesian<T>, KartesianDirection)> for DirectionalKartesian<T> {
|
||||||
|
fn from(value: (Kartesian<T>, KartesianDirection)) -> Self {
|
||||||
|
DirectionalKartesian {
|
||||||
|
x: value.0.x,
|
||||||
|
y: value.0.y,
|
||||||
|
dir: value.1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Integer + Copy> Into<(Kartesian<T>, KartesianDirection)> for &DirectionalKartesian<T> {
|
||||||
|
fn into(self) -> (Kartesian<T>, KartesianDirection) {
|
||||||
|
(
|
||||||
|
Kartesian {
|
||||||
|
x: self.x,
|
||||||
|
y: self.y,
|
||||||
|
},
|
||||||
|
self.dir,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Integer> DirectionalKartesian<T> {
|
||||||
|
fn kartesian(self) -> Kartesian<T> {
|
||||||
|
Kartesian::new(self.x, self.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_guard(map: Table) -> Kartesian<i32> {
|
||||||
|
let mut position = Kartesian::default();
|
||||||
|
for line in map {
|
||||||
|
for char in line {
|
||||||
|
if char == '^' {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
position.y += 1;
|
||||||
|
}
|
||||||
|
position.y = 0;
|
||||||
|
position.x += 1;
|
||||||
|
}
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_path(map: Table) -> Vec<DirectionalKartesian<i32>> {
|
||||||
|
let mut position = (find_guard(map.clone()), KartesianDirection::Top);
|
||||||
|
let maximum = Kartesian::new(map.len() as i32, map[0].len() as i32);
|
||||||
|
debug!(
|
||||||
|
"Guard is on coordinate {}:{}",
|
||||||
|
position.0.x + 1,
|
||||||
|
position.0.y + 1
|
||||||
|
);
|
||||||
|
let mut passed = Vec::new();
|
||||||
|
passed.push(position.into());
|
||||||
|
loop {
|
||||||
|
position.0 = match position.0.checked_add_max(position.1.vector(), maximum) {
|
||||||
|
None => {
|
||||||
|
debug!("Guard left the space after {} steps", passed.len());
|
||||||
|
return passed;
|
||||||
|
}
|
||||||
|
Some(pos) => pos,
|
||||||
|
};
|
||||||
|
if map[position.0.x as usize][position.0.y as usize] != '#' {
|
||||||
|
passed.push(position.into());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
position.0 -= position.1.vector();
|
||||||
|
debug!(
|
||||||
|
"Guard turned right on {}:{}",
|
||||||
|
position.0.x + 1,
|
||||||
|
position.0.y + 1
|
||||||
|
);
|
||||||
|
position.1 = position.1.clockwise(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solver1(input: &str) -> usize {
|
||||||
|
let map = convert_to_array(input, line_to_char);
|
||||||
|
let mut path = get_path(map);
|
||||||
|
path.sort();
|
||||||
|
path.dedup_by_key(|p| (p.x, p.y));
|
||||||
|
path.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_looping(
|
||||||
|
path: Vec<DirectionalKartesian<i32>>,
|
||||||
|
start_point: DirectionalKartesian<i32>,
|
||||||
|
) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables, unused_mut)]
|
||||||
|
fn solver2(input: &str) -> usize {
|
||||||
|
let map = convert_to_array(input, line_to_char);
|
||||||
|
let maximum = Kartesian::new(map.len() as i32, map[0].len() as i32);
|
||||||
|
let mut path = get_path(map.clone());
|
||||||
|
let mut p = path.iter();
|
||||||
|
let mut looppoints = Vec::new();
|
||||||
|
let startpoint = p.next().unwrap().kartesian();
|
||||||
|
|
||||||
|
let mut currentpoint: (Kartesian<i32>, KartesianDirection);
|
||||||
|
for point in p {
|
||||||
|
if point.kartesian() == startpoint {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
currentpoint = point.into();
|
||||||
|
currentpoint.1 = currentpoint.1.clockwise(false);
|
||||||
|
loop {
|
||||||
|
currentpoint.0 = match currentpoint
|
||||||
|
.0
|
||||||
|
.checked_add_max(currentpoint.1.vector(), maximum)
|
||||||
|
{
|
||||||
|
None => break,
|
||||||
|
Some(p) => p,
|
||||||
|
};
|
||||||
|
if path.contains(¤tpoint.into()) {
|
||||||
|
looppoints.push(point.kartesian());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if map[currentpoint.0.x as usize][currentpoint.0.y as usize] == '#' {
|
||||||
|
currentpoint.0 -= currentpoint.1.vector();
|
||||||
|
currentpoint.1 = currentpoint.1.clockwise(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
looppoints.dedup();
|
||||||
|
looppoints.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!(
|
||||||
|
"Guard left the space after walking through {} distinct positions",
|
||||||
|
solver1(DATA)
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"There are {} positions that are good for loops",
|
||||||
|
solver2(DATA)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
include_example!(EXAMPLE 2024 06);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_solution_1() {
|
||||||
|
assert_eq!(solver1(EXAMPLE), 41);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_solution_2() {
|
||||||
|
assert_eq!(solver2(EXAMPLE), 6);
|
||||||
|
}
|
||||||
|
}
|
112
src/lib.rs
112
src/lib.rs
|
@ -5,6 +5,8 @@ use num::*;
|
||||||
pub mod strings;
|
pub mod strings;
|
||||||
pub use advent_of_code_macros::*;
|
pub use advent_of_code_macros::*;
|
||||||
|
|
||||||
|
pub type Table = Vec<Vec<char>>;
|
||||||
|
|
||||||
pub fn matrix(zero: bool, diag: bool, non_diag: bool) -> Vec<(i32, i32)> {
|
pub fn matrix(zero: bool, diag: bool, non_diag: bool) -> Vec<(i32, i32)> {
|
||||||
const MIN: i32 = -1;
|
const MIN: i32 = -1;
|
||||||
const MAX: i32 = 1;
|
const MAX: i32 = 1;
|
||||||
|
@ -47,7 +49,7 @@ impl<T: Integer> Add for Kartesian<T> {
|
||||||
type Output = Kartesian<T>;
|
type Output = Kartesian<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Integer + Euclidian> AddAssign for Kartesian<T> {
|
impl<T: Integer + AddAssign> AddAssign for Kartesian<T> {
|
||||||
fn add_assign(&mut self, rhs: Self) {
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
self.x += rhs.x;
|
self.x += rhs.x;
|
||||||
self.y += rhs.y;
|
self.y += rhs.y;
|
||||||
|
@ -65,7 +67,7 @@ impl<T: Integer> Sub for Kartesian<T> {
|
||||||
type Output = Kartesian<T>;
|
type Output = Kartesian<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Integer + Euclidian> SubAssign for Kartesian<T> {
|
impl<T: Integer + SubAssign> SubAssign for Kartesian<T> {
|
||||||
fn sub_assign(&mut self, rhs: Self) {
|
fn sub_assign(&mut self, rhs: Self) {
|
||||||
self.x -= rhs.x;
|
self.x -= rhs.x;
|
||||||
self.y -= rhs.y;
|
self.y -= rhs.y;
|
||||||
|
@ -78,6 +80,31 @@ impl<T: Integer> Kartesian<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Integer + CheckedAdd + Default> Kartesian<T> {
|
||||||
|
pub fn checked_add_max(self, rhs: Kartesian<T>, max: Kartesian<T>) -> Option<Kartesian<T>> {
|
||||||
|
let mut new = Kartesian::default();
|
||||||
|
new.x = match self.x.checked_add(&rhs.x) {
|
||||||
|
None => return None,
|
||||||
|
Some(x) => {
|
||||||
|
if x < T::default() || x >= max.x {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
x
|
||||||
|
}
|
||||||
|
};
|
||||||
|
new.y = match self.y.checked_add(&rhs.y) {
|
||||||
|
None => return None,
|
||||||
|
Some(y) => {
|
||||||
|
if y < T::default() || y >= max.y {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
y
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(new)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Euclidian<T>
|
pub struct Euclidian<T>
|
||||||
where
|
where
|
||||||
|
@ -100,7 +127,7 @@ impl<T: Integer> Add for Euclidian<T> {
|
||||||
type Output = Euclidian<T>;
|
type Output = Euclidian<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Integer + Euclidian> AddAssign for Euclidian<T> {
|
impl<T: Integer + AddAssign> AddAssign for Euclidian<T> {
|
||||||
fn add_assign(&mut self, rhs: Self) {
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
self.x += rhs.x;
|
self.x += rhs.x;
|
||||||
self.y += rhs.y;
|
self.y += rhs.y;
|
||||||
|
@ -120,7 +147,7 @@ impl<T: Integer> Sub for Euclidian<T> {
|
||||||
type Output = Euclidian<T>;
|
type Output = Euclidian<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Integer + Euclidian> SubAssign for Euclidian<T> {
|
impl<T: Integer + SubAssign> SubAssign for Euclidian<T> {
|
||||||
fn sub_assign(&mut self, rhs: Self) {
|
fn sub_assign(&mut self, rhs: Self) {
|
||||||
self.x -= rhs.x;
|
self.x -= rhs.x;
|
||||||
self.y -= rhs.y;
|
self.y -= rhs.y;
|
||||||
|
@ -129,13 +156,11 @@ impl<T: Integer + Euclidian> SubAssign for Euclidian<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Integer> Euclidian<T> {
|
impl<T: Integer> Euclidian<T> {
|
||||||
pub const fn new(x: T, y: T) -> Self {
|
pub const fn new(x: T, y: T, z: T) -> Self {
|
||||||
Self { x: x, y: y, z: z }
|
Self { x: x, y: y, z: z }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Table = Vec<Vec<char>>;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum KartesianDirection {
|
pub enum KartesianDirection {
|
||||||
TopLeft,
|
TopLeft,
|
||||||
|
@ -167,4 +192,77 @@ impl KartesianDirection {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clockwise(self, diagonal: bool) -> KartesianDirection {
|
||||||
|
match (self, diagonal) {
|
||||||
|
(KartesianDirection::TopLeft, _) => Self::Top,
|
||||||
|
(KartesianDirection::Top, true) => Self::TopRight,
|
||||||
|
(KartesianDirection::Top, false) => Self::Right,
|
||||||
|
(KartesianDirection::TopRight, _) => Self::Right,
|
||||||
|
(KartesianDirection::Left, true) => Self::TopLeft,
|
||||||
|
(KartesianDirection::Left, false) => Self::Top,
|
||||||
|
(KartesianDirection::None, _) => Self::None,
|
||||||
|
(KartesianDirection::Right, true) => Self::BottomRight,
|
||||||
|
(KartesianDirection::Right, false) => Self::Bottom,
|
||||||
|
(KartesianDirection::BottomLeft, _) => Self::Left,
|
||||||
|
(KartesianDirection::Bottom, true) => Self::BottomLeft,
|
||||||
|
(KartesianDirection::Bottom, false) => Self::Left,
|
||||||
|
(KartesianDirection::BottomRight, _) => Self::Bottom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn anticlockwise(self, diagonal: bool) -> KartesianDirection {
|
||||||
|
match (self, diagonal) {
|
||||||
|
(KartesianDirection::TopLeft, _) => Self::Left,
|
||||||
|
(KartesianDirection::Top, true) => Self::TopLeft,
|
||||||
|
(KartesianDirection::Top, false) => Self::Left,
|
||||||
|
(KartesianDirection::TopRight, _) => Self::Top,
|
||||||
|
(KartesianDirection::Left, true) => Self::BottomLeft,
|
||||||
|
(KartesianDirection::Left, false) => Self::Bottom,
|
||||||
|
(KartesianDirection::None, _) => Self::None,
|
||||||
|
(KartesianDirection::Right, true) => Self::TopRight,
|
||||||
|
(KartesianDirection::Right, false) => Self::Top,
|
||||||
|
(KartesianDirection::BottomLeft, _) => Self::Bottom,
|
||||||
|
(KartesianDirection::Bottom, true) => Self::BottomRight,
|
||||||
|
(KartesianDirection::Bottom, false) => Self::Right,
|
||||||
|
(KartesianDirection::BottomRight, _) => Self::Right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_clockwise() {
|
||||||
|
let mut current = KartesianDirection::Top;
|
||||||
|
let clock = [
|
||||||
|
KartesianDirection::Top,
|
||||||
|
KartesianDirection::TopRight,
|
||||||
|
KartesianDirection::Right,
|
||||||
|
KartesianDirection::BottomRight,
|
||||||
|
KartesianDirection::Bottom,
|
||||||
|
KartesianDirection::BottomLeft,
|
||||||
|
KartesianDirection::Left,
|
||||||
|
KartesianDirection::TopLeft,
|
||||||
|
];
|
||||||
|
for hand in clock {
|
||||||
|
assert_eq!(current, hand);
|
||||||
|
current = current.clockwise(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_anticlockwise() {
|
||||||
|
let mut current = KartesianDirection::Top;
|
||||||
|
let clock = [
|
||||||
|
KartesianDirection::Top,
|
||||||
|
KartesianDirection::TopLeft,
|
||||||
|
KartesianDirection::Left,
|
||||||
|
KartesianDirection::BottomLeft,
|
||||||
|
KartesianDirection::Bottom,
|
||||||
|
KartesianDirection::BottomRight,
|
||||||
|
KartesianDirection::Right,
|
||||||
|
KartesianDirection::TopRight,
|
||||||
|
];
|
||||||
|
for hand in clock {
|
||||||
|
assert_eq!(current, hand);
|
||||||
|
current = current.anticlockwise(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Laden …
Tabelle hinzufügen
In neuem Issue referenzieren