use crate::slices::min_repeating_len;
use alloc::vec::Vec;
use core::iter::{Chain, Cycle};
fn rational_sequence_reduce<T: Eq>(non_repeating: &mut Vec<T>, repeating: &mut Vec<T>) {
if repeating.is_empty() {
return;
}
repeating.truncate(min_repeating_len(repeating));
if non_repeating.is_empty() {
return;
}
let extra_non_repeating = non_repeating
.iter()
.rev()
.zip(repeating.iter().rev().cycle())
.take_while(|(x, y)| x == y)
.count();
if extra_non_repeating != 0 {
non_repeating.truncate(non_repeating.len() - extra_non_repeating);
let len = repeating.len();
repeating.rotate_right(extra_non_repeating % len);
}
}
pub_test! {rational_sequence_is_reduced<T: Eq>(non_repeating: &[T], repeating: &[T]) -> bool {
if repeating.is_empty() {
return true;
}
if min_repeating_len(repeating) != repeating.len() {
return false;
}
if non_repeating.is_empty() {
return true;
}
non_repeating
.iter()
.rev()
.zip(repeating.iter().rev().cycle())
.take_while(|(x, y)| x == y)
.count()
== 0
}}
#[derive(Clone, Default, Eq, Hash, PartialEq)]
pub struct RationalSequence<T: Eq> {
non_repeating: Vec<T>,
repeating: Vec<T>,
}
impl<T: Eq> RationalSequence<T> {
pub const fn is_empty(&self) -> bool {
self.non_repeating.is_empty() && self.repeating.is_empty()
}
pub const fn is_finite(&self) -> bool {
self.repeating.is_empty()
}
pub const fn len(&self) -> Option<usize> {
if self.repeating.is_empty() {
Some(self.non_repeating.len())
} else {
None
}
}
pub const fn component_len(&self) -> usize {
self.non_repeating.len() + self.repeating.len()
}
pub fn iter(&self) -> Chain<core::slice::Iter<'_, T>, Cycle<core::slice::Iter<'_, T>>> {
self.non_repeating
.iter()
.chain(self.repeating.iter().cycle())
}
}
impl<T: Clone + Eq> RationalSequence<T> {
#[cfg(feature = "test_build")]
pub fn is_valid(&self) -> bool {
rational_sequence_is_reduced(&self.non_repeating, &self.repeating)
}
}
pub mod access;
pub mod cmp;
pub mod conversion;
pub mod exhaustive;
#[cfg(feature = "random")]
pub mod random;
pub mod to_string;