Skip to content

Commit 677fa30

Browse files
committed
2017 day 9
1 parent ce90f4b commit 677fa30

File tree

4 files changed

+113
-5
lines changed

4 files changed

+113
-5
lines changed

crates/utils/src/parser/base.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,20 @@ impl Parser for u8 {
425425
}
426426
}
427427

428+
/// Allow custom functions and closures to be used as parsers.
429+
impl<O, F: Fn(&[u8]) -> ParseResult<O>> Parser for F {
430+
type Output<'i> = O;
431+
type Then<T: Parser> = Then2<Self, T>;
432+
433+
fn parse<'i>(&self, input: &'i [u8]) -> ParseResult<'i, Self::Output<'i>> {
434+
self(input)
435+
}
436+
437+
fn then<T: Parser>(self, next: T) -> Self::Then<T> {
438+
Then2::new(self, next)
439+
}
440+
}
441+
428442
/// Trait for types that have a canonical parser.
429443
pub trait Parseable {
430444
type Parser: for<'i> Parser<Output<'i> = Self>;

crates/year2015/src/day12.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@ pub struct Day12 {
1010

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

crates/year2017/src/day09.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use utils::parser::{ParseError, ParseResult};
2+
use utils::prelude::*;
3+
4+
/// Parsing a nested structure.
5+
#[derive(Clone, Debug)]
6+
pub struct Day09 {
7+
part1: u32,
8+
part2: u32,
9+
}
10+
11+
impl Day09 {
12+
pub fn new(input: &str, _: InputType) -> Result<Self, InputError> {
13+
let (part1, part2) = Self::parse.parse_complete(input)?;
14+
Ok(Self { part1, part2 })
15+
}
16+
17+
// Parses either a (nested) group or a single piece of garbage.
18+
fn parse(mut input: &[u8]) -> ParseResult<(u32, u32)> {
19+
let mut group_depth = 0;
20+
let mut in_garbage = false;
21+
22+
let mut group_score = 0;
23+
let mut garbage_count = 0;
24+
25+
loop {
26+
input = if in_garbage {
27+
match input {
28+
[b'!', _, rest @ ..] => rest,
29+
[b'>', rest @ ..] => {
30+
in_garbage = false;
31+
if group_depth == 0 {
32+
return Ok(((group_score, garbage_count), rest));
33+
}
34+
rest
35+
}
36+
[_, rest @ ..] => {
37+
garbage_count += 1;
38+
rest
39+
}
40+
[] => return Err((ParseError::ExpectedByte(b'>'), input)),
41+
}
42+
} else {
43+
match input {
44+
[b'{', rest @ ..] => {
45+
group_depth += 1;
46+
group_score += group_depth;
47+
rest
48+
}
49+
[b'}', rest @ ..] if group_depth > 0 => {
50+
group_depth -= 1;
51+
if group_depth == 0 {
52+
return Ok(((group_score, garbage_count), rest));
53+
}
54+
rest
55+
}
56+
[b'<', rest @ ..] => {
57+
in_garbage = true;
58+
rest
59+
}
60+
[b',', rest @ ..] if group_depth > 0 => rest,
61+
_ if group_depth > 0 => {
62+
return Err((ParseError::Custom("expected '{', '}', ',' or '<'"), input))
63+
}
64+
_ => return Err((ParseError::Custom("expected '{' or '<'"), input)),
65+
}
66+
}
67+
}
68+
}
69+
70+
#[must_use]
71+
pub fn part1(&self) -> u32 {
72+
self.part1
73+
}
74+
75+
#[must_use]
76+
pub fn part2(&self) -> u32 {
77+
self.part2
78+
}
79+
}
80+
81+
examples!(Day09 -> (u32, u32) [
82+
{input: "{}", part1: 1},
83+
{input: "{{{}}}", part1: 6},
84+
{input: "{{},{}}", part1: 5},
85+
{input: "{{{},{},{{}}}}", part1: 16},
86+
{input: "{<a>,<a>,<a>,<a>}", part1: 1},
87+
{input: "{{<ab>},{<ab>},{<ab>},{<ab>}}", part1: 9},
88+
{input: "{{<!!>},{<!!>},{<!!>},{<!!>}}", part1: 9},
89+
{input: "{{<a!>},{<a!>},{<a!>},{<ab>}}", part1: 3},
90+
{input: "<>", part2: 0},
91+
{input: "<random characters>", part2: 17},
92+
{input: "<<<<>", part2: 3},
93+
{input: "<{!>}>", part2: 2},
94+
{input: "<!!>", part2: 0},
95+
{input: "<!!!>>", part2: 0},
96+
{input: "<{o\"i!a,<{i<a>", part2: 10},
97+
]);

crates/year2017/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ utils::year!(2017 => year2017, ${
1010
6 => day06::Day06,
1111
7 => day07::Day07<'_>,
1212
8 => day08::Day08,
13+
9 => day09::Day09,
1314
});

0 commit comments

Comments
 (0)