mirror of
https://github.com/kmc7468/cs220.git
synced 2025-12-12 21:08:45 +00:00
Assignment 11 Done
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user