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() }