use std::io::{self, Read}; use std::collections::HashSet; fn main() { let mut buffer = String::new(); io::stdin().read_to_string(&mut buffer).unwrap(); let (end, real) = follow_instructions(&buffer); if let Some((x, y)) = end { println!("end position: x={}, y={}", x, y); } if let Some((x, y)) = real { println!("real position: x={}, y={}", x, y); } } fn follow_instructions(input: &str) -> (Option<(i32, i32)>, Option<(i32, i32)>) { let instructions = input .split(",") .map(|x| x.trim()) .map(|x| x.split_at(1)) .map(|(x, y)| (x, y.parse::().unwrap())); let mut x = 0; let mut y = 0; let mut delta = (0, 1); let mut visited = HashSet::new(); let mut position: Option<(i32, i32)> = None; for (direction, steps) in instructions { delta = match direction { "R" => (delta.1, delta.0 * -1), "L" => (delta.1 * -1, delta.0), _ => delta, }; for _ in 0..steps { x += delta.0; y += delta.1; if position.is_none() { if visited.contains(&(x, y)) { position = Some((x, y)); } else { visited.insert((x, y)); } } } } (Some((x, y)), position) } #[cfg(test)] mod tests { use super::follow_instructions; #[test] fn example_01() { let input = "R2, L3"; assert_eq!((Some((2, 3)), None), follow_instructions(input)); } #[test] fn example_02() { let input = "R2, R2, R2"; assert_eq!((Some((0, -2)), None), follow_instructions(input)); } #[test] fn example_03() { let input = "R5, L5, R5, R3"; assert_eq!((Some((10, 2)), None), follow_instructions(input)); } #[test] fn example_04() { let input = "R8, R4, R4, R8"; assert_eq!((Some((4, 4)), Some((4, 0))), follow_instructions(input)); } }