Skip to main content

RingSeq

Trait RingSeq 

Source
pub trait RingSeq<T> {
Show 35 methods // Required methods fn index_from(&self, i: isize) -> usize; fn apply_o(&self, i: isize) -> &T; fn rotate_right(&self, step: isize) -> Vec<T> where T: Clone; fn rotate_left(&self, step: isize) -> Vec<T> where T: Clone; fn start_at(&self, i: isize) -> Vec<T> where T: Clone; fn reflect_at(&self, i: isize) -> Vec<T> where T: Clone; fn segment_length(&self, pred: impl Fn(&T) -> bool, from: isize) -> usize; fn take_while(&self, pred: impl Fn(&T) -> bool, from: isize) -> Vec<T> where T: Clone; fn drop_while(&self, pred: impl Fn(&T) -> bool, from: isize) -> Vec<T> where T: Clone; fn span(&self, pred: impl Fn(&T) -> bool, from: isize) -> (Vec<T>, Vec<T>) where T: Clone; fn slice_o(&self, from: isize, to: isize) -> Vec<T> where T: Clone; fn contains_slice(&self, slice: &[T]) -> bool where T: PartialEq; fn index_of_slice(&self, slice: &[T], from: isize) -> Option<usize> where T: PartialEq; fn last_index_of_slice(&self, slice: &[T], end: isize) -> Option<usize> where T: PartialEq; fn circular_windows(&self, size: usize, step: usize) -> SlidingO<T> where T: Clone; fn circular_chunks(&self, size: usize) -> SlidingO<T> where T: Clone; fn circular_enumerate(&self, from: isize) -> Vec<(T, usize)> where T: Clone; fn rotations(&self) -> Rotations<'_, T> ; fn reflections(&self) -> Reflections<'_, T> ; fn reversions(&self) -> Reversions<'_, T> ; fn rotations_and_reflections(&self) -> RotationsAndReflections<'_, T> where T: Clone; fn is_rotation_of(&self, that: &[T]) -> bool where T: PartialEq; fn is_reflection_of(&self, that: &[T]) -> bool where T: PartialEq + Clone; fn is_reversion_of(&self, that: &[T]) -> bool where T: PartialEq; fn is_rotation_or_reflection_of(&self, that: &[T]) -> bool where T: PartialEq + Clone; fn rotation_offset(&self, that: &[T]) -> Option<usize> where T: PartialEq; fn hamming_distance(&self, that: &[T]) -> usize where T: PartialEq; fn min_rotational_hamming_distance(&self, that: &[T]) -> usize where T: PartialEq + Clone; fn canonical_index(&self) -> usize where T: Ord; fn canonical(&self) -> Vec<T> where T: Clone + Ord; fn bracelet(&self) -> Vec<T> where T: Clone + Ord; fn rotational_symmetry(&self) -> usize where T: PartialEq; fn symmetry_indices(&self) -> Vec<usize> where T: PartialEq; fn reflectional_symmetry_axes(&self) -> Vec<(AxisLocation, AxisLocation)> where T: PartialEq; fn symmetry(&self) -> usize where T: PartialEq;
}
Expand description

Circular (ring) sequence operations on [T].

Import this trait to gain circular methods on slices, Vecs, and arrays:

use ring_seq::RingSeq;

Required Methods§

Source

fn index_from(&self, i: isize) -> usize

Normalizes a circular index to [0, len).

Uses Euclidean remainder so that negative indices wrap correctly.

§Panics

Panics if the slice is empty (division by zero).

§Examples
use ring_seq::RingSeq;

assert_eq!([10, 20, 30].index_from(4), 1);
assert_eq!([10, 20, 30].index_from(-1), 2);
Source

fn apply_o(&self, i: isize) -> &T

Returns a reference to the element at circular index i.

§Panics

Panics if the slice is empty.

§Examples
use ring_seq::RingSeq;

assert_eq!(*[10, 20, 30].apply_o(3), 10);
assert_eq!(*[10, 20, 30].apply_o(-1), 30);
Source

fn rotate_right(&self, step: isize) -> Vec<T>
where T: Clone,

Rotates the sequence to the right by step positions, returning a new Vec.

A negative step rotates to the left.

§Examples
use ring_seq::RingSeq;

