Advent of Rust // Day 3
I was surprised there’s no built-in way to find the intersection of multiple sets. I started to implement a function for this, but quickly discarded it in favor of a more specific one for the task at hand. After all, there’s exactly one character to find for each bunch of strings.
fn first_intersecting_character(strings: Vec<&str>) -> char {
'next_char: for c in strings[0].chars() {
for s in strings[1..].iter() {
if !s.contains(c) {
continue 'next_char;
}
}
return c;
}
panic!("No intersecting character found");
}
Converting chars to priorites was pretty straightforward once I learned that you can simply cast a char to an int. I also learned that there’s no ternary, but you can use if conditions inline.
fn priority_sum(items: Vec<char>) -> u32 {
return items.iter()
.map(|c| (*c as u32) - if c.is_uppercase() { 38 } else { 96 })
.sum();
}
Plugging it all together was easy. Part one: priority sum of the intersecting character of the left and right half of each line. I wish there was a way to convert a tuple to a vector inline, though.
fn part_one(input: Vec<&str>) -> u32 {
return priority_sum(
input.iter()
.map(|line| {
let (a, b) = line.split_at(line.len() / 2);
return first_intersecting_character(vec![a, b]);
})
.collect()
);
}
Part two: Priority sum of the intersecting character of every chunk of three lines:
fn part_two(input: Vec<&str>) -> u32 {
return priority_sum(
input.chunks(3)
.map(|lines| first_intersecting_character(lines.to_vec()))
.collect()
);
}
I also had a look at how tests work in Rust today. As someone who recently addressed his liking for Colocating Tests and Production Code, I enjoyed putting them right into the same file. Not sure if I’m a fan of assertion arguments named left
and right
instead of expected
and actual
.
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn first_intersecting_character_should_return_only_the_first_if_there_are_multiple_intersections() {
let result = first_intersecting_character(vec!["abcd", "bcde", "cdef"]);
assert_eq!('c', result);
}
#[test]
#[should_panic]
fn first_intersecting_character_should_panic_if_there_is_no_intersecting_character() {
first_intersecting_character(vec!["abc", "def", "ghi"]);
}
#[test]
fn part_one_example() {
let result = part_one(vec![
"vJrwpWtwJgWrhcsFMMfFFhFp",
"jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL",
"PmmdzqPrVvPwwTWBwg",
"wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn",
"ttgJtRGJQctTZtZT",
"CrZsJsPPZsGzwwsLwLmpwMDw",
]);
assert_eq!(157, result);
}
#[test]
fn part_two_example() {
let result = part_two(vec![
"vJrwpWtwJgWrhcsFMMfFFhFp",
"jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL",
"PmmdzqPrVvPwwTWBwg",
"wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn",
"ttgJtRGJQctTZtZT",
"CrZsJsPPZsGzwwsLwLmpwMDw",
]);
assert_eq!(70, result);
}
}
The full source and solutions for the others puzzles of Advent of Code can be found in my GitHub repository.
Comments
You can leave a comment by replying to this post on Mastodon.