use std::env;
use std::io::BufRead;
#[derive(Debug, Copy, Clone)]
enum Tile {
Blank,
Tree,
}
struct Pairs<I> {
inner: I,
}
impl<I> Pairs<I> {
fn new(inner: I) -> Self {
Pairs { inner: inner }
}
}
impl<I> Iterator for Pairs<I>
where
I: Iterator,
{
type Item = (<I as Iterator>::Item, <I as Iterator>::Item);
fn next(&mut self) -> Option<Self::Item> {
let a = self.inner.next()?;
let b = self.inner.next()?;
Some((a, b))
}
}
fn tile(c: char) -> Tile {
match c {
'.' => Tile::Blank,
'#' => Tile::Tree,
_ => panic!("Unrecognized tile"),
}
}
fn trees_hit(grid: &Vec<Vec<Tile>>, dx: usize, dy: usize) -> u64 {
let mut count = 0;
let mut x = 0;
for row in grid.iter().step_by(dy) {
match row[x % row.len()] {
Tile::Blank => {}
Tile::Tree => {
count += 1;
}
};
x += dx;
}
count
}
fn main() {
let args: Vec<_> = env::args().collect();
let grid: Vec<Vec<Tile>> = std::io::BufReader::new(std::fs::File::open(&args[1]).unwrap())
.lines()
.map(Result::unwrap)
.map(|l| l.chars().map(tile).collect())
.collect();
let slopes: Vec<(usize, usize)> =
Pairs::new(args[2].split(",").map(|s| s.parse::<usize>().unwrap())).collect();
println!(
"{}",
slopes
.iter()
.map(|(dx, dy)| trees_hit(&grid, *dx, *dy))
.product::<u64>()
);
}