day19 working part1, not working part2.

I don't really understand what's expected of part2 and the example is
not simple enough for me to step through in my brain so I'm probably not
going to get it.
This commit is contained in:
2020-12-19 16:26:37 -08:00
parent 2448b9a538
commit 769937bf97
4 changed files with 672 additions and 5 deletions

103
src/day19.rs Normal file
View File

@@ -0,0 +1,103 @@
use crate::split_once;
use aoc_runner_derive::aoc;
use std::collections::HashMap;
#[derive(Debug)]
enum Parser<'a> {
Lit(&'a str),
Seq(Vec<usize>),
Alt(Vec<usize>, Vec<usize>),
}
impl<'a> Parser<'a> {
fn new(parser_def: &'a str) -> Option<(usize, Self)> {
let (idx, def) = split_once(parser_def, ": ")?;
let idx = idx.parse().ok()?;
if let Some((a, b)) = split_once(def, " | ") {
let a = a
.split(' ')
.map(|x| x.parse().ok())
.collect::<Option<Vec<usize>>>()?;
let b = b
.split(' ')
.map(|x| x.parse().ok())
.collect::<Option<Vec<usize>>>()?;
Some((idx, Parser::Alt(a, b)))
} else if let Some(_) = def.find('"') {
Some((idx, Parser::Lit(&def[1..def.len() - 1])))
} else {
let seq = def
.split(' ')
.map(|x| x.parse().ok())
.collect::<Option<Vec<usize>>>()?;
Some((idx, Parser::Seq(seq)))
}
}
// returns Some(remaining_input) when valid, None when doesn't match.
fn parse<'b>(&self, parsers: &HashMap<usize, Parser>, input: &'b str) -> Option<&'b str> {
match self {
&Parser::Lit(s) => {
if input.is_empty() || &input[..s.len()] != s {
None
} else {
Some(&input[s.len()..])
}
}
Parser::Seq(a) => {
let mut input = input;
let mut iter = a.iter().copied();
while let Some(parser_idx) = iter.next() {
input = parsers
.get(&parser_idx)
.and_then(|p| p.parse(parsers, input))?;
}
Some(input)
}
Parser::Alt(a, b) => {
let parser_a = Parser::Seq(a.clone());
match parser_a.parse(parsers, input) {
Some(input) => Some(input),
None => {
let parser_b = Parser::Seq(b.clone());
parser_b.parse(parsers, input)
}
}
}
}
}
}
#[aoc(day19, part1)]
fn solve_d19_p1(input: &str) -> usize {
let (parser_input, pattern_input) = split_once(input, "\n\n").unwrap();
let parsers: HashMap<usize, Parser> = parser_input
.split('\n')
.map(|parser_def| Parser::new(parser_def).unwrap())
.collect();
let rule0 = parsers.get(&0).unwrap();
pattern_input
.split('\n')
.filter(|pattern| rule0.parse(&parsers, pattern) == Some(""))
.count()
}
#[aoc(day19, part2)]
fn solve_d19_p2(input: &str) -> usize {
let (parser_input, pattern_input) = split_once(input, "\n\n").unwrap();
let mut parsers: HashMap<usize, Parser> = parser_input
.split('\n')
.map(|parser_def| Parser::new(parser_def).unwrap())
.collect();
parsers.insert(8, Parser::Alt(vec![42], vec![42, 8]));
parsers.insert(11, Parser::Alt(vec![42, 31], vec![42, 11, 31]));
let rule0 = parsers.get(&0).unwrap();
pattern_input
.split('\n')
.filter(|pattern| rule0.parse(&parsers, pattern) == Some(""))
.count()
}