2020/19/2

This commit is contained in:
kageru 2020-12-19 13:02:01 +01:00
parent cd6b531a5e
commit ca14b85812
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2

View File

@ -23,29 +23,42 @@ type Parsed<'a> = (RuleSet, &'a str);
struct RuleSet(Vec<Rule>); struct RuleSet(Vec<Rule>);
impl RuleSet { impl RuleSet {
fn matches(&self, s: &str, rule: Rule) -> Option<usize> { fn matches(&self, s: &str, rule: Rule) -> Vec<usize> {
if s.len() == 0 { if s.len() == 0 {
return None; return vec![];
} }
let res = match rule { match rule {
Rule::Char(c) => (s.as_bytes().first() == Some(&c)).then_some(1), Rule::Char(c) => (s.as_bytes().first() == Some(&c)).then(|| vec![1]).unwrap_or_else(Vec::new),
Rule::And((r1, r2)) => self Rule::And((r1, r2)) => self
.matches(s, self.0[r1]) .matches(s, self.0[r1])
.and_then(|i| self.matches(&s[i..], self.0[r2]).map(|j| i + j)), .into_iter()
.flat_map(|i| self.matches(&s[i..], self.0[r2]).into_iter().map(move |j| i + j))
.collect(),
Rule::AndOr((r1, r2), (r3, r4)) => self Rule::AndOr((r1, r2), (r3, r4)) => self
.matches(s, Rule::And((r1, r2))) .matches(s, Rule::And((r1, r2)))
.or_else(|| self.matches(s, Rule::And((r3, r4)))), .into_iter()
Rule::Or((r1, r2)) => self.matches(s, Rule::Useless(r1)).or_else(|| self.matches(s, self.0[r2])), .chain(self.matches(s, Rule::And((r3, r4))))
.collect(),
Rule::Or((r1, r2)) => self.matches(s, self.0[r1]).into_iter().chain(self.matches(s, self.0[r2])).collect(),
Rule::Useless(r) => self.matches(s, self.0[r]), Rule::Useless(r) => self.matches(s, self.0[r]),
// part 2 shit below: // part 2 shit below:
Rule::Special8(first, second) => self.matches(s, self.0[first]).or_else(|| self.matches(s, Rule::And(second))), Rule::Special8(first, second) => self
Rule::Special11(first, second) => self.matches(s, Rule::And(first)).or_else(|| self.matches(s, Rule::Triple(second))), .matches(s, self.0[first])
.into_iter()
.chain(self.matches(s, Rule::And(second)))
.collect(),
Rule::Special11(first, second) => self
.matches(s, Rule::And(first))
.into_iter()
.chain(self.matches(s, Rule::Triple(second)))
.collect(),
Rule::Triple((r1, r2, r3)) => self Rule::Triple((r1, r2, r3)) => self
.matches(s, self.0[r1]) .matches(s, self.0[r1])
.and_then(|i| self.matches(&s[i..], self.0[r2]).map(|j| i + j)) .into_iter()
.and_then(|i| self.matches(&s[i..], self.0[r3]).map(|j| i + j)), .flat_map(|i| self.matches(&s[i..], self.0[r2]).into_iter().map(move |j| i + j))
}; .flat_map(|i| self.matches(&s[i..], self.0[r3]).into_iter().map(move |j| i + j))
res .collect(),
}
} }
} }
@ -81,7 +94,7 @@ fn parse_input<'a>(raw: &'a str) -> Parsed<'a> {
} }
fn part1((rules, input): &Parsed) -> usize { fn part1((rules, input): &Parsed) -> usize {
input.lines().filter(|l| rules.matches(l, rules.0[0]) == Some(l.len())).count() input.lines().filter(|l| rules.matches(l, rules.0[0]).contains(&l.len())).count()
} }
fn part2(parsed: &Parsed) -> usize { fn part2(parsed: &Parsed) -> usize {
@ -89,14 +102,13 @@ fn part2(parsed: &Parsed) -> usize {
rules.0[8] = Rule::Special8(42, (42, 8)); rules.0[8] = Rule::Special8(42, (42, 8));
rules.0[11] = Rule::Special11((42, 31), (42, 11, 31)); rules.0[11] = Rule::Special11((42, 31), (42, 11, 31));
dbg!(parsed.1.lines().map(|l| (l, rules.matches(l, rules.0[0]))).collect_vec()); dbg!(parsed.1.lines().map(|l| (l, rules.matches(l, rules.0[0]))).collect_vec());
parsed.1.lines().filter(|l| rules.matches(l, rules.0[0]) == Some(l.len())).count() parsed.1.lines().filter(|l| rules.matches(l, rules.0[0]).contains(&l.len())).count()
} }
fn main() { fn main() {
let raw = read_input(); let raw = read_input();
let input = parse_input(&raw); let input = parse_input(&raw);
println!("Part 1: {}", part1(&input)); println!("Part 1: {}", part1(&input));
// 265 too low, 395 too high. apparently 379? no idea how that’s supposed to work
println!("Part 2: {}", part2(&input)); println!("Part 2: {}", part2(&input));
} }
@ -170,6 +182,6 @@ aabbbbbaabbbaaaaaabbbbbababaaaaabbaaabba"#;
test!(part1() == 3); test!(part1() == 3);
test!(part2() == 12); test!(part2() == 12);
bench!(part1() == 235); bench!(part1() == 235);
// bench!(part2() == 0); bench!(part2() == 379);
// bench_input!(0.len == 0); // bench_input!(0.len == 0);
} }