assert_eq!([0, 1, 2].rotate_right(1), vec![2, 0, 1]);
assert_eq!([0, 1, 2].rotate_right(-1), vec![1, 2, 0]);
Source

fn rotate_left(&self, step: isize) -> Vec<T>
where T: Clone,

Rotates the sequence to the left by step positions, returning a new Vec.

A negative step rotates to the right.

§Examples
use ring_seq::RingSeq;

assert_eq!([0, 1, 2].rotate_left(1), vec![1, 2, 0]);
Source

fn start_at(&self, i: isize) -> Vec<T>
where T: Clone,

Rotates the sequence so that circular index i becomes the first element.

Equivalent to rotate_left.

§Examples
use ring_seq::RingSeq;

assert_eq!([0, 1, 2].start_at(1), vec![1, 2, 0]);
Source

fn reflect_at(&self, i: isize) -> Vec<T>
where T: Clone,

Reflects (reverses) the sequence and rotates so that circular index i is the first element.

Equivalent to start_at(i + 1) followed by reverse.

§Examples
use ring_seq::RingSeq;

assert_eq!([0, 1, 2].reflect_at(0), vec![0, 2, 1]);
Source

fn segment_length(&self, pred: impl Fn(&T) -> bool, from: isize) -> usize

Length of the longest prefix of elements, starting from circular index from, that satisfy pred.

§Examples
use ring_seq::RingSeq;

assert_eq!([0, 1, 2].segment_length(|x| x % 2 == 0, 2), 2);
Source

fn take_while(&self, pred: impl Fn(&T) -> bool, from: isize) -> Vec<T>
where T: Clone,

Takes the longest prefix of elements, starting from circular index from, that satisfy pred.

§Examples
use ring_seq::RingSeq;

assert_eq!([0, 1, 2, 3, 4].take_while(|&x| x < 3, 1), vec![1, 2]);
Source

fn drop_while(&self, pred: impl Fn(&T) -> bool, from: isize) -> Vec<T>
where T: Clone,

Drops the longest prefix of elements, starting from circular index from, that satisfy pred.

§Examples
use ring_seq::RingSeq;

assert_eq!([0, 1, 2, 3, 4].drop_while(|&x| x < 3, 1), vec![3, 4, 0]);
Source

fn span(&self, pred: impl Fn(&T) -> bool, from: isize) -> (Vec<T>, Vec<T>)
where T: Clone,

Splits the circular sequence at the first element (starting from circular index from) that does not satisfy pred.

Returns (take_while(pred, from), drop_while(pred, from)).

§Examples
use ring_seq::RingSeq;

let (a, b) = [0, 1, 2, 3, 4].span(|&x| x < 3, 1);
assert_eq!(a, vec![1, 2]);
assert_eq!(b, vec![3, 4, 0]);
Source

fn slice_o(&self, from: isize, to: isize) -> Vec<T>
where T: Clone,

Selects a circular interval of elements from index from (inclusive) to index to (exclusive).

The resulting slice can be longer than the ring when to - from exceeds the ring length, because the ring repeats circularly.

Returns an empty Vec when from >= to or the ring is empty.

§Examples
use ring_seq::RingSeq;

assert_eq!([0, 1, 2].slice_o(-1, 4), vec![2, 0, 1, 2, 0]);
assert_eq!([0, 1, 2].slice_o(1, 3), vec![1, 2]);
Source

fn contains_slice(&self, slice: &[T]) -> bool
where T: PartialEq,

Tests whether this ring contains slice as a contiguous circular subsequence.

The slice may wrap around the ring boundary and may even be longer than the ring (repeating elements are matched cyclically).

§Examples
use ring_seq::RingSeq;

assert!([0, 1, 2].contains_slice(&[2, 0, 1, 2, 0]));
assert!(![0, 1, 2].contains_slice(&[1, 0]));
Source

fn index_of_slice(&self, slice: &[T], from: isize) -> Option<usize>
where T: PartialEq,

Finds the first circular index at or after from where slice appears as a contiguous subsequence.

Returns None if not found.

§Examples
use ring_seq::RingSeq;

assert_eq!([0, 1, 2].index_of_slice(&[2, 0, 1, 2, 0], 0), Some(2));
Source

fn last_index_of_slice(&self, slice: &[T], end: isize) -> Option<usize>
where T: PartialEq,

