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