const INPUT: &str = include_str!("../../data/day3"); struct Forest { pub rows: usize, stride: usize, trees: Vec, } impl Forest { fn parse(text: &str) -> Self { let first_line = text.lines().next().unwrap(); let stride = first_line.len(); let mut trees = Vec::new(); let mut rows = 0; for line in text.lines() { assert_eq!(line.len(), stride); trees.extend(line.as_bytes().iter().map(|&c| c == b'#')); rows += 1; } Self { rows, stride, trees, } } fn is_tree(&self, row: usize, column: u64) -> bool { assert!(row < self.rows); let column = (column % self.stride as u64) as usize; self.trees[column + row * self.stride] } fn hit_trees(&self, slope_y: usize, slope_x: u64) -> u64 { let mut row = slope_y; let mut col = slope_x; let mut hits = 0; while row < self.rows { if self.is_tree(row, col) { hits += 1; } row += slope_y; col += slope_x; } hits } } const TEST_SLOPES: &[(usize, u64)] = &[ (1, 1), (1, 3), (1, 5), (1, 7), (2, 1), ]; fn main() { let forest = Forest::parse(INPUT); println!("Hit trees: {}", forest.hit_trees(1, 3)); println!( "Hit product: {}", TEST_SLOPES.iter().map(|(slope_y, slope_x)| { forest.hit_trees(*slope_y, *slope_x) }).product::(), ); }