Completed day 19 part 2

Terribly inefficient algorithm but at this point I don't care.
This commit is contained in:
Tyler Hallada 2020-12-24 19:23:15 -05:00
parent 2fb9b4ed4a
commit c248cb0bbd
2 changed files with 42 additions and 40 deletions

View File

@ -1,15 +1,7 @@
0: 1 | 2 0: 1 2
1: 3 | 3 1 1: 3 | 3 1
2: 3 4 | 3 2 4 2: 3 4 | 3 2 4
3: "a" 3: "a"
4: "b" 4: "b"
a aaaaabb
aa
aaa
b
ab
aabb
aaabbb
aaaabbb
aaabbbb

View File

@ -60,48 +60,58 @@ fn string_matches_rule<'a>(
rules: &HashMap<usize, Rule>, rules: &HashMap<usize, Rule>,
rule: &Rule, rule: &Rule,
ends: bool, ends: bool,
) -> (&'a str, bool) { ) -> Vec<(&'a str, bool)> {
if s.is_empty() {
return (s, false);
}
match rule { match rule {
Rule::Char(c) => { Rule::Char(c) => {
if s.len() < 1 { if s.len() < 1 {
(s, false) vec![(s, false)]
} else if s.chars().next().expect("non-empty string") == *c { } else if s.chars().next().expect("non-empty string") == *c {
let rest = &s[1..]; let rest = &s[1..];
if !ends || (ends && rest.is_empty()) { if !ends || (ends && rest.is_empty()) {
(rest, true) vec![(rest, true)]
} else { } else {
(rest, false) vec![(rest, false)]
} }
} else { } else {
(s, false) vec![(s, false)]
} }
} }
Rule::Seq(seq) => { Rule::Seq(seq) => {
let mut rest = s; let mut possibilities: Vec<(&'a str, bool)> = Vec::new();
for (i, rule_index) in seq.iter().enumerate() { for (i, rule_index) in seq.iter().enumerate() {
let result = string_matches_rule( if i == 0 {
rest, possibilities = string_matches_rule(
rules, s,
&rules[rule_index], rules,
if i == seq.len() - 1 { ends } else { false }, &rules[rule_index],
); if i == seq.len() - 1 { ends } else { false },
if !result.1 { );
return result; } else {
let mut new_possibilities = Vec::new();
for possibility in possibilities {
if possibility.1 {
new_possibilities.append(&mut string_matches_rule(
possibility.0,
rules,
&rules[rule_index],
if i == seq.len() - 1 { ends } else { false },
));
}
}
possibilities = new_possibilities;
} }
rest = result.0;
} }
(rest, true) possibilities
} }
Rule::Or((left, right)) => { Rule::Or((left, right)) => {
let result = string_matches_rule(s, rules, &Rule::Seq(left.to_vec()), ends); let mut possibilities = string_matches_rule(s, rules, &Rule::Seq(left.to_vec()), ends);
if result.1 { possibilities.append(&mut string_matches_rule(
return result; s,
} rules,
let result = string_matches_rule(s, rules, &Rule::Seq(right.to_vec()), ends); &Rule::Seq(right.to_vec()),
result ends,
));
possibilities
} }
} }
} }
@ -126,8 +136,8 @@ fn solve_part1(input_path: &str) -> Result<usize> {
Ok(strings Ok(strings
.iter() .iter()
.filter(|s| { .filter(|s| {
let result = string_matches_rule(&s, &rules, &rules[&0], true); let results = string_matches_rule(&s, &rules, &rules[&0], true);
result.1 && result.0.is_empty() results.iter().any(|result| result.1 && result.0.is_empty())
}) })
.count()) .count())
} }
@ -158,8 +168,8 @@ fn solve_part2(input_path: &str) -> Result<usize> {
Ok(strings Ok(strings
.into_iter() .into_iter()
.filter(|s| { .filter(|s| {
let result = string_matches_rule(&s, &rules, &rules[&0], true); let results = string_matches_rule(&s, &rules, &rules[&0], true);
result.1 && result.0.is_empty() results.iter().any(|result| result.1 && result.0.is_empty())
}) })
.count()) .count())
} }
@ -214,7 +224,7 @@ mod tests {
#[test] #[test]
fn solves_part2() { fn solves_part2() {
assert_eq!(solve_part1(TEST_INPUT2).unwrap(), 3); assert_eq!(solve_part1(TEST_INPUT2).unwrap(), 3);
assert_eq!(solve_part1(TEST_INPUT3).unwrap(), 6); assert_eq!(solve_part1(TEST_INPUT3).unwrap(), 1);
assert_eq!(solve_part2(TEST_INPUT2).unwrap(), 12); assert_eq!(solve_part2(TEST_INPUT2).unwrap(), 12);
} }
} }