diff options
Diffstat (limited to 'src/2020')
-rw-r--r-- | src/2020/3/mod.rs | 94 | ||||
-rw-r--r-- | src/2020/mod.rs | 4 |
2 files changed, 98 insertions, 0 deletions
diff --git a/src/2020/3/mod.rs b/src/2020/3/mod.rs new file mode 100644 index 0000000..58aabfd --- /dev/null +++ b/src/2020/3/mod.rs @@ -0,0 +1,94 @@ +use anyhow::Context as _; +use std::io::Read as _; + +struct Map { + grid: Vec<Vec<bool>>, +} + +impl Map { + fn parse(s: &[u8]) -> anyhow::Result<Self> { + let mut grid = vec![]; + let mut current_row = vec![]; + for c in s { + match c { + b'#' => { + current_row.push(true); + } + b'.' => { + current_row.push(false); + } + b'\n' => { + grid.push(current_row); + current_row = vec![]; + } + _ => { + return Err(anyhow::anyhow!("invalid map char: '{}'", c)); + } + } + } + if !current_row.is_empty() { + grid.push(current_row); + } + Ok(Self { grid }) + } + + fn rows(&self) -> usize { + self.grid.len() + } + + fn tree_at(&self, x: usize, y: usize) -> anyhow::Result<bool> { + // unwrap safe because cycle().nth() can never fail + Ok(*self + .grid + .get(y) + .context("row too large")? + .iter() + .cycle() + .nth(x) + .unwrap()) + } + + fn trees_for_slope( + &self, + x_incr: usize, + y_incr: usize, + ) -> anyhow::Result<usize> { + let mut trees = 0; + for r in 0..self.rows() / y_incr { + let x = r * x_incr; + let y = r * y_incr; + if self.tree_at(x, y)? { + trees += 1; + } + } + Ok(trees) + } +} + +pub fn part1() -> anyhow::Result<()> { + let map = read_map()?; + println!("{}", map.trees_for_slope(3, 1)?); + Ok(()) +} + +pub fn part2() -> anyhow::Result<()> { + let map = read_map()?; + println!( + "{}", + map.trees_for_slope(1, 1)? + * map.trees_for_slope(3, 1)? + * map.trees_for_slope(5, 1)? + * map.trees_for_slope(7, 1)? + * map.trees_for_slope(1, 2)? + ); + Ok(()) +} + +fn read_map() -> anyhow::Result<Map> { + let mut f = std::fs::File::open("data/3.txt") + .context("couldn't find data file 3.txt")?; + let mut map_str = vec![]; + f.read_to_end(&mut map_str) + .context("failed to read map contents")?; + Map::parse(&map_str) +} diff --git a/src/2020/mod.rs b/src/2020/mod.rs index 87ceb55..ff08a7e 100644 --- a/src/2020/mod.rs +++ b/src/2020/mod.rs @@ -2,6 +2,8 @@ mod day1; #[path = "2/mod.rs"] mod day2; +#[path = "3/mod.rs"] +mod day3; pub fn run(day: u8, puzzle: u8) -> anyhow::Result<()> { match (day, puzzle) { @@ -9,6 +11,8 @@ pub fn run(day: u8, puzzle: u8) -> anyhow::Result<()> { (1, 2) => day1::part2(), (2, 1) => day2::part1(), (2, 2) => day2::part2(), + (3, 1) => day3::part1(), + (3, 2) => day3::part2(), _ => Err(anyhow::anyhow!("unknown puzzle {}-{}", day, puzzle)), } } |