mirror of
https://github.com/kmc7468/cs220.git
synced 2025-12-12 21:08:45 +00:00
apply comments
This commit is contained in:
@@ -24,7 +24,7 @@ run_linters || exit 1
|
||||
for RUNNER in "${RUNNERS[@]}"; do
|
||||
echo "Running with $RUNNER..."
|
||||
|
||||
TESTS=("--lib assignment01_grade")
|
||||
TESTS=("--lib assignment01")
|
||||
if [ $(run_tests) -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -24,7 +24,7 @@ run_linters || exit 1
|
||||
for RUNNER in "${RUNNERS[@]}"; do
|
||||
echo "Running with $RUNNER..."
|
||||
|
||||
TESTS=("--lib assignment08_grade")
|
||||
TESTS=("--lib assignment08")
|
||||
if [ $(run_tests) -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -24,7 +24,7 @@ run_linters || exit 1
|
||||
for RUNNER in "${RUNNERS[@]}"; do
|
||||
echo "Running with $RUNNER..."
|
||||
|
||||
TESTS=("--lib assignment13_grade")
|
||||
TESTS=("--lib assignment13")
|
||||
if [ $(run_tests) -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -4,16 +4,9 @@
|
||||
//! Please make sure you're comfortable with developing Rust programs before moving on to the next assignments.
|
||||
//!
|
||||
//! You should fill out `add()` and `sub()` function bodies in such a way that `/scripts/grade-01.sh` works fine.
|
||||
//! See `assignment01_grade.rs` and `/scripts/grade-01.sh` for the test script.
|
||||
//! See `small_problems_grade.rs` and `/scripts/grade-01.sh` for the test script.
|
||||
//!
|
||||
//! Hint: <https://doc.rust-lang.org/std/primitive.usize.html>
|
||||
|
||||
/// Adds two unsigned words. If overflow happens, just wrap around.
|
||||
pub fn add(lhs: usize, rhs: usize) -> usize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Subtracts two unsigned words. If overflow happens, just wrap around.
|
||||
pub fn sub(lhs: usize, rhs: usize) -> usize {
|
||||
todo!()
|
||||
}
|
||||
pub mod small_problems;
|
||||
mod small_problems_grade;
|
||||
12
src/assignments/assignment01/small_problems.rs
Normal file
12
src/assignments/assignment01/small_problems.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
//! Assignment 1: Preparing Rust Development Environment.
|
||||
//! Welcome to the CS220 course!
|
||||
|
||||
/// Adds two unsigned words. If overflow happens, just wrap around.
|
||||
pub fn add(lhs: usize, rhs: usize) -> usize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Subtracts two unsigned words. If overflow happens, just wrap around.
|
||||
pub fn sub(lhs: usize, rhs: usize) -> usize {
|
||||
todo!()
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::super::assignment01::*;
|
||||
use crate::assignments::assignment01::small_problems::*;
|
||||
|
||||
#[test]
|
||||
fn test_add_7_3() {
|
||||
@@ -1,6 +1,6 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::super::semiring::*;
|
||||
use crate::assignments::assignment06::semiring::*;
|
||||
use ntest::assert_about_eq;
|
||||
|
||||
fn test_from_str(s: &str, f: impl Fn(i64) -> i64) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::super::square_matrix::*;
|
||||
use crate::assignments::assignment06::square_matrix::*;
|
||||
use ntest::assert_about_eq;
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::super::symbolic_differentiation::*;
|
||||
use crate::assignments::assignment06::symbolic_differentiation::*;
|
||||
use ntest::assert_about_eq;
|
||||
|
||||
// Constant rationals to use
|
||||
|
||||
@@ -3,7 +3,7 @@ mod test {
|
||||
use itertools::Itertools;
|
||||
use ntest::assert_about_eq;
|
||||
|
||||
use super::super::generator::*;
|
||||
use crate::assignments::assignment07::generator::*;
|
||||
|
||||
#[test]
|
||||
fn test_generator() {
|
||||
|
||||
@@ -3,7 +3,7 @@ mod test {
|
||||
use itertools::Itertools;
|
||||
use ntest::assert_about_eq;
|
||||
|
||||
use super::super::hubo::*;
|
||||
use crate::assignments::assignment07::hubo::*;
|
||||
|
||||
#[test]
|
||||
fn test_hubo_dir4_movement() {
|
||||
|
||||
@@ -3,7 +3,7 @@ mod test {
|
||||
use itertools::Itertools;
|
||||
use ntest::assert_about_eq;
|
||||
|
||||
use super::super::my_itertools::*;
|
||||
use crate::assignments::assignment07::my_itertools::*;
|
||||
|
||||
#[test]
|
||||
fn test_itertools() {
|
||||
|
||||
@@ -3,7 +3,7 @@ mod test {
|
||||
use itertools::Itertools;
|
||||
use ntest::assert_about_eq;
|
||||
|
||||
use super::super::small_exercises::*;
|
||||
use crate::assignments::assignment07::small_exercises::*;
|
||||
|
||||
#[test]
|
||||
fn test_find() {
|
||||
|
||||
@@ -3,7 +3,7 @@ mod test {
|
||||
use itertools::Itertools;
|
||||
use ntest::assert_about_eq;
|
||||
|
||||
use super::super::transform::*;
|
||||
use crate::assignments::assignment07::transform::*;
|
||||
|
||||
#[test]
|
||||
fn test_transform_identity() {
|
||||
|
||||
9
src/assignments/assignment08/mod.rs
Normal file
9
src/assignments/assignment08/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
//! Assignment 8: First-class functions.
|
||||
//!
|
||||
//! The primary goal of this assignment is to get used to first-class functions.
|
||||
//!
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-08.sh` works fine.
|
||||
//! See `small_problems_grade.rs` and `/scripts/grade-08.sh` for the test script.
|
||||
|
||||
pub mod small_problems;
|
||||
mod small_problems_grade;
|
||||
@@ -1,9 +1,4 @@
|
||||
//! Assignment 8: First-class functions.
|
||||
//!
|
||||
//! The primary goal of this assignment is to get used to first-class functions.
|
||||
//!
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-08.sh` works fine.
|
||||
//! See `assignment08_grade.rs` and `/scripts/grade-08.sh` for the test script.
|
||||
//! Assignment 08: First-class functions.
|
||||
|
||||
/// Repeat
|
||||
///
|
||||
@@ -1,6 +1,6 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::super::assignment08::*;
|
||||
use crate::assignments::assignment08::small_problems::*;
|
||||
|
||||
#[test]
|
||||
fn test_repeat() {
|
||||
@@ -3,7 +3,7 @@ mod test {
|
||||
|
||||
use ntest::{assert_false, assert_true};
|
||||
|
||||
use super::super::bigint::*;
|
||||
use crate::assignments::assignment09::bigint::*;
|
||||
|
||||
#[test]
|
||||
fn test_inf_prec_simple() {
|
||||
|
||||
@@ -20,6 +20,9 @@ pub fn vec_add(lhs: &[f64], rhs: &[f64]) -> Vec<f64> {
|
||||
|
||||
/// dot product of two arrays
|
||||
///
|
||||
/// You don't know how to calculate dot product?
|
||||
/// See <https://mathinsight.org/dot_product_examples>
|
||||
///
|
||||
/// # Exmaple
|
||||
///
|
||||
/// ```
|
||||
@@ -37,6 +40,9 @@ pub fn dot_product(lhs: &[f64], rhs: &[f64]) -> f64 {
|
||||
|
||||
/// Matrix multiplication
|
||||
///
|
||||
/// You don't know how to multiply matrix?
|
||||
/// Quite simple! See <https://www.mathsisfun.com/algebra/matrix-multiplying.html>
|
||||
///
|
||||
/// Assume rhs is transposed
|
||||
/// - lhs: (m, n)
|
||||
/// - rhs: (p, n)
|
||||
|
||||
@@ -3,7 +3,7 @@ mod test {
|
||||
|
||||
use ntest::{assert_false, assert_true};
|
||||
|
||||
use super::super::small_exercises::*;
|
||||
use crate::assignments::assignment09::small_exercises::*;
|
||||
|
||||
#[test]
|
||||
fn test_is_fibonacci() {
|
||||
|
||||
@@ -3,7 +3,7 @@ mod test {
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
|
||||
use super::super::labyrinth::*;
|
||||
use crate::assignments::assignment10::labyrinth::*;
|
||||
|
||||
type Wife = usize;
|
||||
type Rooms = Vec<Wife>;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
mod test {
|
||||
use std::collections::HashSet;
|
||||
|
||||
use super::super::small_exercises::*;
|
||||
use crate::assignments::assignment10::small_exercises::*;
|
||||
|
||||
#[test]
|
||||
fn test_inversion() {
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
//! Binary Search Tree
|
||||
//!
|
||||
//! Refer `bst_grade.rs` for test cases.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::Debug;
|
||||
use std::ops::Deref;
|
||||
use std::rc::{Rc, Weak};
|
||||
|
||||
/// Node struct of tree
|
||||
#[derive(Debug, Clone)]
|
||||
struct Node<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
value: T,
|
||||
parent: Option<Weak<RefCell<Node<T>>>>,
|
||||
left: Option<Rc<RefCell<Node<T>>>>,
|
||||
right: Option<Rc<RefCell<Node<T>>>>,
|
||||
}
|
||||
|
||||
impl<T> Node<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
fn new(value: T) -> Rc<RefCell<Node<T>>> {
|
||||
Rc::new(RefCell::new(Node {
|
||||
value,
|
||||
parent: None,
|
||||
left: None,
|
||||
right: None,
|
||||
}))
|
||||
}
|
||||
|
||||
fn with_parent(value: T, parent: Weak<RefCell<Node<T>>>) -> Rc<RefCell<Node<T>>> {
|
||||
Rc::new(RefCell::new(Node {
|
||||
value,
|
||||
parent: Some(parent),
|
||||
left: None,
|
||||
right: None,
|
||||
}))
|
||||
}
|
||||
|
||||
/// Minimum node starting from cursor
|
||||
fn min_node(mut cursor: Rc<RefCell<Node<T>>>) -> Rc<RefCell<Node<T>>> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
/// Upgraded parent node.
|
||||
/// `None` if the node has no parent.
|
||||
fn parent(&self) -> Option<Rc<RefCell<Node<T>>>> {
|
||||
self.parent.as_ref().and_then(|p| p.upgrade())
|
||||
}
|
||||
}
|
||||
|
||||
/// Binary Search Tree
|
||||
#[derive(Debug)]
|
||||
pub struct Tree<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
root: Option<Rc<RefCell<Node<T>>>>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl<T: Ord> Default for Tree<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Tree<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
/// New tree
|
||||
pub fn new() -> Tree<T> {
|
||||
Tree { root: None, len: 0 }
|
||||
}
|
||||
|
||||
/// Length of the tree
|
||||
pub fn len(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
|
||||
/// Check if the tree is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len == 0
|
||||
}
|
||||
|
||||
/// Check if the tree contains the value.
|
||||
pub fn contains(&self, value: &T) -> bool {
|
||||
if let Some(mut cursor) = self.root.clone() {
|
||||
todo!();
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert the value into the tree.
|
||||
/// If there was no equal value in the tree, it returns `true`.
|
||||
/// Otherwise, it returns `false`.
|
||||
pub fn insert(&mut self, value: T) -> bool {
|
||||
self.len += 1;
|
||||
if let Some(mut cursor) = self.root.clone() {
|
||||
todo!();
|
||||
} else {
|
||||
self.root = Some(Node::new(value));
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove the node from the tree.
|
||||
/// Returns the value of the removed node.
|
||||
fn remove_node(&mut self, mut node: Rc<RefCell<Node<T>>>) -> T {
|
||||
todo!();
|
||||
}
|
||||
|
||||
/// Remove the value from the tree.
|
||||
/// If there is an equal value in the tree, it returns `true`.
|
||||
/// Otherwise, it returns `false`.
|
||||
pub fn remove(&mut self, value: &T) -> Option<T> {
|
||||
let res = if let Some(root) = self.root.clone() {
|
||||
let mut cursor = root;
|
||||
|
||||
loop {
|
||||
let mut cursor_ref = cursor.deref().borrow_mut();
|
||||
let child = match value.cmp(&cursor_ref.value) {
|
||||
Ordering::Less => cursor_ref.left.clone(),
|
||||
Ordering::Greater => cursor_ref.right.clone(),
|
||||
Ordering::Equal => {
|
||||
drop(cursor_ref);
|
||||
break Some(self.remove_node(cursor));
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(child) = child {
|
||||
drop(cursor_ref);
|
||||
cursor = child;
|
||||
} else {
|
||||
break None;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
self.len -= res.is_some() as usize;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for Tree<T>
|
||||
where
|
||||
T: Ord + Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Tree {
|
||||
root: self.root.clone(),
|
||||
len: self.len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// IntoIterator for Tree
|
||||
#[derive(Debug)]
|
||||
pub struct IntoIter<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
tree: Tree<T>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for Tree<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
let len = self.len;
|
||||
IntoIter { tree: self, len }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Iterator for IntoIter<T>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(self.len, Some(self.len))
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
//! Test cases for assignment11/bst.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_bst {
|
||||
use super::super::bst::*;
|
||||
|
||||
#[test]
|
||||
fn bst_insert_test() {
|
||||
let mut tree = Tree::new();
|
||||
|
||||
let _ = tree.insert(1);
|
||||
let _ = tree.insert(5);
|
||||
let _ = tree.insert(3);
|
||||
let _ = tree.insert(7);
|
||||
|
||||
assert_eq!(tree.into_iter().collect::<Vec<_>>(), vec![1, 3, 5, 7]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bst_remove_test() {
|
||||
let mut tree = Tree::new();
|
||||
|
||||
let _ = tree.insert(1);
|
||||
let _ = tree.insert(5);
|
||||
let _ = tree.insert(3);
|
||||
let _ = tree.insert(7);
|
||||
let _ = tree.remove(&7);
|
||||
|
||||
assert_eq!(tree.into_iter().collect::<Vec<_>>(), vec![1, 3, 5]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bst_complex_test() {
|
||||
let mut tree = Tree::new();
|
||||
|
||||
let _ = tree.insert(1);
|
||||
let _ = tree.insert(5);
|
||||
let _ = tree.insert(3);
|
||||
let _ = tree.insert(7);
|
||||
let _ = tree.remove(&7);
|
||||
let _ = tree.insert(7);
|
||||
let _ = tree.insert(6);
|
||||
let _ = tree.insert(8);
|
||||
let _ = tree.remove(&5);
|
||||
let _ = tree.remove(&1);
|
||||
let _ = tree.remove(&3);
|
||||
let _ = tree.remove(&7);
|
||||
let _ = tree.remove(&6);
|
||||
let _ = tree.remove(&8);
|
||||
|
||||
assert_eq!(tree.into_iter().collect::<Vec<_>>(), vec![]);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_doubly_linked_list {
|
||||
use super::super::doubly_linked_list::*;
|
||||
use crate::assignments::assignment11::doubly_linked_list::*;
|
||||
|
||||
#[test]
|
||||
fn test_works() {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_graph {
|
||||
use super::super::graph::*;
|
||||
use crate::assignments::assignment11::graph::*;
|
||||
|
||||
#[test]
|
||||
fn test_graph() {
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
//! Singly linked list.
|
||||
//!
|
||||
//! Consult <https://doc.rust-lang.org/book/ch15-01-box.html>.
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// Node of the list.
|
||||
#[derive(Debug)]
|
||||
pub struct Node<T: Debug> {
|
||||
/// Value of current node.
|
||||
pub value: T,
|
||||
|
||||
/// Pointer to the next node. If it is `None`, there is no next node.
|
||||
pub next: Option<Box<Node<T>>>,
|
||||
}
|
||||
|
||||
impl<T: Debug> Node<T> {
|
||||
/// Creates a new node.
|
||||
pub fn new(value: T) -> Self {
|
||||
Self { value, next: None }
|
||||
}
|
||||
}
|
||||
|
||||
/// A singly-linked list.
|
||||
#[derive(Debug)]
|
||||
pub struct SinglyLinkedList<T: Debug> {
|
||||
/// Head node of the list. If it is `None`, the list is empty.
|
||||
head: Option<Node<T>>,
|
||||
}
|
||||
|
||||
impl<T: Debug> Default for SinglyLinkedList<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Debug> SinglyLinkedList<T> {
|
||||
/// Creates a new list.
|
||||
pub fn new() -> Self {
|
||||
Self { head: None }
|
||||
}
|
||||
|
||||
/// Adds the given node to the front of the list.
|
||||
pub fn push_front(&mut self, value: T) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Adds the given node to the back of the list.
|
||||
pub fn push_back(&mut self, value: T) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Removes and returns the node at the front of the list.
|
||||
pub fn pop_front(&mut self) -> Option<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Removes and returns the node at the back of the list.
|
||||
pub fn pop_back(&mut self) -> Option<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Create a new list from the given vector `vec`.
|
||||
pub fn from_vec(vec: Vec<T>) -> Self {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Convert the current list into a vector.
|
||||
pub fn as_vec(&self) -> Vec<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Return the length (i.e., number of nodes) of the list.
|
||||
pub fn length(&self) -> usize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Apply function `f` on every element of the list.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// `self`: `[1, 2]`, `f`: `|x| x + 1` ==> `[2, 3]`
|
||||
pub fn map<F: Fn(T) -> T>(&mut self, f: F) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Insert given list `another` at the specified index `idx`.
|
||||
/// If `idx` is out-of-bound of `self`, append `another` at the end of `self`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// `self`: `[1, 2]`, `another`: `[3, 4]`, `idx`: `1` ==> `[1, 3, 4, 2]`
|
||||
/// `self`: `[1, 2]`, `another`: `[3, 4]`, `idx`: `5` ==> `[1, 2, 3, 4]`
|
||||
pub fn insert(&mut self, another: &Self, idx: usize) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Reverse the list in a chunk of size `n`.
|
||||
/// If `n == 0`, do nothing.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// `self`: `[1, 2, 3, 4, 5, 6, 7, 8, 9]`, `n`: `3`
|
||||
/// // each chunk of size `3`: `[1, 2, 3]`, `[4, 5, 6]`, `[7, 8, 9]`
|
||||
/// // reversed sequence of chunks: `[7, 8, 9]`, `[4, 5, 6]`, `[1, 2, 3]`
|
||||
/// ==> `[7, 8, 9, 4, 5, 6, 1, 2, 3]`,
|
||||
///
|
||||
/// `self`: `[1, 2, 3, 4, 5, 6, 7, 8, 9]`, `n`: `4`
|
||||
/// // each chunk of size `4`: `[1, 2, 3, 4]`, `[5, 6, 7, 8]`, `[9]`
|
||||
/// // reversed sequence of chunks: `[9]`, `[5, 6, 7, 8]`, `[1, 2, 3, 4]`
|
||||
/// ==> `[9, 5, 6, 7, 8, 1, 2, 3, 4]`
|
||||
pub fn chunk_reverse(&mut self, n: usize) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Apply given function `f` for each adjacent pair of elements in the list.
|
||||
/// If `self.length() < 2`, do nothing.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// `self`: `[1, 2, 3, 4]`, `f`: `|x, y| x + y`
|
||||
/// // each adjacent pair of elements: `(1, 2)`, `(2, 3)`, `(3, 4)`
|
||||
/// // apply `f` to each pair: `f(1, 2) == 3`, `f(2, 3) == 5`, `f(3, 4) == 7`
|
||||
/// ==> `[3, 5, 7]`
|
||||
pub fn pair_map<F: Fn(T, T) -> T>(&mut self, f: F) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
// A list of lists.
|
||||
impl<T: Debug> SinglyLinkedList<SinglyLinkedList<T>> {
|
||||
/// Flatten the list of lists into a single list.
|
||||
///
|
||||
/// # Examples
|
||||
/// `self`: `[[1, 2, 3], [4, 5, 6], [7, 8]]`
|
||||
/// ==> `[1, 2, 3, 4, 5, 6, 7, 8]`
|
||||
pub fn flatten(self) -> SinglyLinkedList<T> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
#[cfg(test)]
|
||||
mod test_linked_list {
|
||||
use crate::assignments::assignment11::linked_list::*;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct V(usize);
|
||||
|
||||
#[test]
|
||||
fn test_push_pop() {
|
||||
let mut list = SinglyLinkedList::new();
|
||||
list.push_back(V(3));
|
||||
list.push_front(V(2));
|
||||
list.push_back(V(4));
|
||||
list.push_front(V(1));
|
||||
list.push_back(V(5));
|
||||
|
||||
assert_eq!(list.pop_front(), Some(V(1)));
|
||||
assert_eq!(list.pop_back(), Some(V(5)));
|
||||
assert_eq!(list.pop_front(), Some(V(2)));
|
||||
assert_eq!(list.pop_back(), Some(V(4)));
|
||||
assert_eq!(list.pop_front(), Some(V(3)));
|
||||
assert_eq!(list.pop_back(), None);
|
||||
assert_eq!(list.pop_front(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_as_vec() {
|
||||
assert_eq!(SinglyLinkedList::<i32>::new().as_vec(), vec![]);
|
||||
assert_eq!(
|
||||
SinglyLinkedList::from_vec(vec![1, 2, 3]).as_vec(),
|
||||
vec![1, 2, 3]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_length() {
|
||||
let list = SinglyLinkedList::from_vec(vec![1, 2, 3]);
|
||||
assert_eq!(list.length(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_map() {
|
||||
let mut list = SinglyLinkedList::from_vec(vec![1, 2, 3]);
|
||||
let incr = |x: i32| x + 1;
|
||||
list.map(incr);
|
||||
assert_eq!(list.as_vec(), vec![2, 3, 4]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert() {
|
||||
let mut list1 = SinglyLinkedList::from_vec(vec![1, 2, 3]);
|
||||
let mut list2 = SinglyLinkedList::from_vec(vec![1, 2, 3]);
|
||||
let mut list3 = SinglyLinkedList::from_vec(vec![1, 2, 3]);
|
||||
let list4 = SinglyLinkedList::from_vec(vec![4, 5, 6]);
|
||||
|
||||
list1.insert(&list4, 0);
|
||||
assert_eq!(list1.as_vec(), vec![4, 5, 6, 1, 2, 3]);
|
||||
|
||||
list2.insert(&list4, 1);
|
||||
assert_eq!(list2.as_vec(), vec![1, 4, 5, 6, 2, 3]);
|
||||
|
||||
list3.insert(&list4, 4);
|
||||
assert_eq!(list3.as_vec(), vec![1, 2, 3, 4, 5, 6]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_chunk_reverse() {
|
||||
let mut list1 = SinglyLinkedList::from_vec(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
list1.chunk_reverse(3);
|
||||
assert_eq!(list1.as_vec(), vec![7, 8, 9, 3, 4, 5, 1, 2, 3]);
|
||||
|
||||
let mut list2 = SinglyLinkedList::from_vec(vec![1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
list2.chunk_reverse(3);
|
||||
assert_eq!(list2.as_vec(), vec![7, 8, 4, 5, 6, 1, 2, 3]);
|
||||
|
||||
let mut list3 = SinglyLinkedList::from_vec(vec![1, 2, 3]);
|
||||
list3.chunk_reverse(4);
|
||||
assert_eq!(list3.as_vec(), vec![1, 2, 3]);
|
||||
|
||||
let mut list4 = SinglyLinkedList::from_vec(vec![1, 2, 3, 4]);
|
||||
list4.chunk_reverse(1);
|
||||
assert_eq!(list4.as_vec(), vec![4, 3, 2, 1]);
|
||||
|
||||
let mut list5 = SinglyLinkedList::from_vec(vec![1, 2, 3, 4]);
|
||||
list4.chunk_reverse(0);
|
||||
assert_eq!(list4.as_vec(), vec![1, 2, 3, 4]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pair_map() {
|
||||
let mut list = SinglyLinkedList::from_vec(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
let add = |x: i32, y: i32| x + y;
|
||||
|
||||
list.pair_map(add);
|
||||
assert_eq!(list.as_vec(), vec![3, 5, 7, 9, 11, 13, 15, 17]);
|
||||
|
||||
list.pair_map(add);
|
||||
assert_eq!(list.as_vec(), vec![8, 12, 16, 20, 24, 28, 32]);
|
||||
|
||||
list.pair_map(add);
|
||||
assert_eq!(list.as_vec(), vec![20, 28, 36, 44, 52, 60]);
|
||||
|
||||
list.pair_map(add);
|
||||
assert_eq!(list.as_vec(), vec![48, 64, 80, 96, 112]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten() {
|
||||
let list1 = SinglyLinkedList::from_vec(vec![1, 2]);
|
||||
let list2 = SinglyLinkedList::from_vec(vec![3]);
|
||||
let list3 = SinglyLinkedList::from_vec(vec![4, 5, 6, 7]);
|
||||
let list4 = SinglyLinkedList::<i32>::new();
|
||||
let list5 = SinglyLinkedList::from_vec(vec![8, 9, 10]);
|
||||
|
||||
let list_list = SinglyLinkedList::from_vec(vec![list1, list2, list3, list4, list5]);
|
||||
|
||||
assert_eq!(
|
||||
list_list.flatten().as_vec(),
|
||||
vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_mock_storage {
|
||||
use super::super::mock_storage::*;
|
||||
use crate::assignments::assignment11::mock_storage::*;
|
||||
|
||||
#[test]
|
||||
fn test_mock_storage() {
|
||||
|
||||
@@ -4,15 +4,6 @@
|
||||
//! See `assignment11_grade.rs` and `/scripts/grade-11.sh` for the test script.
|
||||
//! Run `/scripts/prepare-submissions.sh` and submit `/target/assignment11.zip` to <https://gg.kaist.ac.kr>.
|
||||
|
||||
pub mod linked_list;
|
||||
mod linked_list_grade;
|
||||
|
||||
pub mod peano_nat;
|
||||
mod peano_nat_grade;
|
||||
|
||||
pub mod bst;
|
||||
mod bst_grade;
|
||||
|
||||
pub mod doubly_linked_list;
|
||||
mod doubly_linked_list_grade;
|
||||
|
||||
@@ -24,6 +15,3 @@ pub mod mock_storage_grade;
|
||||
|
||||
pub mod tv_room;
|
||||
pub mod tv_room_grade;
|
||||
|
||||
pub mod turing_machine;
|
||||
pub mod turing_machine_grade;
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
//! Peano natural number.
|
||||
|
||||
/// We can represent any natural number using only two symbols: 0 and S.
|
||||
///
|
||||
/// E.g.
|
||||
/// O == 0
|
||||
/// S(O) == 1
|
||||
/// S(S(O)) == 2
|
||||
/// ... so on.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Nat {
|
||||
/// Zero
|
||||
O,
|
||||
/// Plus one
|
||||
S(Box<Nat>),
|
||||
}
|
||||
|
||||
impl Nat {
|
||||
/// Create `Nat` from `usize`
|
||||
pub fn from_usize(n: usize) -> Nat {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Convert `Nat` into nonnegative integer
|
||||
pub fn as_usize(&self) -> usize {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
// Implement `Add` operator (i.e. `+`) for `Nat`.
|
||||
impl std::ops::Add for Nat {
|
||||
type Output = Nat;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
// Implement `Sub` operator (i.e. `-`) for `Nat`.
|
||||
// If the result is negative, return `Nat::O`.
|
||||
impl std::ops::Sub for Nat {
|
||||
type Output = Nat;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
// Implement `Mul` operator (i.e. `*`) for `Nat`.
|
||||
impl std::ops::Mul for Nat {
|
||||
type Output = Nat;
|
||||
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
#[cfg(test)]
|
||||
mod test_peano_nat {
|
||||
use crate::assignments::assignment11::peano_nat::*;
|
||||
|
||||
#[test]
|
||||
fn test_from_as_usize() {
|
||||
assert_eq!(Nat::from_usize(0), Nat::O);
|
||||
assert_eq!(
|
||||
Nat::from_usize(2),
|
||||
Nat::S(Box::new(Nat::S(Box::new(Nat::O))))
|
||||
);
|
||||
|
||||
for n in 0..100 {
|
||||
assert_eq!(Nat::from_usize(n).as_usize(), n);
|
||||
}
|
||||
}
|
||||
|
||||
fn safe_sub(i: usize, j: usize) -> usize {
|
||||
if i > j {
|
||||
i - j
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_sub_mul() {
|
||||
for i in 0..30 {
|
||||
let n = Nat::from_usize(i);
|
||||
for j in 0..30 {
|
||||
let m = Nat::from_usize(j);
|
||||
assert_eq!((n.clone() + m.clone()).as_usize(), i + j);
|
||||
assert_eq!((n.clone() - m.clone()).as_usize(), safe_sub(i, j));
|
||||
assert_eq!((n.clone() * m.clone()).as_usize(), i * j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
//! Simple Turing machien emulator
|
||||
//!
|
||||
//! Simple One-head, One-tape turing machine
|
||||
//! See <https://en.wikipedia.org/wiki/Turing_machine> that describes what turing machine is.
|
||||
//! See `test_turing_machine` module in `assignment11_grade.rs` for examples.
|
||||
//!
|
||||
//! Goal: To be accustomed with `RefCell`, `HashMap`
|
||||
//!
|
||||
//! Refer `turing_machine.rs` for test cases.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{self, Formatter};
|
||||
use thiserror::Error;
|
||||
|
||||
/// Error type for Turing machine
|
||||
/// <https://google.github.io/comprehensive-rust/error-handling/deriving-error-enums.html>
|
||||
#[derive(Debug, Error, PartialEq, Eq)]
|
||||
pub enum TuringMachineError {
|
||||
/// Invalid movement
|
||||
/// You can't move left from the leftmost location
|
||||
/// or move right from the rightmost location.
|
||||
#[error("Invalid movement")]
|
||||
InvalidMovement,
|
||||
|
||||
/// Exceeded maximum steps
|
||||
#[error("Exceeded maximum steps")]
|
||||
ExceedMaxSteps,
|
||||
|
||||
/// Invalid state or value
|
||||
/// Occurs when you cannot find instruction for the current state and value
|
||||
#[error("Invalid state or value")]
|
||||
InvalidStateOrValue,
|
||||
}
|
||||
|
||||
/// Turing Machine implementation
|
||||
#[derive(Debug)]
|
||||
pub struct TuringMachine<TMState, TMValue>
|
||||
where
|
||||
TMState: Default + Eq + PartialEq + std::hash::Hash + Clone,
|
||||
TMValue: Eq + PartialEq + std::hash::Hash + Clone,
|
||||
{
|
||||
/// Number of steps taken by the Turing machine
|
||||
pub steps: RefCell<usize>,
|
||||
|
||||
/// Table of instructions for the Turing machine
|
||||
pub table: HashMap<(TMState, TMValue), (TMState, Move, TMValue)>,
|
||||
|
||||
/// Tape of the Turing machine. Finite length
|
||||
pub tape: Vec<RefCell<TMValue>>,
|
||||
}
|
||||
|
||||
/// Implementation of the movement instructions of the head of the tape.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Move {
|
||||
/// Move Left
|
||||
L,
|
||||
/// Move Right
|
||||
R,
|
||||
/// Don't move
|
||||
N,
|
||||
}
|
||||
|
||||
/// Cursor for Turing machine
|
||||
#[derive(Debug)]
|
||||
pub struct Cursor<'a, TMState, TMValue>
|
||||
where
|
||||
TMState: Default + Eq + PartialEq + std::hash::Hash + Clone,
|
||||
TMValue: Eq + PartialEq + std::hash::Hash + Clone,
|
||||
{
|
||||
// Turing mahcine
|
||||
tm: &'a TuringMachine<TMState, TMValue>,
|
||||
// Index of the tape
|
||||
index: usize,
|
||||
// Current state of the Turing machine
|
||||
state: TMState,
|
||||
}
|
||||
|
||||
impl<'a, TMState, TMValue> Cursor<'a, TMState, TMValue>
|
||||
where
|
||||
TMState: Default + Eq + PartialEq + std::hash::Hash + Clone,
|
||||
TMValue: Eq + PartialEq + std::hash::Hash + Clone,
|
||||
{
|
||||
/// Generate new cursor
|
||||
pub fn new(tm: &'a TuringMachine<TMState, TMValue>, state: TMState, index: usize) -> Self {
|
||||
Cursor { tm, index, state }
|
||||
}
|
||||
|
||||
/// Run the Turing machine until it halts (if it halts). Print every step of that.
|
||||
pub fn run(&mut self, max_step: usize) -> Result<(TMValue, usize), TuringMachineError> {
|
||||
let mut steps = self.tm.steps.borrow_mut();
|
||||
while self.state != TMState::default() {
|
||||
*steps += 1;
|
||||
if *steps > max_step {
|
||||
return Err(TuringMachineError::ExceedMaxSteps);
|
||||
}
|
||||
self.step()?;
|
||||
// println!("{}", self);
|
||||
}
|
||||
Ok((self.get(), *steps))
|
||||
}
|
||||
|
||||
/// Set tape value at the current index with `value`
|
||||
/// You may need this function for `mov` function
|
||||
fn set(&mut self, value: TMValue) -> TMValue {
|
||||
todo!();
|
||||
}
|
||||
|
||||
/// Step the Turing machine
|
||||
/// Look at the `run` function to see how this function is used.
|
||||
fn step(&mut self) -> Result<(), TuringMachineError> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
/// Move the cursor while setting the value of the current index
|
||||
fn mov(&mut self, new_value: TMValue, movement: &Move) -> Result<(), TuringMachineError> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
/// Get the value of the current index
|
||||
/// Look at the `run` function to see how this function is used.
|
||||
fn get(&self) -> TMValue {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
impl<TMState, TMValue> TuringMachine<TMState, TMValue>
|
||||
where
|
||||
TMState: Default + Eq + PartialEq + std::hash::Hash + Clone,
|
||||
TMValue: Eq + PartialEq + std::hash::Hash + Clone,
|
||||
{
|
||||
/// Generate new Turing machine
|
||||
pub fn new(
|
||||
table: HashMap<(TMState, TMValue), (TMState, Move, TMValue)>,
|
||||
tape: Vec<RefCell<TMValue>>,
|
||||
) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -1,309 +0,0 @@
|
||||
//! Test cases for assignment11/turing_machine.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_turing_machine {
|
||||
use super::super::turing_machine::*;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[test]
|
||||
fn test_invalid_movement() {
|
||||
/// Cell value of the tape
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
enum TMValue {
|
||||
/// Zero
|
||||
Zero,
|
||||
|
||||
/// One
|
||||
One,
|
||||
}
|
||||
|
||||
/// State for Turing machine
|
||||
/// TODO: Modify this so that users can implement their own state
|
||||
#[derive(Default, Debug, Eq, PartialEq, Hash, Clone)]
|
||||
enum TMState {
|
||||
/// Halt
|
||||
#[default]
|
||||
Halt,
|
||||
|
||||
/// A
|
||||
A,
|
||||
|
||||
/// B
|
||||
B,
|
||||
}
|
||||
|
||||
let tape: Vec<RefCell<TMValue>> = vec![
|
||||
TMValue::One,
|
||||
TMValue::Zero,
|
||||
TMValue::One,
|
||||
TMValue::One,
|
||||
TMValue::One,
|
||||
TMValue::Zero,
|
||||
TMValue::One,
|
||||
]
|
||||
.into_iter()
|
||||
.map(|x| RefCell::new(x))
|
||||
.collect();
|
||||
|
||||
let instr = HashMap::from([
|
||||
(
|
||||
(TMState::A, TMValue::Zero),
|
||||
(TMState::B, Move::R, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::A, TMValue::One),
|
||||
(TMState::B, Move::L, TMValue::Zero),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::Zero),
|
||||
(TMState::A, Move::L, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::One),
|
||||
(TMState::A, Move::R, TMValue::Zero),
|
||||
),
|
||||
]);
|
||||
|
||||
let mut tm = TuringMachine::new(instr, tape);
|
||||
let mut cursor = Cursor::new(&tm, TMState::A, 0);
|
||||
|
||||
let result = cursor.run(1000);
|
||||
assert_eq!(result, Err(TuringMachineError::InvalidMovement));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_15_fail_move() {
|
||||
/// Cell value of the tape
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
enum TMValue {
|
||||
/// Zero
|
||||
Zero,
|
||||
|
||||
/// One
|
||||
One,
|
||||
}
|
||||
|
||||
/// State for Turing machine
|
||||
/// TODO: Modify this so that users can implement their own state
|
||||
#[derive(Default, Debug, Eq, PartialEq, Hash, Clone)]
|
||||
enum TMState {
|
||||
/// Halt
|
||||
#[default]
|
||||
Halt,
|
||||
|
||||
/// A
|
||||
A,
|
||||
|
||||
/// B
|
||||
B,
|
||||
}
|
||||
|
||||
let tape: Vec<RefCell<TMValue>> = vec![TMValue::Zero; 10]
|
||||
.into_iter()
|
||||
.map(|x| RefCell::new(x))
|
||||
.collect();
|
||||
|
||||
let instr = HashMap::from([
|
||||
(
|
||||
(TMState::A, TMValue::Zero),
|
||||
(TMState::B, Move::R, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::A, TMValue::One),
|
||||
(TMState::B, Move::L, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::Zero),
|
||||
(TMState::A, Move::L, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::One),
|
||||
(TMState::Halt, Move::R, TMValue::One),
|
||||
),
|
||||
]);
|
||||
|
||||
let mut tm = TuringMachine::new(instr, tape);
|
||||
let mut cursor = Cursor::new(&tm, TMState::A, 0);
|
||||
|
||||
let result = cursor.run(1000);
|
||||
assert_eq!(result, Err(TuringMachineError::InvalidMovement));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_15_pass() {
|
||||
/// Cell value of the tape
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
enum TMValue {
|
||||
/// Zero
|
||||
Zero,
|
||||
|
||||
/// One
|
||||
One,
|
||||
}
|
||||
|
||||
/// State for Turing machine
|
||||
/// TODO: Modify this so that users can implement their own state
|
||||
#[derive(Default, Debug, Eq, PartialEq, Hash, Clone)]
|
||||
enum TMState {
|
||||
/// Halt
|
||||
#[default]
|
||||
Halt,
|
||||
|
||||
/// A
|
||||
A,
|
||||
|
||||
/// B
|
||||
B,
|
||||
}
|
||||
|
||||
let tape: Vec<RefCell<TMValue>> = vec![TMValue::Zero; 10]
|
||||
.into_iter()
|
||||
.map(|x| RefCell::new(x))
|
||||
.collect();
|
||||
|
||||
let instr = HashMap::from([
|
||||
(
|
||||
(TMState::A, TMValue::Zero),
|
||||
(TMState::B, Move::R, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::A, TMValue::One),
|
||||
(TMState::B, Move::L, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::Zero),
|
||||
(TMState::A, Move::L, TMValue::One),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::One),
|
||||
(TMState::Halt, Move::R, TMValue::One),
|
||||
),
|
||||
]);
|
||||
|
||||
let mut tm = TuringMachine::new(instr, tape);
|
||||
let mut cursor = Cursor::new(&tm, TMState::A, 2);
|
||||
|
||||
let result = cursor.run(1000);
|
||||
for (idx, val) in tm.tape.iter().enumerate() {
|
||||
if idx < 4 {
|
||||
assert_eq!(*val.borrow(), TMValue::One);
|
||||
} else {
|
||||
assert_eq!(*val.borrow(), TMValue::Zero);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_zero_ones_fail_step() {
|
||||
/// Cell value of the tape
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
enum TMValue {
|
||||
/// Empty
|
||||
Empty,
|
||||
|
||||
/// Zero
|
||||
Zero,
|
||||
|
||||
/// One
|
||||
One,
|
||||
}
|
||||
|
||||
/// State for Turing machine
|
||||
/// TODO: Modify this so that users can implement their own state
|
||||
#[derive(Default, Debug, Eq, PartialEq, Hash, Clone)]
|
||||
enum TMState {
|
||||
/// Halt
|
||||
#[default]
|
||||
Halt,
|
||||
|
||||
/// A
|
||||
A,
|
||||
|
||||
/// B
|
||||
B,
|
||||
}
|
||||
|
||||
let tape: Vec<RefCell<TMValue>> = vec![TMValue::Empty; 100]
|
||||
.into_iter()
|
||||
.map(|x| RefCell::new(x))
|
||||
.collect();
|
||||
|
||||
let instr = HashMap::from([
|
||||
(
|
||||
(TMState::A, TMValue::Empty),
|
||||
(TMState::B, Move::R, TMValue::Zero),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::Empty),
|
||||
(TMState::A, Move::R, TMValue::One),
|
||||
),
|
||||
]);
|
||||
|
||||
let mut tm = TuringMachine::new(instr, tape);
|
||||
let mut cursor = Cursor::new(&tm, TMState::A, 0);
|
||||
|
||||
let result = cursor.run(10);
|
||||
assert_eq!(result, Err(TuringMachineError::ExceedMaxSteps));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_zero_ones() {
|
||||
/// Cell value of the tape
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||
enum TMValue {
|
||||
/// Empty
|
||||
Empty,
|
||||
|
||||
/// Zero
|
||||
Zero,
|
||||
|
||||
/// One
|
||||
One,
|
||||
}
|
||||
|
||||
/// State for Turing machine
|
||||
/// TODO: Modify this so that users can implement their own state
|
||||
#[derive(Default, Debug, Eq, PartialEq, Hash, Clone)]
|
||||
enum TMState {
|
||||
/// Halt
|
||||
#[default]
|
||||
Halt,
|
||||
|
||||
/// A
|
||||
A,
|
||||
|
||||
/// B
|
||||
B,
|
||||
}
|
||||
|
||||
let tape: Vec<RefCell<TMValue>> = vec![TMValue::Empty; 100]
|
||||
.into_iter()
|
||||
.map(|x| RefCell::new(x))
|
||||
.collect();
|
||||
|
||||
let instr = HashMap::from([
|
||||
(
|
||||
(TMState::A, TMValue::Empty),
|
||||
(TMState::B, Move::R, TMValue::Zero),
|
||||
),
|
||||
(
|
||||
(TMState::B, TMValue::Empty),
|
||||
(TMState::A, Move::R, TMValue::One),
|
||||
),
|
||||
]);
|
||||
|
||||
let mut tm = TuringMachine::new(instr, tape);
|
||||
let mut cursor = Cursor::new(&tm, TMState::A, 0);
|
||||
|
||||
let result = cursor.run(1000);
|
||||
assert_eq!(result, Err(TuringMachineError::InvalidMovement));
|
||||
for (idx, val) in tm.tape.iter().enumerate() {
|
||||
if idx % 2 == 0 {
|
||||
assert_eq!(*val.borrow(), TMValue::Zero);
|
||||
} else {
|
||||
assert_eq!(*val.borrow(), TMValue::One);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_tv_room {
|
||||
use super::super::tv_room::*;
|
||||
use crate::assignments::assignment11::tv_room::*;
|
||||
|
||||
#[test]
|
||||
fn test_tv_room() {
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_card {
|
||||
use super::super::card::*;
|
||||
use crate::assignments::assignment12::card::*;
|
||||
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::thread;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_demux {
|
||||
use super::super::demux::*;
|
||||
use crate::assignments::assignment12::demux::*;
|
||||
use ntest::timeout;
|
||||
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_funnel {
|
||||
use super::super::funnel::*;
|
||||
use crate::assignments::assignment12::funnel::*;
|
||||
use ntest::timeout;
|
||||
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_pingpong {
|
||||
use super::super::small_exercises::*;
|
||||
use crate::assignments::assignment12::small_exercises::*;
|
||||
use ntest::timeout;
|
||||
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
10
src/assignments/assignment13/mod.rs
Normal file
10
src/assignments/assignment13/mod.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
//! Assignment 13: Parallelism.
|
||||
//!
|
||||
//! The primary goal of this assignment is to get used to data parallelism.
|
||||
//!
|
||||
//! Refer to your solution for assignment 09. You will implement the parallelized version of assignment 09.
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-13.sh` works fine.
|
||||
//! See `assignment13_grade.rs` and `/scripts/grade-13.sh` for the test script.
|
||||
|
||||
pub mod small_problems;
|
||||
mod small_problems_grade;
|
||||
@@ -1,10 +1,7 @@
|
||||
//! Assignment 13: Parallelism.
|
||||
//!
|
||||
//! The primary goal of this assignment is to get used to data parallelism.
|
||||
//!
|
||||
//! Refer to your solution for assignment 09. You will implement the parallelized version of assignment 09.
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-13.sh` works fine.
|
||||
//! See `assignment13_grade.rs` and `/scripts/grade-13.sh` for the test script.
|
||||
//! If you did well on assignment 09, you will do well on this assignment.
|
||||
//! Take it easy!
|
||||
|
||||
use rayon::prelude::*;
|
||||
|
||||
@@ -65,6 +62,9 @@ pub fn vec_add_par(lhs: &[f64], rhs: &[f64]) -> Vec<f64> {
|
||||
|
||||
/// Parallel dot product of two arrays
|
||||
///
|
||||
/// You don't know how to calculate dot product?
|
||||
/// See <https://mathinsight.org/dot_product_examples>
|
||||
///
|
||||
/// # Exmaple
|
||||
///
|
||||
/// ```
|
||||
@@ -82,6 +82,9 @@ pub fn dot_product_par(lhs: &[f64], rhs: &[f64]) -> f64 {
|
||||
|
||||
/// Parallel Matrix multiplication
|
||||
///
|
||||
/// You don't know how to multiply matrix?
|
||||
/// Quite simple! See <https://www.mathsisfun.com/algebra/matrix-multiplying.html>
|
||||
///
|
||||
/// Assume rhs is transposed
|
||||
/// - lhs: (m, n)
|
||||
/// - rhs: (p, n)
|
||||
@@ -1,7 +1,7 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::super::assignment09::matmul::*;
|
||||
use super::super::assignment13::*;
|
||||
use crate::assignments::assignment09::matmul::*;
|
||||
use crate::assignments::assignment13::small_problems::*;
|
||||
use approx::*;
|
||||
use itertools::Itertools;
|
||||
use ndarray::prelude::*;
|
||||
@@ -7,17 +7,14 @@
|
||||
#![allow(unreachable_code)]
|
||||
|
||||
pub mod assignment01;
|
||||
mod assignment01_grade;
|
||||
pub mod assignment02;
|
||||
pub mod assignment03;
|
||||
pub mod assignment04;
|
||||
pub mod assignment06;
|
||||
pub mod assignment07;
|
||||
pub mod assignment08;
|
||||
mod assignment08_grade;
|
||||
pub mod assignment09;
|
||||
pub mod assignment10;
|
||||
pub mod assignment11;
|
||||
pub mod assignment12;
|
||||
pub mod assignment13;
|
||||
mod assignment13_grade;
|
||||
|
||||
Reference in New Issue
Block a user