use std::fmt;
#[derive(Clone, Debug)]
pub struct PushStack<T> {
elements: Vec<T>,
}
pub trait PushPrint {
fn to_pstring(&self) -> String;
}
impl PushPrint for f32 {
fn to_pstring(&self) -> String {
format!("{:.1}", self)
}
}
impl PushPrint for i32 {
fn to_pstring(&self) -> String {
self.to_string()
}
}
impl PushPrint for String {
fn to_pstring(&self) -> String {
self.to_string()
}
}
impl PushPrint for bool {
fn to_pstring(&self) -> String {
format!("{}", self.to_string().to_uppercase())
}
}
impl<T> PushStack<T>
where
T: Clone + fmt::Display + PartialEq + PushPrint,
{
pub fn new() -> Self {
Self {
elements: Vec::new(),
}
}
pub fn from_vec(elements: Vec<T>) -> Self {
Self { elements: elements }
}
pub fn to_string(&self) -> String {
let mut result = "".to_string();
for (_i, x) in self.elements.iter().rev().enumerate() {
result.push_str(&format!(" {}", x.to_pstring()));
}
result.trim().to_string()
}
pub fn size(&self) -> usize {
return self.elements.len();
}
pub fn last_eq(&self, item: &T) -> bool {
return Some(item) == self.elements.last();
}
pub fn equal_at(&self, i: usize, el: &T) -> Option<bool> {
if i > self.size() {
None
} else {
Some(self.elements[self.size() - (i + 1)].to_string() == *el.to_string())
}
}
pub fn bottom_mut(&mut self) -> Option<&mut T> {
if self.size() > 0 {
self.elements.first_mut()
} else {
None
}
}
pub fn flush(&mut self) {
self.elements = Vec::new();
}
pub fn replace(&mut self, i: usize, new_el: T) -> Result<(), usize> {
let size = &mut self.size();
match i.checked_sub(*size) {
None => {
let _ = std::mem::replace(&mut self.elements[*size - (i + 1)], new_el);
Ok(())
}
Some(diff) => Err(diff + 1),
}
}
pub fn remove(&mut self, i: usize) {
let size = self.size();
if i < size {
self.elements.remove(size - (i + 1));
}
}
pub fn reverse(&mut self) {
self.elements.reverse();
}
pub fn get_mut(&mut self, i: usize) -> Option<&mut T> {
let size = &mut self.size();
if i < *size {
Some(&mut self.elements[*size - (i + 1)])
} else {
None
}
}
pub fn get(&self, i: usize) -> Option<&T> {
let size = self.size();
if i < size {
Some(&self.elements[size - (i + 1)])
} else {
None
}
}
pub fn push(&mut self, value: T) {
self.elements.push(value);
}
pub fn push_front(&mut self, value: T) {
self.elements.insert(0, value);
}
pub fn yank(&mut self, index: usize) {
if index > 0 && index < self.size() {
let el = self.elements.remove(self.size() - (index + 1));
self.elements.push(el);
}
}
pub fn shove(&mut self, index: usize) {
if index > 0 && index < self.size() {
if let Some(el) = self.elements.pop() {
let top_down_index = self.size() - index;
self.elements.insert(top_down_index, el);
}
}
}
pub fn swap(&mut self, i: usize, j: usize) {
self.elements.swap(i, j);
}
pub fn pop_front(&mut self) -> Option<T> {
if self.elements.is_empty() {
return None;
}
Some(self.elements.remove(0))
}
pub fn pop(&mut self) -> Option<T> {
self.elements.pop()
}
pub fn pop_vec(&mut self, n: usize) -> Option<Vec<T>> {
if n > self.elements.len() {
None
} else {
Some(
self.elements
.split_off(self.elements.len() - n)
.into_iter()
.collect(),
)
}
}
pub fn copy(&self, i: usize) -> Option<T> {
if self.size() == 0 || i > self.size() - 1 {
None
} else {
Some(self.elements[self.size() - (i + 1)].clone())
}
}
pub fn copy_vec(&self, n: usize) -> Option<Vec<T>> {
if n > self.size() {
None
} else {
let mut cpy = Vec::with_capacity(n);
for i in 0..n {
cpy.push(self.elements[self.size() - n + i].clone());
}
Some(cpy)
}
}
pub fn push_vec(&mut self, to_push: Vec<T>) {
self.elements.extend(to_push);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pop_vec_in_right_order() {
let mut test_stack = PushStack {
elements: vec![1, 2, 3],
};
match test_stack.pop_vec(2) {
None => assert!(false),
Some(pv) => assert_eq!(pv[0], 2),
}
}
#[test]
fn pop_vec_max_index() {
let mut test_stack = PushStack {
elements: vec![1, 2, 3],
};
match test_stack.pop_vec(4) {
None => assert!(true),
Some(_pv) => assert!(false),
}
}
#[test]
fn push_vec_in_right_order() {
let mut test_stack = PushStack {
elements: vec![1, 2, 3],
};
let test_vec = vec![4, 5];
test_stack.push_vec(test_vec);
assert_eq!(test_stack.elements, [1, 2, 3, 4, 5]);
}
#[test]
fn copy_vec_preserves_stack() {
let test_stack = PushStack {
elements: vec![1, 2, 3],
};
match test_stack.copy_vec(2) {
None => assert!(false, "Should return values"),
Some(cv) => {
assert_eq!(cv.len(), 2);
assert_eq!(cv[0], 2);
assert_eq!(cv[1], 3);
}
}
assert_eq!(
test_stack.elements.len(),
3,
"Test stack should remain the same"
)
}
#[test]
fn equal_at_checks_equality_at_right_index() {
let test_stack = PushStack {
elements: vec![1, 2, 3, 4, 5],
};
assert_eq!(test_stack.equal_at(0, &5), Some(true));
assert_eq!(test_stack.equal_at(3, &2), Some(true));
assert_eq!(test_stack.equal_at(3, &1), Some(false));
}
#[test]
fn yank_vec_returns_right_order() {
let mut test_stack = PushStack {
elements: vec![1, 2, 3, 4, 5],
};
let mut test_idx = 1;
test_stack.yank(test_idx);
assert_eq!(test_stack.elements, [1, 2, 3, 5, 4]);
test_idx = 5; test_stack.yank(test_idx);
assert_eq!(test_stack.elements, [1, 2, 3, 5, 4]);
test_idx = 3;
test_stack.yank(test_idx);
assert_eq!(test_stack.elements, [1, 3, 5, 4, 2]);
test_idx = 0; test_stack.yank(test_idx);
assert_eq!(test_stack.elements, [1, 3, 5, 4, 2]);
}
#[test]
fn shove_vec_returns_right_order() {
let mut test_stack = PushStack {
elements: vec![1, 2, 3, 4, 5],
};
let mut test_idx = 1;
test_stack.shove(test_idx);
assert_eq!(test_stack.elements, [1, 2, 3, 5, 4]);
test_idx = 4; test_stack.shove(test_idx);
assert_eq!(test_stack.elements, [4, 1, 2, 3, 5]);
test_idx = 3;
test_stack.shove(test_idx);
assert_eq!(test_stack.elements, [4, 5, 1, 2, 3]);
test_idx = 0; test_stack.shove(test_idx);
assert_eq!(test_stack.elements, [4, 5, 1, 2, 3]);
}
#[test]
fn last_eq_preserves_vector() {
let test_stack = PushStack {
elements: vec![1, 2, 3, 4, 5],
};
let candidate = 5;
assert_eq!(test_stack.last_eq(&candidate), true);
let candidate = 4;
assert_eq!(test_stack.last_eq(&candidate), false);
assert_eq!(test_stack.size(), 5);
let test_stack = PushStack {
elements: Vec::new(),
};
assert_eq!(test_stack.last_eq(&candidate), false);
}
#[test]
fn replace_returns_right_offset() {
let mut test_stack = PushStack {
elements: vec![1, 2, 3, 4, 5],
};
assert_eq!(test_stack.replace(1, 19), Ok(()));
assert_eq!(test_stack.replace(5, 19), Err(1));
assert_eq!(test_stack.replace(6, 19), Err(2));
assert_eq!(test_stack.replace(4, 19), Ok(()));
assert_eq!(test_stack.replace(0, 19), Ok(()));
assert_eq!(test_stack.to_string(), "19 19 3 2 19");
}
#[test]
fn reverse_elements() {
let mut test_stack = PushStack {
elements: vec![1, 2, 3, 4, 5],
};
test_stack.reverse();
assert_eq!(test_stack.elements, [5, 4, 3, 2, 1]);
}
}