Skip to content

Commit

Permalink
WIP need to count inner sides
Browse files Browse the repository at this point in the history
  • Loading branch information
tom-anders committed Dec 12, 2024
1 parent 6b1e289 commit 966c31f
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 44 deletions.
69 changes: 66 additions & 3 deletions day12/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,41 @@ impl UnweightedGraph for Map {
}
}

fn sides(region: &HashSet<Vec2D>, map: &Map) -> usize {
if region.len() == 1 {
return 4;
}

let top_left = region.iter().min_by_key(|pos| pos.x + pos.y).unwrap();

let mut sides = 0;

let mut normal = Vec2D::new(0, -1);
let mut pos = *top_left;

loop {
if !region.contains(&(pos + normal)) && !region.contains(&(pos + normal.rotated_right())) {
normal = normal.rotated_right();
sides += 1;
} else if region.contains(&(pos + normal.rotated_right()))
&& region.contains(&(pos + normal.rotated_right() + normal))
{
pos = pos + normal.rotated_right() + normal;
normal = normal.rotated_left();
sides += 1;
} else {
pos += normal.rotated_right();
}
if pos == *top_left && normal == (0, -1) {
break;
}
}

println!("region {} has {sides} sides", map[*top_left]);

sides
}

#[aoc_main]
fn solve(input: Input) -> impl Into<Solution> {
let map = Map::from(input.char_grid());
Expand Down Expand Up @@ -49,7 +84,14 @@ fn solve(input: Input) -> impl Into<Solution> {
})
.sum_usize();

(part1)
let part2 = region_map
.iter()
.map(|(c, regions)| {
regions.iter().map(|region| region.len() * sides(region, &map)).sum_usize()
})
.sum_usize();

(part1, part2)
}

#[cfg(test)]
Expand All @@ -59,11 +101,13 @@ mod tests {
fn test_examples() {
use utils::assert_example;
assert_example!(
r#"AAAA
r#"
AAAA
BBCD
BBCC
EEEC"#,
"140"
140,
80
);

assert_example!(
Expand All @@ -88,5 +132,24 @@ MIIISIJEEE
MMMISSJEEE",
1930
);

assert_part2!(
"EEEEE
EXXXX
EEEEE
EXXXX
EEEEE",
236
);

assert_part2!(
"AAAAAA
AAABBA
AAABBA
ABBAAA
ABBAAA
AAAAAA",
368
);
}
}
75 changes: 34 additions & 41 deletions utils/src/math/vec2d.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
use parse_display::FromStr;

#[derive(Copy, Clone, Debug, Eq, Hash, FromStr, PartialOrd, Ord)]
#[derive(Copy, Clone, Debug, Eq, Hash, FromStr, PartialOrd, Ord, derive_more::Display)]
#[display("({x}, {y})")]
// Parses [1, 2] or (1, 2) or {1, 2}
#[from_str(regex = r"[\[\(\{](?<x>-?\d+),\s*(?<y>-?\d+)[\]\)\}]")]
pub struct Vec2D {
pub x: i64,
pub y: i64,
}

impl<T> PartialEq<T> for Vec2D where T: Into<Vec2D> + Copy {
impl<T> PartialEq<T> for Vec2D
where
T: Into<Vec2D> + Copy,
{
fn eq(&self, other: &T) -> bool {
let other: Vec2D = (*other).into();
self.x == other.x && self.y == other.y
Expand Down Expand Up @@ -70,25 +74,15 @@ impl Vec2D {
}

pub fn diagonal_neighbors(&self) -> impl Iterator<Item = Vec2D> + '_ {
[
Vec2D { x: 1, y: 1 },
Vec2D { x: -1, y: 1 },
Vec2D { x: 1, y: -1 },
Vec2D { x: -1, y: -1 },
]
.iter()
.map(move |&dir| *self + dir)
[Vec2D { x: 1, y: 1 }, Vec2D { x: -1, y: 1 }, Vec2D { x: 1, y: -1 }, Vec2D { x: -1, y: -1 }]
.iter()
.map(move |&dir| *self + dir)
}

pub fn orthogonal_neighbors(&self) -> impl Iterator<Item = Vec2D> + '_ {
[
Vec2D { x: 1, y: 0 },
Vec2D { x: -1, y: 0 },
Vec2D { x: 0, y: 1 },
Vec2D { x: 0, y: -1 },
]
.iter()
.map(move |&dir| *self + dir)
[Vec2D { x: 1, y: 0 }, Vec2D { x: -1, y: 0 }, Vec2D { x: 0, y: 1 }, Vec2D { x: 0, y: -1 }]
.iter()
.map(move |&dir| *self + dir)
}

pub fn all_neighbors(&self) -> impl Iterator<Item = Vec2D> + '_ {
Expand Down Expand Up @@ -128,14 +122,11 @@ where
type Output = Vec2D;

fn mul(self, rhs: T) -> Self::Output {
Vec2D::new(
self.x * rhs.to_i64().unwrap(),
self.y * rhs.to_i64().unwrap(),
)
Vec2D::new(self.x * rhs.to_i64().unwrap(), self.y * rhs.to_i64().unwrap())
}
}

