mirror of
https://github.com/kmc7468/cs220.git
synced 2025-12-14 22:18:46 +00:00
Assignment 11 Done
This commit is contained in:
@@ -16,6 +16,8 @@ use std::cell::RefCell;
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug)]
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
enum VisitStatus {
|
enum VisitStatus {
|
||||||
Unvisited,
|
Unvisited,
|
||||||
@@ -23,6 +25,12 @@ enum VisitStatus {
|
|||||||
Visited,
|
Visited,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Node {
|
||||||
|
value: i32,
|
||||||
|
next: Vec<Rc<RefCell<Node>>>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Handle to a graph node.
|
/// Handle to a graph node.
|
||||||
///
|
///
|
||||||
/// `NodeHandle` should implement `Clone`, which clones the handle without cloning the underlying
|
/// `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.
|
/// You can freely add fields to this struct.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct NodeHandle;
|
pub struct NodeHandle {
|
||||||
|
node: Rc<RefCell<Node>>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Error type for graph operations.
|
/// Error type for graph operations.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -41,12 +51,19 @@ pub struct GraphError;
|
|||||||
///
|
///
|
||||||
/// You can freely add fields to this struct.
|
/// You can freely add fields to this struct.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SubGraph;
|
pub struct SubGraph {
|
||||||
|
nodes: Vec<Rc<RefCell<Node>>>,
|
||||||
|
}
|
||||||
|
|
||||||
impl NodeHandle {
|
impl NodeHandle {
|
||||||
/// Creates a node and returns the handle to it.
|
/// Creates a node and returns the handle to it.
|
||||||
pub fn new(value: i32) -> Self {
|
pub fn new(value: i32) -> Self {
|
||||||
todo!()
|
NodeHandle {
|
||||||
|
node: Rc::new(RefCell::new(Node {
|
||||||
|
value,
|
||||||
|
next: vec![],
|
||||||
|
})),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds an edge to `to`.
|
/// Adds an edge to `to`.
|
||||||
@@ -54,7 +71,16 @@ impl NodeHandle {
|
|||||||
/// `Err(GraphError)`. Returns `Ok(true)` if the edge is successfully added.
|
/// `Err(GraphError)`. Returns `Ok(true)` if the edge is successfully added.
|
||||||
/// Returns `Ok(false)` if an edge to `to` already exits.
|
/// Returns `Ok(false)` if an edge to `to` already exits.
|
||||||
pub fn add_edge(&self, to: NodeHandle) -> Result<bool, GraphError> {
|
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`.
|
/// Removes the edge to `to`.
|
||||||
@@ -62,14 +88,32 @@ impl NodeHandle {
|
|||||||
/// `Err(GraphError)`. Returns `Ok(true)` if the edge is successfully removed.
|
/// `Err(GraphError)`. Returns `Ok(true)` if the edge is successfully removed.
|
||||||
/// Returns `Ok(false)` if an edge to `to` does not exist.
|
/// Returns `Ok(false)` if an edge to `to` does not exist.
|
||||||
pub fn remove_edge(&self, to: &NodeHandle) -> Result<bool, GraphError> {
|
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.
|
/// Removes all edges.
|
||||||
/// If the modification cannot be done, e.g. because of aliasing issues, returns
|
/// If the modification cannot be done, e.g. because of aliasing issues, returns
|
||||||
/// `Err(GraphError)`.
|
/// `Err(GraphError)`.
|
||||||
pub fn clear_edges(&self) -> Result<(), 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 {
|
impl SubGraph {
|
||||||
/// Creates a new subgraph.
|
/// Creates a new subgraph.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
todo!()
|
SubGraph { nodes: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a node to the subgraph. Returns true iff the node is newly added.
|
/// Adds a node to the subgraph. Returns true iff the node is newly added.
|
||||||
pub fn add_node(&mut self, node: NodeHandle) -> bool {
|
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.
|
/// Removes a node from the subgraph. Returns true iff the node is successfully removed.
|
||||||
pub fn remove_node(&mut self, node: &NodeHandle) -> bool {
|
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
|
/// 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.
|
/// are ignored. See <https://en.wikipedia.org/wiki/Cycle_(graph_theory)> for an algorithm.
|
||||||
pub fn detect_cycle(&self) -> bool {
|
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.
|
/// Adds the given node to the front of the list.
|
||||||
pub fn push_front(&mut self, value: T) {
|
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.
|
/// Adds the given node to the back of the list.
|
||||||
pub fn push_back(&mut self, value: T) {
|
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.
|
/// Removes and returns the node at the front of the list.
|
||||||
pub fn pop_front(&mut self) -> Option<T> {
|
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.
|
/// Removes and returns the node at the back of the list.
|
||||||
pub fn pop_back(&mut self) -> Option<T> {
|
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`.
|
/// Create a new list from the given vector `vec`.
|
||||||
pub fn from_vec(vec: Vec<T>) -> Self {
|
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.
|
/// Convert the current list into a vector.
|
||||||
pub fn into_vec(self) -> Vec<T> {
|
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.
|
/// Return the length (i.e., number of nodes) of the list.
|
||||||
pub fn length(&self) -> usize {
|
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.
|
/// 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]`
|
/// `self`: `[1, 2]`, `f`: `|x| x + 1` ==> `[2, 3]`
|
||||||
pub fn map<F: Fn(T) -> T>(self, f: F) -> Self {
|
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.
|
/// Apply given function `f` for each adjacent pair of elements in the list.
|
||||||
@@ -97,7 +155,23 @@ impl<T: Debug> SinglyLinkedList<T> {
|
|||||||
where
|
where
|
||||||
T: Clone,
|
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]]`
|
/// `self`: `[[1, 2, 3], [4, 5, 6], [7, 8]]`
|
||||||
/// ==> `[1, 2, 3, 4, 5, 6, 7, 8]`
|
/// ==> `[1, 2, 3, 4, 5, 6, 7, 8]`
|
||||||
pub fn flatten(self) -> SinglyLinkedList<T> {
|
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 {
|
impl Storage for MockStorage {
|
||||||
fn upload(&self, name: &str, size: usize) -> Result<(), usize> {
|
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 {
|
fn used(&self) -> usize {
|
||||||
todo!()
|
let mut result = 0;
|
||||||
|
|
||||||
|
for size in self.files.borrow().values() {
|
||||||
|
result += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn capacity(&self) -> usize {
|
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.
|
/// Uploads a file to the internal storage.
|
||||||
pub fn upload(&self, name: &str, size: usize) -> Result<(), usize> {
|
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.
|
/// Returns `true` if the usage of the internal storage is under the bound.
|
||||||
pub fn is_usage_under_bound(&self) -> bool {
|
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.
|
/// Returns `None` if the TV room is already opened.
|
||||||
pub fn open(&self) -> Option<Manager<'_>> {
|
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.
|
/// Returns whether the TV room is opened or not.
|
||||||
pub fn is_opened(&self) -> bool {
|
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.
|
/// Adds new guest to the TV room.
|
||||||
pub fn new_guest(&self) -> Guest<'a> {
|
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<'_> {
|
impl Drop for Watcher<'_> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// When the last person leaves the TV room, the TV room should be closed.
|
// 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