use std::collections::HashSet; fn parse(input: &str) -> Vec<(i64, i64)> { input .lines() .map(|s| { let (y, x) = s.split_once(',').unwrap(); (x.parse().unwrap(), y.parse().unwrap()) }) .collect() } fn solve_1(input: &str, steps: usize, range: i64) -> Option { let memory = parse(input); let memory: HashSet<_> = memory[..steps].into_iter().collect(); let mut visited: HashSet<(i64, i64)> = HashSet::new(); let mut path_length = 0; let mut stack: HashSet<_> = [(0, 0)].into_iter().collect(); let dirs = [(1, 0), (-1, 0), (0, 1), (0, -1)]; loop { path_length += 1; let mut new_stack = HashSet::new(); if stack.is_empty() { return None; } for pos in stack { if pos == (range, range) { return Some(path_length - 1); } visited.insert(pos); for dir in dirs { let new_pos = (pos.0 + dir.0, pos.1 + dir.1); if new_pos.0 >= 0 && new_pos.0 <= range && new_pos.1 >= 0 && new_pos.1 <= range { if !visited.contains(&new_pos) && !memory.contains(&new_pos) { new_stack.insert(new_pos); } } } } stack = new_stack; } } fn solve_2(input: &str, range: i64) -> (i64, i64) { let memory = parse(input); for i in 0..memory.len() { if solve_1(input, i, range).is_none() { return memory[i - 1]; } } return (0, 0); } fn main() { println!("Hello, this is Patrick!"); let input = include_str!("../input.txt"); let result_1 = solve_1(input, 1024, 70); println!( "The number of steps of the shortest route from beginning to end is {}", result_1.unwrap() ); let result_2 = solve_2(input, 70); println!( "The first byte that prevents a path being laid is {},{}", result_2.1, result_2.0 ); } #[cfg(test)] mod tests { use super::*; #[test] fn test_1() { let test_input = include_str!("../test.txt"); assert_eq!(solve_1(test_input, 12, 6).unwrap(), 22); } #[test] fn test_2() { let test_input = include_str!("../test.txt"); assert_eq!(solve_2(test_input, 6), (1, 6)); } }