use std::fs; fn main() -> Result<(), Box> { let input = fs::read_to_string("input")?; let slope = parse_slope(&input)?; // Part 1 let encounters = count_encounters(&slope, (1, 3)); println!("{}", encounters); // Part 2 let encounters: usize = [(1, 1), (1, 3), (1, 5), (1, 7), (2, 1)] .iter() .map(|angle| count_encounters(&slope, *angle)) .product(); println!("{}", encounters); Ok(()) } fn parse_slope(input: &str) -> Result>, String> { input .lines() .map(|line| { line.chars() .map(|c| match c { '.' => Ok(0), '#' => Ok(1), other => Err(format!("Invalid slope; contains character: {}", other)), }) .collect() }) .collect() } fn count_encounters(input: &Vec>, angle: (usize, usize)) -> usize { input .iter() .enumerate() .step_by(angle.0) .map(|(i, row)| row[(i * angle.1 / angle.0) % row.len()]) .sum() } #[cfg(test)] mod tests { use super::*; use indoc::indoc; #[test] fn test_simple() -> Result<(), Box> { let example = indoc!( "..##....... #...#...#.. .#....#..#. ..#.#...#.# .#...##..#. ..#.##..... .#.#.#....# .#........# #.##...#... #...##....# .#..#...#.#" ); let parsed = parse_slope(example)?; assert_eq!(count_encounters(&parsed, (1, 3)), 7); Ok(()) } #[test] fn test_simple2() -> Result<(), Box> { let example = indoc!( "..##....... #...#...#.. .#....#..#. ..#.#...#.# .#...##..#. ..#.##..... .#.#.#....# .#........# #.##...#... #...##....# .#..#...#.#" ); let parsed = parse_slope(example)?; assert_eq!(count_encounters(&parsed, (2, 1)), 2); Ok(()) } }