pub mod offline;
pub mod online;
pub mod wrapper;
pub trait Pack {
fn size(&self) -> usize;
}
#[derive(Debug)]
#[cfg_attr(test, derive(Eq, PartialEq))]
pub struct Bin<T> {
contents: Vec<T>,
remaining_capacity: usize,
}
impl<T> Bin<T> {
#[doc(hidden)]
pub(crate) const fn with_capacity(capacity: usize) -> Self {
Self {
contents: vec![],
remaining_capacity: capacity,
}
}
#[doc(hidden)]
pub(crate) fn with_item(capacity: usize, item: T) -> Self
where
T: Pack,
{
Self {
remaining_capacity: capacity.saturating_sub(item.size()),
contents: vec![item],
}
}
#[doc(hidden)]
pub(crate) fn with_item_and_size(capacity: usize, item: T, size: usize) -> Self {
Self {
remaining_capacity: capacity.saturating_sub(size),
contents: vec![item],
}
}
#[doc(hidden)]
pub(crate) fn add(&mut self, item: T)
where
T: Pack,
{
self.remaining_capacity = self.remaining_capacity.saturating_sub(item.size());
self.contents.push(item);
}
#[doc(hidden)]
pub(crate) fn add_with_size(&mut self, item: T, size: usize) {
self.remaining_capacity = self.remaining_capacity.saturating_sub(size);
self.contents.push(item);
}
pub fn contents(&self) -> &[T] {
&self.contents
}
pub fn into_contents(self) -> Vec<T> {
self.contents
}
pub fn map<U>(self, transform_fn: impl Fn(T) -> U) -> Bin<U> {
Bin {
contents: self.contents.into_iter().map(transform_fn).collect(),
remaining_capacity: self.remaining_capacity,
}
}
}
#[cfg(test)]
pub mod tests {
use super::*;
#[allow(dead_code)]
#[derive(Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct MyItem {
pub size: usize,
}
impl Pack for MyItem {
fn size(&self) -> usize {
self.size
}
}
#[allow(dead_code)]
#[derive(Debug, Eq, PartialEq)]
pub struct MyItemUnpacked {
pub size: usize,
}
impl MyItem {
pub fn make_unpacked(self) -> MyItemUnpacked {
MyItemUnpacked { size: self.size }
}
}
pub fn generate_test_set_a() -> (Vec<MyItem>, usize) {
(
vec![
MyItem { size: 1 },
MyItem { size: 1 },
MyItem { size: 1 },
MyItem { size: 1 },
MyItem { size: 3 },
MyItem { size: 4 },
MyItem { size: 10 },
MyItem { size: 10 },
MyItem { size: 10 },
MyItem { size: 19 },
MyItem { size: 19 },
],
20,
)
}
pub fn generate_test_bins(bin_size: usize, data: Vec<Vec<usize>>) -> Vec<Bin<MyItem>> {
data.into_iter()
.map(|bin_data| expected_test_bin(bin_size, bin_data))
.collect::<Vec<_>>()
}
pub fn expected_test_bin(bin_size: usize, data: Vec<usize>) -> Bin<MyItem> {
Bin {
contents: data.iter().map(|i| MyItem { size: *i }).collect::<Vec<_>>(),
remaining_capacity: bin_size - data.iter().sum::<usize>(),
}
}
}