Finds the last circular index at or before end where slice appears as a contiguous subsequence.

Returns None if not found.

§Examples
use ring_seq::RingSeq;

assert_eq!(
    [0, 1, 2, 0, 1, 2].last_index_of_slice(&[2, 0], -1),
    Some(5),
);
Source

fn circular_windows(&self, size: usize, step: usize) -> SlidingO<T>
where T: Clone,

Sliding windows of size elements, advancing by step each time, wrapping around the ring boundary.

§Panics

Panics if size or step is zero.

§Examples
use ring_seq::RingSeq;

let windows: Vec<_> = [0, 1, 2].circular_windows(2, 1).collect();
assert_eq!(windows, vec![vec![0, 1], vec![1, 2], vec![2, 0]]);
Source

fn circular_chunks(&self, size: usize) -> SlidingO<T>
where T: Clone,

Fixed-size circular groups (like circular_windows with step == size).

§Panics

Panics if size is zero.

§Examples
use ring_seq::RingSeq;

let groups: Vec<_> = [0, 1, 2, 3, 4].circular_chunks(2).collect();
assert_eq!(
    groups,
    vec![vec![0, 1], vec![2, 3], vec![4, 0], vec![1, 2], vec![3, 4]],
);
Source

fn circular_enumerate(&self, from: isize) -> Vec<(T, usize)>
where T: Clone,

Pairs each element with its original (circular) index, starting from circular index from.

§Examples
use ring_seq::RingSeq;

assert_eq!(
    ['a', 'b', 'c'].circular_enumerate(1),
    vec![('b', 1), ('c', 2), ('a', 0)],
);
Source

fn rotations(&self) -> Rotations<'_, T>

All rotations of this ring.

Yields n items for a non-empty ring (starting from the identity rotation), or a single empty Vec for an empty ring.

§Examples
use ring_seq::RingSeq;

let rots: Vec<_> = [0, 1, 2].rotations().collect();
assert_eq!(rots, vec![vec![0, 1, 2], vec![1, 2, 0], vec![2, 0, 1]]);
Source

fn reflections(&self) -> Reflections<'_, T>

The original ring and its reflection at index 0.

Yields 2 items for a non-empty ring, or a single empty Vec for an empty ring.

§Examples
use ring_seq::RingSeq;

let refs: Vec<_> = [0, 1, 2].reflections().collect();
assert_eq!(refs, vec![vec![0, 1, 2], vec![0, 2, 1]]);
Source

fn reversions(&self) -> Reversions<'_, T>

The original ring and its reversal.

Yields 2 items for a non-empty ring, or a single empty Vec for an empty ring.

§Examples
use ring_seq::RingSeq;

let revs: Vec<_> = [0, 1, 2].reversions().collect();
assert_eq!(revs, vec![vec![0, 1, 2], vec![2, 1, 0]]);
Source

fn rotations_and_reflections(&self) -> RotationsAndReflections<'_, T>
where T: Clone,

All rotations of the original ring followed by all rotations of its reflection.

Yields 2n items for a non-empty ring, or a single empty Vec for an empty ring.

§Examples
use ring_seq::RingSeq;

let all: Vec<_> = [0, 1, 2].rotations_and_reflections().collect();
assert_eq!(all, vec![
    vec![0, 1, 2], vec![1, 2, 0], vec![2, 0, 1],
    vec![0, 2, 1], vec![2, 1, 0], vec![1, 0, 2],
]);
Source

fn is_rotation_of(&self, that: &[T]) -> bool
where T: PartialEq,

Tests whether this ring is a rotation of that.

Two sequences are rotations of each other iff they have the same length and one appears as a contiguous substring inside the other repeated twice.

§Examples
use ring_seq::RingSeq;

assert!([0, 1, 2].is_rotation_of(&[1, 2, 0]));
assert!(![0, 1, 2].is_rotation_of(&[0, 2, 1]));
Source

fn is_reflection_of(&self, that: &[T]) -> bool
where T: PartialEq + Clone,

Tests whether this ring is the reflection at index 0 of that (or identical to it).

This checks a single specific reflection axis. For rotation-insensitive comparison, see is_rotation_or_reflection_of.

§Examples
use ring_seq::RingSeq;

