refactor part 1 to solve part 2 easier and finished part 2

This commit is contained in:
Dylan Thies
2023-12-19 10:10:36 -05:00
parent 5842e18ea4
commit 43309b2079
2 changed files with 158 additions and 71 deletions

View File

@@ -1,8 +1,7 @@
#![warn(clippy::all, clippy::pedantic)] #![warn(clippy::all, clippy::pedantic)]
use std::collections::HashMap; use glam::I64Vec2;
use itertools::Itertools;
use glam::IVec2;
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::tag, bytes::complete::tag,
@@ -21,7 +20,7 @@ enum Direction {
struct Step { struct Step {
pub direction: Direction, pub direction: Direction,
pub count: i32, pub count: i64,
pub _color: String, pub _color: String,
} }
@@ -35,69 +34,38 @@ struct Step {
#[must_use] #[must_use]
pub fn part1(input: &str) -> String { pub fn part1(input: &str) -> String {
let (_, steps) = parse_input(input).expect("valid aoc content not found"); let (_, steps) = parse_input(input).expect("valid aoc content not found");
let mut cursor = IVec2::splat(0); let corners = steps
let mut grid = HashMap::from([(IVec2::splat(0), '#')]); .iter()
for step in &steps { .scan(I64Vec2::splat(0), |cursor, next| {
match step.direction { let dir =match next.direction {
Direction::Up => { Direction::Up => I64Vec2::NEG_Y,
(1..=step.count).for_each(|x| { Direction::Down => I64Vec2::Y,
let pos = cursor - IVec2::new(0, x); Direction::Left => I64Vec2::NEG_X,
grid.insert(pos, '#'); Direction::Right => I64Vec2::X,
});
cursor -= IVec2::new(0, step.count);
}
Direction::Down => {
(1..=step.count).for_each(|x| {
let pos = cursor + IVec2::new(0, x);
grid.insert(pos, '#');
});
cursor += IVec2::new(0, step.count);
}
Direction::Left => {
(1..=step.count).for_each(|x| {
let pos = cursor - IVec2::new(x, 0);
grid.insert(pos, '#');
});
cursor -= IVec2::new(step.count, 0);
}
Direction::Right => {
(1..=step.count).for_each(|x| {
let pos = cursor + IVec2::new(x, 0);
grid.insert(pos, '#');
});
cursor += IVec2::new(step.count, 0);
}
}; };
} *cursor += next.count * dir;
let (min_x, min_y, max_x, max_y) = grid.keys().fold( Some( *cursor)
(i32::MAX, i32::MAX, i32::MIN, i32::MIN), })
|(min_x, min_y, max_x, max_y), pos| { .collect::<Vec<_>>();
( let perimeter = corners
min_x.min(pos.x), .iter()
min_y.min(pos.y), .tuple_windows()
max_x.max(pos.x), .map(|(a, b)| {
max_y.max(pos.y), let dist = (*b - *a).abs();
) dist.x + dist.y
}, })
); .sum::<i64>()
(min_y..=max_y).for_each(|y| { + {
let mut inside = false; let a = corners.last().unwrap();
(min_x..=max_x).for_each(|x| { let b = corners.first().unwrap();
let square = grid.get(&IVec2::new(x, y)); let dist = (*b - *a).abs();
//print!("{}", square.unwrap_or(&'.')); dist.x + dist.y
//is it in or out ogf the loop
inside = if square.is_some() && grid.get(&IVec2::new(x, y + 1)).is_some() {
!inside
} else {
inside
}; };
if square.is_none() && inside { let area = (corners.iter().tuple_windows().map(|(a,b)| {
grid.insert(IVec2::new(x, y), '#'); a.x * b.y -a.y *b.x
} }).sum::<i64>() + perimeter
}); )/2 +1;
//print!("\n"); area.to_string()
});
grid.len().to_string()
} }
fn parse_step(input: &str) -> IResult<&str, Step> { fn parse_step(input: &str) -> IResult<&str, Step> {
@@ -110,7 +78,7 @@ fn parse_step(input: &str) -> IResult<&str, Step> {
tag("R").map(|_| Direction::Right), tag("R").map(|_| Direction::Right),
)), )),
complete::space1, complete::space1,
complete::i32, complete::i64,
), ),
complete::space1, complete::space1,
delimited(tag("("), preceded(tag("#"), complete::hex_digit1), tag(")")), delimited(tag("("), preceded(tag("#"), complete::hex_digit1), tag(")")),

View File

@@ -1,19 +1,138 @@
#![warn(clippy::all, clippy::pedantic)] #![warn(clippy::all, clippy::pedantic)]
//use std::collections::HashMap;
use glam::I64Vec2;
use itertools::Itertools;
use nom::{
branch::alt,
bytes::complete::tag,
character::complete,
multi::separated_list1,
sequence::{delimited, preceded, separated_pair},
IResult, Parser,
};
#[derive(Debug)]
enum Direction {
Up,
Down,
Left,
Right,
}
#[derive(Debug)]
struct Step {
pub direction: Direction,
pub count: i64,
}
/// day 18 part 2 of aoc 2023
///
/// # Arguments
/// - input the input for today's puzzle
///
/// # Panics
/// panics whne it cannot parse the input OR when ever the number of game numbers is greater than
#[must_use] #[must_use]
pub fn part2(_input: &str) -> String { pub fn part2(input: &str) -> String {
"Not Finished".to_string() let (_, steps) = parse_input(input).expect("valid aoc content not found");
let corners = steps
.iter()
.scan(I64Vec2::splat(0), |cursor, next| {
let dir = match next.direction {
Direction::Up => I64Vec2::NEG_Y,
Direction::Down => I64Vec2::Y,
Direction::Left => I64Vec2::NEG_X,
Direction::Right => I64Vec2::X,
};
*cursor += next.count * dir;
Some( *cursor)
})
.collect::<Vec<_>>();
let perimeter = corners
.iter()
.tuple_windows()
.map(|(a, b)| {
let dist = (*b - *a).abs();
dist.x + dist.y
})
.sum::<i64>()
+ {
let a = corners.last().unwrap();
let b = corners.first().unwrap();
let dist = (*b - *a).abs();
dist.x + dist.y
};
let area = ((corners
.iter()
.tuple_windows()
.map(|(a, b)| a.x * b.y - a.y * b.x)
.sum::<i64>()
+ perimeter)
/ 2)
.abs()
+ 1;
(area ).to_string()
}
fn parse_step(input: &str) -> IResult<&str, Step> {
let (input, (_, color)) = separated_pair(
separated_pair(
alt((
tag("U").map(|_| Direction::Up),
tag("D").map(|_| Direction::Down),
tag("L").map(|_| Direction::Left),
tag("R").map(|_| Direction::Right),
)),
complete::space1,
complete::i32,
),
complete::space1,
delimited(tag("("), preceded(tag("#"), complete::hex_digit1), tag(")")),
)(input)?;
let direction = match color.chars().last().unwrap() {
'0' => Direction::Right,
'1' => Direction::Down,
'2' => Direction::Left,
'3' => Direction::Up,
x => unimplemented!("Direction for value {x} not iimplemented"),
};
let count = i64::from_str_radix(&color.chars().take(5).collect::<String>(), 16)
.expect("this should just you know work");
Ok((input, Step { direction, count }))
}
fn parse_input(input: &str) -> IResult<&str, Vec<Step>> {
separated_list1(complete::line_ending, parse_step)(input)
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
const INPUT: &str = ""; const INPUT: &str = "R 6 (#70c710)
D 5 (#0dc571)
L 2 (#5713f0)
D 2 (#d2c081)
R 2 (#59c680)
D 2 (#411b91)
L 5 (#8ceee2)
U 2 (#caa173)
L 1 (#1b58a2)
U 2 (#caa171)
R 2 (#7807d2)
U 3 (#a77fa3)
L 2 (#015232)
U 2 (#7a21e3)";
#[test] #[test]
fn part2_works() { fn part2_works() {
let result = part2(INPUT); let result = part2(INPUT);
assert_eq!(result, "Not Finished".to_string()); assert_eq!(result, "952408144115".to_string());
} }
} }