rust -- print snake matrix

Serpentine Matrix

Output a serpentine matrix of any order like the following

1 2    1 2 3        01 02 03 04

4 3    8 9 4        12 13 14 05

         7 6 5        11 16 15 06

                         10 09 08 07

plan

According to the serpentine assignment order, the next point that should be assigned can be calculated through the currently assigned point coordinates (i, j).

accomplish

lib.rs

#[derive(Debug)]
pub struct Matrix {
    matrix: Vec<Vec<usize>>
}

fn get_min(list:Vec<usize>) -> usize{
    let mut min_num = list[0];
    for num in list.iter(){
        if num < &min_num{
            min_num = *num;
        }
    }
    return min_num;
}

impl Matrix {
    pub fn new(size:usize) -> Matrix{
        let mut matrix: Vec<Vec<usize>> = Vec::with_capacity(size);
        for _ in 0..size{
            let mut temp: Vec<usize> = Vec::with_capacity(size);
            for _ in 0..size {
                temp.push(0);
            }
            matrix.push(temp);
        }
        let mut snake_matrix = Matrix{
            matrix,
        };
        (&mut snake_matrix).generate(size);
        return snake_matrix;
    }

    pub fn size(&self) -> usize{
        self.matrix.len()
    }

//计算出当前所在的圈数
    fn get_loop(&self,point: &(usize,usize)) ->usize{
        get_min(vec![point.0,point.1,self.size()-point.0-1,self.size()-point.1-1])
    }

    pub fn get(&self,i:usize,j:usize) -> Result<usize,&str>{
        let size = self.matrix.len();
        if i >= size || j >= size{
            Err("the index is out of range")
        }else{
            Ok(self.matrix[i][j])
        }
    }
//当前节点赋值,并计算出下一个需要赋值的节点坐标
    fn next(&mut self,point:&mut (usize,usize),num:usize){
        let &mut(i,j) = point;
        self.matrix[i][j] = num;
        let loop_count = self.get_loop(&point);
        if j>=i && i < self.size()-loop_count-1{
            if j < self.size()-loop_count-1{
                point.1 = j+1;
            }else{
                point.0 = i+1;
            }
        }else {
            if j > loop_count{
                point.1=j-1;
            }else if i > loop_count+1{
                point.0=i-1;
            }else{
                point.1=j+1;
            }
        }

    }

    fn generate(&mut self,size:usize) {
        let last_num = size * size;
        let mut point = (0,0);
        for num in 1..last_num+1 {
            self.next(&mut point,num);
        }
    }

    fn get_list(&self,index:usize)-> &Vec<usize>{
        &self.matrix[index]
    }

    pub fn print_matrix(&self){
        for i in 0..self.size() {
            println!("{:?}",self.get_list(i));
        }
    }

}

main.rs

extern crate snakematrix;

fn main() {
    let matrix = snakematrix::Matrix::new(5);
    matrix.print_matrix();
}

ps: If you want to make an external input matrix order, you can refer to my other article (rust console integer reading )

Detailed Algorithm

~ bla bla bla ~

note

Rust needs to pay attention to reference types when comparing and pattern matching, and will not automatically dereference. The reason why the vec reference is not stored in the two-dimensional array, but directly stored in the vec, is because the Matrix class has full ownership of the two-dimensional array.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326928583&siteId=291194637