🎄
Advent of Code 2020 day03
part1
..##.......
#...#...#..
.#....#..#.
..#.#...#.#
.#...##..#.
..#.##.....
.#.#.#....#
.#........#
#.##...#...
#...##....#
.#..#...#.#
のように .
と #
で表されるmap(ただし横方向に無限に同じパターンが続いている)で、左上を起点に一定方向に降りていくと何回 #
にぶつかるか、を数える。
part1は「右に3
、下に1
」で進むと何回ぶつかるか。
入力をparseして #
のときのみ true
として扱い、単純にfor loopで見ていく。横方向には同じパターンが続いているということで、常にwidthでのmodを見ておけば はみ出た場合を考慮できる。
impl Solution {
fn new(inputs: Vec<String>) -> Self {
Self {
grid: inputs
.iter()
.map(|row| row.chars().map(|c| c == '#').collect())
.collect(),
}
}
fn solve_1(&self) -> usize {
let width = self.grid[0].len();
(0..self.grid.len())
.filter(|&i| self.grid[i][(i * 3) % width])
.count()
}
}
part2
part1では「右に3
、下に1
」の場合だけを考えれば良かったが、他の進み方をしたときも計算する必要がある。ので各方向の場合で数えるメソッドを用意し、それぞれの回数を求めて掛け合わせる。
fn solve_2(&self) -> usize {
[(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)]
.iter()
.map(|&(right, down)| self.count(right, down))
.product()
}
fn count(&self, right: usize, down: usize) -> usize {
let width = self.grid[0].len();
(0..self.grid.len() / down)
.filter(|&i| self.grid[i * down][(i * right) % width])
.count()
}
code
use std::io::{BufRead, BufReader};
struct Solution {
grid: Vec<Vec<bool>>,
}
impl Solution {
fn new(inputs: Vec<String>) -> Self {
Self {
grid: inputs
.iter()
.map(|row| row.chars().map(|c| c == '#').collect())
.collect(),
}
}
fn solve_1(&self) -> usize {
self.count(3, 1)
}
fn solve_2(&self) -> usize {
[(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)]
.iter()
.map(|&(right, down)| self.count(right, down))
.product()
}
fn count(&self, right: usize, down: usize) -> usize {
let width = self.grid[0].len();
(0..self.grid.len() / down)
.filter(|&i| self.grid[i * down][(i * right) % width])
.count()
}
}
fn main() {
let inputs: Vec<String> = BufReader::new(std::io::stdin().lock())
.lines()
.filter_map(|line| line.ok())
.collect();
let solution = Solution::new(inputs);
println!("{}", solution.solve_1());
println!("{}", solution.solve_2());
}
Discussion