dsalgo 0.3.10

A package for Datastructures and Algorithms.
Documentation
use std::collections::VecDeque;

pub trait Group {
    type T;

    fn op(
        &self,
        _: Self::T,
        _: Self::T,
    ) -> Self::T;

    fn e(&self) -> Self::T;

    fn inv(
        &self,
        _: Self::T,
    ) -> Self::T;
}

pub struct SWAGDeque<G: Group> {
    g: G,
    v: G::T,
    que: VecDeque<G::T>,
}

impl<G: Group> SWAGDeque<G>
where
    G::T: Clone,
{
    pub fn new(g: G) -> Self {
        let v = g.e();

        Self { g, v, que: VecDeque::new() }
    }

    pub fn size(&self) -> usize {
        self.que.len()
    }

    pub fn push_right(
        &mut self,
        x: G::T,
    ) {
        self.v = self.g.op(self.v.clone(), x.clone());

        self.que.push_back(x);
    }

    pub fn push_left(
        &mut self,
        x: G::T,
    ) {
        self.v = self.g.op(x.clone(), self.v.clone());

        self.que.push_front(x);
    }

    pub fn pop_left(&mut self) {
        let inv = self.g.inv(self.que.pop_front().unwrap());

        self.v = self.g.op(inv, self.v.clone());
    }

    pub fn pop_right(&mut self) {
        let inv = self.g.inv(self.que.pop_back().unwrap());

        self.v = self.g.op(self.v.clone(), inv);
    }

    pub fn fold(&self) -> G::T {
        self.v.clone()
    }
}

#[cfg(test)]

mod tests {

    use super::*;

    #[test]

    fn test() {
        struct G;

        impl Group for G {
            type T = i64;

            fn op(
                &self,
                l: i64,
                r: i64,
            ) -> i64 {
                l + r
            }

            fn e(&self) -> i64 {
                0
            }

            fn inv(
                &self,
                x: i64,
            ) -> i64 {
                -x
            }
        }

        let mut swag = SWAGDeque::new(G {});

        assert_eq!(swag.fold(), 0);

        swag.push_right(1);

        assert_eq!(swag.fold(), 1);

        swag.push_right(2);

        assert_eq!(swag.fold(), 3);

        swag.pop_left();

        assert_eq!(swag.fold(), 2);

        swag.pop_left();

        assert_eq!(swag.fold(), 0);
    }
}