Skip to content

Commit 5ea5ed1

Browse files
committed
to ascii
1 parent 8d818a6 commit 5ea5ed1

File tree

6 files changed

+314
-69
lines changed

6 files changed

+314
-69
lines changed

packages/solver-r/src/_test_grid_samples.rs

Lines changed: 11 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,7 @@ use wasm_bindgen::prelude::wasm_bindgen;
22

33
use crate::grid::{Color, Grid, Point};
44

5-
fn grid_from_ascii(ascii: &str) -> Grid<Color> {
6-
let rows: Vec<_> = ascii.trim().split('\n').collect();
7-
8-
let width = rows.iter().fold(0, |max_len, r| max_len.max(r.len()));
9-
let height = rows.len();
10-
11-
let mut grid = Grid::<Color>::create(width as u8, height as u8);
12-
13-
for x in 0..width {
14-
for y in 0..height {
15-
let c = rows[y].chars().nth(x).unwrap_or(' ');
16-
let cell = match c {
17-
' ' => Color::Empty,
18-
'_' => Color::Empty,
19-
'1' => Color::Color1,
20-
'2' => Color::Color2,
21-
'3' => Color::Color3,
22-
'4' => Color::Color4,
23-
24-
'.' => Color::Color1,
25-
'o' => Color::Color2,
26-
'O' => Color::Color3,
27-
'#' => Color::Color4,
28-
_ => panic!("unknow char \"{}\"", c),
29-
};
30-
grid.set(
31-
&Point {
32-
x: x as i8,
33-
y: y as i8,
34-
},
35-
cell,
36-
);
37-
}
38-
}
39-
40-
grid
41-
}
42-
43-
fn randomly_fill_grid(grid: &mut Grid<Color>, probability: &[Color], seed: u32) -> () {
5+
fn randomly_fill_grid<T: Copy + Default>(grid: &mut Grid<T>, probability: &[T], seed: u32) -> () {
446
// Pseudorandom number generator from the "Xorshift RNGs" paper by George Marsaglia.
457
// https://github.com/rust-lang/rust/blob/1.55.0/library/core/src/slice/sort.rs#L559-L573
468
fn random_numbers(seed: u32) -> impl Iterator<Item = u32> {
@@ -58,8 +20,8 @@ fn randomly_fill_grid(grid: &mut Grid<Color>, probability: &[Color], seed: u32)
5820
for x in 0..(grid.width as i8) {
5921
for y in 0..(grid.height as i8) {
6022
let random = rng.next().unwrap();
61-
let cell = probability[random as usize % probability.len()];
62-
grid.set(&Point { x, y }, cell);
23+
let value: T = probability[random as usize % probability.len()];
24+
grid.set(&Point { x, y }, value);
6325
}
6426
}
6527
}
@@ -74,17 +36,17 @@ pub enum SampleGrid {
7436
}
7537
pub fn get_grid_sample(g: SampleGrid) -> Grid<Color> {
7638
match g {
77-
SampleGrid::Empty => grid_from_ascii(
78-
&r#"
39+
SampleGrid::Empty => Grid::<_>::from(
40+
r#"
7941
_
8042
_
8143
_
8244
_
8345
"#,
8446
),
8547

86-
SampleGrid::OneDot => grid_from_ascii(
87-
&r#"
48+
SampleGrid::OneDot => Grid::<_>::from(
49+
r#"
8850
_
8951
_
9052
. _
@@ -93,8 +55,8 @@ pub fn get_grid_sample(g: SampleGrid) -> Grid<Color> {
9355
"#,
9456
),
9557

96-
SampleGrid::Realistic => grid_from_ascii(
97-
&r#"
58+
SampleGrid::Realistic => Grid::<_>::from(
59+
r#"
9860
231 412 12213 13 213 421 121131 32123112 332 _
9961
412 12 4 331213 12214431 412 413 42133123 23 21
10062
123 2143 21211 2423 213 123 1233123432 223331233_
@@ -105,8 +67,8 @@ pub fn get_grid_sample(g: SampleGrid) -> Grid<Color> {
10567
"#,
10668
),
10769

108-
SampleGrid::Labyrinthe => grid_from_ascii(
109-
&r#"
70+
SampleGrid::Labyrinthe => Grid::<_>::from(
71+
r#"
11072
################################################## #
11173
# #
11274
# ##################################################

packages/solver-r/src/astar_snake.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ impl PartialOrd for Node {
2626
}
2727

2828
pub fn get_snake_path<F>(
29-
mut walkable: F,
29+
walkable: F,
3030
snake: &[Point],
3131
end: &Point,
3232
max_weight: usize,
3333
) -> Option<Vec<Point>>
3434
where
35-
F: FnMut(&Point) -> bool,
35+
F: Fn(&Point) -> bool,
3636
{
3737
let snake_length = snake.len();
3838

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,38 @@
1-
use crate::grid::{Color, Grid};
1+
use std::u32;
22

3-
pub fn get_exit_cost_grid(color_grid: &Grid<Color>) -> Grid<u8> {
4-
let mut exit_cost_grid = Grid::<u8>::create(color_grid.width, color_grid.height);
3+
use crate::grid::{iter_neighbour4, Color, Grid};
4+
5+
pub fn get_exit_cost_grid(color_grid: &Grid<Color>) -> Grid<u32> {
6+
let mut exit_cost_grid = Grid::<u32>::create(color_grid.width, color_grid.height);
7+
exit_cost_grid.fill(u32::MAX);
8+
9+
let mut open_list = color_grid.iter_hull().collect::<Vec<_>>();
10+
11+
while let Some(p) = open_list.pop() {
12+
let neighbour_cost_min = iter_neighbour4(&p)
13+
.map(|u| {
14+
if !color_grid.is_inside(&u) {
15+
0
16+
} else {
17+
exit_cost_grid.get(&u)
18+
}
19+
})
20+
.min()
21+
.unwrap();
22+
let self_cost = (10 as u32).pow(color_grid.get(&p) as u32);
23+
24+
let cost = neighbour_cost_min + self_cost;
25+
26+
if exit_cost_grid.get(&p) != cost {
27+
exit_cost_grid.set(&p, cost);
28+
29+
open_list.append(
30+
&mut iter_neighbour4(&p)
31+
.filter(|u| color_grid.is_inside(u))
32+
.collect(),
33+
);
34+
}
35+
}
536

637
exit_cost_grid
738
}

packages/solver-r/src/grid.rs

Lines changed: 110 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use std::collections::HashSet;
22

3+
use crate::grid_ascii::{grid_from_ascii, grid_to_ascii};
4+
35
pub const DIRECTION_RIGHT: Point = Point { x: 1, y: 0 };
46
pub const DIRECTION_LEFT: Point = Point { x: -1, y: 0 };
57
pub const DIRECTION_UP: Point = Point { x: 0, y: 1 };
@@ -16,6 +18,26 @@ pub struct Point {
1618
pub x: i8,
1719
pub y: i8,
1820
}
21+
pub fn iter_neighbour4(p: &Point) -> impl Iterator<Item = Point> {
22+
let mut i: usize = 0;
23+
let px = p.x;
24+
let py = p.y;
25+
std::iter::from_fn(move || {
26+
let out = DIRECTIONS.get(i).map(|dir| Point {
27+
x: px + dir.x,
28+
y: py + dir.y,
29+
});
30+
31+
i += 1;
32+
out
33+
})
34+
}
35+
pub fn add(a: &Point, b: &Point) -> Point {
36+
Point {
37+
x: a.x + b.x,
38+
y: a.y + b.y,
39+
}
40+
}
1941
pub fn get_distance(a: &Point, b: &Point) -> u8 {
2042
(a.x - b.x).abs() as u8 + (a.y - b.y).abs() as u8
2143
}
@@ -29,38 +51,26 @@ pub enum Color {
2951
Color3 = 3,
3052
Color4 = 4,
3153
}
32-
3354
impl Default for Color {
3455
fn default() -> Self {
3556
Color::Empty
3657
}
3758
}
3859

39-
#[derive(Clone)]
60+
#[derive(Clone, Debug, PartialEq)]
4061
pub struct Grid<T: Copy> {
4162
pub width: u8,
4263
pub height: u8,
4364
pub cells: Vec<T>,
4465
}
45-
impl<T: Copy + Default> Grid<T> {
46-
pub fn create(width: u8, height: u8) -> Grid<T> {
47-
let n = (width as usize) * (height as usize);
48-
let cells = (0..n).map(|_| T::default()).collect();
49-
50-
Grid {
51-
width,
52-
height,
53-
cells,
54-
}
55-
}
56-
66+
impl<T: Copy> Grid<T> {
5767
fn get_index(&self, x: i8, y: i8) -> usize {
5868
return (x as usize) * (self.height as usize) + (y as usize);
5969
}
6070

6171
pub fn fill(&mut self, value: T) -> () {
6272
let n = (self.width as usize) * (self.height as usize);
63-
for i in (0..n) {
73+
for i in 0..n {
6474
self.cells[i] = value;
6575
}
6676
}
@@ -97,6 +107,69 @@ impl<T: Copy + Default> Grid<T> {
97107
}
98108
})
99109
}
110+
pub fn iter_hull(&self) -> impl Iterator<Item = Point> {
111+
let mut i: usize = 0;
112+
let width = self.width as usize;
113+
let height = self.height as usize;
114+
std::iter::from_fn(move || {
115+
let mut p = Point { x: 0, y: 0 };
116+
117+
let mut k = i;
118+
119+
if k < width {
120+
p.x = k as i8;
121+
p.y = 0;
122+
} else {
123+
k -= width;
124+
if k < width {
125+
p.x = k as i8;
126+
p.y = (height - 1) as i8;
127+
} else {
128+
k -= width;
129+
if k < height {
130+
p.x = 0;
131+
p.y = k as i8;
132+
} else {
133+
k -= height;
134+
if k < height {
135+
p.x = (width - 1) as i8;
136+
p.y = k as i8;
137+
} else {
138+
return None;
139+
}
140+
}
141+
}
142+
}
143+
144+
i += 1;
145+
146+
Some(p)
147+
})
148+
}
149+
}
150+
impl<T: Default + Copy> Grid<T> {
151+
pub fn create(width: u8, height: u8) -> Grid<T> {
152+
let n = (width as usize) * (height as usize);
153+
let cells = (0..n).map(|_| T::default()).collect();
154+
155+
Grid {
156+
width,
157+
height,
158+
cells,
159+
}
160+
}
161+
}
162+
impl<T: Copy> Grid<T> {
163+
pub fn create_with(width: u8, height: u8, item: T) -> Grid<T> {
164+
let n = (width as usize) * (height as usize);
165+
let cells = (0..n).map(|_| item).collect();
166+
167+
Grid {
168+
width,
169+
height,
170+
cells,
171+
}
172+
}
100173
}
101174

102175
#[test]
@@ -136,3 +209,25 @@ fn it_should_iterate() {
136209
])
137210
);
138211
}
212+
#[test]
213+
fn it_should_iterate_hull() {
214+
let grid = Grid::<Color>::create(3, 3);
215+
216+
assert_eq!(
217+
grid.iter_hull().collect::<HashSet<_>>(),
218+
HashSet::from([
219+
Point { x: 0, y: 0 },
220+
Point { x: 0, y: 1 },
221+
Point { x: 0, y: 2 },
222+
Point { x: 2, y: 0 },
223+
Point { x: 2, y: 1 },
224+
Point { x: 2, y: 2 },
225+
Point { y: 0, x: 0 },
226+
Point { y: 0, x: 1 },
227+
Point { y: 0, x: 2 },
228+
Point { y: 2, x: 0 },
229+
Point { y: 2, x: 1 },
230+
Point { y: 2, x: 2 },
231+
])
232+
);
233+
}

0 commit comments

Comments
 (0)