This commit is contained in:
Joseph Montanaro 2022-12-04 20:38:46 -08:00
parent 86eb94514e
commit 3bc97158bc
3 changed files with 107 additions and 12 deletions

View File

@ -15,6 +15,10 @@ path = "src/day1.rs"
name = "day2" name = "day2"
path = "src/day2.rs" path = "src/day2.rs"
[[bin]]
name = "day3"
path = "src/day3.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]

103
2022/src/day3.rs Normal file
View File

@ -0,0 +1,103 @@
use std::str::FromStr;
const DATA: &'static str = include_str!("../data/day3.txt");
// const DATA: &'static str = "
// vJrwpWtwJgWrhcsFMMfFFhFp
// jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
// PmmdzqPrVvPwwTWBwg
// wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
// ttgJtRGJQctTZtZT
// CrZsJsPPZsGzwwsLwLmpwMDw
// ";
#[derive(Debug)]
enum DataError {
Imbalanced,
UnknownValue,
NoDuplicate,
NoTriplicate,
ShortGroup,
}
struct Rucksack {
left: Vec<u8>,
right: Vec<u8>,
}
impl Rucksack {
fn find_duplicate(&self) -> Option<u8> {
// pretty sure this is faster than hash set, given the sizes involved
self.left.iter()
.find(|c| self.right.contains(c))
.map(|c| *c)
}
fn iter_all(&self) -> impl Iterator<Item = &u8> {
self.left.iter().chain(self.right.iter())
}
fn contains(&self, v: u8) -> bool {
self.left.contains(&v) || self.right.contains(&v)
}
}
impl FromStr for Rucksack {
type Err = DataError;
fn from_str(line: &str) -> Result<Rucksack, DataError> {
let line = line.trim();
if line.len() % 2 != 0 {
return Err(DataError::Imbalanced);
}
let (a, b) = line.as_bytes().split_at(line.len() / 2);
Ok(Rucksack {
left: a.into(),
right: b.into(),
})
}
}
fn priority(c: u8) -> Result<u64, DataError> {
match c {
// lowercase
97..=122 => Ok(c as u64 - 96),
// uppercase
65..=90 => Ok(c as u64 - 38),
_ => Err(DataError::UnknownValue),
}
}
fn main() -> Result<(), DataError> {
let mut dup_total = 0;
let rucks = DATA.trim()
.split("\n")
.map(|line| Rucksack::from_str(line))
.collect::<Result<Vec<Rucksack>, DataError>>()?;
for ruck in rucks.iter() {
let dup = ruck.find_duplicate()
.ok_or(DataError::NoDuplicate)?;
dup_total += priority(dup)?;
}
println!("Part 1: {dup_total}");
let mut groups_total = 0;
for (idx, ruck) in rucks.iter().enumerate().step_by(3) {
if idx > rucks.len() - 3 {
return Err(DataError::ShortGroup);
}
let badge = *ruck.iter_all()
.find(|&v| rucks[idx + 1].contains(*v) && rucks[idx + 2].contains(*v))
.ok_or(DataError::NoTriplicate)?;
groups_total += priority(badge)?;
}
println!("Part 2: {groups_total}");
Ok(())
}

View File

@ -1,12 +0,0 @@
#[allow(unused_macros)]
macro_rules! get_data {
($filename: literal) => {
include_str!(concat!("../data/", $filename, ".txt"))
}
}
#[allow(dead_code)]
fn main() {
todo!();
}