How to easily convert a two-dimensional array into a two-dimensional vector?
I'm focusing on rust wasm tutorial. I hope to easily add a ship (a real shape) to the universe in the game of life
As a first step, I want to convert a two-dimensional array of 0 or 1 representing shapes into an index vector representing shape coordinates in the universe
I have a working code, but I want to make it more user-friendly:
const WIDTH: u32 = 64;
const HEIGHT: u32 = 64;
/// glider: [[0,1,0],[0,1],[1,1]]
fn make_ship(shape: Vec<Vec<u32>>) -> Vec<u32> {
let mut ship: Vec<u32> = Vec::new();
for row_idx in 0..shape.len() {
for col_idx in 0..shape[row_idx].len() {
let cell = shape[row_idx][col_idx];
if cell == 1 {
ship.push(col_idx as u32 + row_idx as u32 * WIDTH);
}
}
}
ship
}
#[test]
fn glider() {
let glider = vec![vec![0,vec![0,vec![1,1]];
println!("{:?}",make_ship(glider));
}
The test showed my problem: VEC! S level of detail Ideally, I want to be able to write it without all VECs! make_ The ship code should not care about the size of the shape array Ideal example:
let glider = [[0,];
The problem is: how to express the shape well with a simple array and make the function make_ Ship uses a two-dimensional vector of any size?
Solution
Using custom macro can reduce VEC! Number of S:
#[macro_export]
macro_rules! vec2d {
($($i:expr),+) => { // handle numbers
{
let mut ret = Vec::new();
$(ret.push($i);)*
ret
}
};
([$($arr:tt),+]) => { // handle sets
{
let mut ret = Vec::new();
$(ret.push(vec!($arr));)*
ret
}
};
}
fn main() {
let glider = vec2d![[0,1]];
let glider2 = vec2d![[0,0]];
println!("{:?}",glider); // [[0,1]]
println!("{:?}",glider2); // [[0,0]]
}
With the help of rust's iterator, your initial function can also use some improvements:
fn make_ship(shape: Vec<Vec<u32>>) -> Vec<u32> {
shape
.iter()
.enumerate()
.flat_map(|(row,v)| {
v.iter().enumerate().filter_map(move |(col,x)| {
if *x == 1 {
Some(col as u32 + row as u32 * WIDTH)
} else {
None
}
})
})
.collect()
}
