Skip to content

Commit

Permalink
turns out vecs are just fast. oh well
Browse files Browse the repository at this point in the history
  • Loading branch information
kcaffrey committed Dec 15, 2023
1 parent 88f7a8a commit d6acc87
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 207 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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**
<!--- benchmarking table --->

---
Expand Down
2 changes: 1 addition & 1 deletion data/examples/15.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7
rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7
214 changes: 10 additions & 204 deletions src/bin/15.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,43 +61,31 @@ impl<'a> From<&'a [u8]> for Operation<'a> {
}

struct LensMap<'a> {
boxes: [List<Lens<'a>>; 256],
}

struct List<T> {
head: Option<usize>,
tail: Option<usize>,
elems: Vec<Option<ListElement<T>>>,
next_free: usize,
len: usize,
}

struct ListElement<T> {
value: T,
next: Option<usize>,
prev: Option<usize>,
boxes: [Vec<Lens<'a>>; 256],
}

impl<'a> LensMap<'a> {
pub const fn new() -> Self {
const EMPTY_LIST: List<Lens> = List::new();
const EMPTY_VEC: Vec<Lens> = 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 {
Expand All @@ -121,140 +109,6 @@ impl<'a> LensMap<'a> {
}
}

impl<T> List<T> {
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<Item = &T> {
self.into_iter()
}

pub fn find<F: Fn(&T) -> 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<F: Fn(&T) -> 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<T> {
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<T>,
next: Option<usize>,
}

impl<'a, T> Iterator for ListIterator<'a, T> {
type Item = &'a T;

fn next(&mut self) -> Option<Self::Item> {
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::*;
Expand All @@ -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::<u32>::new();
assert!(list.is_empty());
assert_eq!(list.iter().copied().collect::<Vec<_>>(), vec![]);

list.push(5);
assert!(!list.is_empty());
assert_eq!(list.len(), 1);
assert_eq!(list.iter().copied().collect::<Vec<_>>(), 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<_>>(), vec![5]);

list.remove_one_with(|&el| el < 10);
assert!(list.is_empty());
assert_eq!(list.iter().copied().collect::<Vec<_>>(), 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<_>>(), 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<_>>(), vec![1, 3]);

list.push(5);
assert_eq!(list.iter().copied().collect::<Vec<_>>(), 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<_>>(), vec![1]);

for i in 2..20 {
list.push(i);
}
assert_eq!(
list.iter().copied().collect::<Vec<_>>(),
(1..20).collect::<Vec<_>>()
);
}
}

0 comments on commit d6acc87

Please sign in to comment.