Skip to content

Commit 4416b68

Browse files
committed
chore: WIP y2025::day_09::part_2
1 parent c2ac784 commit 4416b68

File tree

1 file changed

+49
-59
lines changed

1 file changed

+49
-59
lines changed

aoclp_solutions/src/y2025/day_09.rs

Lines changed: 49 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use std::cmp::{max, min};
2-
use std::collections::HashMap;
2+
use std::collections::HashSet;
33
use std::iter::{once, successors};
44

55
use aoclp::positioning::direction::four_points::Direction4;
66
use aoclp::positioning::pt::{rectangular_area, Pt};
77
use aoclp::solvers_impl::input::safe_get_input_as_many;
88
use itertools::Itertools;
9+
use aoclp::positioning::turtle::Turtle;
910

1011
pub fn part_1() -> i64 {
1112
input()
@@ -18,41 +19,14 @@ pub fn part_1() -> i64 {
1819

1920
pub fn part_2() -> i64 {
2021
let red_tiles = input();
21-
let path = build_path(&red_tiles);
2222

23-
let safe_line = red_tiles.iter().map(|p| p.y).min().unwrap() - 1;
24-
let mut pt_safety = HashMap::new();
25-
let mut safe_pt = |p: Pt| {
26-
if let Some(&safe) = pt_safety.get(&p) {
27-
return safe;
28-
}
29-
30-
let safe = successors(Some(p), |&p| (p.y > safe_line).then_some(p + Direction4::Up))
31-
.filter(|p| path.get(p).is_some_and(|&step| step == PathStep::LeftRight))
32-
.count()
33-
% 2
34-
!= 0;
35-
pt_safety.insert(p, safe);
36-
safe
37-
};
38-
let mut safe_line = |a: Pt, b: Pt| -> bool {
39-
let displacement = Pt::new((b.x - a.x).signum(), (b.y - a.y).signum());
40-
successors(Some(a), |&p| (p != b).then_some(p + displacement))
41-
.chain(Some(b))
42-
.all(&mut safe_pt)
23+
let red_zone = build_red_zone(&red_tiles);
24+
let rectangle_points = |a: Pt, b: Pt| {
25+
let (left, right, top, bottom) = (min(a.x, b.x), max(a.x, b.x), min(a.y, b.y), max(a.y, b.y));
26+
(left..=right).flat_map(move |x| (top..=bottom).map(move |y| Pt::new(x, y)))
4327
};
44-
let mut safe_rectangle = |a: Pt, b: Pt| {
45-
let corners = [
46-
Pt::new(min(a.x, b.x), min(a.y, b.y)),
47-
Pt::new(min(a.x, b.x), max(a.y, b.y)),
48-
Pt::new(max(a.x, b.x), max(a.y, b.y)),
49-
Pt::new(max(a.x, b.x), min(a.y, b.y)),
50-
Pt::new(min(a.x, b.x), min(a.y, b.y)),
51-
];
52-
corners
53-
.iter()
54-
.tuple_windows()
55-
.all(|(&a, &b)| safe_line(a, b))
28+
let safe_rectangle = |a, b| {
29+
rectangle_points(a, b).all(|p| !red_zone.contains(&p))
5630
};
5731

5832
red_tiles
@@ -66,38 +40,54 @@ pub fn part_2() -> i64 {
6640
.unwrap()
6741
}
6842

69-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
70-
enum PathStep {
71-
Corner,
72-
LeftRight,
73-
TopDown,
74-
}
75-
76-
impl PathStep {
77-
fn for_pair(a: Pt, b: Pt) -> Self {
78-
if (a.x - b.x).abs().signum() != 0 {
79-
Self::LeftRight
80-
} else {
81-
Self::TopDown
82-
}
83-
}
84-
}
85-
86-
fn build_path(red_tiles: &[Pt]) -> HashMap<Pt, PathStep> {
87-
red_tiles
43+
fn build_red_zone(red_tiles: &[Pt]) -> HashSet<Pt> {
44+
let path_tiles: HashSet<_> = red_tiles
8845
.iter()
8946
.copied()
9047
.chain(once(red_tiles[0]))
9148
.tuple_windows()
9249
.flat_map(|(a, b)| {
93-
let step = PathStep::for_pair(a, b);
9450
let displacement = Pt::new((b.x - a.x).signum(), (b.y - a.y).signum());
95-
successors(Some((a, PathStep::Corner)), move |&(p, _)| {
96-
(p != b).then_some((p + displacement, step))
97-
})
98-
.chain(once((b, PathStep::Corner)))
51+
successors(Some(a), move |&p| (p != b).then_some(p + displacement))
52+
.chain(once(b))
9953
})
100-
.collect()
54+
.collect();
55+
let path_tiles = &path_tiles;
56+
57+
println!("Path tiles count: {}", path_tiles.len());
58+
59+
let starting_point = red_tiles
60+
.iter()
61+
.sorted_by(|a, b| a.x.cmp(&b.x).then(a.y.cmp(&b.y)))
62+
.copied()
63+
.next()
64+
.unwrap();
65+
66+
println!("Starting point: {starting_point}");
67+
68+
let starting_turtle = Turtle::new(starting_point, Direction4::Right);
69+
let turtle_path = successors(Some((starting_turtle, 0usize)), move |&(t, i)| {
70+
if t == starting_turtle && i != 0 {
71+
return None;
72+
}
73+
Some([t, t.turn_left(), t.turn_right()]
74+
.iter()
75+
.map(|next| (next.advance(), i + 1))
76+
.find(|(next, _)| path_tiles.contains(&next.position))
77+
.unwrap())
78+
});
79+
80+
let red_zone: HashSet<_> = turtle_path
81+
.map(|(turtle, _)| turtle.turn_left().advance())
82+
.filter(|turtle| !path_tiles.contains(&turtle.position))
83+
.map(|turtle| turtle.position)
84+
.collect();
85+
86+
if !red_zone.is_empty() {
87+
println!("Red zone tiles count: {}", red_zone.len());
88+
}
89+
90+
red_zone
10191
}
10292

10393
fn input() -> Vec<Pt> {

0 commit comments

Comments
 (0)