diff --git a/src/assignments/assignment11/graph.rs b/src/assignments/assignment11/graph.rs index 77b8586..e8d1c0d 100644 --- a/src/assignments/assignment11/graph.rs +++ b/src/assignments/assignment11/graph.rs @@ -16,6 +16,8 @@ use std::cell::RefCell; use std::collections::HashSet; use std::rc::Rc; +use itertools::Itertools; + #[derive(PartialEq, Eq, Debug)] enum VisitStatus { Unvisited, @@ -23,6 +25,12 @@ enum VisitStatus { Visited, } +#[derive(Debug)] +struct Node { + value: i32, + next: Vec>>, +} + /// Handle to a graph node. /// /// `NodeHandle` should implement `Clone`, which clones the handle without cloning the underlying @@ -31,7 +39,9 @@ enum VisitStatus { /// /// You can freely add fields to this struct. #[derive(Debug, Clone)] -pub struct NodeHandle; +pub struct NodeHandle { + node: Rc>, +} /// Error type for graph operations. #[derive(Debug)] @@ -41,12 +51,19 @@ pub struct GraphError; /// /// You can freely add fields to this struct. #[derive(Debug)] -pub struct SubGraph; +pub struct SubGraph { + nodes: Vec>>, +} impl NodeHandle { /// Creates a node and returns the handle to it. pub fn new(value: i32) -> Self { - todo!() + NodeHandle { + node: Rc::new(RefCell::new(Node { + value, + next: vec![], + })), + } } /// Adds an edge to `to`. @@ -54,7 +71,16 @@ impl NodeHandle { /// `Err(GraphError)`. Returns `Ok(true)` if the edge is successfully added. /// Returns `Ok(false)` if an edge to `to` already exits. pub fn add_edge(&self, to: NodeHandle) -> Result { - todo!() + let mut my_node = match self.node.try_borrow_mut() { + Ok(r) => r, + Err(_) => return Err(GraphError), + }; + if my_node.next.iter().any(|v| Rc::ptr_eq(v, &to.node)) { + Ok(false) + } else { + my_node.next.push(to.node.clone()); + Ok(true) + } } /// Removes the edge to `to`. @@ -62,14 +88,32 @@ impl NodeHandle { /// `Err(GraphError)`. Returns `Ok(true)` if the edge is successfully removed. /// Returns `Ok(false)` if an edge to `to` does not exist. pub fn remove_edge(&self, to: &NodeHandle) -> Result { - todo!() + let mut my_node = match self.node.try_borrow_mut() { + Ok(r) => r, + Err(_) => return Err(GraphError), + }; + let index = my_node + .next + .iter() + .find_position(|v| Rc::ptr_eq(v, &to.node)); + if let Some((index, _)) = index { + let _unused = my_node.next.remove(index); + Ok(true) + } else { + Ok(false) + } } /// Removes all edges. /// If the modification cannot be done, e.g. because of aliasing issues, returns /// `Err(GraphError)`. pub fn clear_edges(&self) -> Result<(), GraphError> { - todo!() + let mut my_node = match self.node.try_borrow_mut() { + Ok(r) => r, + Err(_) => return Err(GraphError), + }; + my_node.next.clear(); + Ok(()) } } @@ -82,22 +126,65 @@ impl Default for SubGraph { impl SubGraph { /// Creates a new subgraph. pub fn new() -> Self { - todo!() + SubGraph { nodes: vec![] } } /// Adds a node to the subgraph. Returns true iff the node is newly added. pub fn add_node(&mut self, node: NodeHandle) -> bool { - todo!() + let index = self + .nodes + .iter() + .find_position(|v| Rc::ptr_eq(v, &node.node)); + if index.is_none() { + self.nodes.push(node.node.clone()); + true + } else { + false + } } /// Removes a node from the subgraph. Returns true iff the node is successfully removed. pub fn remove_node(&mut self, node: &NodeHandle) -> bool { - todo!() + let index = self + .nodes + .iter() + .find_position(|v| Rc::ptr_eq(v, &node.node)); + if let Some((index, _)) = index { + let _unused = self.nodes.remove(index); + true + } else { + false + } } /// Returns true iff the subgraph contains a cycle. Nodes that do not belong to this subgraph /// are ignored. See for an algorithm. pub fn detect_cycle(&self) -> bool { - todo!() + fn helper(subgraph: &SubGraph, visited: &mut HashSet, node: usize) -> bool { + if visited.contains(&node) { + return true; + } + + let _ = visited.insert(node); + + for next in &subgraph.nodes[node].borrow().next { + let next_index = subgraph.nodes.iter().find_position(|n| Rc::ptr_eq(n, next)); + if let Some((next_index, _)) = next_index { + let mut visited = visited.clone(); + if helper(subgraph, &mut visited, next_index) { + return true; + } + } + } + false + } + + for i in 0..self.nodes.len() { + let mut visited = HashSet::new(); + if helper(self, &mut visited, i) { + return true; + } + } + false } } diff --git a/src/assignments/assignment11/linked_list.rs b/src/assignments/assignment11/linked_list.rs index 8cb7718..4e5acca 100644 --- a/src/assignments/assignment11/linked_list.rs +++ b/src/assignments/assignment11/linked_list.rs @@ -42,37 +42,87 @@ impl SinglyLinkedList { /// Adds the given node to the front of the list. pub fn push_front(&mut self, value: T) { - todo!() + let next = self.head.take().map(Box::new); + self.head = Some(Node { value, next }) } /// Adds the given node to the back of the list. pub fn push_back(&mut self, value: T) { - todo!() + let new_node = Node { value, next: None }; + if let Some(ref mut head) = self.head { + let mut current = head; + while let Some(ref mut next) = current.next { + current = next; + } + current.next = Some(Box::new(new_node)); + } else { + self.head = Some(new_node); + } } /// Removes and returns the node at the front of the list. pub fn pop_front(&mut self) -> Option { - todo!() + if let Some(head) = self.head.take() { + self.head = head.next.map(|n| *n); + Some(head.value) + } else { + None + } } /// Removes and returns the node at the back of the list. pub fn pop_back(&mut self) -> Option { - todo!() + if let Some(head) = &mut self.head { + if head.next.is_none() { + return Some(self.head.take().unwrap().value); + } + + let mut prev = head; + while let Some(next) = &mut prev.next.as_mut().unwrap().next { + prev = prev.next.as_mut().unwrap(); + } + + Some(prev.next.take().unwrap().value) + } else { + None + } } /// Create a new list from the given vector `vec`. pub fn from_vec(vec: Vec) -> Self { - todo!() + let mut result = Self::new(); + + for e in vec { + result.push_back(e); + } + + result } /// Convert the current list into a vector. pub fn into_vec(self) -> Vec { - todo!() + let mut result = vec![]; + let mut current = self.head; + + while let Some(node) = current { + result.push(node.value); + current = node.next.map(|n| *n); + } + + result } /// Return the length (i.e., number of nodes) of the list. pub fn length(&self) -> usize { - todo!() + let mut result = 0; + let mut current = self.head.as_ref(); + + while let Some(node) = current { + result += 1; + current = node.next.as_deref(); + } + + result } /// Apply function `f` on every element of the list. @@ -81,7 +131,15 @@ impl SinglyLinkedList { /// /// `self`: `[1, 2]`, `f`: `|x| x + 1` ==> `[2, 3]` pub fn map T>(self, f: F) -> Self { - todo!() + let mut result = Self::new(); + let mut current = self.head; + + while let Some(node) = current { + result.push_back(f(node.value)); + current = node.next.map(|n| *n); + } + + result } /// Apply given function `f` for each adjacent pair of elements in the list. @@ -97,7 +155,23 @@ impl SinglyLinkedList { where T: Clone, { - todo!() + if self.length() < 2 { + return self; + } + + let mut result = SinglyLinkedList::new(); + let (mut prev, mut current) = { + let head = self.head.unwrap(); + (head.value, head.next) + }; + + while let Some(node) = current { + result.push_back(f(prev, node.value.clone())); + prev = node.value; + current = node.next; + } + + result } } @@ -109,6 +183,19 @@ impl SinglyLinkedList> { /// `self`: `[[1, 2, 3], [4, 5, 6], [7, 8]]` /// ==> `[1, 2, 3, 4, 5, 6, 7, 8]` pub fn flatten(self) -> SinglyLinkedList { - todo!() + let mut result = SinglyLinkedList::new(); + let mut current = self.head; + + while let Some(node) = current { + let mut inner_current = node.value.head; + while let Some(node) = inner_current { + result.push_back(node.value); + inner_current = node.next.map(|n| *n); + } + + current = node.next.map(|n| *n); + } + + result } } diff --git a/src/assignments/assignment11/mock_storage.rs b/src/assignments/assignment11/mock_storage.rs index 4e0edc2..657c875 100644 --- a/src/assignments/assignment11/mock_storage.rs +++ b/src/assignments/assignment11/mock_storage.rs @@ -47,15 +47,30 @@ pub trait Storage { impl Storage for MockStorage { fn upload(&self, name: &str, size: usize) -> Result<(), usize> { - todo!() + let used = self.used(); + let mut files = self.files.borrow_mut(); + let old_size = files.get(name).unwrap_or(&0); + + if used - old_size + size <= self.capacity() { + let _ = files.insert(String::from(name), size); + Ok(()) + } else { + Err(size - (self.capacity - (used - old_size))) + } } fn used(&self) -> usize { - todo!() + let mut result = 0; + + for size in self.files.borrow().values() { + result += size; + } + + result } fn capacity(&self) -> usize { - todo!() + self.capacity } } @@ -75,7 +90,7 @@ impl<'a, T: Storage> FileUploader<'a, T> { /// Uploads a file to the internal storage. pub fn upload(&self, name: &str, size: usize) -> Result<(), usize> { - todo!() + self.storage.upload(name, size) } } @@ -94,6 +109,6 @@ impl<'a, T: Storage> UsageAnalyzer<'a, T> { /// Returns `true` if the usage of the internal storage is under the bound. pub fn is_usage_under_bound(&self) -> bool { - todo!() + (self.storage.used() as f64) / (self.storage.capacity() as f64) <= self.bound } } diff --git a/src/assignments/assignment11/tv_room.rs b/src/assignments/assignment11/tv_room.rs index d1ae8b6..1101858 100644 --- a/src/assignments/assignment11/tv_room.rs +++ b/src/assignments/assignment11/tv_room.rs @@ -56,12 +56,20 @@ impl TVRoom { /// /// Returns `None` if the TV room is already opened. pub fn open(&self) -> Option> { - todo!() + if self.is_opened() { + None + } else { + *self.state.borrow_mut() = TVRoomState::Opened; + Some(Manager::new(&self.state)) + } } /// Returns whether the TV room is opened or not. pub fn is_opened(&self) -> bool { - todo!() + match *self.state.borrow() { + TVRoomState::Opened => true, + TVRoomState::Closed => false, + } } } @@ -84,7 +92,9 @@ impl<'a> Manager<'a> { /// Adds new guest to the TV room. pub fn new_guest(&self) -> Guest<'a> { - todo!() + Guest { + inner: self.inner.clone(), + } } } @@ -108,6 +118,6 @@ impl<'a> Watcher<'a> { impl Drop for Watcher<'_> { fn drop(&mut self) { // When the last person leaves the TV room, the TV room should be closed. - todo!() + *self.tvstate.borrow_mut() = TVRoomState::Closed; } }