Skip to content

Instantly share code, notes, and snippets.

@Jeffrey04
Created August 29, 2018 07:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jeffrey04/85d992570297646cc24b22902ad51582 to your computer and use it in GitHub Desktop.
Save Jeffrey04/85d992570297646cc24b22902ad51582 to your computer and use it in GitHub Desktop.
Implementing Simple Linked List @ Exercism
pub struct SimpleLinkedList<T> {
head: Option<Box<Node<T>>>,
}
pub struct Node<T> {
data: T,
next: Option<Box<Node<T>>>,
}
impl<T> SimpleLinkedList<T> {
pub fn new() -> Self {
Self { head: None }
}
pub fn len(&self) -> usize {
self.head.as_ref().map_or(0, |x| x.len())
}
pub fn push(&mut self, _element: T) {
if self.head.is_none() {
std::mem::replace(&mut self.head, Some(Box::new(Node::new(_element))));
} else {
let next = self.head.take().unwrap();
std::mem::replace(&mut self.head, Some(Box::new(next.push(_element))));
}
}
pub fn pop(&mut self) -> Option<T> {
if self.head.is_none() {
None
} else {
let mut node = self.head.take().unwrap();
std::mem::swap(&mut node.next, &mut self.head);
Some(node.data)
}
}
pub fn peek(&self) -> Option<&T> {
match self.head {
None => None,
ref node => node.as_ref().map(|x| &x.data),
}
}
}
impl<T> Node<T> {
pub fn new(data: T) -> Self {
Self {
data: data,
next: None,
}
}
fn len(&self) -> usize {
1 + self.next.as_ref().map_or(0, |x| x.len())
}
fn push(self, _element: T) -> Self {
Self {
data: _element,
next: Some(Box::new(self)),
}
}
}
impl<T: Clone> SimpleLinkedList<T> {
pub fn rev(&self) -> SimpleLinkedList<T> {
rev_recurse(&mut vec![], &self.head).into_iter().fold(
SimpleLinkedList::new(),
|mut current, incoming| {
// this clone is possibly not needed
current.push(incoming.clone());
current
},
)
}
}
impl<'a, T: Clone> From<&'a [T]> for SimpleLinkedList<T> {
fn from(_item: &[T]) -> Self {
_item
.to_vec()
.into_iter()
.fold(SimpleLinkedList::new(), |mut current, incoming| {
current.push(incoming);
current
})
}
}
impl<T> Into<Vec<T>> for SimpleLinkedList<T> {
fn into(self) -> Vec<T> {
into_recurse(vec![], self.head)
}
}
pub fn rev_recurse<'a, T: Clone>(
result: &'a mut Vec<T>,
node: &Option<Box<Node<T>>>,
) -> &'a Vec<T> {
match node {
None => result,
Some(ref node) => {
result.push(node.data.clone());
rev_recurse(result, &node.next)
}
}
}
fn into_recurse<T>(mut result: Vec<T>, node: Option<Box<Node<T>>>) -> Vec<T> {
match node {
None => result,
Some(mut node) => {
let next = node.next.take();
result.insert(0, node.data);
into_recurse(result, next)
}
}
}
extern crate simple_linked_list;
use simple_linked_list::SimpleLinkedList;
#[test]
fn test_new_list_is_empty() {
let list: SimpleLinkedList<u32> = SimpleLinkedList::new();
assert_eq!(list.len(), 0, "list's length must be 0");
}
#[test]
fn test_push_increments_length() {
let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new();
list.push(1);
assert_eq!(list.len(), 1, "list's length must be 1");
list.push(2);
assert_eq!(list.len(), 2, "list's length must be 2");
}
#[test]
fn test_pop_decrements_length() {
let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new();
list.push(1);
list.push(2);
list.pop();
assert_eq!(list.len(), 1, "list's length must be 1");
list.pop();
assert_eq!(list.len(), 0, "list's length must be 0");
}
#[test]
fn test_pop_returns_last_added_element() {
let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new();
list.push(1);
list.push(2);
assert_eq!(list.pop(), Some(2), "Element must be 2");
assert_eq!(list.pop(), Some(1), "Element must be 1");
assert_eq!(list.pop(), None, "No element should be contained in list");
}
#[test]
fn test_peek_returns_head_element() {
let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new();
assert_eq!(list.peek(), None, "No element should be contained in list");
list.push(2);
assert_eq!(list.peek(), Some(&2), "Element must be 2");
assert_eq!(list.peek(), Some(&2), "Element must be still 2");
}
#[test]
fn test_from_slice() {
let array = ["1", "2", "3", "4"];
let mut list = SimpleLinkedList::from(array.as_ref());
assert_eq!(list.pop(), Some("4"));
assert_eq!(list.pop(), Some("3"));
assert_eq!(list.pop(), Some("2"));
assert_eq!(list.pop(), Some("1"));
}
#[test]
fn test_reverse() {
let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new();
list.push(1);
list.push(2);
list.push(3);
let mut rev_list = list.rev();
assert_eq!(rev_list.pop(), Some(1));
assert_eq!(rev_list.pop(), Some(2));
assert_eq!(rev_list.pop(), Some(3));
assert_eq!(rev_list.pop(), None);
}
#[test]
fn test_into_vector() {
let mut v = Vec::new();
let mut s = SimpleLinkedList::new();
for i in 1..4 {
v.push(i);
s.push(i);
}
let s_as_vec: Vec<i32> = s.into();
assert_eq!(v, s_as_vec);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment