From f2208c69f22238e1a1a45529441790966b80c2c9 Mon Sep 17 00:00:00 2001 From: Berack96 Date: Tue, 30 Apr 2024 19:11:47 +0200 Subject: [PATCH] Es 06 Lists - with T:copy --- src/es06_list.rs | 209 +++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 4 + tests/es06_list.rs | 164 +++++++++++++++++++++++++++++++++++ 3 files changed, 377 insertions(+) create mode 100644 src/es06_list.rs create mode 100644 tests/es06_list.rs diff --git a/src/es06_list.rs b/src/es06_list.rs new file mode 100644 index 0000000..e75733d --- /dev/null +++ b/src/es06_list.rs @@ -0,0 +1,209 @@ +#![allow(unused)] + +/** + * implementerete una struttura di lista doppiamente linkata. + * Di seguito ho messo le dichiarazioni delle strutture dati e le funzioni e i metodi che dovete implementare. + * Dovete implementare anche dei test usando come tipo di T qualcosa di piu’ complesso di un tipo primitivo,, ad esempio una struttura punto con 2 componenti intere. + +#[derive(Default)] +struct Node { + item: T, + next: Pointer, + prev: Pointer, +} +impl Node { + fn new(item: T) -> Self +} + +type Pointer = Option>>>; + +#[derive(Default)] +pub struct DoublyPointedList { + head: Pointer, + tail: Pointer, + size: usize, +} +impl DoublyPointedList { + pub fn new() -> Self + pub fn is_empty(&self) -> bool + pub fn len(&self) -> usize + pub fn push_back(&mut self, item: T) + pub fn push_front(&mut self, item: T) + pub fn pop_back(&mut self) -> Option + pub fn pop_front(&mut self) -> Option + // Se n e' positivo ritornate l'ennesimo elemento dall'inizio + //della lista mentre se e' negativo lo ritornate dalla coda + //(-1 e' il primo elemento dalla coda) + pub fn get(& self, n:i32) -> Option +} +*/ +use std::{ + cell::{RefCell, RefMut}, + fmt::Debug, + rc::Rc, +}; + +type Pointer = Option>>; + +pub struct LinkedList { + size: usize, + head: Pointer>, + tail: Pointer>, +} + +struct Node { + element: T, + next: Pointer>, + prev: Pointer>, +} + +impl Node { + pub fn new(element: T) -> Self { + Self { + element, + next: None, + prev: None, + } + } + pub fn get(node: &Rc>>) -> RefMut> { + node.as_ref().borrow_mut() + } + pub fn as_memref(self) -> Rc>> { + Rc::new(RefCell::new(self)) + } +} + +impl LinkedList { + pub fn new() -> Self { + Self { + size: 0, + head: None, + tail: None, + } + } + + pub fn is_empty(&self) -> bool { + self.size == 0 + } + + pub fn len(&self) -> usize { + self.size + } + + pub fn push_front(&mut self, element: T) { + let element = Node::new(element).as_memref(); + if let Some(head) = self.head.as_ref() { + Node::get(head).prev = Some(element.clone()); + Node::get(&element).next = Some(head.clone()); + } + if let None = self.tail.as_ref() { + self.tail = Some(element.clone()); + } + + self.head = Some(element.clone()); + self.size += 1; + } + pub fn push_back(&mut self, element: T) { + let element = Node::new(element).as_memref(); + if let Some(tail) = self.tail.as_ref() { + Node::get(tail).next = Some(element.clone()); + Node::get(&element).prev = Some(tail.clone()); + } + if let None = self.tail.as_ref() { + self.head = Some(element.clone()); + } + + self.tail = Some(element.clone()); + self.size += 1; + } + + pub fn pop_front(&mut self) -> Option { + self.pop(true) + } + pub fn pop_back(&mut self) -> Option { + self.pop(false) + } + fn pop(&mut self, from_head: bool) -> Option { + let ptr = if from_head { + &mut self.head + } else { + &mut self.tail + }; + + if let Some(node) = ptr.clone() { + let node = Node::get(&node); + + let other = if from_head { + node.next.clone() + } else { + node.prev.clone() + }; + + if let Some(node) = other.clone() { + *ptr = other; + if from_head { + Node::get(&node).prev = None; + } else { + Node::get(&node).next = None; + } + } else { + self.head = None; + self.tail = None; + } + + self.size -= 1; + return Some(node.element); + } + None + } + + pub fn get_front(&self) -> Option { + match self.head.clone() { + Some(head) => Some(Node::get(&head).element), + _ => None, + } + } + pub fn get_back(&self) -> Option { + match self.tail.clone() { + Some(tail) => Some(Node::get(&tail).element), + _ => None, + } + } + + pub fn get(&self, n: i32) -> Option { + if self.size > 0 { + let index = n + if n < 0 { self.size as i32 } else { 0 }; + if let Some(node) = self.find(index) { + return Some(Node::get(&node).element); + } + } + + None + } + + fn find(&self, index: i32) -> Pointer> { + if index < 0 || index as usize >= self.size { + return None; + } + + let index = index as usize; + let delta_back = (self.size - index) - 1_usize; + let from_head = index <= delta_back; + + let node = if from_head { &self.head } else { &self.tail }; + let index = if from_head { index } else { delta_back }; + Self::find_node(node, index, from_head) + } + fn find_node(node: &Pointer>, index: usize, from_head: bool) -> Pointer> { + if let Some(node) = node { + return if index == 0 { + Some(node.clone()) + } else { + let node = node.as_ref().borrow(); + let node = if from_head { &node.next } else { &node.prev }; + Self::find_node(node, index - 1, from_head) + }; + } + None + } +} diff --git a/src/lib.rs b/src/lib.rs index b33b911..5550ca2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,4 +3,8 @@ pub mod es02_rational; pub mod es03_game; pub mod es04_rational_traits; pub mod es05_bank; +pub mod es06_list; +pub mod es07_list_generic; +pub mod es08_folds; +pub mod es09_auction; diff --git a/tests/es06_list.rs b/tests/es06_list.rs new file mode 100644 index 0000000..dfe06ba --- /dev/null +++ b/tests/es06_list.rs @@ -0,0 +1,164 @@ +use esercizi::es06_list::LinkedList; + +#[test] +fn test_front() { + let mut list = LinkedList::new(); + + assert_eq!(None, list.get_front()); + assert_eq!(None, list.pop_front()); + assert_eq!(None, list.get_front()); + + list.push_front(50); + assert_eq!(Some(50), list.get_front()); + assert_eq!(Some(50), list.pop_front()); + assert_eq!(None, list.get_front()); + + list.push_front(50); + list.push_front(20); + assert_eq!(Some(20), list.get_front()); + assert_eq!(Some(20), list.pop_front()); + assert_eq!(Some(50), list.get_front()); + assert_eq!(Some(50), list.pop_front()); + assert_eq!(None, list.get_front()); + + list.push_front(50); + list.push_front(20); + list.push_front(150); + assert_eq!(Some(150), list.get_front()); + assert_eq!(Some(150), list.pop_front()); + assert_eq!(Some(20), list.get_front()); + assert_eq!(Some(20), list.pop_front()); + assert_eq!(Some(50), list.get_front()); + assert_eq!(Some(50), list.pop_front()); + assert_eq!(None, list.get_front()); +} + +#[test] +fn test_back() { + let mut list = LinkedList::new(); + + assert_eq!(None, list.get_back()); + assert_eq!(None, list.pop_back()); + assert_eq!(None, list.get_back()); + + list.push_back(50); + assert_eq!(Some(50), list.get_back()); + assert_eq!(Some(50), list.pop_back()); + assert_eq!(None, list.get_back()); + + list.push_back(50); + list.push_back(20); + assert_eq!(Some(20), list.get_back()); + assert_eq!(Some(20), list.pop_back()); + assert_eq!(Some(50), list.get_back()); + assert_eq!(Some(50), list.pop_back()); + assert_eq!(None, list.get_back()); + + list.push_back(50); + list.push_back(20); + list.push_back(150); + assert_eq!(Some(150), list.get_back()); + assert_eq!(Some(150), list.pop_back()); + assert_eq!(Some(20), list.get_back()); + assert_eq!(Some(20), list.pop_back()); + assert_eq!(Some(50), list.get_back()); + assert_eq!(Some(50), list.pop_back()); + assert_eq!(None, list.get_back()); +} + +#[test] +fn test_mixed() { + let mut list: LinkedList = LinkedList::new(); + assert_eq!(0, list.len()); + + list.push_back(50); + assert_eq!(Some(50), list.get_back()); + assert_eq!(Some(50), list.get_front()); + assert_eq!(1, list.len()); + + list.push_front(20); + assert_eq!(Some(50), list.get_back()); + assert_eq!(Some(20), list.get_front()); + assert_eq!(2, list.len()); + + list.push_front(10); + assert_eq!(Some(50), list.get_back()); + assert_eq!(Some(10), list.get_front()); + assert_eq!(3, list.len()); + + list.push_back(150); + list.push_back(15); + list.push_front(0); + assert_eq!(Some(15), list.get_back()); + assert_eq!(Some(0), list.get_front()); + assert_eq!(6, list.len()); + + assert_eq!(Some(15), list.pop_back()); + assert_eq!(5, list.len()); + assert_eq!(Some(0), list.pop_front()); + assert_eq!(4, list.len()); + assert_eq!(Some(150), list.pop_back()); + assert_eq!(3, list.len()); + assert_eq!(Some(50), list.pop_back()); + assert_eq!(2, list.len()); + assert_eq!(Some(10), list.pop_front()); + assert_eq!(1, list.len()); + assert_eq!(Some(20), list.pop_front()); + assert_eq!(0, list.len()); + + assert_eq!(None, list.pop_back()); + assert_eq!(None, list.pop_front()); + + // creo lista [50, 20, 10, 30, 40] + list.push_back(10); + list.push_front(20); + list.push_back(30); + list.push_back(40); + list.push_front(50); + + assert_eq!(Some(50), list.pop_front()); + assert_eq!(Some(20), list.pop_front()); + assert_eq!(Some(10), list.pop_front()); + assert_eq!(Some(30), list.pop_front()); + assert_eq!(Some(40), list.pop_front()); + assert_eq!(None, list.pop_front()); + + list.push_back(10); + list.push_front(20); + list.push_back(30); + list.push_back(40); + list.push_front(50); + + assert_eq!(Some(40), list.pop_back()); + assert_eq!(Some(30), list.pop_back()); + assert_eq!(Some(10), list.pop_back()); + assert_eq!(Some(20), list.pop_back()); + assert_eq!(Some(50), list.pop_back()); + assert_eq!(None, list.pop_back()); +} + +#[test] +fn test_get() { + let mut list = LinkedList::new(); + // creo lista [50, 20, 10, 30, 40] + list.push_back(10); + list.push_front(20); + list.push_back(30); + list.push_back(40); + list.push_front(50); + + assert_eq!(5, list.len()); + assert_eq!(Some(10), list.get(2)); + assert_eq!(Some(20), list.get(1)); + assert_eq!(Some(30), list.get(3)); + assert_eq!(Some(40), list.get(4)); + assert_eq!(Some(50), list.get(0)); + assert_eq!(None, list.get(5)); + + assert_eq!(Some(40), list.get(-1)); + assert_eq!(Some(30), list.get(-2)); + assert_eq!(Some(10), list.get(-3)); + assert_eq!(Some(20), list.get(-4)); + assert_eq!(Some(50), list.get(-5)); + assert_eq!(None, list.get(-6)); +}