2024 day-6 part one submitted no clippy

This commit is contained in:
Dylan Thies
2024-12-06 10:26:48 -05:00
parent fb33e62a56
commit 951cab12f3
2 changed files with 219 additions and 6 deletions

View File

@@ -15,6 +15,7 @@ log.workspace = true
error-stack.workspace = true error-stack.workspace = true
thiserror.workspace = true thiserror.workspace = true
dhat.workspace = true dhat.workspace = true
glam.workspace =true
[dev-dependencies] [dev-dependencies]
test-log.workspace = true test-log.workspace = true

View File

@@ -1,35 +1,247 @@
#![warn(clippy::all, clippy::pedantic)] #![warn(clippy::all, clippy::pedantic)]
use error_stack::Result; use std::{collections::HashSet, ops::Sub};
use glam::IVec2;
use thiserror::Error; use thiserror::Error;
// day-6 // day-6
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum Day6Part1Error{ pub enum Day6Part1Error {
#[error("Problem parsing Day 6")] #[error("Problem parsing Day 6")]
ParseError, ParseError,
} }
#[derive(Debug)]
enum Direction {
North,
East,
South,
West,
}
impl From<&Direction> for IVec2 {
fn from(value: &Direction) -> Self {
match value {
Direction::North => IVec2::NEG_X,
Direction::East => IVec2::Y,
Direction::South => IVec2::X,
Direction::West => IVec2::NEG_Y,
}
}
}
impl Sub<&Direction> for &IVec2 {
type Output = IVec2;
fn sub(self, rhs: &Direction) -> Self::Output {
self - (match rhs {
Direction::North => IVec2::NEG_X,
Direction::East => IVec2::Y,
Direction::South => IVec2::X,
Direction::West => IVec2::NEG_Y,
})
}
}
impl Direction {
pub fn next(&self) -> Self {
match self {
Direction::North => Direction::East,
Direction::East => Direction::South,
Direction::South => Direction::West,
Direction::West => Direction::North,
}
}
}
#[derive(Debug)]
struct MyMap {
pub obstacles: HashSet<IVec2>,
pub height: u32,
pub width: u32,
}
impl MyMap {
pub fn next_obstacle(&self, start_pos: &IVec2, direction: &Direction) -> Option<&IVec2> {
self.obstacles
.iter()
.filter(|obstacle| match direction {
Direction::North => obstacle.y == start_pos.y && obstacle.x < start_pos.x,
Direction::East => obstacle.x == start_pos.x && obstacle.y > start_pos.y,
Direction::South => obstacle.y == start_pos.y && obstacle.x > start_pos.x,
Direction::West => obstacle.x == start_pos.x && obstacle.y < start_pos.y,
})
.fold(None, |acc, obstacle| match direction {
Direction::North if acc == None || obstacle.x > acc.unwrap().x => Some(obstacle),
Direction::East if acc == None || obstacle.y < acc.unwrap().y => Some(obstacle),
Direction::South if acc == None || obstacle.x < acc.unwrap().x => Some(obstacle),
Direction::West if acc == None || obstacle.y > acc.unwrap().y => Some(obstacle),
_ => acc,
})
}
}
/// Day-6 Part 2 for 2024 advent of code /// Day-6 Part 2 for 2024 advent of code
/// Problem can be found here: <https://adventofcode.com/2024/day/6> /// Problem can be found here: <https://adventofcode.com/2024/day/6>
/// ///
/// # Errors /// # Errors
/// - `ParseError` there was an issue with the parser /// - `ParseError` there was an issue with the parser
pub fn part1 (_input: &str) -> Result<String, Day6Part1Error> { pub fn part1(input: &str) -> Result<String, Day6Part1Error> {
Ok("Not Finished".to_string()) //let input = Span::new(input);
//TODO figure out how to real error
let (mut guard_pos, map) = parse_input(input);
let mut guard_dir = Direction::North;
let mut visited = HashSet::new();
while guard_pos.x >= 0
&& guard_pos.y >= 0
&& (guard_pos.x as u32) < map.height
&& (guard_pos.y as u32) < map.width
{
let _ = visited.insert(guard_pos);
if let Some(next_obstacle) = map.next_obstacle(&guard_pos, &guard_dir) {
// println!("Hit row {}, col {} going {:?}", next_obstacle.x, next_obstacle.y, guard_dir);
match guard_dir {
Direction::North => {
((next_obstacle.x+1)..guard_pos.x)
.map(|x| IVec2::new(x, guard_pos.y))
.for_each(|x| {
visited.insert(x);
});
},
Direction::South => {
(guard_pos.x..(next_obstacle.x-1))
.map(|x| IVec2::new(x, guard_pos.y))
.for_each(|x| {
visited.insert(x);
});
},
Direction::East => {
(guard_pos.y..(next_obstacle.y-1))
.map(|y| IVec2::new(guard_pos.x, y))
.for_each(|x| {
visited.insert(x);
});
},
Direction::West => {
((next_obstacle.y+1)..guard_pos.y)
.map(|y| IVec2::new(guard_pos.x, y))
.for_each(|x| {
visited.insert(x);
});
},
};
guard_pos = next_obstacle - &guard_dir;
} else {
let new_pos = match guard_dir {
Direction::North => IVec2::new(-1, guard_pos.y),
Direction::East => IVec2::new(guard_pos.x, map.width.try_into().unwrap()),
Direction::South => IVec2::new(map.height.try_into().unwrap(), guard_pos.y),
Direction::West => IVec2::new(guard_pos.x, -1),
};
// println!("Left map at row {}, col {}", new_pos.x, new_pos.y);
match guard_dir {
Direction::North => {
((new_pos.x+1)..guard_pos.x)
.map(|x| IVec2::new(x, guard_pos.y))
.for_each(|x| {
visited.insert(x);
});
}
Direction::South => {
(guard_pos.x..new_pos.x)
.map(|x| IVec2::new(x, guard_pos.y))
.for_each(|x| {
visited.insert(x);
});
}
Direction::East => {
(guard_pos.y..new_pos.y)
.map(|y| IVec2::new(guard_pos.x, y))
.for_each(|x| {
visited.insert(x);
});
}
Direction::West => {
((new_pos.y+1)..guard_pos.y)
.map(|y| IVec2::new(guard_pos.x, y))
.for_each(|x| {
visited.insert(x);
});
}
};
guard_pos = new_pos;
//break
}
guard_dir = guard_dir.next();
/*
for row in 0.. map.height.try_into().unwrap() {
for col in 0..map.width.try_into().unwrap() {
let pos = IVec2::new(row, col);
if visited.contains(&pos) {
print!("X");
} else {
print!(".");
}
}
print!("\n");
}*/
}
Ok(visited.iter().count().to_string())
} }
fn parse_input(input: &str) -> (IVec2, MyMap) {
let (pos, height, width, obstacles) = input.lines().into_iter().enumerate().fold(
(IVec2::ZERO, 0, 0, HashSet::new()),
|mut acc, (row_no, row)| {
acc.1 = row_no.try_into().unwrap();
acc.2 = row.len().try_into().unwrap();
row.chars()
.enumerate()
.filter(|(_, c)| *c == '#' || *c == '^')
.for_each(|(col_no, c)| {
if c == '#' {
acc.3.insert(IVec2::new(
row_no.try_into().unwrap(),
col_no.try_into().unwrap(),
));
} else {
acc.0 = IVec2::new(row_no.try_into().unwrap(), col_no.try_into().unwrap());
}
});
acc
},
);
(
pos,
MyMap {
obstacles,
height: height + 1,
width,
},
)
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
const INPUT: &str = ""; const INPUT: &str = "....#.....
.........#
..........
..#.......
.......#..
..........
.#..^.....
........#.
#.........
......#...";
#[test_log::test] #[test_log::test]
#[test_log(default_log_filter = "trace")] #[test_log(default_log_filter = "trace")]
fn part1_works() { fn part1_works() {
let result = part1(INPUT).unwrap(); let result = part1(INPUT).unwrap();
assert_eq!(result, "Not Finished".to_string()); assert_eq!(result, "41".to_string());
} }
} }