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:
@@ -1,10 +1,6 @@
|
||||
use aoc_runner_derive::aoc;
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
fn split_once<'a>(input: &'a str, delimeter: &str) -> Option<(&'a str, &'a str)> {
|
||||
let idx = input.find(delimeter)?;
|
||||
Some((&input[..idx], &input[idx + delimeter.len()..]))
|
||||
}
|
||||
use crate::split_once;
|
||||
|
||||
struct Rule<'a> {
|
||||
name: &'a str,
|
||||
|
||||
103
src/day19.rs
Normal file
103
src/day19.rs
Normal 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()
|
||||
}
|
||||
@@ -8,6 +8,7 @@ pub mod day15;
|
||||
pub mod day16;
|
||||
pub mod day17;
|
||||
pub mod day18;
|
||||
pub mod day19;
|
||||
pub mod day2;
|
||||
pub mod day3;
|
||||
pub mod day4;
|
||||
@@ -18,3 +19,8 @@ pub mod day8;
|
||||
pub mod day9;
|
||||
|
||||
aoc_runner_derive::aoc_lib! { year = 2020 }
|
||||
|
||||
fn split_once<'a>(input: &'a str, delimeter: &str) -> Option<(&'a str, &'a str)> {
|
||||
let idx = input.find(delimeter)?;
|
||||
Some((&input[..idx], &input[idx + delimeter.len()..]))
|
||||
}
|
||||
Reference in New Issue
Block a user