adventofcode-2020/day-3/src/main.rs

92 lines
2.2 KiB
Rust

use std::fs;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let input = fs::read_to_string("input")?;
let slope = parse_slope(&input)?;
// Part 1
let encounters = count_encounters(&slope, (1, 3));
println!("{}", encounters);
// Part 2
let encounters: usize = [(1, 1), (1, 3), (1, 5), (1, 7), (2, 1)]
.iter()
.map(|angle| count_encounters(&slope, *angle))
.product();
println!("{}", encounters);
Ok(())
}
fn parse_slope(input: &str) -> Result<Vec<Vec<usize>>, String> {
input
.lines()
.map(|line| {
line.chars()
.map(|c| match c {
'.' => Ok(0),
'#' => Ok(1),
other => Err(format!("Invalid slope; contains character: {}", other)),
})
.collect()
})
.collect()
}
fn count_encounters(input: &Vec<Vec<usize>>, angle: (usize, usize)) -> usize {
input
.iter()
.enumerate()
.step_by(angle.0)
.map(|(i, row)| row[(i * angle.1 / angle.0) % row.len()])
.sum()
}
#[cfg(test)]
mod tests {
use super::*;
use indoc::indoc;
#[test]
fn test_simple() -> Result<(), Box<dyn std::error::Error>> {
let example = indoc!(
"..##.......
#...#...#..
.#....#..#.
..#.#...#.#
.#...##..#.
..#.##.....
.#.#.#....#
.#........#
#.##...#...
#...##....#
.#..#...#.#"
);
let parsed = parse_slope(example)?;
assert_eq!(count_encounters(&parsed, (1, 3)), 7);
Ok(())
}
#[test]
fn test_simple2() -> Result<(), Box<dyn std::error::Error>> {
let example = indoc!(
"..##.......
#...#...#..
.#....#..#.
..#.#...#.#
.#...##..#.
..#.##.....
.#.#.#....#
.#........#
#.##...#...
#...##....#
.#..#...#.#"
);
let parsed = parse_slope(example)?;
assert_eq!(count_encounters(&parsed, (2, 1)), 2);
Ok(())
}
}