assert!([0, 1, 2].is_reflection_of(&[0, 2, 1]));
Source

fn is_reversion_of(&self, that: &[T]) -> bool
where T: PartialEq,

Tests whether this ring is the reversal of that (or identical to it).

§Examples
use ring_seq::RingSeq;

assert!([0, 1, 2].is_reversion_of(&[2, 1, 0]));
Source

fn is_rotation_or_reflection_of(&self, that: &[T]) -> bool
where T: PartialEq + Clone,

Tests whether this ring is a rotation or a reflection of that.

§Examples
use ring_seq::RingSeq;

assert!([0, 1, 2].is_rotation_or_reflection_of(&[2, 0, 1]));
assert!([0, 1, 2].is_rotation_or_reflection_of(&[0, 2, 1]));
Source

fn rotation_offset(&self, that: &[T]) -> Option<usize>
where T: PartialEq,

Finds the rotation offset that aligns this ring with that.

Returns Some(k) such that self.start_at(k) == that, or None if no rotation matches (or sizes differ).

§Examples
use ring_seq::RingSeq;

assert_eq!([0, 1, 2].rotation_offset(&[2, 0, 1]), Some(2));
assert_eq!([0, 1, 2].rotation_offset(&[0, 2, 1]), None);
Source

fn hamming_distance(&self, that: &[T]) -> usize
where T: PartialEq,

The number of positions at which corresponding elements differ.

§Panics

Panics if the two slices have different lengths.

§Examples
use ring_seq::RingSeq;

assert_eq!([1, 0, 1, 1].hamming_distance(&[1, 1, 0, 1]), 2);
Source

fn min_rotational_hamming_distance(&self, that: &[T]) -> usize
where T: PartialEq + Clone,

The minimum Hamming distance over all rotations of this ring.

Returns 0 iff that is a rotation of self.

§Panics

Panics if the two slices have different lengths.

§Examples
use ring_seq::RingSeq;

assert_eq!([1, 0, 1, 1].min_rotational_hamming_distance(&[1, 1, 0, 1]), 0);
Source

fn canonical_index(&self) -> usize
where T: Ord,

The starting index of the lexicographically smallest rotation (Booth’s algorithm, O(n)).

Returns 0 for empty or single-element sequences.

§Examples
use ring_seq::RingSeq;

assert_eq!([2, 0, 1].canonical_index(), 1);
Source

fn canonical(&self) -> Vec<T>
where T: Clone + Ord,

The lexicographically smallest rotation of this ring (necklace canonical form).

Two rings are rotations of each other iff their canonical forms are equal — useful for hashing and deduplicating equivalent rings.

§Examples
use ring_seq::RingSeq;

assert_eq!([2, 0, 1].canonical(), vec![0, 1, 2]);
Source

fn bracelet(&self) -> Vec<T>
where T: Clone + Ord,

The lexicographically smallest representative under both rotation and reflection (bracelet canonical form).

Two rings belong to the same bracelet equivalence class iff their bracelet forms are equal — useful when mirror images are considered identical.

§Examples
use ring_seq::RingSeq;

assert_eq!([2, 1, 0].bracelet(), vec![0, 1, 2]);
assert_eq!([0, 1, 2].bracelet(), vec![0, 1, 2]);
Source

fn rotational_symmetry(&self) -> usize
where T: PartialEq,

The order of rotational symmetry: the number of distinct rotations that map the ring onto itself.

Returns 1 for sequences with no rotational symmetry (only the identity), and n when all elements are equal.

§Examples
use ring_seq::RingSeq;

assert_eq!([0, 1, 2, 0, 1, 2].rotational_symmetry(), 2);
assert_eq!([0, 1, 2].rotational_symmetry(), 1);
assert_eq!([5, 5, 5].rotational_symmetry(), 3);
Source

fn symmetry_indices(&self) -> Vec<usize>
where T: PartialEq,

Indices of elements where a reflectional-symmetry axis passes nearby.

More precisely, the “shift” values for which the ring equals its reversal rotated by that shift.

§Examples
use ring_seq::RingSeq;

assert_eq!(
    [2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2].symmetry_indices(),
    vec![0, 3, 6, 9],
);
Source

fn reflectional_symmetry_axes(&self) -> Vec<(AxisLocation, AxisLocation)>
where T: PartialEq,

