1
0
Fork 0

day(15): add solution

Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
Matej Focko 2023-12-16 15:27:19 +01:00
parent 911e1f6342
commit 57d3761793
Signed by: mfocko
GPG key ID: 7C47D46246790496
2 changed files with 119 additions and 0 deletions

1
samples/day15.txt Normal file
View file

@ -0,0 +1 @@
rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7

118
src/bin/day15.rs Normal file
View file

@ -0,0 +1,118 @@
use std::str::FromStr;
use aoc_2023::*;
type Output1 = i32;
type Output2 = Output1;
fn hash_algorithm(s: &str) -> i32 {
s.chars().fold(0, |mut h, c| {
let mut b = [0];
c.encode_utf8(&mut b);
h += b[0] as i32;
h *= 17;
h %= 256;
h
})
}
enum Step {
Del(String),
Ins(String, i32),
}
impl FromStr for Step {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (label, focal_length) = s.split_once(['=', '-']).unwrap();
Ok(match focal_length {
"" => Step::Del(label.to_owned()),
_ => Step::Ins(label.to_owned(), focal_length.parse().unwrap()),
})
}
}
impl Step {
fn hash_step(&self) -> i32 {
let original = match self {
Step::Del(label) => format!("{}-", label),
Step::Ins(label, length) => format!("{}={}", label, length),
};
hash_algorithm(&original)
}
fn label(&self) -> &str {
match self {
Step::Del(l) | Step::Ins(l, _) => l,
}
}
fn hash_label(&self) -> i32 {
hash_algorithm(self.label())
}
}
struct Day15 {
steps: Vec<Step>,
}
impl Solution<Output1, Output2> for Day15 {
fn new<P: AsRef<Path>>(pathname: P) -> Self {
Self {
steps: file_to_string(pathname)
.trim_end()
.split(',')
.map(|s| s.parse().unwrap())
.collect_vec(),
}
}
fn part_1(&mut self) -> Output1 {
self.steps.iter().map(|s| s.hash_step()).sum()
}
fn part_2(&mut self) -> Output2 {
let mut boxes: Vec<Vec<(&str, i32)>> = vec![];
boxes.resize_with(256, Vec::new);
for step in &self.steps {
let h = step.hash_label();
let b: &mut Vec<(&str, i32)> = &mut boxes[h as usize];
match step {
Step::Del(_) => {
if let Some(idx) = b.iter().position(|&(l, _)| l == step.label()) {
b.remove(idx);
}
}
Step::Ins(label, l) => match b.iter().position(|&(l, _)| l == step.label()) {
Some(idx) => b[idx] = (label, *l),
None => b.push((label, *l)),
},
}
}
boxes
.iter()
.enumerate()
.map(|(i, b)| {
b.iter()
.enumerate()
.map(|(j, (_, l))| (i as i32 + 1) * (j as i32 + 1) * l)
.sum::<i32>()
})
.sum()
}
}
fn main() -> Result<()> {
Day15::main()
}
test_sample!(day_15, Day15, 1320, 145);