RPM build fix (reverted CI changes which will need to be un-reverted or made conditional) and vendor Rust dependencies to make builds much faster in any CI system.
This commit is contained in:
280
zeroidc/vendor/itertools/src/permutations.rs
vendored
Normal file
280
zeroidc/vendor/itertools/src/permutations.rs
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
use alloc::vec::Vec;
|
||||
use std::fmt;
|
||||
use std::iter::once;
|
||||
|
||||
use super::lazy_buffer::LazyBuffer;
|
||||
|
||||
/// An iterator adaptor that iterates through all the `k`-permutations of the
|
||||
/// elements from an iterator.
|
||||
///
|
||||
/// See [`.permutations()`](crate::Itertools::permutations) for
|
||||
/// more information.
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
pub struct Permutations<I: Iterator> {
|
||||
vals: LazyBuffer<I>,
|
||||
state: PermutationState,
|
||||
}
|
||||
|
||||
impl<I> Clone for Permutations<I>
|
||||
where I: Clone + Iterator,
|
||||
I::Item: Clone,
|
||||
{
|
||||
clone_fields!(vals, state);
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum PermutationState {
|
||||
StartUnknownLen {
|
||||
k: usize,
|
||||
},
|
||||
OngoingUnknownLen {
|
||||
k: usize,
|
||||
min_n: usize,
|
||||
},
|
||||
Complete(CompleteState),
|
||||
Empty,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum CompleteState {
|
||||
Start {
|
||||
n: usize,
|
||||
k: usize,
|
||||
},
|
||||
Ongoing {
|
||||
indices: Vec<usize>,
|
||||
cycles: Vec<usize>,
|
||||
}
|
||||
}
|
||||
|
||||
enum CompleteStateRemaining {
|
||||
Known(usize),
|
||||
Overflow,
|
||||
}
|
||||
|
||||
impl<I> fmt::Debug for Permutations<I>
|
||||
where I: Iterator + fmt::Debug,
|
||||
I::Item: fmt::Debug,
|
||||
{
|
||||
debug_fmt_fields!(Permutations, vals, state);
|
||||
}
|
||||
|
||||
pub fn permutations<I: Iterator>(iter: I, k: usize) -> Permutations<I> {
|
||||
let mut vals = LazyBuffer::new(iter);
|
||||
|
||||
if k == 0 {
|
||||
// Special case, yields single empty vec; `n` is irrelevant
|
||||
let state = PermutationState::Complete(CompleteState::Start { n: 0, k: 0 });
|
||||
|
||||
return Permutations {
|
||||
vals,
|
||||
state
|
||||
};
|
||||
}
|
||||
|
||||
let mut enough_vals = true;
|
||||
|
||||
while vals.len() < k {
|
||||
if !vals.get_next() {
|
||||
enough_vals = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let state = if enough_vals {
|
||||
PermutationState::StartUnknownLen { k }
|
||||
} else {
|
||||
PermutationState::Empty
|
||||
};
|
||||
|
||||
Permutations {
|
||||
vals,
|
||||
state
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Iterator for Permutations<I>
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Clone
|
||||
{
|
||||
type Item = Vec<I::Item>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.advance();
|
||||
|
||||
let &mut Permutations { ref vals, ref state } = self;
|
||||
|
||||
match *state {
|
||||
PermutationState::StartUnknownLen { .. } => panic!("unexpected iterator state"),
|
||||
PermutationState::OngoingUnknownLen { k, min_n } => {
|
||||
let latest_idx = min_n - 1;
|
||||
let indices = (0..(k - 1)).chain(once(latest_idx));
|
||||
|
||||
Some(indices.map(|i| vals[i].clone()).collect())
|
||||
}
|
||||
PermutationState::Complete(CompleteState::Start { .. }) => None,
|
||||
PermutationState::Complete(CompleteState::Ongoing { ref indices, ref cycles }) => {
|
||||
let k = cycles.len();
|
||||
|
||||
Some(indices[0..k].iter().map(|&i| vals[i].clone()).collect())
|
||||
},
|
||||
PermutationState::Empty => None
|
||||
}
|
||||
}
|
||||
|
||||
fn count(self) -> usize {
|
||||
let Permutations { vals, state } = self;
|
||||
|
||||
fn from_complete(complete_state: CompleteState) -> usize {
|
||||
match complete_state.remaining() {
|
||||
CompleteStateRemaining::Known(count) => count,
|
||||
CompleteStateRemaining::Overflow => {
|
||||
panic!("Iterator count greater than usize::MAX");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match state {
|
||||
PermutationState::StartUnknownLen { k } => {
|
||||
let n = vals.len() + vals.it.count();
|
||||
let complete_state = CompleteState::Start { n, k };
|
||||
|
||||
from_complete(complete_state)
|
||||
}
|
||||
PermutationState::OngoingUnknownLen { k, min_n } => {
|
||||
let prev_iteration_count = min_n - k + 1;
|
||||
let n = vals.len() + vals.it.count();
|
||||
let complete_state = CompleteState::Start { n, k };
|
||||
|
||||
from_complete(complete_state) - prev_iteration_count
|
||||
},
|
||||
PermutationState::Complete(state) => from_complete(state),
|
||||
PermutationState::Empty => 0
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match self.state {
|
||||
PermutationState::StartUnknownLen { .. } |
|
||||
PermutationState::OngoingUnknownLen { .. } => (0, None), // TODO can we improve this lower bound?
|
||||
PermutationState::Complete(ref state) => match state.remaining() {
|
||||
CompleteStateRemaining::Known(count) => (count, Some(count)),
|
||||
CompleteStateRemaining::Overflow => (::std::usize::MAX, None)
|
||||
}
|
||||
PermutationState::Empty => (0, Some(0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Permutations<I>
|
||||
where
|
||||
I: Iterator,
|
||||
I::Item: Clone
|
||||
{
|
||||
fn advance(&mut self) {
|
||||
let &mut Permutations { ref mut vals, ref mut state } = self;
|
||||
|
||||
*state = match *state {
|
||||
PermutationState::StartUnknownLen { k } => {
|
||||
PermutationState::OngoingUnknownLen { k, min_n: k }
|
||||
}
|
||||
PermutationState::OngoingUnknownLen { k, min_n } => {
|
||||
if vals.get_next() {
|
||||
PermutationState::OngoingUnknownLen { k, min_n: min_n + 1 }
|
||||
} else {
|
||||
let n = min_n;
|
||||
let prev_iteration_count = n - k + 1;
|
||||
let mut complete_state = CompleteState::Start { n, k };
|
||||
|
||||
// Advance the complete-state iterator to the correct point
|
||||
for _ in 0..(prev_iteration_count + 1) {
|
||||
complete_state.advance();
|
||||
}
|
||||
|
||||
PermutationState::Complete(complete_state)
|
||||
}
|
||||
}
|
||||
PermutationState::Complete(ref mut state) => {
|
||||
state.advance();
|
||||
|
||||
return;
|
||||
}
|
||||
PermutationState::Empty => { return; }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl CompleteState {
|
||||
fn advance(&mut self) {
|
||||
*self = match *self {
|
||||
CompleteState::Start { n, k } => {
|
||||
let indices = (0..n).collect();
|
||||
let cycles = ((n - k)..n).rev().collect();
|
||||
|
||||
CompleteState::Ongoing {
|
||||
cycles,
|
||||
indices
|
||||
}
|
||||
},
|
||||
CompleteState::Ongoing { ref mut indices, ref mut cycles } => {
|
||||
let n = indices.len();
|
||||
let k = cycles.len();
|
||||
|
||||
for i in (0..k).rev() {
|
||||
if cycles[i] == 0 {
|
||||
cycles[i] = n - i - 1;
|
||||
|
||||
let to_push = indices.remove(i);
|
||||
indices.push(to_push);
|
||||
} else {
|
||||
let swap_index = n - cycles[i];
|
||||
indices.swap(i, swap_index);
|
||||
|
||||
cycles[i] -= 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CompleteState::Start { n, k }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remaining(&self) -> CompleteStateRemaining {
|
||||
use self::CompleteStateRemaining::{Known, Overflow};
|
||||
|
||||
match *self {
|
||||
CompleteState::Start { n, k } => {
|
||||
if n < k {
|
||||
return Known(0);
|
||||
}
|
||||
|
||||
let count: Option<usize> = (n - k + 1..n + 1).fold(Some(1), |acc, i| {
|
||||
acc.and_then(|acc| acc.checked_mul(i))
|
||||
});
|
||||
|
||||
match count {
|
||||
Some(count) => Known(count),
|
||||
None => Overflow
|
||||
}
|
||||
}
|
||||
CompleteState::Ongoing { ref indices, ref cycles } => {
|
||||
let mut count: usize = 0;
|
||||
|
||||
for (i, &c) in cycles.iter().enumerate() {
|
||||
let radix = indices.len() - i;
|
||||
let next_count = count.checked_mul(radix)
|
||||
.and_then(|count| count.checked_add(c));
|
||||
|
||||
count = match next_count {
|
||||
Some(count) => count,
|
||||
None => { return Overflow; }
|
||||
};
|
||||
}
|
||||
|
||||
Known(count)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user