Axes of reflectional symmetry, expressed as pairs of AxisLocations where each axis intersects the ring.

§Examples
use ring_seq::{AxisLocation, RingSeq};

let axes = [0, 1, 0].reflectional_symmetry_axes();
assert_eq!(axes.len(), 1);
assert_eq!(axes[0], (AxisLocation::Vertex(1), AxisLocation::Edge(2, 0)));
Source

fn symmetry(&self) -> usize
where T: PartialEq,

The number of reflectional symmetries (the number of symmetry axes).

§Examples
use ring_seq::RingSeq;

assert_eq!([2, 1, 2, 2, 1, 2, 2, 1, 2, 2, 1, 2].symmetry(), 4);
assert_eq!([0, 1, 2].symmetry(), 0);

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl<T> RingSeq<T> for [T]

Source§

fn index_from(&self, i: isize) -> usize

Source§

fn apply_o(&self, i: isize) -> &T

Source§

fn rotate_right(&self, step: isize) -> Vec<T>
where T: Clone,

Source§

fn rotate_left(&self, step: isize) -> Vec<T>
where T: Clone,

Source§

fn start_at(&self, i: isize) -> Vec<T>
where T: Clone,

Source§

fn reflect_at(&self, i: isize) -> Vec<T>
where T: Clone,

Source§

fn segment_length(&self, pred: impl Fn(&T) -> bool, from: isize) -> usize

Source§

fn take_while(&self, pred: impl Fn(&T) -> bool, from: isize) -> Vec<T>
where T: Clone,

Source§

fn drop_while(&self, pred: impl Fn(&T) -> bool, from: isize) -> Vec<T>
where T: Clone,

Source§

fn span(&self, pred: impl Fn(&T) -> bool, from: isize) -> (Vec<T>, Vec<T>)
where T: Clone,

Source§

fn slice_o(&self, from: isize, to: isize) -> Vec<T>
where T: Clone,

Source§

fn contains_slice(&self, slice: &[T]) -> bool
where T: PartialEq,

Source§

fn index_of_slice(&self, slice: &[T], from: isize) -> Option<usize>
where T: PartialEq,

Source§

fn last_index_of_slice(&self, slice: &[T], end: isize) -> Option<usize>
where T: PartialEq,

Source§

fn circular_windows(&self, size: usize, step: usize) -> SlidingO<T>
where T: Clone,

Source§

fn circular_chunks(&self, size: usize) -> SlidingO<T>
where T: Clone,

Source§

fn circular_enumerate(&self, from: isize) -> Vec<(T, usize)>
where T: Clone,

Source§

fn rotations(&self) -> Rotations<'_, T>

Source§

fn reflections(&self) -> Reflections<'_, T>

Source§

fn reversions(&self) -> Reversions<'_, T>

Source§

fn rotations_and_reflections(&self) -> RotationsAndReflections<'_, T>
where T: Clone,

Source§

fn is_rotation_of(&self, that: &[T]) -> bool
where T: PartialEq,

Source§

fn is_reflection_of(&self, that: &[T]) -> bool
where T: PartialEq + Clone,

Source§

fn is_reversion_of(&self, that: &[T]) -> bool
where T: PartialEq,

Source§

fn is_rotation_or_reflection_of(&self, that: &[T]) -> bool
where T: PartialEq + Clone,

Source§

fn rotation_offset(&self, that: &[T]) -> Option<usize>
where T: PartialEq,

Source§

fn hamming_distance(&self, that: &[T]) -> usize
where T: PartialEq,

Source§

fn min_rotational_hamming_distance(&self, that: &[T]) -> usize
where T: PartialEq + Clone,

Source§

fn canonical_index(&self) -> usize
where T: Ord,

Source§

fn canonical(&self) -> Vec<T>
where T: Clone + Ord,

Source§

fn bracelet(&self) -> Vec<T>
where T: Clone + Ord,

Source§

fn rotational_symmetry(&self) -> usize
where T: PartialEq,

Source§

fn symmetry_indices(&self) -> Vec<usize>
where T: PartialEq,

Source§

fn reflectional_symmetry_axes(&self) -> Vec<(AxisLocation, AxisLocation)>
where T: PartialEq,

Source§

fn symmetry(&self) -> usize
where T: PartialEq,

Implementors§