fn main() { println!("Hello, world!"); } pub const DEBUG : bool = true; pub struct Trail { waypoints: Vec, directions: Vec, } impl Trail { pub fn new() -> Trail { Trail { waypoints: Vec::new(), directions: Vec::new(), } } pub fn start(&mut self, way: String) -> DistArea { if !way.is_empty() { let mut da = DistArea{dist: 0, area: 0, size: 0}; let split = way.split_whitespace(); let mut plan : Vec = Vec::new(); for s in split { plan.push(String::from(s)); } let steps = match plan.remove(0).parse::() { Err(_) => 0, Ok(i) => i, }; self.directions.push(Direction::North); self.waypoints.push(Point{x: 0, y: 0}); da.dist = self.walk(plan, steps); let mut min = Point{x: 0, y: 0}; let mut max = Point{x: 0, y: 0}; for i in &self.waypoints { if i.x < min.x { min.x = i.x; } if i.y < min.y { min.y = i.y; } if i.x > max.x { max.x = i.x; } if i.y > max.y { max.y = i.y; } } da.area = (max.x - min.x) * (max.y - min.y); da } else { DistArea{dist:0, area:0, size:0} } } fn walk(&mut self, mut plan: Vec, steps: i32) -> i32 { if steps == 0 { 0 } else { let mut stepcount = 0; let part = plan.remove(0); let count = match plan.remove(0).parse::() { Err(_) => 0, Ok(i) => i, }; let mut dir = self.directions.last().unwrap().clone(); let mut pos = self.waypoints.last().unwrap().clone(); for _i in 0 .. count { for c in part.chars() { match c { 'F' => { pos.add(dir, 1); if DEBUG { println!("F, pos: x={} y={}, dir: {:?}", pos.x, pos.y, dir); } stepcount += 1; }, 'L' => { dir = Direction::turn_left(dir); if DEBUG { print!("L"); } }, 'R' => { dir = Direction::turn_right(dir); if DEBUG { print!("R"); } }, _ => (), } self.directions.push(dir); self.waypoints.push(pos); } } stepcount += self.walk(plan, steps - 1); stepcount } } } #[derive(Copy, Clone, Debug)] pub enum Direction { North, East, South, West, } impl Direction { pub fn turn_right(dir: Direction) -> Direction { match dir { Direction::North => Direction::East, Direction::East => Direction::South, Direction::South => Direction::West, Direction::West => Direction::North, } } pub fn turn_left(dir: Direction) -> Direction { match dir { Direction::North => Direction::West, Direction::East => Direction::North, Direction::South => Direction::East, Direction::West => Direction::South, } } } #[derive(Copy, Clone, Debug)] pub struct Point { x: i32, y: i32, } impl Point { pub fn add(&mut self, dir: Direction, len: i32) { match dir { Direction::North => self.y += len, Direction::East => self.x += len, Direction::South => self.y -= len, Direction::West => self.x -= len, }; } } #[derive(Copy, Clone, Debug)] pub struct DistArea { pub dist: i32, pub area: i32, pub size: i32, } impl PartialEq for DistArea { fn eq(&self, other: &DistArea) -> bool { let mut res = self.dist == other.dist; res &= self.area == other.area; res &= self.size == other.size; res } } impl Eq for DistArea {} #[cfg(test)] mod tests { use super::*; #[test] fn level1_1() { let input = String::from("1 FFFR 4"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.dist, 12); } #[test] fn level1_2() { let input = String::from("9 F 6 R 1 F 4 RFF 2 LFF 1 LFFFR 1 F 2 R 1 F 5"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.dist, 26); } #[test] fn level1_3() { let input = String::from("14 L 1 FR 1 FFFFFL 1 FFFFL 1 F 12 L 1 F 12 L 1 F 12 L 1 FFFFL 1 FFFFFFFFR 1 FFFR 1 FFFL 1"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.dist, 64); } #[test] fn level1_4() { let input = String::from("32 FFRFLFLFFRFRFLFF 3 R 1 FFLFRFRFLFFF 3 R 1 FFFFFF 3 L 1 FFFRFLFLFRFF 2 R 1 FFFRFLFLFRFF 3 R 1 FFFFFF 1 L 1 FFRFLFLFFRFRFLFF 3 R 1 FFLFRFRFFLFLFRFF 2 L 1 FFLFRFRFFLFLFRFF 3 R 1 FFRFLFLFFRFRFLFF 2 R 1 FFRFLFLFFRFRFLFF 2 L 1 FFFFFF 3 R 1 FFFRFLFLFRFF 5 R 1 FFLFRFRFLFFF 1 L 1 FFLFRFRFFLFLFRFF 2 R 1 FFRFLFLFFRFRFLFF 2 L 1"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.dist, 344); } #[test] fn level1_5() { let input = String::from("10 FFLFRFRFFLFLFRFF 5 L 1 FFFRFLFLFRFF 4 L 1 FFLFRFRFFLFLFRFF 8 L 1 FFLFRFRFFLFLFRFF 4 L 1 FFFFFF 3 R 1"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.dist, 220); } #[test] fn level2_1() { let input = String::from("1 FFFR 4"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.area, 9); } #[test] fn level2_2() { let input = String::from("9 F 6 R 1 F 4 RFF 2 LFF 1 LFFFR 1 F 2 R 1 F 5"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.area, 30); } #[test] fn level2_3() { let input = String::from("14 L 1 FR 1 FFFFFL 1 FFFFL 1 F 12 L 1 F 12 L 1 F 12 L 1 FFFFL 1 FFFFFFFFR 1 FFFR 1 FFFL 1"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.area, 144); } #[test] fn level2_4() { let input = String::from("32 FFRFLFLFFRFRFLFF 3 R 1 FFLFRFRFLFFF 3 R 1 FFFFFF 3 L 1 FFFRFLFLFRFF 2 R 1 FFFRFLFLFRFF 3 R 1 FFFFFF 1 L 1 FFRFLFLFFRFRFLFF 3 R 1 FFLFRFRFFLFLFRFF 2 L 1 FFLFRFRFFLFLFRFF 3 R 1 FFRFLFLFFRFRFLFF 2 R 1 FFRFLFLFFRFRFLFF 2 L 1 FFFFFF 3 R 1 FFFRFLFLFRFF 5 R 1 FFLFRFRFLFFF 1 L 1 FFLFRFRFFLFLFRFF 2 R 1 FFRFLFLFFRFRFLFF 2 L 1"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.area, 3552); } #[test] fn level2_5() { let input = String::from("10 FFLFRFRFFLFLFRFF 5 L 1 FFFRFLFLFRFF 4 L 1 FFLFRFRFFLFLFRFF 8 L 1 FFLFRFRFFLFLFRFF 4 L 1 FFFFFF 3 R 1"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.area, 1300); } #[test] fn level3_1() { let input = String::from("1 FFFR 4"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.size, 12); } #[test] fn level3_2() { let input = String::from("9 F 6 R 1 F 4 RFF 2 LFF 1 LFFFR 1 F 2 R 1 F 5"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.size, 12); } #[test] fn level3_3() { let input = String::from("14 L 1 FR 1 FFFFFL 1 FFFFL 1 F 12 L 1 F 12 L 1 F 12 L 1 FFFFL 1 FFFFFFFFR 1 FFFR 1 FFFL 1"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.size, 12); } #[test] fn level3_4() { let input = String::from("32 FFRFLFLFFRFRFLFF 3 R 1 FFLFRFRFLFFF 3 R 1 FFFFFF 3 L 1 FFFRFLFLFRFF 2 R 1 FFFRFLFLFRFF 3 R 1 FFFFFF 1 L 1 FFRFLFLFFRFRFLFF 3 R 1 FFLFRFRFFLFLFRFF 2 L 1 FFLFRFRFFLFLFRFF 3 R 1 FFRFLFLFFRFRFLFF 2 R 1 FFRFLFLFFRFRFLFF 2 L 1 FFFFFF 3 R 1 FFFRFLFLFRFF 5 R 1 FFLFRFRFLFFF 1 L 1 FFLFRFRFFLFLFRFF 2 R 1 FFRFLFLFFRFRFLFF 2 L 1"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.size, 12); } #[test] fn level3_5() { let input = String::from("10 FFLFRFRFFLFLFRFF 5 L 1 FFFRFLFLFRFF 4 L 1 FFLFRFRFFLFLFRFF 8 L 1 FFLFRFRFFLFLFRFF 4 L 1 FFFFFF 3 R 1"); let mut trail = Trail::new(); let mut res = trail.start(input); assert_eq!(res.size, 12); } }