Clean up day 13 a little.

This commit is contained in:
2021-12-13 08:52:57 +01:00
parent d471f170b3
commit ffe8d27469
2 changed files with 51 additions and 31 deletions

View File

@@ -53,7 +53,7 @@ impl<'a, I: FromStr> LineParser<'a, I> {
} }
} }
impl<'a, I: FromStr> Iterator for LineParser<'a, I> { impl<I: FromStr> Iterator for LineParser<'_, I> {
type Item = I; type Item = I;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
@@ -61,6 +61,15 @@ impl<'a, I: FromStr> Iterator for LineParser<'a, I> {
} }
} }
impl<'a, I: FromStr> From<LineIter<'a>> for LineParser<'a, I> {
fn from(iter: LineIter<'a>) -> Self {
Self {
iter,
_data: PhantomData,
}
}
}
/// Return two arguments in their natural PartialOrd order /// Return two arguments in their natural PartialOrd order
pub fn ordered<O: PartialOrd>(a: O, b: O) -> (O, O) { pub fn ordered<O: PartialOrd>(a: O, b: O) -> (O, O) {
if a < b { if a < b {

View File

@@ -1,12 +1,16 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::io::Read; use std::io::Read;
use std::str::FromStr;
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::error::Error;
use nom::sequence::tuple; use nom::sequence::tuple;
use nom::Finish;
use nom::IResult; use nom::IResult;
use crate::common::LineIter; use crate::common::LineIter;
use crate::common::LineParser;
type Coords = (u16, u16); type Coords = (u16, u16);
@@ -15,6 +19,21 @@ enum Fold {
Y(u16), Y(u16),
} }
impl FromStr for Fold {
type Err = Error<String>;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (_, fold) = parse_fold(s)
.finish()
.map_err(|Error { input, code }| Error {
input: input.to_string(),
code,
})?;
Ok(fold)
}
}
fn parse_coordinates(input: &str) -> IResult<&str, Coords> { fn parse_coordinates(input: &str) -> IResult<&str, Coords> {
use nom::character::complete::char; use nom::character::complete::char;
use nom::character::complete::u16; use nom::character::complete::u16;
@@ -44,9 +63,23 @@ fn parse_fold(input: &str) -> IResult<&str, Fold> {
Ok((input, fold)) Ok((input, fold))
} }
fn apply_fold(dots: &mut HashSet<Coords>, fold: Fold) { fn read_dots(reader: &mut LineIter<'_>) -> HashSet<Coords> {
let mut to_fold = Vec::new(); let mut dots = HashSet::new();
while let Some(line) = reader.next() {
if line.is_empty() {
break;
}
let (_, coords) = parse_coordinates(line).unwrap();
dots.insert(coords);
}
dots
}
fn apply_fold(dots: &mut HashSet<Coords>, fold: Fold, to_fold: &mut Vec<Coords>) {
match fold { match fold {
Fold::X(coord) => dots.retain(|&(x, y)| { Fold::X(coord) => dots.retain(|&(x, y)| {
if x < coord { if x < coord {
@@ -95,20 +128,10 @@ fn print_dots(dots: &HashSet<Coords>) -> String {
pub fn part1(input: &mut dyn Read) -> String { pub fn part1(input: &mut dyn Read) -> String {
let mut reader = LineIter::new(input); let mut reader = LineIter::new(input);
let mut dots = HashSet::new(); let mut dots = read_dots(&mut reader);
while let Some(line) = reader.next() { let fold = reader.next().unwrap().parse().unwrap();
if line == "" { apply_fold(&mut dots, fold, &mut Vec::new());
break;
}
let (_, coords) = parse_coordinates(line).unwrap();
dots.insert(coords);
}
let fold = parse_fold(reader.next().unwrap()).unwrap().1;
apply_fold(&mut dots, fold);
dots.len().to_string() dots.len().to_string()
} }
@@ -116,22 +139,10 @@ pub fn part1(input: &mut dyn Read) -> String {
pub fn part2(input: &mut dyn Read) -> String { pub fn part2(input: &mut dyn Read) -> String {
let mut reader = LineIter::new(input); let mut reader = LineIter::new(input);
let mut dots = HashSet::new(); let mut dots = read_dots(&mut reader);
let mut to_fold = Vec::new();
while let Some(line) = reader.next() { LineParser::from(reader).for_each(|fold| apply_fold(&mut dots, fold, &mut to_fold));
if line == "" {
break;
}
let (_, coords) = parse_coordinates(line).unwrap();
dots.insert(coords);
}
while let Some(line) = reader.next() {
let fold = parse_fold(line).unwrap().1;
apply_fold(&mut dots, fold);
}
print_dots(&dots) print_dots(&dots)
} }