rustgym 0.2.0

rustgym solutions
Documentation
struct Solution;

#[derive(Debug, PartialEq, Eq, Hash, Default)]
struct Point {
    x: i32,
    y: i32,
}

impl Point {
    fn new(x: i32, y: i32) -> Self {
        Point { x, y }
    }
    fn from(v: Vec<i32>) -> Self {
        Point { x: v[0], y: v[1] }
    }
    fn square_distance(&self) -> i32 {
        self.x * self.x + self.y * self.y
    }
}

#[derive(Default)]
struct Robot {
    position: Point,
    direction: usize,
}

impl Robot {
    fn new() -> Self {
        Robot {
            position: Point { x: 0, y: 0 },
            direction: 0,
        }
    }
    fn left(&mut self) {
        self.direction = (self.direction + 1) % 4;
    }
    fn right(&mut self) {
        self.direction = (self.direction + 3) % 4;
    }
    fn next(&self) -> Point {
        let x = self.position.x;
        let y = self.position.y;
        match self.direction {
            0 => Point::new(x, y + 1),
            1 => Point::new(x - 1, y),
            2 => Point::new(x, y - 1),
            3 => Point::new(x + 1, y),
            _ => unreachable!(),
        }
    }
    fn walk(&mut self, step: usize, grid: &Grid) {
        let mut i = 0;
        while i < step && !grid.obstacles.contains(&self.next()) {
            self.position = self.next();
            i += 1;
        }
    }
}

use std::collections::HashSet;

struct Grid {
    obstacles: HashSet<Point>,
}

impl Grid {
    fn new(obstacles: Vec<Point>) -> Self {
        let mut hs: HashSet<Point> = HashSet::new();
        for x in obstacles {
            hs.insert(x);
        }
        Grid { obstacles: hs }
    }
}

impl Solution {
    fn robot_sim(commands: Vec<i32>, obstacles: Vec<Vec<i32>>) -> i32 {
        let grid: Grid = Grid::new(obstacles.iter().map(|v| Point::new(v[0], v[1])).collect());
        let mut robot = Robot::new();
        let mut max = 0;
        for command in commands {
            match command {
                -2 => robot.left(),
                -1 => robot.right(),
                _ => {
                    robot.walk(command as usize, &grid);
                    max = i32::max(robot.position.square_distance(), max);
                }
            }
        }
        max as i32
    }
}

#[test]
fn test() {
    let commands: Vec<i32> = vec![4, -1, 3];
    let obstacles: Vec<Vec<i32>> = vec![];
    assert_eq!(Solution::robot_sim(commands, obstacles), 25);
    let commands: Vec<i32> = vec![4, -1, 4, -2, 4];
    let obstacles: Vec<Vec<i32>> = vec![vec![2, 4]];
    assert_eq!(Solution::robot_sim(commands, obstacles), 65);
}