AoC2020/src/day3.rs

78 lines
1.9 KiB
Rust

use std::io::BufRead;
#[derive(Debug, std::cmp::PartialEq)]
enum Cell {
Tree,
Empty
}
type Forest = Vec<Vec<Cell>>;
struct ForestSlopeIterator<'a> {
forest: &'a Forest,
horizontal_shift: usize,
vertical_shift: usize,
pos_x: usize,
pos_y: usize,
}
trait IterSlope {
fn iter_slope(&self, horizontal_shift: usize, vertical_shift: usize) -> ForestSlopeIterator;
}
impl IterSlope for Forest {
fn iter_slope(&self, horizontal_shift: usize, vertical_shift: usize) -> ForestSlopeIterator {
ForestSlopeIterator {
forest: self,
horizontal_shift,
vertical_shift,
pos_x: 0,
pos_y: 0,
}
}
}
impl<'a> Iterator for ForestSlopeIterator<'a> {
type Item = &'a Cell;
fn next(&mut self) -> Option<Self::Item> {
if self.pos_y >= self.forest.len() {
None
} else {
let cell = &self.forest[self.pos_y][self.pos_x];
self.pos_y += self.vertical_shift;
self.pos_x = (self.pos_x + self.horizontal_shift) % self.forest[0].len();
Some(cell)
}
}
}
fn challenge<F: BufRead> (input: F, slopes: &[(usize, usize)]) -> usize {
let forest: Forest = input.lines()
.map(
|line| line.unwrap().chars().map(
|c| match c {
'.' => Cell::Empty,
'#' => Cell::Tree,
_ => unreachable!()
}
).collect::<Vec<_>>()
)
.collect();
slopes.iter().map(
|(h_shift, v_shift)| forest.iter_slope(*h_shift, *v_shift)
.filter(|cell| **cell == Cell::Tree)
.count()
).fold(1, |acc, count| acc * count)
}
pub fn part1<F: BufRead> (input: F) {
println!("{}", challenge(input, &[(3, 1)]))
}
pub fn part2<F: BufRead> (input: F) {
let slopes = [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)];
println!("{}", challenge(input, &slopes))
}