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 day12;
|
||||||
mod day13;
|
mod day13;
|
||||||
mod day14;
|
mod day14;
|
||||||
|
mod day15;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
day14::run();
|
day15::run();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue