From 4ed4c4edf8aca30e83c9239fe89e9aac8a9c4bda Mon Sep 17 00:00:00 2001 From: Jason Staten Date: Tue, 26 Jun 2018 20:15:09 -0600 Subject: [PATCH] linked lists --- src/lib.rs | 2 + src/linked.rs | 81 ++++++++++++++++++++++++++++++++++++ src/linked_im.rs | 104 +++++++++++++++++++++++++++++++++++++++++++++++ src/search.rs | 1 + src/tree.rs | 1 + src/vec_basic.rs | 1 + 6 files changed, 190 insertions(+) create mode 100644 src/linked.rs create mode 100644 src/linked_im.rs diff --git a/src/lib.rs b/src/lib.rs index 758e2b4..a72ce42 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,8 @@ #![feature(test)] extern crate test; +mod linked; +mod linked_im; mod search; mod tree; mod vec_basic; diff --git a/src/linked.rs b/src/linked.rs new file mode 100644 index 0000000..9ff1b43 --- /dev/null +++ b/src/linked.rs @@ -0,0 +1,81 @@ +use std::iter::FromIterator; +use std::mem; + +#[allow(unused)] +#[derive(Debug, PartialEq)] +enum Node { + Cons(T, Box>), + Nil, +} + +impl Node { + fn iter(self) -> Iter { + Iter { node: self } + } +} + +impl<'a, T> FromIterator for Node { + fn from_iter>(iter: I) -> Self { + let mut output = Node::Nil; + + for x in iter { + output = Node::Cons(x, Box::new(output)); + } + + output + } +} + +struct Iter { + node: Node, +} + +impl Iterator for Iter { + type Item = T; + + fn next(&mut self) -> Option { + let old_node = mem::replace(&mut self.node, Node::Nil); + + match old_node { + Node::Cons(head, tail) => { + self.node = *tail; + Some(head) + } + Node::Nil => None, + } + } +} + +#[cfg(test)] +mod test { + use self::Node::*; + use super::*; + + #[test] + fn test_can_construct() { + if let Cons(head, tail) = Cons("home", Box::new(Nil)) { + assert_eq!(head, "home"); + assert_eq!(tail, Box::new(Nil)); + } else { + assert!(false, "Not a Cons") + } + } + + #[test] + fn test_from_iter() { + let expected = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil)))))); + + let result = Node::from_iter(vec![3, 2, 1]); + assert_eq!(result, expected); + } + + #[test] + fn test_iterate() { + let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil)))))); + let i = list.iter(); + let result: Vec = i.collect(); + let expected = vec![1, 2, 3]; + + assert_eq!(result, expected); + } +} diff --git a/src/linked_im.rs b/src/linked_im.rs new file mode 100644 index 0000000..bd9c0a1 --- /dev/null +++ b/src/linked_im.rs @@ -0,0 +1,104 @@ +use std::iter::FromIterator; +use std::rc::Rc; + +type Link = Option>>; + +struct Node { + value: T, + next: Link, +} + +struct LinkedList { + head: Link, +} + +impl LinkedList { + fn new() -> LinkedList { + LinkedList { head: Option::None } + } + + fn append(self, el: T) -> LinkedList { + LinkedList { + head: Option::Some(Rc::new(Node { + value: el, + next: self.head, + })), + } + } + + fn head(&self) -> Option<&T> { + self.head.as_ref().map(|node| &node.value) + } + + fn tail(&self) -> LinkedList { + LinkedList { + head: self.head.as_ref().and_then(|node| node.next.clone()), + } + } +} + +impl<'a, T> FromIterator for LinkedList { + fn from_iter>(source: I) -> Self { + source + .into_iter() + .fold(LinkedList::new(), LinkedList::append) + } +} + +#[cfg(test)] +mod test { + use super::LinkedList; + use std::iter::FromIterator; + + #[test] + fn test_append() { + let list = LinkedList:: { head: Option::None }; + let appended = list.append(42); + match appended.head { + Option::Some(node) => assert_eq!((*node).value, 42), + _ => assert!(false, "was not Some"), + } + } + + #[test] + fn test_append_str() { + let list = LinkedList::<&str> { head: Option::None }; + let appended = list.append("one").append("two").append("three"); + match appended.head { + Option::Some(node) => assert_eq!((*node).value, "three"), + _ => assert!(false, "was not Some"), + } + } + + #[test] + fn test_head() { + let list = LinkedList::<&str> { head: Option::None }; + let appended = list.append("one").append("two").append("three"); + match appended.head() { + Option::Some(val) => assert_eq!(val, &"three"), + _ => assert!(false, "was not Some"), + } + } + + #[test] + fn test_tail() { + let list = LinkedList::<&str> { head: Option::None }; + let appended = list.append("one").append("two").append("three"); + match appended.tail().head() { + Option::Some(val) => assert_eq!(val, &"two"), + _ => assert!(false, "was not Some"), + } + } + + #[test] + fn test_from_iter() { + let list = LinkedList::from_iter(vec![1, 2, 3]); + let h1 = list.head().unwrap().clone(); + let h2 = list.tail().head().unwrap().clone(); + let h3 = list.tail().tail().head().unwrap().clone(); + + assert_eq!(h1, 3); + assert_eq!(h2, 2); + assert_eq!(h3, 1); + } +} diff --git a/src/search.rs b/src/search.rs index 5638e17..c8013e1 100644 --- a/src/search.rs +++ b/src/search.rs @@ -1,3 +1,4 @@ +#![allow(unused)] #[allow(unused_imports)] extern crate test; use test::Bencher; diff --git a/src/tree.rs b/src/tree.rs index d8a02c1..e95a1c6 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,3 +1,4 @@ +#![allow(unused)] #[derive(Debug)] struct Node<'a>(&'a str, Vec>); diff --git a/src/vec_basic.rs b/src/vec_basic.rs index d383627..c88b79d 100644 --- a/src/vec_basic.rs +++ b/src/vec_basic.rs @@ -1,3 +1,4 @@ +#![allow(unused)] #[allow(unused_imports)] extern crate test; use test::Bencher;