AtCoder Beginner Contest 258 B(2)

https://atcoder.jp/contests/abc258/tasks/abc258_b

全てのマスから全ての方向を計算して、そこまでのうち最大のものだけ残して、その方向に1歩進めるというのを繰り返します。
あまりうまくIteratorが使えずに、結局collectしてVecにしています。

// Number Box
#![allow(non_snake_case)]

use std::ops::Add;
use std::ops::Mul;


//////////////////// library ////////////////////

fn read<T: std::str::FromStr>() -> T {
    let mut line = String::new();
    std::io::stdin().read_line(&mut line).ok();
    line.trim().parse().ok().unwrap()
}

fn read_matrix() -> Vec<Vec<i32>> {
    fn read_row() -> Vec<i32> {
        read::<String>().chars().map(|c| (c as i32) - 48).collect()
    }
    
    let N: i32 = read();
    (0..N).map(|_| read_row()).collect()
}

fn modulo(n: i32, d: i32) -> i32 {
    let r = n % d;
    if r >= 0 {
        r
    }
    else {
        r + d
    }
}


//////////////////// Point ////////////////////

#[derive(Clone, Copy)]
struct Point {
    x: i32,
    y: i32,
}

impl Add for Point {
    type Output = Self;
    
    fn add(self, other: Self) -> Self {
        Self { x: self.x + other.x, y: self.y + other.y }
    }
}

impl Mul<i32> for Point {
    type Output = Self;
    
    fn mul(self, c: i32) -> Self {
        Self { x: self.x * c, y: self.y * c }
    }
}


//////////////////// Box ////////////////////

struct Box {
    A: Vec<Vec<i32>>
}

impl Box {
    fn value(&self, pt: Point) -> i64 {
        let pt2 = self.mod_point(pt);
        self.A[pt2.x as usize][pt2.y as usize] as i64
    }
    
    fn mod_point(&self, pt: Point) -> Point {
        let d = self.A.len() as i32;
        Point { x: modulo(pt.x, d), y: modulo(pt.y, d) }
    }
    
    fn make_dirs() -> Vec<Point> {
        (0..9).filter(|&i| i != 4).
        map(|i| Point { x: i/3-1, y: i%3-1 }).collect()
    }
}


//////////////////// ValueSet ////////////////////

#[derive(Clone, Copy)]
struct ValueSet {
    pt0: Point,
    dir: Point,
    i: i32,
    n: i64
}

impl ValueSet {
    fn next(&self, b: &Box) -> ValueSet {
        let pt = self.next_point();
        let i = self.i + 1;
        let n = 10 * self.n + b.value(pt);
        ValueSet { pt0: self.pt0, dir: self.dir, i, n }
    }
    
    fn next_point(&self) -> Point {
        self.pt0 + self.dir * (self.i + 1)
    }
    
    fn create(i: usize, dirs: &Vec<Point>, N: usize) -> ValueSet {
        let M = N as i32;
        let L = dirs.len();
        let r = i % L;
        let q = (i / L) as i32;
        let pt = Point { x: q / M, y: q % M };
        ValueSet { pt0: pt, dir: dirs[r], i: -1, n: 0 }
    }
}


//////////////////// process ////////////////////

fn max_elements(w: &Vec<ValueSet>) -> Vec<ValueSet> {
    let mut v = Vec::<ValueSet>::new();
    if w.len() == 0 {
        return v
    }
    
    v.push(w[0]);
    for i in 1..w.len() {
        let e = w[i];
        if e.n > v[0].n {
            v.clear();
            v.push(e)
        }
        else if e.n == v[0].n {
            v.push(e)
        }
    }
    
    return v
}

fn main() {
    let A = read_matrix();
    let N = A.len();
    let b = Box { A };
    let dirs = Box::make_dirs();
    
    let mut v: Vec<ValueSet> = (0..(N*N*8)).
                                map(|i| ValueSet::create(i, &dirs, N)).
                                collect();
    for _ in 0..N {
        let w = max_elements(&v);
        v = w.iter().map(|&s| s.next(&b)).collect();
    }
    
    match v.iter().next() {
        Some(x) => println!("{}", x.n),
        None    => ()
    }
}