Day 3 part 1.
This commit is contained in:
117
2020/src/day3.rs
Normal file
117
2020/src/day3.rs
Normal file
@@ -0,0 +1,117 @@
|
||||
//! --- Day 3: Toboggan Trajectory ---
|
||||
//! With the toboggan login problems resolved, you set off toward the airport. While travel by toboggan might be easy, it's certainly not safe: there's very minimal steering and the area is covered in trees. You'll need to see which angles will take you near the fewest trees.
|
||||
//!
|
||||
//! Due to the local geology, trees in this area only grow on exact integer coordinates in a grid. You make a map (your puzzle input) of the open squares (.) and trees (#) you can see. For example:
|
||||
//!
|
||||
//! ..##.......
|
||||
//! #...#...#..
|
||||
//! .#....#..#.
|
||||
//! ..#.#...#.#
|
||||
//! .#...##..#.
|
||||
//! ..#.##.....
|
||||
//! .#.#.#....#
|
||||
//! .#........#
|
||||
//! #.##...#...
|
||||
//! #...##....#
|
||||
//! .#..#...#.#
|
||||
//! These aren't the only trees, though; due to something you read about once involving arboreal genetics and biome stability, the same pattern repeats to the right many times:
|
||||
//!
|
||||
//! ..##.........##.........##.........##.........##.........##....... --->
|
||||
//! #...#...#..#...#...#..#...#...#..#...#...#..#...#...#..#...#...#..
|
||||
//! .#....#..#..#....#..#..#....#..#..#....#..#..#....#..#..#....#..#.
|
||||
//! ..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#
|
||||
//! .#...##..#..#...##..#..#...##..#..#...##..#..#...##..#..#...##..#.
|
||||
//! ..#.##.......#.##.......#.##.......#.##.......#.##.......#.##..... --->
|
||||
//! .#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....#
|
||||
//! .#........#.#........#.#........#.#........#.#........#.#........#
|
||||
//! #.##...#...#.##...#...#.##...#...#.##...#...#.##...#...#.##...#...
|
||||
//! #...##....##...##....##...##....##...##....##...##....##...##....#
|
||||
//! .#..#...#.#.#..#...#.#.#..#...#.#.#..#...#.#.#..#...#.#.#..#...#.# --->
|
||||
//! You start on the open square (.) in the top-left corner and need to reach the bottom (below the bottom-most row on your map).
|
||||
//!
|
||||
//! The toboggan can only follow a few specific slopes (you opted for a cheaper model that prefers rational numbers); start by counting all the trees you would encounter for the slope right 3, down 1:
|
||||
//!
|
||||
//! From your starting position at the top-left, check the position that is right 3 and down 1. Then, check the position that is right 3 and down 1 from there, and so on until you go past the bottom of the map.
|
||||
//!
|
||||
//! The locations you'd check in the above example are marked here with O where there was an open square and X where there was a tree:
|
||||
//!
|
||||
//! ..##.........##.........##.........##.........##.........##....... --->
|
||||
//! #..O#...#..#...#...#..#...#...#..#...#...#..#...#...#..#...#...#..
|
||||
//! .#....X..#..#....#..#..#....#..#..#....#..#..#....#..#..#....#..#.
|
||||
//! ..#.#...#O#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#..#.#...#.#
|
||||
//! .#...##..#..X...##..#..#...##..#..#...##..#..#...##..#..#...##..#.
|
||||
//! ..#.##.......#.X#.......#.##.......#.##.......#.##.......#.##..... --->
|
||||
//! .#.#.#....#.#.#.#.O..#.#.#.#....#.#.#.#....#.#.#.#....#.#.#.#....#
|
||||
//! .#........#.#........X.#........#.#........#.#........#.#........#
|
||||
//! #.##...#...#.##...#...#.X#...#...#.##...#...#.##...#...#.##...#...
|
||||
//! #...##....##...##....##...#X....##...##....##...##....##...##....#
|
||||
//! .#..#...#.#.#..#...#.#.#..#...X.#.#..#...#.#.#..#...#.#.#..#...#.# --->
|
||||
//! In this example, traversing the map using this slope would cause you to encounter 7 trees.
|
||||
//!
|
||||
//! Starting at the top-left corner of your map and following a slope of right 3 and down 1, how many trees would you encounter?
|
||||
|
||||
use std::ops::Index;
|
||||
|
||||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct Bitmap {
|
||||
width: usize,
|
||||
height: usize,
|
||||
bits: Vec<bool>,
|
||||
}
|
||||
|
||||
impl Index<(usize, usize)> for Bitmap {
|
||||
type Output = bool;
|
||||
|
||||
// Perform 2-dimensional indexing of bits, wrapping the X coordinates if it is larger than the
|
||||
// width of the Bitmap.
|
||||
fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
|
||||
&self.bits[x % self.width + y * self.width]
|
||||
}
|
||||
}
|
||||
#[aoc_generator(day3)]
|
||||
fn parse(input: &str) -> Bitmap {
|
||||
let mut height = 0;
|
||||
let bits: Vec<bool> = input
|
||||
.chars()
|
||||
.filter_map(|c| match c {
|
||||
'.' => Some(false),
|
||||
'#' => Some(true),
|
||||
'\n' => {
|
||||
height += 1;
|
||||
None
|
||||
}
|
||||
_ => panic!("Unexpected character"),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let width = bits.len() / height;
|
||||
Bitmap {
|
||||
width,
|
||||
height,
|
||||
bits,
|
||||
}
|
||||
}
|
||||
|
||||
#[aoc(day3, part1)]
|
||||
fn answer(map: &Bitmap) -> usize {
|
||||
(0..map.height).filter(|y| map[(*y * 3, *y)]).count()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn make_bitmap() {
|
||||
assert_eq!(
|
||||
parse("..##\n##..\n"),
|
||||
Bitmap {
|
||||
width: 4,
|
||||
height: 2,
|
||||
bits: vec![false, false, true, true, true, true, false, false]
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
mod day1;
|
||||
mod day2;
|
||||
mod day3;
|
||||
|
||||
use aoc_runner_derive::aoc_lib;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user