Day 15
This commit is contained in:
parent
1ac02b2ac7
commit
d9435c84ff
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,202 @@
|
|||
use itertools::Itertools;
|
||||
|
||||
pub fn run() {
|
||||
let input = include_str!("../input/day15.txt");
|
||||
dbg!(sum_hashes(input));
|
||||
let ops = parse_ops(input);
|
||||
let mut boxes: Vec<Vec<Lens>> = vec![vec![]; 256];
|
||||
run_ops(ops, &mut boxes);
|
||||
dbg!(focusing_power(&boxes));
|
||||
}
|
||||
|
||||
fn sum_hashes(s: &str) -> usize {
|
||||
s.trim().split(",").map(hash).sum()
|
||||
}
|
||||
|
||||
fn hash(s: &str) -> usize {
|
||||
assert!(s.is_ascii());
|
||||
let mut res = 0;
|
||||
for c in s.chars() {
|
||||
let cur = c as usize;
|
||||
res += cur;
|
||||
res *= 17;
|
||||
res %= 256;
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn parse_ops(s: &str) -> Vec<Op> {
|
||||
let mut v = vec![];
|
||||
let mut cs = s.trim().chars().peekable();
|
||||
while cs.peek().is_some() {
|
||||
let label = cs
|
||||
.take_while_ref(|&c| c != '-' && c != '=')
|
||||
.collect::<String>();
|
||||
let ty = match cs.next() {
|
||||
Some('-') => OpType::Dash,
|
||||
Some('=') => {
|
||||
let focal_length = cs
|
||||
.take_while_ref(|c| c.is_ascii_digit())
|
||||
.collect::<String>()
|
||||
.parse::<u8>()
|
||||
.unwrap();
|
||||
OpType::Equals(focal_length)
|
||||
}
|
||||
x => panic!("unexpected char {:?}", x),
|
||||
};
|
||||
v.push(Op { label, ty });
|
||||
if cs.peek().is_some() {
|
||||
assert_eq!(cs.next(), Some(','));
|
||||
}
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
struct Op {
|
||||
label: String,
|
||||
ty: OpType,
|
||||
}
|
||||
|
||||
impl Op {
|
||||
fn hash(&self) -> usize {
|
||||
hash(&self.label)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum OpType {
|
||||
Dash,
|
||||
Equals(u8),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
struct Lens {
|
||||
label: String,
|
||||
focal_length: u8,
|
||||
}
|
||||
|
||||
fn run_ops(ops: Vec<Op>, boxes: &mut Vec<Vec<Lens>>) {
|
||||
for op in ops.into_iter() {
|
||||
let hash = op.hash();
|
||||
let existing = boxes[hash]
|
||||
.iter()
|
||||
.find_position(|lens| lens.label == op.label);
|
||||
match op.ty {
|
||||
OpType::Dash => {
|
||||
if let Some((idx, _)) = existing {
|
||||
boxes[hash].remove(idx);
|
||||
}
|
||||
}
|
||||
OpType::Equals(focal_length) => {
|
||||
let new_lens = Lens {
|
||||
label: op.label,
|
||||
focal_length,
|
||||
};
|
||||
if let Some((idx, _)) = existing {
|
||||
boxes[hash][idx] = new_lens;
|
||||
} else {
|
||||
boxes[hash].push(new_lens);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn focusing_power(boxes: &[Vec<Lens>]) -> usize {
|
||||
let mut res = 0;
|
||||
for (i, lenses) in boxes.iter().enumerate() {
|
||||
for (j, lens) in lenses.iter().enumerate() {
|
||||
res += (i + 1) * (j + 1) * lens.focal_length as usize;
|
||||
}
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io::BufRead;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_hash() {
|
||||
assert_eq!(hash("HASH"), 52);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sum_hashes() {
|
||||
assert_eq!(
|
||||
sum_hashes("rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7"),
|
||||
1320
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_ops() {
|
||||
assert_eq!(
|
||||
parse_ops("rn=1,cm-"),
|
||||
vec![
|
||||
Op {
|
||||
label: "rn".into(),
|
||||
ty: OpType::Equals(1)
|
||||
},
|
||||
Op {
|
||||
label: "cm".into(),
|
||||
ty: OpType::Dash
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_run_ops() {
|
||||
let ops = parse_ops("rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7");
|
||||
let mut boxes: Vec<Vec<Lens>> = vec![vec![]; 256];
|
||||
run_ops(ops, &mut boxes);
|
||||
assert_eq!(
|
||||
boxes[0],
|
||||
vec![
|
||||
Lens {
|
||||
label: "rn".into(),
|
||||
focal_length: 1
|
||||
},
|
||||
Lens {
|
||||
label: "cm".into(),
|
||||
focal_length: 2
|
||||
},
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
boxes[3],
|
||||
vec![
|
||||
Lens {
|
||||
label: "ot".into(),
|
||||
focal_length: 7
|
||||
},
|
||||
Lens {
|
||||
label: "ab".into(),
|
||||
focal_length: 5
|
||||
},
|
||||
Lens {
|
||||
label: "pc".into(),
|
||||
focal_length: 6
|
||||
},
|
||||
]
|
||||
);
|
||||
for i in 0..256 {
|
||||
if i == 0 || i == 3 {
|
||||
continue;
|
||||
}
|
||||
assert!(boxes[i].is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_focusing_power() {
|
||||
let ops = parse_ops("rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7");
|
||||
let mut boxes: Vec<Vec<Lens>> = vec![vec![]; 256];
|
||||
run_ops(ops, &mut boxes);
|
||||
assert_eq!(focusing_power(&boxes), 145);
|
||||
}
|
||||
}
|
|
@ -15,7 +15,8 @@ mod day11;
|
|||
mod day12;
|
||||
mod day13;
|
||||
mod day14;
|
||||
mod day15;
|
||||
|
||||
fn main() {
|
||||
day14::run();
|
||||
day15::run();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue