ciclo 0.1.0

Exhaustive cycle enumeration.
Documentation
use std::fmt::Debug;

#[derive(Debug, PartialEq, Hash, Eq)]
pub struct Cycle<T>(Vec<T>);

impl<T: PartialOrd + Debug> Cycle<T> {
    pub fn new(nodes: Vec<T>) -> Self {
        let rotation = rotation(&nodes);
        let rotated = rotate(nodes, rotation);
        let flipped = if &rotated[1] > rotated.last().expect("last") {
            flip(rotated)
        } else {
            rotated
        };

        Self(flipped)
    }
}

fn rotation<T: PartialOrd + Debug>(nodes: &Vec<T>) -> usize {
    let mut iter = nodes.iter().rev().enumerate();
    let (mut index, mut value) = iter.next().expect("");

    while let Some((i, v)) = iter.next() {
        if v < &value {
            value = v;
            index = i
        }
    }

    if index == nodes.len() - 1 {
        0
    } else {
        index + 1
    }
}

fn rotate<T: Debug>(mut nodes: Vec<T>, count: usize) -> Vec<T> {
    let mut result = Vec::new();

    for _ in 0..count {
        result.push(nodes.pop().expect(""));
    }

    result.reverse();
    result.append(&mut nodes);

    result
}

fn flip<T: Debug>(mut nodes: Vec<T>) -> Vec<T> {
    let mut stack = Vec::new();

    for _ in 0..(nodes.len() - 1) {
        stack.push(nodes.pop().expect(""))
    }

    println!("stack {:?}", stack);

    nodes.append(&mut stack);

    nodes
}

#[cfg(test)]
mod rotate {
    use super::*;
    use pretty_assertions::assert_eq;

    #[test]
    fn zero() {
        let nodes = vec![0, 1, 2];

        assert_eq!(rotate(nodes, 0), vec![0, 1, 2])
    }

    #[test]
    fn one() {
        let nodes = vec![0, 1, 2];

        assert_eq!(rotate(nodes, 1), vec![2, 0, 1])
    }

    #[test]
    fn two() {
        let nodes = vec![1, 0, 2];

        assert_eq!(rotate(nodes, 2), vec![0, 2, 1])
    }

    #[test]
    fn foo() {
        let nodes = vec![1, 0, 2];

        assert_eq!(rotate(nodes, 2), vec![0, 2, 1])
    }
}

#[cfg(test)]
mod rotation {
    use super::*;
    use pretty_assertions::assert_eq;

    #[test]
    fn min_left() {
        let nodes = vec![0, 1, 2];

        assert_eq!(rotation(&nodes), 0)
    }

    #[test]
    fn min_middle() {
        let nodes = vec![1, 0, 2];

        assert_eq!(rotation(&nodes), 2)
    }

    #[test]
    fn min_right() {
        let nodes = vec![1, 2, 0];

        assert_eq!(rotation(&nodes), 1)
    }
}

#[cfg(test)]
mod flip {
    use super::*;
    use pretty_assertions::assert_eq;

    #[test]
    fn foo() {
        let nodes = vec![0, 2, 1];

        assert_eq!(flip(nodes), vec![0, 1, 2])
    }
}

#[cfg(test)]
mod new {
    use super::*;
    use pretty_assertions::assert_eq;

    #[test]
    fn no_rotate_no_flip() {
        let nodes = vec![0, 1, 2];

        assert_eq!(Cycle::new(nodes), Cycle(vec![0, 1, 2]))
    }

    #[test]
    fn rotate_no_flip() {
        let nodes = vec![2, 0, 1];

        assert_eq!(Cycle::new(nodes), Cycle(vec![0, 1, 2]))
    }

    #[test]
    fn no_rotate_flip() {
        let nodes = vec![0, 2, 1];

        assert_eq!(Cycle::new(nodes), Cycle(vec![0, 1, 2]))
    }
}