impl <T> std::ops::MulAssign<T> for Vec2D
impl<T> std::ops::MulAssign<T> for Vec2D
where
T: num::ToPrimitive + num::Integer,
{
Expand All @@ -151,7 +142,7 @@ macro_rules! impl_left_mul {
$(
impl std::ops::Mul<Vec2D> for $t {
type Output = Vec2D;

fn mul(self, rhs: Vec2D) -> Self::Output {
rhs * self
}
Expand All @@ -161,7 +152,10 @@ macro_rules! impl_left_mul {
}
impl_left_mul!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);

impl<T> std::ops::Add<T> for Vec2D where T: Into<Vec2D> {
impl<T> std::ops::Add<T> for Vec2D
where
T: Into<Vec2D>,
{
type Output = Vec2D;

fn add(self, rhs: T) -> Self::Output {
Expand All @@ -170,13 +164,19 @@ impl<T> std::ops::Add<T> for Vec2D where T: Into<Vec2D> {
}
}

impl<T> std::ops::AddAssign<T> for Vec2D where T: Into<Vec2D> {
impl<T> std::ops::AddAssign<T> for Vec2D
where
T: Into<Vec2D>,
{
fn add_assign(&mut self, rhs: T) {
*self = *self + rhs;
}
}

impl<T> std::ops::Sub<T> for Vec2D where T: Into<Vec2D> {
impl<T> std::ops::Sub<T> for Vec2D
where
T: Into<Vec2D>,
{
type Output = Vec2D;

fn sub(self, rhs: T) -> Self::Output {
Expand All @@ -185,7 +185,10 @@ impl<T> std::ops::Sub<T> for Vec2D where T: Into<Vec2D> {
}
}

impl<T> std::ops::SubAssign<T> for Vec2D where T: Into<Vec2D> {
impl<T> std::ops::SubAssign<T> for Vec2D
where
T: Into<Vec2D>,
{
fn sub_assign(&mut self, rhs: T) {
*self = *self - rhs;
}
Expand Down Expand Up @@ -246,7 +249,7 @@ mod tests {
assert_eq!(Vec2D::new(1, -2).manhattan_dist(), 3);
}

#[test]
#[test]
fn inside_box() {
assert!(Vec2D::new(1, 2).inside_box((0, 0), (2, 3)));
assert!(Vec2D::new(1, 2).inside_box((1, 2), (1, 2)));
Expand Down Expand Up @@ -275,21 +278,11 @@ mod tests {
#[test]
fn neighbors() {
assert_eq!(
HashSet::from([
Vec2D::new(2, 2),
Vec2D::new(0, 2),
Vec2D::new(1, 3),
Vec2D::new(1, 1)
]),
HashSet::from([Vec2D::new(2, 2), Vec2D::new(0, 2), Vec2D::new(1, 3), Vec2D::new(1, 1)]),
Vec2D::new(1, 2).orthogonal_neighbors().collect(),
);
assert_eq!(
HashSet::from([
Vec2D::new(2, 3),
Vec2D::new(0, 3),
Vec2D::new(2, 1),
Vec2D::new(0, 1)
]),
HashSet::from([Vec2D::new(2, 3), Vec2D::new(0, 3), Vec2D::new(2, 1), Vec2D::new(0, 1)]),
Vec2D::new(1, 2).diagonal_neighbors().collect(),
);
assert_eq!(
Expand Down

0 comments on commit 966c31f

Please sign in to comment.