day(15): add solution
Signed-off-by: Matej Focko <me@mfocko.xyz>
This commit is contained in:
parent
911e1f6342
commit
57d3761793
2 changed files with 119 additions and 0 deletions
1
samples/day15.txt
Normal file
1
samples/day15.txt
Normal 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
118
src/bin/day15.rs
Normal 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);
|
Loading…
Reference in a new issue