Skip to content

Commit

Permalink
2017 day 9
Browse files Browse the repository at this point in the history
  • Loading branch information
ictrobot committed Oct 29, 2024
1 parent ce90f4b commit 677fa30
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 5 deletions.
14 changes: 14 additions & 0 deletions crates/utils/src/parser/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,20 @@ impl Parser for u8 {
}
}

/// Allow custom functions and closures to be used as parsers.
impl<O, F: Fn(&[u8]) -> ParseResult<O>> Parser for F {
type Output<'i> = O;
type Then<T: Parser> = Then2<Self, T>;

fn parse<'i>(&self, input: &'i [u8]) -> ParseResult<'i, Self::Output<'i>> {
self(input)
}

fn then<T: Parser>(self, next: T) -> Self::Then<T> {
Then2::new(self, next)
}
}

/// Trait for types that have a canonical parser.
pub trait Parseable {
type Parser: for<'i> Parser<Output<'i> = Self>;
Expand Down
6 changes: 1 addition & 5 deletions crates/year2015/src/day12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@ pub struct Day12 {

impl Day12 {
pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
let (part1, part2) = match Self::parse(input.as_bytes()) {
Ok(((part1, part2), &[])) => Ok((part1, part2)),
Ok((_, remaining)) => Err(InputError::new(input, remaining, "expected end of input")),
Err((err, position)) => Err(InputError::new(input, position, err)),
}?;
let (part1, part2) = Self::parse.parse_complete(input)?;
Ok(Self { part1, part2 })
}

Expand Down
97 changes: 97 additions & 0 deletions crates/year2017/src/day09.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use utils::parser::{ParseError, ParseResult};
use utils::prelude::*;

/// Parsing a nested structure.
#[derive(Clone, Debug)]
pub struct Day09 {
part1: u32,
part2: u32,
}

impl Day09 {
pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
let (part1, part2) = Self::parse.parse_complete(input)?;
Ok(Self { part1, part2 })
}

// Parses either a (nested) group or a single piece of garbage.
fn parse(mut input: &[u8]) -> ParseResult<(u32, u32)> {
let mut group_depth = 0;
let mut in_garbage = false;

let mut group_score = 0;
let mut garbage_count = 0;

loop {
input = if in_garbage {
match input {
[b'!', _, rest @ ..] => rest,
[b'>', rest @ ..] => {
in_garbage = false;
if group_depth == 0 {
return Ok(((group_score, garbage_count), rest));
}
rest
}
[_, rest @ ..] => {
garbage_count += 1;
rest
}
[] => return Err((ParseError::ExpectedByte(b'>'), input)),
}
} else {
match input {
[b'{', rest @ ..] => {
group_depth += 1;
group_score += group_depth;
rest
}
[b'}', rest @ ..] if group_depth > 0 => {
group_depth -= 1;
if group_depth == 0 {
return Ok(((group_score, garbage_count), rest));
}
rest
}
[b'<', rest @ ..] => {
in_garbage = true;
rest
}
[b',', rest @ ..] if group_depth > 0 => rest,
_ if group_depth > 0 => {
return Err((ParseError::Custom("expected '{', '}', ',' or '<'"), input))
}
_ => return Err((ParseError::Custom("expected '{' or '<'"), input)),
}
}
}
}

#[must_use]
pub fn part1(&self) -> u32 {
self.part1
}

#[must_use]
pub fn part2(&self) -> u32 {
self.part2
}
}

examples!(Day09 -> (u32, u32) [
{input: "{}", part1: 1},
{input: "{{{}}}", part1: 6},
{input: "{{},{}}", part1: 5},
{input: "{{{},{},{{}}}}", part1: 16},
{input: "{<a>,<a>,<a>,<a>}", part1: 1},
{input: "{{<ab>},{<ab>},{<ab>},{<ab>}}", part1: 9},
{input: "{{<!!>},{<!!>},{<!!>},{<!!>}}", part1: 9},
{input: "{{<a!>},{<a!>},{<a!>},{<ab>}}", part1: 3},
{input: "<>", part2: 0},
{input: "<random characters>", part2: 17},
{input: "<<<<>", part2: 3},
{input: "<{!>}>", part2: 2},
{input: "<!!>", part2: 0},
{input: "<!!!>>", part2: 0},
{input: "<{o\"i!a,<{i<a>", part2: 10},
]);
1 change: 1 addition & 0 deletions crates/year2017/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ utils::year!(2017 => year2017, ${
6 => day06::Day06,
7 => day07::Day07<'_>,
8 => day08::Day08,
9 => day09::Day09,
});

0 comments on commit 677fa30

Please sign in to comment.