Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
Martin Ockajak committed Jul 9, 2024
1 parent 6ad3fa8 commit c60120a
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 6 deletions.
77 changes: 71 additions & 6 deletions src/extensions/collectible.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use std::iter::{Product, Sum};
pub trait Collectible<Item>: IntoIterator<Item = Item> {
// FIXME - implement these methods
// cartesian_product
// combinations_repetitive

/// Original collection type
type This<I>;
Expand Down Expand Up @@ -155,6 +154,35 @@ pub trait Collectible<Item>: IntoIterator<Item = Item> {
Item: Clone,
Self: Sized;

/// Creates a collection containing all combinations with repetition of specified size
/// from the elements of the original collection.
///
/// The order or combined values is preserved for ordered collections.
///
/// # Example
///
/// ```
/// use cantrip::*;
///
/// let a = vec![1, 2, 3];
///
/// assert_eq!(a.combinations_repetitive(1), vec![vec![1], vec![2], vec![3]]);
/// assert_eq!(
/// a.combinations_repetitive(2),
/// vec![vec![1, 1], vec![1, 2], vec![1, 3], vec![2, 2], vec![2, 3], vec![3, 3]]
/// );
/// assert_eq!(
/// a.combinations_repetitive(3), vec![
/// vec![1, 1, 1], vec![1, 1, 2], vec![1, 1, 3], vec![1, 2, 2], vec![1, 2, 3],
/// vec![1, 3, 3], vec![2, 2, 2], vec![2, 2, 3], vec![2, 3, 3], vec![3, 3, 3],
/// ]
/// );
/// ```
fn combinations_repetitive(&self, k: usize) -> Vec<Self>
where
Item: Clone,
Self: Sized;

/// Creates a collection containing an element
/// specified number of times.
///
Expand Down Expand Up @@ -1347,32 +1375,69 @@ where
compute_combinations(&values, k)
}

pub(crate) fn combinations_repetitive<'a, Item, Collection>(
iterator: impl Iterator<Item = &'a Item>, k: usize,
) -> Vec<Collection>
where
Item: Clone + 'a,
Collection: FromIterator<Item> + Sized,
{
if k == 0 {
return Vec::from_iter(iter::once(Collection::from_iter(iter::empty())));
}
let values = Vec::from_iter(iterator);
let size = values.len();
let mut combination = Vec::fill(0, k);
unfold(k > size, |done| {
if *done {
return None;
}
let result = Some(Collection::from_iter(combination.iter().map(|index| values[*index].clone())));
let mut current_slot = k - 1;
while combination[current_slot] >= size - 1 {
if current_slot > 0 {
current_slot -= 1;
} else {
*done = true;
return result;
}
}
let current_index = combination[current_slot] + 1;
#[allow(clippy::needless_range_loop)]
for slot in current_slot..k {
combination[slot] = current_index;
}
result
})
.collect()
}

pub(crate) fn compute_combinations<'a, Item, Collection>(values: &[&Item], k: usize) -> Vec<Collection>
where
Item: Clone + 'a,
Collection: FromIterator<Item> + Sized,
{
let size = values.len();
let mut combination_indices = Vec::from_iter(0..k);
let mut combination = Vec::from_iter(0..k);
unfold(k > size, |done| {
if *done {
return None;
}
let result = Some(Collection::from_iter(combination_indices.iter().map(|index| values[*index].clone())));
let result = Some(Collection::from_iter(combination.iter().map(|index| values[*index].clone())));
let mut current_slot = k - 1;
while combination_indices[current_slot] >= size + current_slot - k {
while combination[current_slot] >= size + current_slot - k {
if current_slot > 0 {
current_slot -= 1;
} else {
*done = true;
return result;
}
}
let mut current_index = combination_indices[current_slot];
let mut current_index = combination[current_slot];
#[allow(clippy::needless_range_loop)]
for slot in current_slot..k {
current_index += 1;
combination_indices[slot] = current_index;
combination[slot] = current_index;
}
result
})
Expand Down
9 changes: 9 additions & 0 deletions src/extensions/collections/binary_heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ impl<Item: Ord> Collectible<Item> for BinaryHeap<Item> {
combinations(self.iter(), k)
}

#[inline]
fn combinations_repetitive(&self, k: usize) -> Vec<Self>
where
Item: Clone,
Self: Sized
{
combinations_repetitive(self.iter(), k)
}

#[inline]
fn filter_map<B>(&self, function: impl FnMut(&Item) -> Option<B>) -> Self::This<B>
where
Expand Down
9 changes: 9 additions & 0 deletions src/extensions/collections/btree_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ impl<Item: Ord> Collectible<Item> for BTreeSet<Item> {
combinations(self.iter(), k)
}

#[inline]
fn combinations_repetitive(&self, k: usize) -> Vec<Self>
where
Item: Clone,
Self: Sized
{
combinations_repetitive(self.iter(), k)
}

#[inline]
fn filter_map<B>(&self, function: impl FnMut(&Item) -> Option<B>) -> Self::This<B>
where
Expand Down
9 changes: 9 additions & 0 deletions src/extensions/collections/hash_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ impl<Item: Eq + Hash> Collectible<Item> for HashSet<Item> {
combinations(self.iter(), k)
}

#[inline]
fn combinations_repetitive(&self, k: usize) -> Vec<Self>
where
Item: Clone,
Self: Sized
{
combinations_repetitive(self.iter(), k)
}

#[inline]
fn filter_map<B>(&self, function: impl FnMut(&Item) -> Option<B>) -> Self::This<B>
where
Expand Down
9 changes: 9 additions & 0 deletions src/extensions/collections/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ impl<Item> Collectible<Item> for LinkedList<Item> {
combinations(self.iter(), k)
}

#[inline]
fn combinations_repetitive(&self, k: usize) -> Vec<Self>
where
Item: Clone,
Self: Sized
{
combinations_repetitive(self.iter(), k)
}

#[inline]
fn filter_map<B>(&self, function: impl FnMut(&Item) -> Option<B>) -> Self::This<B>
where
Expand Down
9 changes: 9 additions & 0 deletions src/extensions/collections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ impl<Item> Collectible<Item> for Vec<Item> {
combinations(self.iter(), k)
}

#[inline]
fn combinations_repetitive(&self, k: usize) -> Vec<Self>
where
Item: Clone,
Self: Sized,
{
combinations_repetitive(self.iter(), k)
}

#[inline]
fn filter_map<B>(&self, function: impl FnMut(&Item) -> Option<B>) -> Self::This<B>
where
Expand Down
9 changes: 9 additions & 0 deletions src/extensions/collections/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ impl<Item> Collectible<Item> for VecDeque<Item> {
combinations(self.iter(), k)
}

#[inline]
fn combinations_repetitive(&self, k: usize) -> Vec<Self>
where
Item: Clone,
Self: Sized
{
combinations_repetitive(self.iter(), k)
}

#[inline]
fn filter_map<B>(&self, function: impl FnMut(&Item) -> Option<B>) -> Self::This<B>
where
Expand Down

0 comments on commit c60120a

Please sign in to comment.