-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlib.rs
90 lines (72 loc) · 1.79 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use common::Answer;
use rustc_hash::FxHashMap;
fn parse(s: &str) -> (Vec<&str>, Vec<&str>) {
let mut parts = s.split("\n\n");
let mut patterns = parts
.next()
.unwrap()
.split_whitespace()
.flat_map(|s| s.split(','))
.filter(|s| !s.is_empty())
.collect::<Vec<_>>();
patterns.sort_by_key(|s| !s.len());
let designs = parts.next().unwrap().lines().collect();
(patterns, designs)
}
fn count_possible<'a, 'b>(
design: &'b str,
patterns: &'a Vec<&'b str>,
cache: &'a mut FxHashMap<&'b str, usize>,
) -> usize {
if let Some(value) = cache.get(design) {
*value
} else {
let sum = patterns
.iter()
.filter(|&pattern| design.starts_with(pattern))
.map(|&pattern| count_possible(&design[pattern.len()..], patterns, cache))
.sum();
cache.insert(design, sum);
sum
}
}
fn possible_designs(s: &str) -> Vec<usize> {
let (patterns, designs) = parse(s);
let mut cache = FxHashMap::default();
cache.insert("", 1);
designs
.into_iter()
.map(|design| count_possible(design, &patterns, &mut cache))
.collect()
}
pub fn step1(s: &str) -> Answer {
possible_designs(s)
.into_iter()
.filter(|value| *value != 0)
.count()
.into()
}
pub fn step2(s: &str) -> Answer {
possible_designs(s).iter().sum::<usize>().into()
}
#[cfg(test)]
mod test {
use super::*;
const INPUT: &str = r#"r, wr, b, g, bwu, rb, gb, br
brwrr
bggr
gbbr
rrbgbr
ubwu
bwurrg
brgr
bbrgwb"#;
#[test]
fn step1_example_correct_answer() {
assert_eq!(step1(INPUT), Answer::Unsigned(6));
}
#[test]
fn step2_example_correct_answer() {
assert_eq!(step2(INPUT), Answer::Unsigned(16));
}
}