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 45d877c commit d659985
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 43 deletions.
81 changes: 39 additions & 42 deletions src/extensions/collectible.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use crate::extensions::util::unfold::unfold;
pub trait Collectible<Item>: IntoIterator<Item = Item> {
// FIXME - implement these methods
// cartesian_product
// combinations
// combinations_repetitive
// group_fold
// group_fold_with
Expand Down Expand Up @@ -159,42 +158,10 @@ pub trait Collectible<Item>: IntoIterator<Item = Item> {
/// assert_eq!(a.clone().combinations(2), vec![vec![1, 2], vec![1, 3], vec![2, 3]]);
/// assert_eq!(a.combinations(3), vec![vec![1, 2, 3]]);
/// ```
fn combinations(self, k: usize) -> Self::This<Self>
fn combinations(&self, k: usize) -> Vec<Self>
where
Item: Clone,
Self: FromIterator<Item> + Sized,
Self::This<Self>: FromIterator<Self>,
{
if k == 0 {
return Self::This::from_iter(iter::once(Self::from_iter(iter::empty())));
}
let values = Vec::from_iter(self);
let size = values.len();
let mut combination_indices = Vec::from_iter(0..k);
unfold(k > size, |done| {
if *done {
return None;
}
let result = Some(Self::from_iter(combination_indices.iter().map(|index| values[*index].clone())));
let mut current_slot = k - 1;
while combination_indices[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];
#[allow(clippy::needless_range_loop)]
for slot in current_slot..k {
current_index += 1;
combination_indices[slot] = current_index;
}
result
})
.collect()
}
Self: Sized;

/// Creates a collection containing an element
/// specified number of times.
Expand Down Expand Up @@ -974,13 +941,7 @@ pub trait Collectible<Item>: IntoIterator<Item = Item> {
Self: IntoIterator<Item = Item> + FromIterator<Item>,
{
let mut replaced = Some(replacement);
self.into_iter().map(|item| {
if &item == value {
replaced.take().unwrap_or(item)
} else {
item
}
}).collect()
self.into_iter().map(|item| if &item == value { replaced.take().unwrap_or(item) } else { item }).collect()
}

/// Creates a collection from the original collection by replacing the
Expand Down Expand Up @@ -1205,6 +1166,42 @@ pub trait Collectible<Item>: IntoIterator<Item = Item> {
}
}

pub(crate) fn combinations<'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.cloned());
let size = values.len();
let mut combination_indices = 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 mut current_slot = k - 1;
while combination_indices[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];
#[allow(clippy::needless_range_loop)]
for slot in current_slot..k {
current_index += 1;
combination_indices[slot] = current_index;
}
result
})
.collect()
}

pub(crate) fn partition_map<'a, Item: 'a, A, B, Left: Default + Extend<A>, Right: Default + Extend<B>>(
iterator: impl Iterator<Item = &'a Item>, mut function: impl FnMut(&Item) -> Result<A, B>,
) -> (Left, Right) {
Expand Down
10 changes: 9 additions & 1 deletion src/extensions/collections/binary_heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,17 @@ impl<Item> Traversable<Item> for BinaryHeap<Item> {
}
}

impl<Item> Collectible<Item> for BinaryHeap<Item> {
impl<Item: Ord> Collectible<Item> for BinaryHeap<Item> {
type This<I> = BinaryHeap<I>;

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

#[inline]
fn filter_map<B>(&self, function: impl FnMut(&Item) -> Option<B>) -> Self::This<B>
where
Expand Down
8 changes: 8 additions & 0 deletions src/extensions/collections/btree_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ impl<Item> Traversable<Item> for BTreeSet<Item> {
impl<Item: Ord> Collectible<Item> for BTreeSet<Item> {
type This<I> = BTreeSet<I>;

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

#[inline]
fn filter_map<B>(&self, function: impl FnMut(&Item) -> Option<B>) -> Self::This<B>
where
Expand Down
8 changes: 8 additions & 0 deletions src/extensions/collections/hash_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ impl<Item> Traversable<Item> for HashSet<Item> {
impl<Item: Eq + Hash> Collectible<Item> for HashSet<Item> {
type This<I> = HashSet<I>;

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

#[inline]
fn filter_map<B>(&self, function: impl FnMut(&Item) -> Option<B>) -> Self::This<B>
where
Expand Down
8 changes: 8 additions & 0 deletions src/extensions/collections/linked_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ impl<Item> Reversible<Item> for LinkedList<Item> {
impl<Item> Collectible<Item> for LinkedList<Item> {
type This<I> = LinkedList<I>;

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

#[inline]
fn filter_map<B>(&self, function: impl FnMut(&Item) -> Option<B>) -> Self::This<B>
where
Expand Down
8 changes: 8 additions & 0 deletions src/extensions/collections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ impl<Item> Reversible<Item> for Vec<Item> {
impl<Item> Collectible<Item> for Vec<Item> {
type This<I> = Vec<I>;

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

#[inline]
fn filter_map<B>(&self, function: impl FnMut(&Item) -> Option<B>) -> Self::This<B>
where
Expand Down
8 changes: 8 additions & 0 deletions src/extensions/collections/vec_deque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ impl<Item> Reversible<Item> for VecDeque<Item> {
impl<Item> Collectible<Item> for VecDeque<Item> {
type This<I> = VecDeque<I>;

#[inline]
fn combinations(&self, k: usize) -> Vec<Self>
where
Item: Clone,
{
combinations(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 d659985

Please sign in to comment.