Skip to content

Commit 53a1249

Browse files
committed
1 parent e59483d commit 53a1249

File tree

2 files changed

+219
-0
lines changed

2 files changed

+219
-0
lines changed

packages/solver-r/src/grid.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@ impl<T: Copy> Grid<T> {
181181
}
182182
}
183183

184+
impl Grid<Color> {
185+
pub fn is_walkable(&self, walkable: Color, p: &Point) -> bool {
186+
!self.is_inside(p) || self.get(p) <= walkable
187+
}
188+
}
189+
184190
#[test]
185191
fn it_should_sort_cell() {
186192
assert_eq!(Color::Empty < Color::Color1, true);

packages/solver-r/src/pocket.rs

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
use crate::grid::{add, Color, Grid, Point, DIRECTIONS};
2+
use std::collections::{HashMap, HashSet};
3+
4+
pub fn get_pocket_size(color_grid: &Grid<Color>, walkable: Color, p: &Point) -> usize {
5+
let mut filled: HashSet<Point> = HashSet::new();
6+
let mut open_list: Vec<Point> = Vec::new();
7+
open_list.push(*p);
8+
9+
while let Some(p) = open_list.pop() {
10+
if filled.contains(&p) {
11+
continue;
12+
}
13+
if !color_grid.is_inside(&p) {
14+
return usize::MAX;
15+
}
16+
if !(color_grid.get(&p) <= walkable) {
17+
continue;
18+
}
19+
20+
let reachable: bool = 'outer: {
21+
let mut open_list: Vec<Point> = Vec::new();
22+
let mut close_list: HashSet<Point> = HashSet::new();
23+
let mut color: HashMap<Point, i8> = HashMap::new();
24+
25+
for (i, dir) in DIRECTIONS.iter().enumerate() {
26+
let q = add(&p, &dir);
27+
if color_grid.is_walkable(walkable, &q) {
28+
color.insert(q, i as i8);
29+
open_list.push(q);
30+
}
31+
}
32+
33+
while let Some(u) = open_list.pop() {
34+
if close_list.contains(&u) {
35+
continue;
36+
}
37+
38+
let i = *color.get(&u).unwrap();
39+
40+
for dir in DIRECTIONS {
41+
let q = add(&u, &dir);
42+
43+
if q == p {
44+
continue;
45+
}
46+
47+
if color.get(&q).is_some_and(|j| *j != i) {
48+
break 'outer true;
49+
}
50+
51+
if !close_list.contains(&q)
52+
&& color_grid.is_walkable(walkable, &q)
53+
&& color_grid.is_inside_margin(&q, 1)
54+
{
55+
open_list.push(q);
56+
color.insert(q, i);
57+
}
58+
}
59+
60+
close_list.insert(u);
61+
}
62+
63+
false
64+
};
65+
66+
if reachable {
67+
filled.insert(p);
68+
for dir in DIRECTIONS {
69+
let q = add(&p, &dir);
70+
open_list.push(q);
71+
}
72+
}
73+
}
74+
75+
filled.len()
76+
}
77+
78+
#[test]
79+
fn it_should_compute_pocket_size_round_small_hole() {
80+
let color_grid = Grid::<Color>::from(
81+
r#"
82+
_#### _
83+
# #
84+
# #
85+
####
86+
"#,
87+
);
88+
89+
assert_eq!(
90+
get_pocket_size(&color_grid, Color::Color1, &Point { x: 3, y: 1 }),
91+
4
92+
);
93+
}
94+
95+
#[test]
96+
fn it_should_compute_pocket_size_round_hole() {
97+
let color_grid = Grid::<Color>::from(
98+
r#"
99+
_##### _
100+
#....#
101+
#....#
102+
#####
103+
"#,
104+
);
105+
106+
assert_eq!(
107+
get_pocket_size(&color_grid, Color::Color1, &Point { x: 3, y: 1 }),
108+
8
109+
);
110+
}
111+
112+
#[test]
113+
fn it_should_compute_pocket_size_open() {
114+
let color_grid = Grid::<Color>::from(
115+
r#"
116+
_#####...
117+
#.......
118+
#.......
119+
########
120+
"#,
121+
);
122+
123+
assert!(get_pocket_size(&color_grid, Color::Color1, &Point { x: 3, y: 1 }) > 100);
124+
}
125+
126+
#[test]
127+
fn it_should_compute_pocket_size_loop() {
128+
let color_grid = Grid::<Color>::from(
129+
r#"
130+
###### _
131+
#....#
132+
#.##.#
133+
#....#
134+
######
135+
"#,
136+
);
137+
138+
assert_eq!(
139+
get_pocket_size(&color_grid, Color::Color1, &Point { x: 3, y: 1 }),
140+
10
141+
);
142+
}
143+
144+
#[test]
145+
fn it_should_compute_pocket_size_dead_end() {
146+
let color_grid = Grid::<Color>::from(
147+
r#"
148+
###########
149+
## #######
150+
## ######
151+
###########
152+
"#,
153+
);
154+
155+
assert_eq!(
156+
get_pocket_size(&color_grid, Color::Color1, &Point { x: 3, y: 1 }),
157+
4
158+
);
159+
}
160+
161+
#[test]
162+
fn it_should_compute_pocket_size_dead_end_2() {
163+
let color_grid = Grid::<Color>::from(
164+
r#"
165+
###########
166+
##....#####
167+
##.......##
168+
###########
169+
"#,
170+
);
171+
172+
assert_eq!(
173+
get_pocket_size(&color_grid, Color::Color1, &Point { x: 3, y: 1 }),
174+
8
175+
);
176+
}
177+
178+
#[test]
179+
fn it_should_compute_pocket_size_dead_end_3() {
180+
let color_grid = Grid::<Color>::from(
181+
r#"
182+
###########
183+
## #######
184+
##
185+
###########
186+
"#,
187+
);
188+
189+
assert_eq!(
190+
get_pocket_size(&color_grid, Color::Color1, &Point { x: 3, y: 1 }),
191+
4
192+
);
193+
}
194+
195+
#[test]
196+
fn it_should_compute_pocket_size_dead_end_4() {
197+
let color_grid = Grid::<Color>::from(
198+
r#"
199+
#########
200+
##....###
201+
##.....##
202+
##.....##
203+
#.....###
204+
###..####
205+
#########
206+
"#,
207+
);
208+
209+
assert_eq!(
210+
get_pocket_size(&color_grid, Color::Color1, &Point { x: 3, y: 1 }),
211+
20
212+
);
213+
}

0 commit comments

Comments
 (0)