diff --git a/src/day15.rs b/src/day15.rs index 500ce3e..6cec2d6 100644 --- a/src/day15.rs +++ b/src/day15.rs @@ -1,4 +1,4 @@ -use itertools::Itertools; +use std::collections::HashMap; use std::io; fn hash(s: &str) -> u64 { @@ -19,20 +19,11 @@ pub fn hash_sequence() -> u64 { buffer.trim().split(',').map(hash).sum() } -#[derive(Eq, PartialEq, Copy, Clone, Hash)] enum Op<'a> { Add(&'a str, u64), Rem(&'a str), } -fn same_operand(a: &Op, b: &Op) -> bool { - match a { - Op::Add(s, _) | Op::Rem(s) => match b { - Op::Add(t, _) | Op::Rem(t) => s == t, - }, - } -} - fn parseop<'a>(op: &'a str) -> Op<'a> { if op.ends_with('-') { Op::Rem(&op[0..op.len() - 1]) @@ -47,24 +38,35 @@ fn parse<'a>(ops: &Vec<&'a str>) -> Vec> { } fn condense<'a>(ops: &Vec>) -> Vec> { + let mut last_delete_map = HashMap::new(); + ops.iter().enumerate().for_each(|(i, op)| { + if let Op::Rem(opstr) = op { + last_delete_map.insert(opstr, i); + } + }); let remove_deletes = ops.iter().enumerate().filter(|(i, op)| match op { Op::Rem(_) => false, - Op::Add(_, _) => !ops - .iter() - .rposition(|lop| same_operand(op, lop) && matches!(*lop, Op::Rem(_))) - .is_some_and(|j| j > *i), + Op::Add(opstr, _) => !last_delete_map.get(opstr).is_some_and(|j| j > i), }); - let remove_deletes_clone = remove_deletes.clone(); - let map_to_last = remove_deletes.map(|(_, op)| { - *remove_deletes_clone - .clone() - .rfind(|(_, rop)| same_operand(op, rop)) - .unwrap() - .1 + let mut last_value_map = HashMap::new(); + remove_deletes.clone().for_each(|(_, op)| { + if let Op::Add(s, v) = op { + last_value_map.insert(s, v); + } }); - let map_unique = map_to_last.into_iter().unique(); - map_unique.collect() + + let map_to_last = remove_deletes.filter_map(|(_, op)| { + if let Op::Add(opstr, _) = op { + match last_value_map.remove(opstr) { + Some(v) => Some(Op::Add(opstr, *v)), + None => None, + } + } else { + None + } + }); + map_to_last.collect() } fn perform_ops(ops: &Vec<&str>) -> u64 {