diff --git a/README.md b/README.md index 1a895f1..9b067b8 100644 --- a/README.md +++ b/README.md @@ -45,9 +45,9 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www. | [Day 12](./src/bin/12.rs) | `137.9µs` | `618.3µs` | | [Day 13](./src/bin/13.rs) | `12.3µs` | `15.9µs` | | [Day 14](./src/bin/14.rs) | `26.4µs` | `4.3ms` | -| [Day 15](./src/bin/15.rs) | `20.4µs` | `143.7µs` | +| [Day 15](./src/bin/15.rs) | `20.4µs` | `85.9µs` | -**Total: 6.87ms** +**Total: 6.82ms** --- diff --git a/data/examples/15.txt b/data/examples/15.txt index 62f7ed0..4f58f74 100644 --- a/data/examples/15.txt +++ b/data/examples/15.txt @@ -1 +1 @@ -rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7 \ No newline at end of file +rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7 diff --git a/src/bin/15.rs b/src/bin/15.rs index 9303ad3..c15a433 100644 --- a/src/bin/15.rs +++ b/src/bin/15.rs @@ -61,43 +61,31 @@ impl<'a> From<&'a [u8]> for Operation<'a> { } struct LensMap<'a> { - boxes: [List>; 256], -} - -struct List { - head: Option, - tail: Option, - elems: Vec>>, - next_free: usize, - len: usize, -} - -struct ListElement { - value: T, - next: Option, - prev: Option, + boxes: [Vec>; 256], } impl<'a> LensMap<'a> { pub const fn new() -> Self { - const EMPTY_LIST: List = List::new(); + const EMPTY_VEC: Vec = Vec::new(); Self { - boxes: [EMPTY_LIST; 256], + boxes: [EMPTY_VEC; 256], } } pub fn upsert(&mut self, lens: Lens<'a>) { - let hash = self.hash(lens.label) as usize; - if let Some(el) = self.boxes[hash].find(|el| el.label == lens.label) { + let b = &mut self.boxes[self.hash(lens.label) as usize]; + if let Some(el) = b.iter_mut().find(|el| el.label == lens.label) { el.focal_length = lens.focal_length; return; } - self.boxes[hash].push(lens); + b.push(lens); } pub fn remove(&mut self, label: &[u8]) { - let hash = self.hash(label) as usize; - self.boxes[hash].remove_one_with(|el| el.label == label); + let b = &mut self.boxes[self.hash(label) as usize]; + if let Some(index) = b.iter().position(|el| el.label == label) { + b.remove(index); + } } pub fn focusing_power(&self) -> u32 { @@ -121,140 +109,6 @@ impl<'a> LensMap<'a> { } } -impl List { - pub const fn new() -> Self { - Self { - elems: vec![], - next_free: 0, - head: None, - tail: None, - len: 0, - } - } - - #[allow(unused)] - pub const fn len(&self) -> usize { - self.len - } - - #[allow(unused)] - pub const fn is_empty(&self) -> bool { - self.len == 0 - } - - pub fn iter(&self) -> impl Iterator { - self.into_iter() - } - - pub fn find bool>(&mut self, f: F) -> Option<&mut T> { - self.elems - .iter_mut() - .flatten() - .find_map(|el| f(&el.value).then_some(&mut el.value)) - } - - pub fn push(&mut self, elem: T) { - if self.next_free >= self.elems.len() { - self.elems - .resize_with((2 * self.elems.len()).max(8), Default::default); - } - let index = self.next_free; - self.elems[index] = Some(ListElement { - value: elem, - next: None, - prev: None, - }); - self.len += 1; - match self.tail { - None => { - self.head = Some(index); - self.tail = Some(index); - } - Some(tail) => { - self.elems[tail].as_mut().unwrap().next = Some(index); - self.elems[index].as_mut().unwrap().prev = Some(tail); - self.tail = Some(index); - } - } - self.find_next_free(); - } - - pub fn remove_one_with bool>(&mut self, f: F) { - let Some(index) = - (0..self.elems.len()).find(|&i| matches!(&self.elems[i], Some(elem) if f(&elem.value))) - else { - return; - }; - let (prev, next) = { - let elem = self.elems[index].as_ref().unwrap(); - (elem.prev, elem.next) - }; - if let Some(Some(prev)) = self.elems[index] - .as_ref() - .unwrap() - .prev - .map(|i| &mut self.elems[i]) - { - prev.next = next; - } - if let Some(Some(next)) = self.elems[index] - .as_ref() - .unwrap() - .next - .map(|i| &mut self.elems[i]) - { - next.prev = prev; - } - if matches!(self.head, Some(i) if i == index) { - self.head = next; - } - if matches!(self.tail, Some(i) if i == index) { - self.tail = prev; - } - self.elems[index] = None; - self.len -= 1; - if self.next_free >= self.elems.len() { - self.next_free = index; - } - } - - fn find_next_free(&mut self) { - while self.next_free < self.elems.len() && self.elems[self.next_free].is_some() { - self.next_free += 1; - } - } -} - -impl<'a, T> IntoIterator for &'a List { - type Item = &'a T; - - type IntoIter = ListIterator<'a, T>; - - fn into_iter(self) -> Self::IntoIter { - Self::IntoIter { - list: self, - next: self.head, - } - } -} -struct ListIterator<'a, T> { - list: &'a List, - next: Option, -} - -impl<'a, T> Iterator for ListIterator<'a, T> { - type Item = &'a T; - - fn next(&mut self) -> Option { - let next = self.next?; - let elem = self.list.elems[next] - .as_ref() - .expect("should be an element at the stored index"); - self.next = elem.next; - Some(&elem.value) - } -} - #[cfg(test)] mod tests { use super::*; @@ -270,52 +124,4 @@ mod tests { let result = part_two(&advent_of_code::template::read_file("examples", DAY)); assert_eq!(result, Some(145)); } - - #[test] - fn test_list() { - let mut list = List::::new(); - assert!(list.is_empty()); - assert_eq!(list.iter().copied().collect::>(), vec![]); - - list.push(5); - assert!(!list.is_empty()); - assert_eq!(list.len(), 1); - assert_eq!(list.iter().copied().collect::>(), vec![5]); - - list.remove_one_with(|&el| el < 4); - assert!(!list.is_empty()); - assert_eq!(list.len(), 1); - assert_eq!(list.iter().copied().collect::>(), vec![5]); - - list.remove_one_with(|&el| el < 10); - assert!(list.is_empty()); - assert_eq!(list.iter().copied().collect::>(), vec![]); - - list.push(1); - list.push(2); - list.push(3); - assert!(!list.is_empty()); - assert_eq!(list.len(), 3); - assert_eq!(list.iter().copied().collect::>(), vec![1, 2, 3]); - - list.remove_one_with(|&el| el == 2); - assert!(!list.is_empty()); - assert_eq!(list.len(), 2); - assert_eq!(list.iter().copied().collect::>(), vec![1, 3]); - - list.push(5); - assert_eq!(list.iter().copied().collect::>(), vec![1, 3, 5]); - - list.remove_one_with(|&el| el > 1); - list.remove_one_with(|&el| el > 1); - assert_eq!(list.iter().copied().collect::>(), vec![1]); - - for i in 2..20 { - list.push(i); - } - assert_eq!( - list.iter().copied().collect::>(), - (1..20).collect::>() - ); - } }