mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Reinstroduce the humble index set
This commit is contained in:
@@ -133,3 +133,42 @@ pub fn get_both<T>(slice: &mut [T], first: usize, second: usize) -> (&mut T, &mu
|
|||||||
Ordering::Equal => panic!("Tried to get the same index twice {first}"),
|
Ordering::Equal => panic!("Tried to get the same index twice {first}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct IndexSet(Vec<u32>);
|
||||||
|
|
||||||
|
impl IndexSet {
|
||||||
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
|
Self(Vec::with_capacity(
|
||||||
|
capacity / std::mem::size_of::<u32>() / 8,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ensure_item(&mut self, item: usize) -> &mut u32 {
|
||||||
|
if self.0.len() <= item {
|
||||||
|
self.0.resize(item + 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&mut self.0[item]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn index(index: usize) -> (usize, u8) {
|
||||||
|
const PER_ENTRY: usize = 8 * std::mem::size_of::<u32>();
|
||||||
|
|
||||||
|
(index / PER_ENTRY, (index % PER_ENTRY) as u8)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert(&mut self, index: usize) -> bool {
|
||||||
|
let (entry, pos) = Self::index(index);
|
||||||
|
|
||||||
|
let item = self.ensure_item(entry);
|
||||||
|
|
||||||
|
if *item & (1 << pos) != 0 {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
*item |= 1 << pos;
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ use std::collections::VecDeque;
|
|||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::common::IndexSet;
|
||||||
|
|
||||||
fn can_travel(from: u8, to: u8) -> bool {
|
fn can_travel(from: u8, to: u8) -> bool {
|
||||||
match (from, to) {
|
match (from, to) {
|
||||||
(b'S', b'a'..=b'z') => true,
|
(b'S', b'a'..=b'z') => true,
|
||||||
@@ -24,7 +26,7 @@ pub fn part1(input: &[u8]) -> Result<String> {
|
|||||||
.position(|&c| c == b'S')
|
.position(|&c| c == b'S')
|
||||||
.context("Could not find starting position")?;
|
.context("Could not find starting position")?;
|
||||||
|
|
||||||
let mut visited = vec![false; input.len()];
|
let mut visited = IndexSet::with_capacity(input.len());
|
||||||
|
|
||||||
let mut todo = VecDeque::new();
|
let mut todo = VecDeque::new();
|
||||||
todo.push_back((0, starting_pos));
|
todo.push_back((0, starting_pos));
|
||||||
@@ -35,8 +37,7 @@ pub fn part1(input: &[u8]) -> Result<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut add_todo = |new: usize| {
|
let mut add_todo = |new: usize| {
|
||||||
if can_travel(input[pos], input[new]) && !visited[new] {
|
if can_travel(input[pos], input[new]) && visited.insert(new) {
|
||||||
visited[new] = true;
|
|
||||||
todo.push_back((dist + 1, new));
|
todo.push_back((dist + 1, new));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -73,7 +74,7 @@ pub fn part2(input: &[u8]) -> Result<String> {
|
|||||||
.position(|&c| c == b'E')
|
.position(|&c| c == b'E')
|
||||||
.context("Could not find starting position")?;
|
.context("Could not find starting position")?;
|
||||||
|
|
||||||
let mut visited = vec![false; input.len()];
|
let mut visited = IndexSet::with_capacity(input.len());
|
||||||
|
|
||||||
let mut todo = VecDeque::new();
|
let mut todo = VecDeque::new();
|
||||||
todo.push_back((0, starting_pos));
|
todo.push_back((0, starting_pos));
|
||||||
@@ -84,8 +85,7 @@ pub fn part2(input: &[u8]) -> Result<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut add_todo = |new: usize| {
|
let mut add_todo = |new: usize| {
|
||||||
if can_travel(input[new], input[pos]) && !visited[new] {
|
if can_travel(input[new], input[pos]) && visited.insert(new) {
|
||||||
visited[new] = true;
|
|
||||||
todo.push_back((dist + 1, new));
|
todo.push_back((dist + 1, new));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user