2023-12-20 08:34:15 -06:00
|
|
|
use aoc_runner_derive::{aoc, aoc_generator};
|
|
|
|
use strum_macros::Display;
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
|
|
struct Step {
|
|
|
|
dir: Direction,
|
|
|
|
length: i32
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Display, PartialEq, Eq, Clone, Copy)]
|
|
|
|
enum Direction {
|
|
|
|
Up,
|
|
|
|
Down,
|
|
|
|
Left,
|
|
|
|
Right
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Direction {
|
|
|
|
fn get_coordinate_modifier(&self) -> (i32, i32) {
|
|
|
|
match self {
|
|
|
|
Direction::Up => (0, 1),
|
|
|
|
Direction::Down => (0, -1),
|
|
|
|
Direction::Left => (-1, 0),
|
|
|
|
Direction::Right => (1, 0),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
trait DirectionConvertable {
|
|
|
|
fn to_direction(&self) -> Direction;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DirectionConvertable for &str {
|
|
|
|
fn to_direction(&self) -> Direction {
|
|
|
|
match *self {
|
|
|
|
"U" => Direction::Up,
|
|
|
|
"D" => Direction::Down,
|
|
|
|
"L" => Direction::Left,
|
|
|
|
"R" => Direction::Right,
|
|
|
|
_ => panic!("Invalid Direction")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-20 09:10:02 -06:00
|
|
|
impl DirectionConvertable for i32 {
|
|
|
|
fn to_direction(&self) -> Direction {
|
|
|
|
match self {
|
|
|
|
3 => Direction::Up,
|
|
|
|
1 => Direction::Down,
|
|
|
|
2 => Direction::Left,
|
|
|
|
0 => Direction::Right,
|
|
|
|
_ => panic!("Invalid Direction")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[aoc_generator(day18, part1)]
|
|
|
|
fn parse_part1(input: &str) -> Vec<Step> {
|
2023-12-20 08:34:15 -06:00
|
|
|
let steps = input.lines()
|
|
|
|
.map(|line| {
|
|
|
|
let mut line = line.split(' ');
|
|
|
|
Step {
|
|
|
|
dir: line.next().unwrap().to_direction(),
|
|
|
|
length: line.next().unwrap().parse::<i32>().unwrap(),
|
|
|
|
}
|
|
|
|
}).collect::<Vec<_>>();
|
|
|
|
|
|
|
|
steps
|
|
|
|
}
|
|
|
|
|
|
|
|
#[aoc(day18, part1)]
|
|
|
|
fn part1(steps: &Vec<Step>) -> i32 {
|
|
|
|
let verticies = get_verticies(steps);
|
|
|
|
|
|
|
|
let mut area = 0;
|
|
|
|
|
|
|
|
for win in verticies.windows(2) {
|
|
|
|
area += win[0].y * win[1].x;
|
|
|
|
area -= win[0].x * win[1].y;
|
|
|
|
}
|
|
|
|
|
|
|
|
(area / 2) + (verticies.len() as i32 / 2) + 1
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
|
|
|
struct Coordinate {
|
|
|
|
x: i32,
|
|
|
|
y: i32
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_verticies(steps: &Vec<Step>) -> Vec<Coordinate> {
|
|
|
|
let mut cur_pos = Coordinate{ x: 0, y: 0 };
|
|
|
|
let mut verticies: Vec<Coordinate> = vec![cur_pos.clone()];
|
|
|
|
|
|
|
|
for step in steps {
|
|
|
|
let (x_mod, y_mod) = step.dir.get_coordinate_modifier();
|
|
|
|
for _ in 0..step.length {
|
|
|
|
let new_pos = Coordinate{
|
|
|
|
x: cur_pos.x + x_mod,
|
|
|
|
y: cur_pos.y + y_mod,
|
|
|
|
};
|
|
|
|
cur_pos = new_pos.clone();
|
|
|
|
verticies.push(new_pos.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
verticies
|
|
|
|
}
|
|
|
|
|
2023-12-20 09:10:02 -06:00
|
|
|
#[aoc_generator(day18, part2)]
|
|
|
|
fn parse_part2(input: &str) -> Vec<Step> {
|
|
|
|
let steps = input.lines()
|
|
|
|
.map(|line| {
|
|
|
|
let line = line.split(' ');
|
|
|
|
parse_hex(line.last().unwrap())
|
|
|
|
}).collect::<Vec<_>>();
|
|
|
|
|
|
|
|
steps
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_hex(hex: &str) -> Step {
|
|
|
|
let hex = hex.trim_matches(['(', ')', '#'].as_slice());
|
|
|
|
let length = "0".to_string() + &hex[0..5];
|
|
|
|
let length = u32::from_str_radix(&length, 16).expect("Cannot parse Hex value");
|
|
|
|
|
|
|
|
let dir = hex.chars().last().unwrap().to_string().parse::<i32>().unwrap().to_direction();
|
|
|
|
|
|
|
|
Step {
|
|
|
|
dir,
|
|
|
|
length: length as i32
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[aoc(day18, part2)]
|
|
|
|
fn part2(steps: &Vec<Step>) -> i64 {
|
|
|
|
let verticies = get_verticies(steps);
|
|
|
|
|
|
|
|
let mut area: i64 = 0;
|
|
|
|
|
|
|
|
for win in verticies.windows(2) {
|
|
|
|
area += win[0].y as i64 * win[1].x as i64;
|
|
|
|
area -= win[0].x as i64 * win[1].y as i64;
|
|
|
|
}
|
|
|
|
|
|
|
|
(area / 2) + (verticies.len() as i64 / 2) + 1
|
|
|
|
}
|
2023-12-20 08:34:15 -06:00
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
const EX: &str = r"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)";
|
|
|
|
|
|
|
|
const EX_2: &str = r"R 6 (#70c710)
|
|
|
|
D 6 (#0dc571)
|
|
|
|
L 6 (#5713f0)
|
|
|
|
U 6 (#d2c081)";
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn part1_example() {
|
2023-12-20 09:10:02 -06:00
|
|
|
assert_eq!(part1(&parse_part1(EX)), 62);
|
2023-12-20 08:34:15 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn part1_example2() {
|
2023-12-20 09:10:02 -06:00
|
|
|
assert_eq!(part1(&parse_part1(EX_2)), 49);
|
2023-12-20 08:34:15 -06:00
|
|
|
}
|
|
|
|
|
2023-12-20 09:10:02 -06:00
|
|
|
#[test]
|
|
|
|
fn part2_example() {
|
|
|
|
assert_eq!(part2(&parse_part2(EX)), 952408144115);
|
|
|
|
}
|
2023-12-20 08:34:15 -06:00
|
|
|
}
|