2024 day-6 part one submitted no clippy
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user