2021: day05: part 1
This commit is contained in:
parent
9c29742b99
commit
44afc3bbdd
5 changed files with 621 additions and 1 deletions
108
aoc2021/src/day05.rs
Normal file
108
aoc2021/src/day05.rs
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
use std::collections::HashMap;
|
||||
use std::fmt::Write;
|
||||
use std::iter;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
const INPUT: &str = include_str!("../input/day05.txt");
|
||||
|
||||
pub fn run() -> Result<String> {
|
||||
let mut res = String::with_capacity(128);
|
||||
|
||||
writeln!(res, "part 1: {}", part1(INPUT)?)?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
fn part1(input: &str) -> Result<usize> {
|
||||
let lines = input
|
||||
.lines()
|
||||
.map(str::parse::<Line>)
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
|
||||
let mut grid = HashMap::new();
|
||||
|
||||
lines
|
||||
.iter()
|
||||
.filter(|l| l.is_horizontal() || l.is_vertical())
|
||||
.for_each(|l| {
|
||||
for cell in l.cells() {
|
||||
*grid.entry(cell).or_insert(0) += 1;
|
||||
}
|
||||
});
|
||||
|
||||
Ok(grid.into_values().filter(|c| *c > 1).count())
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Line {
|
||||
from: (usize, usize),
|
||||
to: (usize, usize),
|
||||
}
|
||||
|
||||
impl Line {
|
||||
fn is_horizontal(&self) -> bool {
|
||||
self.to.1 == self.from.1
|
||||
}
|
||||
|
||||
fn is_vertical(&self) -> bool {
|
||||
self.to.0 == self.from.0
|
||||
}
|
||||
|
||||
fn cells(&self) -> Box<dyn Iterator<Item = (usize, usize)>> {
|
||||
if self.is_horizontal() {
|
||||
let min = self.from.0.min(self.to.0);
|
||||
let max = self.from.0.max(self.to.0);
|
||||
Box::new((min..=max).zip(iter::repeat(self.from.1)))
|
||||
as Box<dyn Iterator<Item = (usize, usize)>>
|
||||
} else {
|
||||
let min = self.from.1.min(self.to.1);
|
||||
let max = self.from.1.max(self.to.1);
|
||||
Box::new(iter::repeat(self.from.0).zip(min..=max))
|
||||
as Box<dyn Iterator<Item = (usize, usize)>>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Line {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self> {
|
||||
let (from, to) = s
|
||||
.split_once(" -> ")
|
||||
.context("couldn't parse line: missing ` -> `")?;
|
||||
|
||||
let from = {
|
||||
let (x, y) = from
|
||||
.split_once(',')
|
||||
.context("couldn't parse line origin: missing `,`")?;
|
||||
(x.parse()?, y.parse()?)
|
||||
};
|
||||
|
||||
let to = {
|
||||
let (x, y) = to
|
||||
.split_once(',')
|
||||
.context("couldn't parse line origin: missing `,`")?;
|
||||
(x.parse()?, y.parse()?)
|
||||
};
|
||||
|
||||
Ok(Line { from, to })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const PROVIDED: &str = include_str!("../input/day05_provided.txt");
|
||||
|
||||
#[test]
|
||||
fn part1_provided() {
|
||||
assert_eq!(part1(PROVIDED).unwrap(), 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part1_real() {
|
||||
assert_eq!(part1(INPUT).unwrap(), 4745);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,3 +4,4 @@ pub mod day01;
|
|||
pub mod day02;
|
||||
pub mod day03;
|
||||
pub mod day04;
|
||||
pub mod day05;
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@ use aoc2021::day01;
|
|||
use aoc2021::day02;
|
||||
use aoc2021::day03;
|
||||
use aoc2021::day04;
|
||||
use aoc2021::day05;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let days: &[DayFunc] = &[day01::run, day02::run, day03::run, day04::run];
|
||||
let days: &[DayFunc] = &[day01::run, day02::run, day03::run, day04::run, day05::run];
|
||||
|
||||
aoc::run(days)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue