Assignment 11 Done

This commit is contained in:
static
2024-12-03 10:11:00 +00:00
parent 03a2c8c2f5
commit 02ab54a6b0
4 changed files with 228 additions and 29 deletions

View File

@@ -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<Rc<RefCell<Node>>>,
}
/// 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<RefCell<Node>>,
}
/// 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<Rc<RefCell<Node>>>,
}
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<bool, GraphError> {
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<bool, GraphError> {
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 <https://en.wikipedia.org/wiki/Cycle_(graph_theory)> for an algorithm.
pub fn detect_cycle(&self) -> bool {
todo!()
fn helper(subgraph: &SubGraph, visited: &mut HashSet<usize>, 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
}
}

View File

@@ -42,37 +42,87 @@ impl<T: Debug> SinglyLinkedList<T> {
/// 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<T> {
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<T> {
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<T>) -> 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<T> {
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<T: Debug> SinglyLinkedList<T> {
///
/// `self`: `[1, 2]`, `f`: `|x| x + 1` ==> `[2, 3]`
pub fn map<F: Fn(T) -> 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<T: Debug> SinglyLinkedList<T> {
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<T: Debug> SinglyLinkedList<SinglyLinkedList<T>> {
/// `self`: `[[1, 2, 3], [4, 5, 6], [7, 8]]`
/// ==> `[1, 2, 3, 4, 5, 6, 7, 8]`
pub fn flatten(self) -> SinglyLinkedList<T> {
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
}
}

View File

@@ -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
}
}

View File

@@ -56,12 +56,20 @@ impl TVRoom {
///
/// Returns `None` if the TV room is already opened.
pub fn open(&self) -> Option<Manager<'_>> {
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;
}
}