aoc2022/src/bin/day3.rs

68 lines
2.3 KiB
Rust
Raw Normal View History

2022-12-15 13:20:33 +00:00
/** Solution for Advent of Code 2022 day 3.
* https://adventofcode.com/2022/day/3
*/
use aoc2022::StdError;
use std::collections::HashSet;
use std::fs::File;
use std::io::{BufRead, BufReader};
2022-12-15 18:49:47 +00:00
// Map a character (indicating an "item") to its "priority".
fn char_to_prio(c: char) -> u32 {
// Fortunately we can cast all chars to u32, which makes this a matter of some simple
// arithmetic.
match c {
'a'..='z' => c as u32 - 'a' as u32 + 1,
'A'..='Z' => c as u32 - 'A' as u32 + 27,
_ => panic!("Got non-ascii alphabetic char!"),
}
}
2022-12-15 13:20:33 +00:00
fn main() -> StdError<()> {
// Open the input file and split all the lines.
let lines: Vec<_> = BufReader::new(File::open("input/day3.txt")?)
.lines()
.collect::<Result<_, _>>()?; // "Short circuit" any Errors in the iterator
2022-12-15 18:49:47 +00:00
let part1: u32 = lines
2022-12-15 13:20:33 +00:00
.iter()
.map(|l| {
assert!(l.len() % 2 == 0); // We won't be able to evenly split a odd-length line!
let (one, two) = (&l[0..l.len() / 2], &l[l.len() / 2..]);
// Make sets out of the characters in each compartment...
HashSet::<char>::from_iter(one.chars())
// ... then calculate the intersection, giving us the "items" (chars) in common
.intersection(&HashSet::from_iter(two.chars()))
2022-12-15 18:49:47 +00:00
.map(|c| char_to_prio(*c))
2022-12-15 13:20:33 +00:00
.sum::<u32>() // Sum the priorities of items in common in each "rucksack"
})
.sum(); // Sum all the rucksacks' priorities
2022-12-15 18:49:47 +00:00
println!("Part 1: {}", part1);
let part2: u32 = lines
// First, map our lines to hashsets of their chars
.iter()
.map(|l| HashSet::from_iter(l.chars()))
.collect::<Vec<_>>()
// Then split them into chunks of 3
.chunks(3)
.map(|c: &[HashSet<_>]| {
// And reduce each chunk of 3 into a single intersection of chars...
let common: Vec<char> = c
.into_iter()
.cloned()
.reduce(|acc, s| acc.intersection(&s).cloned().collect())
.unwrap()
.into_iter()
.collect();
// ... which should only be one!
assert!(common.len() == 1);
common[0]
})
.map(char_to_prio)
.sum();
println!("Part 2: {}", part2);
2022-12-15 13:20:33 +00:00
Ok(())
}