mod hotel_map;
pub use hotel_map::*;
#[derive(Default)]
pub struct Hotel<T> {
floor: Vec<Option<T>>,
holes: Vec<usize>,
}
impl<T: std::fmt::Debug> std::fmt::Debug for Hotel<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[")?;
let mut first = true;
for (_, i) in self.iter() {
if first {
first = false;
} else {
write!(f, ", ")?;
}
write!(f, "{i:?}")?;
}
write!(f, "]")
}
}
impl<T> IntoIterator for Hotel<T> {
type Item = (usize, T);
type IntoIter = HotelIter<T>;
fn into_iter(self) -> Self::IntoIter {
HotelIter {
floor: self.floor,
cursor: 0,
}
}
}
impl<T> Hotel<T> {
pub fn with_capacity(capacity: usize) -> Self {
Hotel {
floor: Vec::with_capacity(capacity),
holes: Vec::new(),
}
}
pub fn new() -> Self {
Hotel {
floor: Vec::new(),
holes: Vec::new(),
}
}
pub fn values(&self) -> impl Iterator<Item = &T> {
self.floor.iter().filter_map(|v| v.as_ref())
}
pub fn put(&mut self, value: T) -> usize {
match self.holes.pop() {
Some(index) => {
self.floor[index] = Some(value);
index
}
None => {
let index = self.floor.len();
self.floor.push(Some(value));
index
}
}
}
pub fn set(&mut self, key: usize, item: T) {
self.floor[key] = Some(item);
}
pub fn get(&self, key: usize) -> Option<&T> {
if let Some(v) = self.floor.get(key).and_then(|v| v.as_ref()) {
Some(v)
} else {
None
}
}
pub fn take(&mut self, key: usize) -> Option<T> {
if self.floor.len() > key && self.floor[key].is_some() {
self.holes.push(key);
return self.floor.remove(key);
}
None
}
pub fn remove(&mut self, key: usize) -> Result<T, ()> {
self.take(key).ok_or(())
}
pub fn iter(&self) -> impl Iterator<Item = (usize, &T)> {
self.floor
.iter()
.enumerate()
.filter_map(|(id, v)| v.as_ref().map(|v| (id, v)))
}
}
pub struct HotelIter<T> {
floor: Vec<Option<T>>,
cursor: usize,
}
impl<T> Iterator for HotelIter<T> {
type Item = (usize, T);
fn next(&mut self) -> Option<Self::Item> {
let cursor = self.cursor;
if cursor >= self.floor.len() {
return None;
}
self.cursor += 1;
if self.floor[cursor].is_none() {
return self.next();
}
let value = self.floor[cursor].take().unwrap();
Some((cursor, value))
}
}
#[cfg(test)]
mod tests {
use super::Hotel;
#[test]
fn inserting() {
let collection = 0..10000;
let mut hotel = Hotel::new();
collection.for_each(|v| {
let key = hotel.put(v);
assert_eq!(key, v as usize);
});
}
#[test]
fn order() {
let collection = 0..10000;
let mut hotel = Hotel::new();
collection.for_each(|v| {
let key = hotel.put(v);
assert_eq!(key, v as usize);
});
hotel.take(0);
hotel.take(15);
hotel.take(32);
hotel.take(3189);
hotel.take(7777);
assert_eq!(hotel.put(0), 7777);
assert_eq!(hotel.put(0), 3189);
assert_eq!(hotel.put(0), 32);
assert_eq!(hotel.put(0), 15);
assert_eq!(hotel.put(0), 0);
}
}