Day 2, add handrolled parse to compare against regex.

This commit is contained in:
Bill Thiede 2020-12-02 20:18:20 -08:00
parent bc8de05d69
commit 80b7312bf8
2 changed files with 70 additions and 30 deletions

View File

@ -24,10 +24,14 @@ Day 1 - Part 2 : 165026160
``` ```
AOC 2020 AOC 2020
Day 2 - Part 1 : 640 Day 2 - Part 1 : 640
generator: 1.821498ms, generator: 1.732103ms,
runner: 115.525µs runner: 100.802µs
Day 2 - Part 1 - handrolled : 640
generator: 157.527µs,
runner: 97.775µs
Day 2 - Part 2 : 472 Day 2 - Part 2 : 472
generator: 1.52241ms, generator: 1.374162ms,
runner: 10.459µs runner: 10.461µs
``` ```

View File

@ -44,7 +44,7 @@ struct Policy {
} }
#[aoc_generator(day2)] #[aoc_generator(day2)]
fn parse(input: &str) -> Vec<Policy> { fn parse_regex(input: &str) -> Vec<Policy> {
let re = Regex::new(r"(\d+)-(\d+) (\w): (.*)").expect("Failed to compile regex"); let re = Regex::new(r"(\d+)-(\d+) (\w): (.*)").expect("Failed to compile regex");
input input
.split('\n') .split('\n')
@ -61,6 +61,38 @@ fn parse(input: &str) -> Vec<Policy> {
.collect() .collect()
} }
#[aoc_generator(day2, part1, handrolled)]
fn parse_handrolled(input: &str) -> Vec<Policy> {
// Example line:
// 1-3 a: abcde
input
.split('\n')
.filter_map(|line| {
let start = 0;
let end = line.find('-')?;
let min: usize = line[start..end].parse().ok()?;
let start = end + 1;
let end = line.find(' ')?;
let max: usize = line[start..end].parse().ok()?;
let start = end + 1;
let end = line.find(':')?;
let letter = line[start..end].to_string();
let start = end + 2;
let password = line[start..].to_string();
Some(Policy {
min,
max,
letter,
password,
})
})
.collect()
}
fn is_valid_policy_part1(p: &Policy) -> bool { fn is_valid_policy_part1(p: &Policy) -> bool {
let c = p.password.matches(&p.letter).count(); let c = p.password.matches(&p.letter).count();
p.min <= c && c <= p.max p.min <= c && c <= p.max
@ -71,6 +103,11 @@ fn valid_policy_count_part1(policies: &[Policy]) -> usize {
policies.iter().filter(|p| is_valid_policy_part1(p)).count() policies.iter().filter(|p| is_valid_policy_part1(p)).count()
} }
#[aoc(day2, part1, handrolled)]
fn valid_policy_count_handrolled_part1(policies: &[Policy]) -> usize {
policies.iter().filter(|p| is_valid_policy_part1(p)).count()
}
fn is_valid_policy_part2(p: &Policy) -> bool { fn is_valid_policy_part2(p: &Policy) -> bool {
let letter = Some(p.letter.as_str()); let letter = Some(p.letter.as_str());
// Password system uses it 1 based numbering, so we -1 to get zero based. // Password system uses it 1 based numbering, so we -1 to get zero based.
@ -97,38 +134,37 @@ mod tests {
"#; "#;
#[test] #[test]
fn parse_policies() { fn parse_policies() {
assert_eq!( let want = vec![
parse(INPUT), Policy {
vec![ min: 1,
Policy { max: 3,
min: 1, letter: "a".to_string(),
max: 3, password: "abcde".to_string(),
letter: "a".to_string(), },
password: "abcde".to_string(), Policy {
}, min: 1,
Policy { max: 3,
min: 1, letter: "b".to_string(),
max: 3, password: "cdefg".to_string(),
letter: "b".to_string(), },
password: "cdefg".to_string(), Policy {
}, min: 2,
Policy { max: 9,
min: 2, letter: "c".to_string(),
max: 9, password: "ccccccccc".to_string(),
letter: "c".to_string(), },
password: "ccccccccc".to_string(), ];
}, assert_eq!(parse_regex(INPUT), want);
] assert_eq!(parse_handrolled(INPUT), want);
);
} }
#[test] #[test]
fn validate_count_part1() { fn validate_count_part1() {
assert_eq!(valid_policy_count_part1(&parse(INPUT)), 2); assert_eq!(valid_policy_count_part1(&parse_regex(INPUT)), 2);
} }
#[test] #[test]
fn validate_count_part2() { fn validate_count_part2() {
assert_eq!(valid_policy_count_part2(&parse(INPUT)), 1); assert_eq!(valid_policy_count_part2(&parse_regex(INPUT)), 1);
} }
} }