This commit is contained in:
Janggun Lee
2024-07-30 15:26:33 +09:00
parent d34f586e4d
commit af889722bc
64 changed files with 452 additions and 384 deletions

2
.gitignore vendored
View File

@@ -1 +1,3 @@
/target /target
rustfmt.toml
/.vscode

10
Cargo.lock generated
View File

@@ -190,12 +190,10 @@ dependencies = [
"ndarray", "ndarray",
"ndarray-rand", "ndarray-rand",
"ntest", "ntest",
"num-traits",
"pest", "pest",
"pest_derive", "pest_derive",
"rand", "rand",
"rayon", "rayon",
"thiserror",
] ]
[[package]] [[package]]
@@ -210,9 +208,9 @@ dependencies = [
[[package]] [[package]]
name = "either" name = "either"
version = "1.12.0" version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]] [[package]]
name = "equivalent" name = "equivalent"
@@ -298,9 +296,9 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]] [[package]]
name = "libm" name = "libm"
version = "0.2.7" version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]] [[package]]
name = "matrixmultiply" name = "matrixmultiply"

View File

@@ -5,19 +5,33 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "cs220"
path = "src/lib.rs"
[[bin]]
name = "calc"
path = "src/bin/calc.rs"
required-features = ["build-calc"]
[[bin]]
name = "par_iter"
path = "src/bin/par_iter.rs"
[features]
build-calc = ["clap"]
[dependencies] [dependencies]
anyhow = "1.0.86" anyhow = "1.0.86"
clap = { version = "4.5.11", features = ["derive"] } clap = { version = "4.5.11", features = ["derive"], optional = true }
etrace = "1.1.1" etrace = "1.1.1"
itertools = "0.13.0" itertools = "0.13.0"
lazy_static = "1.5.0" lazy_static = "1.5.0"
pest = "2.7.11" pest = "2.7.11"
pest_derive = "2.7.11" pest_derive = "2.7.11"
rayon = "1.10.0" rayon = "1.10.0"
thiserror = "1.0.63"
ntest = "0.9.3" ntest = "0.9.3"
approx = "0.5.1" approx = "0.5.1"
num-traits = "0.2.19"
ndarray = "0.15.6" ndarray = "0.15.6"
ndarray-rand = "0.14.0" ndarray-rand = "0.14.0"
rand = "0.8.5" rand = "0.8.5"

View File

@@ -12,7 +12,7 @@
- Announcements: in [issue tracker](https://github.com/kaist-cp/cs220/issues?q=is%3Aissue+is%3Aopen+label%3Aannouncement) - Announcements: in [issue tracker](https://github.com/kaist-cp/cs220/issues?q=is%3Aissue+is%3Aopen+label%3Aannouncement)
+ We assume you read each announcement within 24 hours. + We assume you read each announcement within 24 hours.
+ We strongly recommend you to watch the repository. + We strongly recommend you to watch the repository.
- TA: TBA - TA: [Janggun Lee](https://cp.kaist.ac.kr/janggun.lee)
+ Office Hours: Fri 9:00-10:00, Rm. 4441, Bldg. E3-1. + Office Hours: Fri 9:00-10:00, Rm. 4441, Bldg. E3-1.
If you want to come, do so by 9:15. If you want to come, do so by 9:15.
See [below](https://github.com/kaist-cp/cs220#rules) for the office hour policy. See [below](https://github.com/kaist-cp/cs220#rules) for the office hour policy.
@@ -23,7 +23,7 @@
## Course description ## Course description
This course will equip you with the programming concepts needed to effectively communicate your ideas to computers. This course will equip you with the programming concepts needed to effectively communicate your ideas to computers.
For a detailed overview, please refer to the introduction in the Google Slides presentation. For a detailed overview, please refer to the introduction in the Google Slides presentation.
### Outline ### Outline
@@ -162,7 +162,7 @@ Ensure you are proficient with the following development tools:
- You can run the grading script with the following command: - You can run the grading script with the following command:
```bash ```bash
$ ./scripts/grade.sh <assignment_number> $ ./scripts/grade.sh <assignment_number>
# E.g. To grade `assignment09`, run the following command: # E.g. To grade `assignment09`, run the following command:
$ ./scripts/grade.sh 9 $ ./scripts/grade.sh 9
``` ```
@@ -181,8 +181,8 @@ Ensure you are proficient with the following development tools:
Laptops can also be borrowed from the School of Computing Administration Team. Laptops can also be borrowed from the School of Computing Administration Team.
- We will use [Safe Exam Browser](https://safeexambrowser.org/) to prevent cheatings. - We will use [Safe Exam Browser](https://safeexambrowser.org/) to prevent cheatings.
- You should have your laptop configured with Safe Exam Browser before the exam. - You should have your laptop configured with Safe Exam Browser before the exam.
- TBA: Details will be announced later. - TBA: Details will be announced later.
### Attendance (?%) ### Attendance (?%)

View File

@@ -19,5 +19,5 @@ module BinarySearch
= =
(* IMPORTANT: DON'T MODIFY THE ABOVE LINES *) (* IMPORTANT: DON'T MODIFY THE ABOVE LINES *)
0 (* TODO *) 0 (* TODO *)
end end

View File

@@ -2,11 +2,11 @@
Given an array `a` of integers with length `n` greater than `0`, Given an array `a` of integers with length `n` greater than `0`,
return `max_idx`, the index of the maximum element of that array. return `max_idx`, the index of the maximum element of that array.
E.g. `max_idx [5, 12, 34, 10] 4` will return `2` E.g. `max_idx [5, 12, 34, 10] 4` will return `2`
E.g. `max_idx [4, 3, 2] 3` will return `0` E.g. `max_idx [4, 3, 2] 3` will return `0`
E.g. `max_idx [1, 2, 3, 4] 4` will return `3` E.g. `max_idx [1, 2, 3, 4] 4` will return `3`
Prove the below program indeed follows the given specification, Prove the below program indeed follows the given specification,
by giving an appropriate invariant. by giving an appropriate invariant.
*) *)
@@ -22,12 +22,13 @@ module Max
requires { n = length a } requires { n = length a }
ensures { 0 <= max_idx <= n-1 } ensures { 0 <= max_idx <= n-1 }
ensures { forall i. 0 <= i <= n-1 -> a[i] <= a[max_idx] } ensures { forall i. 0 <= i <= n-1 -> a[i] <= a[max_idx] }
= =
let ref max_idx = 0 in let ref max_idx = 0 in
for i = 0 to n-1 do for i = 0 to n-1 do
invariant { 0 <= max_idx <= n-1 } invariant { 0 <= max_idx <= n-1 }
(* IMPORTANT: DON'T MODIFY THE ABOVE LINES *) (* IMPORTANT: DON'T MODIFY THE ABOVE LINES *)
invariant { true (* TODO: Replace `true` with your solution. Your solution MUST be a single line, at line number 30. DON'T add another line of codes. *) } (* TODO: Replace `true` with your solution. Your solution MUST be a single line, at line 31. DON'T add more code above or below. *)
invariant { true }
(* IMPORTANT: DON'T MODIFY THE BELOW LINES *) (* IMPORTANT: DON'T MODIFY THE BELOW LINES *)
if a[max_idx] < a[i] then max_idx <- i; if a[max_idx] < a[i] then max_idx <- i;
done; done;

View File

@@ -17,9 +17,9 @@ module Pascal
ensures { result >= 1 } ensures { result >= 1 }
= if k = 0 || k = n then 1 else comb (n-1) k + comb (n-1) (k-1) = if k = 0 || k = n then 1 else comb (n-1) k + comb (n-1) (k-1)
(* Computes the Pascal's triangle and returns the `n`th row of it. *) (* Computes Pascal's triangle and returns the `n`th row of it. *)
(* Insert an appropriate invariant so that Why3 can verify this function. *) (* Insert an appropriate invariant so that Why3 can verify this function. *)
(* You SHOULD understand the Pascal's triangle first to find good invariants. *) (* You should understand Pascal's triangle first to find good invariants. *)
let chooses (n : int) : array int let chooses (n : int) : array int
requires { n > 0 } requires { n > 0 }
ensures { forall i: int. ensures { forall i: int.
@@ -28,16 +28,17 @@ module Pascal
let ref row = Array.make 1 1 in let ref row = Array.make 1 1 in
for r = 1 to n do for r = 1 to n do
invariant { length row = r } invariant { length row = r }
invariant { forall c: int. 0 <= c < r -> row[c] = comb (r-1) c } invariant { forall c: int. 0 <= c < r -> row[c] = comb (r-1) c }
let new_row = Array.make (r+1) 1 in let new_row = Array.make (r+1) 1 in
for c = 1 to r-1 do for c = 1 to r-1 do
(* IMPORTANT: DON'T MODIFY THE ABOVE LINES *) (* IMPORTANT: DON'T MODIFY THE ABOVE LINES *)
invariant { true (* TODO: Replace `true` with your solution. Your solution MUST be a single line, at line number 35. DON'T add another lines. *) } (* TODO: Replace `true` with your solution. Your solution MUST be a single line, at line 36. DON'T add more code above or below. *)
invariant { true }
(* IMPORTANT: DON'T MODIFY THE BELOW LINES *) (* IMPORTANT: DON'T MODIFY THE BELOW LINES *)
new_row[c] <- row[c-1] + row[c] new_row[c] <- row[c-1] + row[c]
done; done;
row <- new_row row <- new_row
done; done;
row row
end end

View File

@@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "1.80.0" channel = "1.80.0"
components = [ "rustfmt", "clippy" ] components = ["rustfmt", "clippy"]

View File

@@ -7,7 +7,7 @@
# * RUNNERS: array of "cargo[_asan | _tsan] [--release]" # * RUNNERS: array of "cargo[_asan | _tsan] [--release]"
# * TIMEOUT: default 10s # * TIMEOUT: default 10s
rustup toolchain update stable nightly rustup toolchain update stable
echo_err() { echo_err() {
echo "$@" 1>&2 echo "$@" 1>&2
@@ -37,27 +37,6 @@ run_linters() {
} }
export -f run_linters export -f run_linters
# usage: cargo_asan [SUBCOMMAND] [OPTIONS] [-- <args>...]
# example: cargo_asan test --release TEST_NAME -- --skip SKIPPED
# NOTE: sanitizer documentation at https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html
cargo_asan() {
local SUBCOMMAND=$1; shift
RUSTFLAGS="-Z sanitizer=address" \
RUSTDOCFLAGS="-Z sanitizer=address" \
cargo +nightly $SUBCOMMAND -Z build-std --target x86_64-unknown-linux-gnu "$@"
}
export -f cargo_asan
cargo_tsan() {
local SUBCOMMAND=$1; shift
RUSTFLAGS="-Z sanitizer=thread" \
TSAN_OPTIONS="suppressions=suppress_tsan.txt" \
RUSTDOCFLAGS="-Z sanitizer=thread" \
RUST_TEST_THREADS=1 \
cargo +nightly $SUBCOMMAND -Z build-std --target x86_64-unknown-linux-gnu "$@"
}
export -f cargo_tsan
# usage: _run_tests_with CARGO [OPTIONS] # usage: _run_tests_with CARGO [OPTIONS]
# example: _run_tests_with cargo_tsan --release # example: _run_tests_with cargo_tsan --release
# Echos number of failed tests to stdout. # Echos number of failed tests to stdout.
@@ -80,7 +59,7 @@ _run_tests_with() {
# local NUM_TESTS=$(echo $TESTS | wc -w) # local NUM_TESTS=$(echo $TESTS | wc -w)
for TEST in ${TESTS[@]}; do for TEST in ${TESTS[@]}; do
local TEST_CMD="$CARGO test $* --lib -- $TEST" local TEST_CMD="$CARGO test $* --lib -- $TEST"
# card_game in Assignment12 takes 20 seconds. # card_game in Assignment12 takes 20 seconds.
timeout ${TIMEOUT:-22s} bash -c "$TEST_CMD 2> /dev/null" 1>&2 timeout ${TIMEOUT:-22s} bash -c "$TEST_CMD 2> /dev/null" 1>&2
case $? in case $? in
0) PASSED=$((PASSED + 1));; 0) PASSED=$((PASSED + 1));;

View File

@@ -73,7 +73,6 @@ case $TEST_NAME in
TESTS=( TESTS=(
"assignments::assignment09::bigint_grade::test" "assignments::assignment09::bigint_grade::test"
"assignments::assignment09::small_exercises_grade::test" "assignments::assignment09::small_exercises_grade::test"
"assignments::assignment09::matmul_grade::test"
) )
;; ;;
TEST10) TEST10)

View File

@@ -15,16 +15,6 @@ for i in {01..13} ; do
zip -rj $BASEDIR/target/assignment05.zip $BASEDIR/assets/why3/assignment05 zip -rj $BASEDIR/target/assignment05.zip $BASEDIR/assets/why3/assignment05
continue continue
fi fi
if [ $i -eq 13 ]
then
if [ -f $BASEDIR/target/assignment13.zip ]; then
rm $BASEDIR/target/assignment13.zip
fi
zip -rj $BASEDIR/target/assignment13.zip $BASEDIR/src/assignments/assignment13 $BASEDIR/src/assignments/assignment09/matmul.rs
continue
fi
if [ -f $BASEDIR/target/assignment$i.zip ]; then if [ -f $BASEDIR/target/assignment$i.zip ]; then
rm $BASEDIR/target/assignment$i.zip rm $BASEDIR/target/assignment$i.zip
fi fi

View File

@@ -1,10 +1,11 @@
//! Assignment 1: Preparing Rust Development Environment. //! Assignment 1: Preparing Rust Development Environment.
//! //!
//! The primary goal of this assignment is bringing up SSH, VSCode, and all the other necessary tools to develop Rust programs. //! The primary goal of this assignment is bringing up SSH, VSCode, and all the other necessary
//! Please make sure you're comfortable with developing Rust programs before moving on to the next assignments. //! tools to develop Rust programs. Please make sure you're comfortable with developing Rust
//! programs before moving on to the next assignments.
//! //!
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 1` works fine. //! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 1` works
//! See `assigment01/small_exercises_grade.rs` and `/scripts/grade.sh 1` for the test script. //! fine. See `assigment01/small_exercises_grade.rs` and `/scripts/grade.sh 1` for the test script.
//! //!
//! To submit, run //! To submit, run
//! ```bash //! ```bash

View File

@@ -1,8 +1,8 @@
//! Assignment 1: Preparing Rust Development Environment. //! Assignment 1: Preparing Rust Development Environment.
//! Welcome to the CS220 course! //! Welcome to CS220!
//! //!
//! You should fill out `add()` and `sub()` function bodies in such a way that `/scripts/grade.sh 1` works fine. //! You should fill out `add()` and `sub()` function bodies in such a way that `/scripts/grade.sh 1`
//! See `small_problems_grade.rs` and `/scripts/grade.sh 1` for the test script. //! works fine. See `small_problems_grade.rs` and `/scripts/grade.sh 1` for the test script.
//! //!
//! Hint: <https://doc.rust-lang.org/std/primitive.usize.html> //! Hint: <https://doc.rust-lang.org/std/primitive.usize.html>

View File

@@ -1,10 +1,11 @@
//! Assignment 2: Mastering common programming concepts (1/2). //! Assignment 2: Mastering common programming concepts (1/2).
//! //!
//! The primary goal of this assignment is to re-learn the common programming concepts in Rust, especially those in the Rust Book chapters 3 and 5. //! The primary goal of this assignment is to re-learn the common programming concepts in Rust,
//! Please make sure you're comfortable with the concepts to proceed on to the next assignments. //! especially those in the Rust Book chapters 3 and 5. Please make sure you're comfortable with the
//! concepts to proceed on to the next assignments.
//! //!
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 2` works fine. //! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 2` works
//! See `assigment02/*_grade.rs` and `/scripts/grade.sh 2` for the test script. //! fine. See `assigment02/*_grade.rs` and `/scripts/grade.sh 2` for the test script.
//! //!
//! To submit, run //! To submit, run
//! ```bash //! ```bash

View File

@@ -1,5 +1,7 @@
//! Small problems. //! Small problems.
use std::iter;
const FAHRENHEIT_OFFSET: f64 = 32.0; const FAHRENHEIT_OFFSET: f64 = 32.0;
const FAHRENHEIT_SCALE: f64 = 5.0 / 9.0; const FAHRENHEIT_SCALE: f64 = 5.0 / 9.0;
@@ -18,29 +20,33 @@ pub fn sum_array(input: &[u64]) -> u64 {
todo!() todo!()
} }
/// Given a non-negative integer, say `n`, return the smallest integer of the form `3^m` that's greater than or equal to `n`. /// Given a non-negative integer, say `n`, return the smallest integer of the form `3^m` that's
/// greater than or equal to `n`.
/// ///
/// For instance, up3(6) = 9, up3(9) = 9, up3(10) = 27. (We assume the absence of integer overflow.) /// For instance, up3(6) = 9, up3(9) = 9, up3(10) = 27. (We assume the absence of integer overflow.)
pub fn up3(n: u64) -> u64 { pub fn up3(n: u64) -> u64 {
todo!() todo!()
} }
/// Returns the greatest common divisor (GCD) of two non-negative integers. (We assume the absence of integer overflow.) /// Returns the greatest common divisor (GCD) of two non-negative integers. (We assume the absence
/// of integer overflow.)
pub fn gcd(lhs: u64, rhs: u64) -> u64 { pub fn gcd(lhs: u64, rhs: u64) -> u64 {
todo!() todo!()
} }
/// Returns the array of nC0, nC1, nC2, ..., nCn, where nCk = n! / (k! * (n-k)!). (We assume the absence of integer overflow.) /// Returns the array of nC0, nC1, nC2, ..., nCn, where nCk = n! / (k! * (n-k)!). (We assume the
/// absence of integer overflow.)
/// ///
/// Consult <https://en.wikipedia.org/wiki/Pascal%27s_triangle> for computation of binomial coefficients without integer overflow. /// Consult <https://en.wikipedia.org/wiki/Pascal%27s_triangle> for computation of binomial
/// coefficients without integer overflow.
pub fn chooses(n: u64) -> Vec<u64> { pub fn chooses(n: u64) -> Vec<u64> {
todo!() todo!()
} }
/// Returns the "zip" of two vectors. /// Returns the "zip" of two vectors.
/// ///
/// For instance, `zip(vec![1, 2, 3], vec![4, 5])` equals to `vec![(1, 4), (2, 5)]`. /// For instance, `zip(vec![1, 2, 3], vec![4, 5])` equals to `vec![(1, 4), (2, 5)]`. Here, `3` is
/// Here, `3` is ignored because it doesn't have a partner. /// ignored because it doesn't have a partner.
pub fn zip(lhs: Vec<u64>, rhs: Vec<u64>) -> Vec<(u64, u64)> { pub fn zip(lhs: Vec<u64>, rhs: Vec<u64>) -> Vec<(u64, u64)> {
todo!() todo!()
} }

View File

@@ -2,6 +2,7 @@
//! //!
//! You will implement simple operations on vectors and matrices. //! You will implement simple operations on vectors and matrices.
use std::cmp::PartialEq;
use std::ops::Mul; use std::ops::Mul;
/// 2x2 matrix of the following configuration: /// 2x2 matrix of the following configuration:
@@ -112,13 +113,20 @@ impl FMat2 {
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```ignore
/// assert_eq!( /// assert_eq!(
/// Mat2 { a: 1.0, b: 1.0, c: 2.0, d: 3.0 }.inverse(), /// FMat2 { a: 1.0, b: 1.0, c: 2.0, d: 3.0 }.inverse(),
/// Mat2 { a: 3.0, b: -1.0, c: -2.0, d: 1.0} /// FMat2 { a: 3.0, b: -1.0, c: -2.0, d: 1.0 }
/// ); /// );
/// ``` /// ```
pub fn inverse(self) -> Self { pub fn inverse(self) -> Self {
todo!() todo!()
} }
} }
// Equivalence between two floating-point matrices, as element-wise equivalence
impl PartialEq for FMat2 {
fn eq(&self, other: &FMat2) -> bool {
self.a == other.a && self.b == other.b && self.c == other.c && self.d == other.d
}
}

View File

@@ -16,14 +16,6 @@ mod test {
assert_eq!(fibonacci(92), 12200160415121876738); assert_eq!(fibonacci(92), 12200160415121876738);
} }
// Equivalence between two floating-point matrices, as element-wise equivalence
use std::cmp::PartialEq;
impl PartialEq for FMat2 {
fn eq(&self, other: &FMat2) -> bool {
self.a == other.a && self.b == other.b && self.c == other.c && self.d == other.d
}
}
#[test] #[test]
fn test_inverse() { fn test_inverse() {
assert_eq!( assert_eq!(

View File

@@ -16,7 +16,7 @@ pub enum MyOption<T> {
/// Converts an `MyOption<String>` into an `MyOption<usize>`, consuming the original: /// Converts an `MyOption<String>` into an `MyOption<usize>`, consuming the original:
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment03::{my_map, MyOption}; /// use cs220::assignments::assignment03::custom_operators::*;
/// ///
/// fn len(s: String) -> usize { /// fn len(s: String) -> usize {
/// s.len() /// s.len()
@@ -29,14 +29,15 @@ pub fn my_map<T, U, F: FnOnce(T) -> U>(v: MyOption<T>, f: F) -> MyOption<U> {
todo!() todo!()
} }
/// Returns `MyNone` if the option is `MyNone`, otherwise calls `f` with the wrapped value and returns the result. /// Returns `MyNone` if the option is `MyNone`, otherwise calls `f` with the wrapped value and
/// returns the result.
/// ///
/// Some languages call this operation flatmap. /// Some languages call this operation flatmap.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment03::{MyOption, my_and_then}; /// use cs220::assignments::assignment03::custom_operators::*;
/// ///
/// fn pos_then_to_string(x: isize) -> MyOption<String> { /// fn pos_then_to_string(x: isize) -> MyOption<String> {
/// if x > 0 { /// if x > 0 {
@@ -54,21 +55,21 @@ pub fn my_and_then<T, U, F: FnOnce(T) -> MyOption<U>>(v: MyOption<T>, f: F) -> M
todo!() todo!()
} }
/// Custom operator: `option_op_or(v1, v2, f)` /// Custom operator: `option_op_or(v1, v2, f)`. If neither `v1` nor `v2` is `Some`, returns `None`.
/// If neither `v1` nor `v2` is `Some`, returns `None`. /// If exactly one is `Some`, returns the same `Some` value. If both are `Some`, apply the values
/// If exactly one is `Some`, returns the same `Some` value. /// inside `Some` to `f` and wrap the resulting value inside `Some`.
/// If both are `Some`, apply the values inside `Some` to `f` and wrap the resulting value inside `Some`.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment03::custom_operators::*;
/// fn product(a: i32, b: i32) -> i32 { /// fn product(a: i32, b: i32) -> i32 {
/// a * b /// a * b
/// } /// }
/// ///
/// assert_eq!(option_op_or(None, None, product), None); /// assert_eq!(my_option_op_or(MyOption::MyNone, MyOption::MyNone, product), MyOption::MyNone);
/// assert_eq!(option_op_or(Some(3), None, product), Some(3)); /// assert_eq!(my_option_op_or(MyOption::MySome(3), MyOption::MyNone, product), MyOption::MySome(3));
/// assert_eq!(option_op_or(Some(3), Some(5), product), Some(15)); /// assert_eq!(my_option_op_or(MyOption::MySome(3), MyOption::MySome(5), product), MyOption::MySome(15));
/// ``` /// ```
pub fn my_option_op_or<T, F: FnOnce(T, T) -> T>( pub fn my_option_op_or<T, F: FnOnce(T, T) -> T>(
v1: MyOption<T>, v1: MyOption<T>,

View File

@@ -1,6 +1,7 @@
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::assignments::assignment03::custom_operators::{MyOption::*, *}; use crate::assignments::assignment03::custom_operators::MyOption::*;
use crate::assignments::assignment03::custom_operators::*;
#[test] #[test]
fn test_my_map() { fn test_my_map() {

View File

@@ -1,7 +1,7 @@
//! Assignment 3: Mastering common programming concepts (2/2) //! Assignment 3: Mastering common programming concepts (2/2)
//! //!
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 3` works fine. //! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 3` works
//! See `assignment03/*_grade.rs` and `/scripts/grade.sh 3` for the test script. //! fine. See `assignment03/*_grade.rs` and `/scripts/grade.sh 3` for the test script.
//! //!
//! To submit, run //! To submit, run
//! ```bash //! ```bash

View File

@@ -1,19 +1,22 @@
//! Parsing a shell command. //! Parsing a shell command.
//! //!
//! Shell commands are text-based instructions that you can enter in a command-line interface (CLI) //! Shell commands are text-based instructions that you can enter in a command-line interface (CLI)
//! to interact with operating systems (e.g. Linux) and others. //! to interact with operating systems (e.g. Linux) and others. For example, you can use the `ls`
//! For example, you can use the `ls` command to list files in a directory. //! command to list files in a directory.
//! //!
//! You will parse a given string consists of a small number of shell commands. //! You will parse a given string consists of a small number of shell commands.
/// Parse the string as a shell command. /// Parse the string as a shell command.
/// ///
/// Usually, a shell command is whitespace-separated array of strings. /// Usually, a shell command is whitespace-separated array of strings.
///
/// ```text /// ```text
/// cat file --> ["cat", "file"] /// cat file --> ["cat", "file"]
/// ``` /// ```
/// But sometimes, you may want to include whitespaces in each argument. ///
/// In that case, you can use quotes. /// But sometimes, you may want to include whitespaces in each argument. In that case, you can use
/// quotes.
///
/// ```text /// ```text
/// ls 'VirtualBox VMs' --> ["ls", 'VirtualBox VMs'] /// ls 'VirtualBox VMs' --> ["ls", 'VirtualBox VMs']
/// ls VirtualBox' 'VMs --> ["ls", 'VirtualBox VMs'] /// ls VirtualBox' 'VMs --> ["ls", 'VirtualBox VMs']

View File

@@ -55,16 +55,19 @@ pub fn median(values: Vec<isize>) -> Option<isize> {
todo!() todo!()
} }
/// Given a list of integers, returns its smallest mode (the value that occurs most often; a hash map will be helpful here). /// Given a list of integers, returns its smallest mode (the value that occurs most often; a hash
/// map will be helpful here).
/// ///
/// Returns `None` if the list is empty. /// Returns `None` if the list is empty.
pub fn mode(values: Vec<isize>) -> Option<isize> { pub fn mode(values: Vec<isize>) -> Option<isize> {
todo!() todo!()
} }
/// Converts the given string to Pig Latin. Use the rules below to translate normal English into Pig Latin. /// Converts the given string to Pig Latin. Use the rules below to translate normal English into Pig
/// Latin.
/// ///
/// 1. If a word starts with a consonant and a vowel, move the first letter of the word at the end of the word and add "ay". /// 1. If a word starts with a consonant and a vowel, move the first letter of the word at the end
/// of the word and add "ay".
/// ///
/// Example: "happy" -> "appyh" + "ay" -> "appyhay" /// Example: "happy" -> "appyh" + "ay" -> "appyhay"
/// ///
@@ -99,7 +102,8 @@ pub fn piglatin(input: String) -> String {
/// ///
/// - The result is a map from department to the list of its employees. /// - The result is a map from department to the list of its employees.
/// - An empty department should not appear in the result. /// - An empty department should not appear in the result.
/// - There are three commands: "Add {person} to {department}", "Remove {person} from {department}", and "Move {person} from {department} to {department}". /// - There are three commands: "Add {person} to {department}", "Remove {person} from {department}",
/// and "Move {person} from {department} to {department}".
/// - If a command is not executable, then it's ignored. /// - If a command is not executable, then it's ignored.
/// - There is no space in the name of the person and department. /// - There is no space in the name of the person and department.
/// ///

View File

@@ -3,8 +3,9 @@
use std::collections::HashMap; use std::collections::HashMap;
use anyhow::*; use anyhow::*;
use etrace::*;
use super::syntax::{Command, Expression}; use super::syntax::{BinOp, Command, Expression};
/// Calculator's context. /// Calculator's context.
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
@@ -31,7 +32,8 @@ impl Context {
/// Calculates the given command. (We assume the absence of overflow.) /// Calculates the given command. (We assume the absence of overflow.)
/// ///
/// If there is no variable lhs in the command (i.e. `command.variable = None`), its value should be stored at `$0`, `$1`, `$2`, ... respectively. /// If there is no variable lhs in the command (i.e. `command.variable = None`), its value
/// should be stored at `$0`, `$1`, `$2`, ... respectively.
/// ///
/// # Example /// # Example
/// ///

View File

@@ -1,8 +1,9 @@
//! Assignment 4: Designing a calculator. //! Assignment 4: Designing a calculator.
//! //!
//! The primary goal of this assignment is twofold: //! The primary goal of this assignment is twofold:
//! (1) understanding the `pest` third-party library from documentations; and //! - (1) understanding the `pest` third-party library from documentations; and
//! (2) using programming concepts you've learned so far to implement a simple arithmetic calculator. //! - (2) using programming concepts you've learned so far to implement a simple arithmetic
//! calculator.
//! //!
//! For `pest`, read the following documentations (that contain 90% of the solution): //! For `pest`, read the following documentations (that contain 90% of the solution):
//! - <https://pest.rs/> //! - <https://pest.rs/>
@@ -11,8 +12,9 @@
//! //!
//! For calculator, just reading `syntax.rs` would suffice for you to understand what to do. //! For calculator, just reading `syntax.rs` would suffice for you to understand what to do.
//! //!
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 4` works fine. //! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 4` works
//! See `assignment04/grade.rs` and `/scripts/grade.sh 4` for the test script. //! fine. See `assignment04/grade.rs` and `/scripts/grade.sh 4` for the test script.
//!
//! Run `/scripts/prepare-submissions.sh` and submit `/target/assignment04.zip` to <https://gg.kaist.ac.kr>. //! Run `/scripts/prepare-submissions.sh` and submit `/target/assignment04.zip` to <https://gg.kaist.ac.kr>.
//! //!
//! To submit, run //! To submit, run

View File

@@ -2,8 +2,14 @@
//! Parser. //! Parser.
use anyhow::{bail, Result};
use etrace::*;
use lazy_static::*;
use pest::iterators::{Pair, Pairs};
use pest::prec_climber::*;
use pest::Parser;
use super::syntax::*; use super::syntax::*;
use anyhow::Result;
#[allow(missing_docs)] #[allow(missing_docs)]
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
@@ -15,13 +21,16 @@ mod inner {
pub(crate) struct SyntaxParser; pub(crate) struct SyntaxParser;
} }
use inner::*;
/// Parses command. /// Parses command.
/// ///
/// ## Operator Associativty /// ## Operator Associativty
/// ///
/// For associativity of each operator, please follow [here](https://docs.rs/pest/latest/pest/prec_climber/struct.PrecClimber.html#examples). /// For associativity of each operator, please follow [here](https://docs.rs/pest/latest/pest/prec_climber/struct.PrecClimber.html#examples).
/// ///
/// e.g. `1+2+3` should be parsed into `(1+2)+3`, not `1+(2+3)` because the associativity of plus("add" in our hw) operator is `Left`. /// e.g. `1+2+3` should be parsed into `(1+2)+3`, not `1+(2+3)` because the associativity of
/// plus("add" in our hw) operator is `Left`.
pub fn parse_command(line: &str) -> Result<Command> { pub fn parse_command(line: &str) -> Result<Command> {
todo!("fill here") todo!("fill here")
} }

View File

@@ -2,8 +2,8 @@
//! //!
//! The primary goal of this assignment is to understand generics, traits, and lifetimes. //! The primary goal of this assignment is to understand generics, traits, and lifetimes.
//! //!
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 6` works fine. //! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 6` works
//! See `assignment06/*_grade.rs` and `/scripts/grade.sh 6` for the test script. //! fine. See `assignment06/*_grade.rs` and `/scripts/grade.sh 6` for the test script.
//! //!
//! To submit, run //! To submit, run
//! ```bash //! ```bash

View File

@@ -1,6 +1,9 @@
//! Semiring //! Semiring
use std::{collections::HashMap, fmt::Debug}; use std::collections::HashMap;
use std::fmt::Debug;
use itertools::Itertools;
/// Semiring. /// Semiring.
/// ///
@@ -147,10 +150,8 @@ impl<C: Semiring> From<C> for Polynomial<C> {
/// ///
/// Assumptions: /// Assumptions:
/// - Each term is separated by ` + `. /// - Each term is separated by ` + `.
/// - Each term is one of the following form: /// - Each term is one of the following form: `a`, `x`, `ax`, `x^n`, and `ax^n`, where `a` is a
/// `a`, `x`, `ax`, `x^n`, and `ax^n`, /// `usize` number and `n` is a `u64` number. This `a` should then be converted to a `C` type.
/// where `a` is a `usize` number and `n` is a `u64` number.
/// This `a` should then be converted to a `C` type.
/// - In `a`, it is guaranteed that `a >= 1`. /// - In `a`, it is guaranteed that `a >= 1`.
/// - In `ax` and `ax^n`, it is guaranteed that `a >= 2`. /// - In `ax` and `ax^n`, it is guaranteed that `a >= 2`.
/// - In `x^n` and `ax^n`, it is guaranteed that `n >= 2`. /// - In `x^n` and `ax^n`, it is guaranteed that `n >= 2`.

View File

@@ -1,8 +1,9 @@
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::assignments::assignment06::semiring::*;
use ntest::assert_about_eq; use ntest::assert_about_eq;
use crate::assignments::assignment06::semiring::*;
fn test_from_str(s: &str, f: impl Fn(i64) -> i64) { fn test_from_str(s: &str, f: impl Fn(i64) -> i64) {
let poly = s.parse::<Polynomial<i64>>().unwrap(); let poly = s.parse::<Polynomial<i64>>().unwrap();
for i in 0..10 { for i in 0..10 {

View File

@@ -5,10 +5,12 @@ use std::ops::*;
/// Rational number represented by two isize, numerator and denominator. /// Rational number represented by two isize, numerator and denominator.
/// ///
/// Each Rational number should be normalized so that `demoninator` is nonnegative and `numerator` and `demoninator` are coprime. /// Each Rational number should be normalized so that `demoninator` is nonnegative and `numerator`
/// See `normalize` for examples. As a corner case, 0 is represented by Rational { numerator: 0, demoninator: 0 }. /// and `demoninator` are coprime. See `normalize` for examples. As a corner case, 0 is represented
/// by `Rational { numerator: 0, demoninator: 0 }`.
/// ///
/// For "natural use", Rational also overloads standard arithmetic operations, i.e, `+`, `-`, `*`, `/`. /// For "natural use", it also overloads standard arithmetic operations, i.e, `+`, `-`, `*`, and
/// `/`.
/// ///
/// See [here](https://doc.rust-lang.org/core/ops/index.html) for details. /// See [here](https://doc.rust-lang.org/core/ops/index.html) for details.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -96,9 +98,9 @@ pub enum SingletonPolynomial {
Const(Rational), Const(Rational),
/// Non-const polynomial. /// Non-const polynomial.
Polynomial { Polynomial {
/// coefficent of polynomial. Must be non-zero. /// Coefficent of polynomial. Must be non-zero.
coeff: Rational, coeff: Rational,
/// power of polynomial. Must be non-zero. /// Power of polynomial. Must be non-zero.
power: Rational, power: Rational,
}, },
} }
@@ -156,7 +158,7 @@ pub enum Trignometric {
/// Coefficent /// Coefficent
coeff: Rational, coeff: Rational,
}, },
/// Sine function. /// Cosine function.
Cosine { Cosine {
/// Coefficent /// Coefficent
coeff: Rational, coeff: Rational,

View File

@@ -1,8 +1,9 @@
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::assignments::assignment06::symbolic_differentiation::*;
use ntest::assert_about_eq; use ntest::assert_about_eq;
use crate::assignments::assignment06::symbolic_differentiation::*;
// Constant rationals to use // Constant rationals to use
const TWO: Rational = Rational::new(2, 1); const TWO: Rational = Rational::new(2, 1);
const FOUR: Rational = Rational::new(4, 1); const FOUR: Rational = Rational::new(4, 1);
@@ -172,7 +173,7 @@ mod test {
// Mult // Mult
// //
// d/dx (2x^4 * cos(x) * exp(x)) = // d/dx (2x^4 * cos(x) * exp(x)) =
// 8x^3 * cos(x) * exp(x) - 2x^4 * sin(x) * exp(x) + 2x^4 * cos(x) * exp(x) // 8x^2 * cos(x) * exp(x) - 2x^4 * sin(x) * exp(x) + 2x^4 * cos(x) * exp(x)
let f1 = SingletonPolynomial::new_poly(TWO, FOUR); let f1 = SingletonPolynomial::new_poly(TWO, FOUR);
let f2 = Trignometric::new_cosine(ONE); let f2 = Trignometric::new_cosine(ONE);
let f3 = Exp::new(); let f3 = Exp::new();

View File

@@ -2,8 +2,8 @@
//! //!
//! The primary goal of this assignment is to understand generics, traits, and lifetimes. //! The primary goal of this assignment is to understand generics, traits, and lifetimes.
//! //!
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 7` works fine. //! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 7` works
//! See `assignment07/*_grade.rs` and `/scripts/grade.sh 7` for the test script. //! fine. See `assignment07/*_grade.rs` and `/scripts/grade.sh 7` for the test script.
//! //!
//! To submit, run //! To submit, run
//! ```bash //! ```bash

View File

@@ -1,9 +1,10 @@
//! Implement your own minimal `itertools` crate. //! Implement your own minimal `itertools` crate.
use std::collections::HashSet;
use std::hash::Hash; use std::hash::Hash;
/// Iterator that iterates over the given iterator and returns only unique elements. /// Iterator that iterates over the given iterator and returns only unique elements.
#[allow(missing_debug_implementations)] #[derive(Debug)]
pub struct Unique<I: Iterator> { pub struct Unique<I: Iterator> {
// TODO: remove `_marker` and add necessary fields as you want // TODO: remove `_marker` and add necessary fields as you want
_marker: std::marker::PhantomData<I>, _marker: std::marker::PhantomData<I>,
@@ -21,7 +22,7 @@ where
} }
/// Iterator that chains two iterators together. /// Iterator that chains two iterators together.
#[allow(missing_debug_implementations)] #[derive(Debug)]
pub struct Chain<I1: Iterator, I2: Iterator> { pub struct Chain<I1: Iterator, I2: Iterator> {
// TODO: remove `_marker` and add necessary fields as you want // TODO: remove `_marker` and add necessary fields as you want
_marker: std::marker::PhantomData<(I1, I2)>, _marker: std::marker::PhantomData<(I1, I2)>,
@@ -38,7 +39,7 @@ impl<T: Eq + Hash + Clone, I1: Iterator<Item = T>, I2: Iterator<Item = T>> Itera
} }
/// Iterator that iterates over given iterator and enumerates each element. /// Iterator that iterates over given iterator and enumerates each element.
#[allow(missing_debug_implementations)] #[derive(Debug)]
pub struct Enumerate<I: Iterator> { pub struct Enumerate<I: Iterator> {
// TODO: remove `_marker` and add necessary fields as you want // TODO: remove `_marker` and add necessary fields as you want
_marker: std::marker::PhantomData<I>, _marker: std::marker::PhantomData<I>,
@@ -56,7 +57,7 @@ impl<I: Iterator> Iterator for Enumerate<I> {
/// ///
/// If one iterator is longer than the other one, the remaining elements for the longer element /// If one iterator is longer than the other one, the remaining elements for the longer element
/// should be ignored. /// should be ignored.
#[allow(missing_debug_implementations)] #[derive(Debug)]
pub struct Zip<I1: Iterator, I2: Iterator> { pub struct Zip<I1: Iterator, I2: Iterator> {
// TODO: remove `_marker` and add necessary fields as you want // TODO: remove `_marker` and add necessary fields as you want
_marker: std::marker::PhantomData<(I1, I2)>, _marker: std::marker::PhantomData<(I1, I2)>,

View File

@@ -47,7 +47,8 @@ where
} }
/// Returns and iterator over the generic fibonacci sequence starting from `first` and `second`. /// Returns and iterator over the generic fibonacci sequence starting from `first` and `second`.
/// This is a generic version of `fibonacci` function, which works for any types that implements `std::ops::Add` trait. /// This is a generic version of `fibonacci` function, which works for any types that implements
/// `std::ops::Add` trait.
pub fn fib<T>(first: T, second: T) -> impl Iterator<Item = T> pub fn fib<T>(first: T, second: T) -> impl Iterator<Item = T>
where where
T: std::ops::Add<Output = T> + Copy, T: std::ops::Add<Output = T> + Copy,

View File

@@ -9,6 +9,7 @@
//! - <https://en.wikipedia.org/wiki/Church_encoding> //! - <https://en.wikipedia.org/wiki/Church_encoding>
//! - <https://opendsa-server.cs.vt.edu/OpenDSA/Books/PL/html/ChurchNumerals.html> //! - <https://opendsa-server.cs.vt.edu/OpenDSA/Books/PL/html/ChurchNumerals.html>
use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
/// Church numerals are represented as higher-order functions that take a function `f` /// Church numerals are represented as higher-order functions that take a function `f`
@@ -51,8 +52,9 @@ pub fn mult<T: 'static>(n: Church<T>, m: Church<T>) -> Church<T> {
/// This is the Church numeral equivalent of the natural number operation of exponentiation. /// This is the Church numeral equivalent of the natural number operation of exponentiation.
/// Given two natural numbers `n` and `m`, the function should return a Church numeral /// Given two natural numbers `n` and `m`, the function should return a Church numeral
/// that represents `n` to the power of `m`. The key is to convert `n` and `m` to Church numerals, /// that represents `n` to the power of `m`. The key is to convert `n` and `m` to Church numerals,
/// and then apply the Church numeral for `m` (the exponent) to the Church numeral for `n` (the base). /// and then apply the Church numeral for `m` (the exponent) to the Church numeral for `n` (the
/// Note: This function should be implemented *WITHOUT* using the `to_usize` or any `pow`-like method. /// base). Note: This function should be implemented *WITHOUT* using the `to_usize` or any
/// `pow`-like method.
pub fn exp<T: 'static>(n: usize, m: usize) -> Church<T> { pub fn exp<T: 'static>(n: usize, m: usize) -> Church<T> {
// ACTION ITEM: Uncomment the following lines and replace `todo!()` with your code. // ACTION ITEM: Uncomment the following lines and replace `todo!()` with your code.
// let n = from_usize(n); // let n = from_usize(n);

View File

@@ -2,8 +2,8 @@
//! //!
//! The primary goal of this assignment is to get used to 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.sh 8` works fine. //! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 8` works
//! See `assignment08/*_grade.rs` and `/scripts/grade.sh 8` for the test script. //! fine. See `assignment08/*_grade.rs` and `/scripts/grade.sh 8` for the test script.
//! //!
//! To submit, run //! To submit, run
//! ```bash //! ```bash

View File

@@ -15,7 +15,8 @@ pub fn repeat<T, F: FnMut(T) -> T>(n: usize, mut f: F) -> impl FnMut(T) -> T {
/// ///
/// Applies the given function `f` for `i` times for the `i`-th element of the given vector. /// Applies the given function `f` for `i` times for the `i`-th element of the given vector.
/// ///
/// For instance, `funny_map(f, [v0, v1, v2, v3])` roughly translates to `[v0, f(v1), f(f(v2)), f(f(f(v3)))]`. /// For instance, `funny_map(f, [v0, v1, v2, v3])` roughly translates to `[v0, f(v1), f(f(v2)),
/// f(f(f(v3)))]`.
/// ///
/// Refer `test_funny_map` in `assignment08_grade.rs` for detailed examples. /// Refer `test_funny_map` in `assignment08_grade.rs` for detailed examples.
pub fn funny_map<T, F: Fn(T) -> T>(f: F, vs: Vec<T>) -> Vec<T> { pub fn funny_map<T, F: Fn(T) -> T>(f: F, vs: Vec<T>) -> Vec<T> {
@@ -24,9 +25,8 @@ pub fn funny_map<T, F: Fn(T) -> T>(f: F, vs: Vec<T>) -> Vec<T> {
/// Count Repeat /// Count Repeat
/// ///
/// Returns the number of the elements of the set /// Returns the number of the elements in the set {`x`, `f(x)`, `f(f(x))`, `f(f(f(x)))`, ...}. You
/// {x, f(x), f(f(x)), f(f(f(x))), ...}. /// may assume that the answer is finite and small enough.
/// You may assume that the answer is finite and small enough.
/// ///
/// Refer `test_count_repeat` in `assignment08_grade.rs` for detailed examples. /// Refer `test_count_repeat` in `assignment08_grade.rs` for detailed examples.
pub fn count_repeat<T, F: Fn(T) -> T>(f: F, x: T) -> usize pub fn count_repeat<T, F: Fn(T) -> T>(f: F, x: T) -> usize

View File

@@ -1,7 +1,8 @@
//! Big integer with infinite precision. //! Big integer with infinite precision.
use std::fmt; use std::fmt;
use std::{iter::zip, ops::*}; use std::iter::zip;
use std::ops::*;
/// An signed integer with infinite precision implemented with an "carrier" vector of `u32`s. /// An signed integer with infinite precision implemented with an "carrier" vector of `u32`s.
/// ///
@@ -15,15 +16,17 @@ use std::{iter::zip, ops::*};
/// ///
/// You will implement the `Add` and `Sub` trait for this type. /// You will implement the `Add` and `Sub` trait for this type.
/// ///
/// Unlike standard fix-sized intergers in Rust where overflow will panic, the carrier is extended to save the overflowed bit. /// Unlike standard fix-sized intergers in Rust where overflow will panic, the carrier is extended
/// On the contrary, if the precision is too much (e.g, vec![0,0] is used to represent 0, where `vec![0]` is sufficent), the carrier is truncated. /// to save the overflowed bit. On the contrary, if the precision is too much (e.g, vec![0,0] is
/// used to represent 0, where `vec![0]` is sufficent), the carrier is truncated.
/// ///
/// See [this section](https://en.wikipedia.org/wiki/Two%27s_complement#Arithmetic_operations) for a rouge guide on implementation, /// See [this section](https://en.wikipedia.org/wiki/Two%27s_complement#Arithmetic_operations) for a rouge guide on implementation,
/// while keeping in mind that the carrier should be extended to deal with overflow. /// while keeping in mind that the carrier should be extended to deal with overflow.
/// ///
/// The `sign_extension()`, `two_complement()`, and `truncate()` are non-mandatory helper methods. /// The `sign_extension()`, `two_complement()`, and `truncate()` are non-mandatory helper methods.
/// ///
/// For testing and debugging pruposes, the `Display` trait is implemented for you, which shows the integer in hexadecimal form. /// For testing and debugging pruposes, the `Display` trait is implemented for you, which shows the
/// integer in hexadecimal form.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct BigInt { pub struct BigInt {
/// The carrier for `BigInt`. /// The carrier for `BigInt`.
@@ -39,6 +42,10 @@ impl BigInt {
} }
/// Creates a new `BigInt` from a `Vec<u32>`. /// Creates a new `BigInt` from a `Vec<u32>`.
///
/// # Panic
///
/// Panics if `carrier` is empty.
pub fn new_large(carrier: Vec<u32>) -> Self { pub fn new_large(carrier: Vec<u32>) -> Self {
assert!(!carrier.is_empty()); assert!(!carrier.is_empty());
todo!() todo!()

View File

@@ -43,7 +43,7 @@ mod test {
#[test] #[test]
#[should_panic] #[should_panic]
fn test_inf_prec_panic() { fn test_inf_prec_panic() {
let _ = BigInt::new_large(vec![]); let _unused = BigInt::new_large(vec![]);
} }
#[test] #[test]

View File

@@ -7,7 +7,7 @@ use itertools::*;
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment09::vec_add; /// use cs220::assignments::assignment09::matmul::*;
/// ///
/// let vec1 = vec![1.0, 2.0, 3.0, 4.0, 5.0]; /// let vec1 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
/// let vec2 = vec![1.0, 2.0, 3.0, 4.0, 5.0]; /// let vec2 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
@@ -23,10 +23,10 @@ pub fn vec_add(lhs: &[f64], rhs: &[f64]) -> Vec<f64> {
/// You don't know how to calculate dot product? /// You don't know how to calculate dot product?
/// See <https://mathinsight.org/dot_product_examples> /// See <https://mathinsight.org/dot_product_examples>
/// ///
/// # Exmaple /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment09::dot_product; /// use cs220::assignments::assignment09::matmul::*;
/// ///
/// let vec1 = vec![1.0, 2.0, 3.0, 4.0, 5.0]; /// let vec1 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
/// let vec2 = vec![1.0, 2.0, 3.0, 4.0, 5.0]; /// let vec2 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
@@ -48,10 +48,10 @@ pub fn dot_product(lhs: &[f64], rhs: &[f64]) -> f64 {
/// - rhs: (p, n) /// - rhs: (p, n)
/// - output: (m, p) /// - output: (m, p)
/// ///
/// # Exmaple /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment09::matmul; /// use cs220::assignments::assignment09::matmul::*;
/// ///
/// let mat1 = vec![vec![1.0, 2.0, 3.0], vec![4.0, 5.0, 6.0]]; /// let mat1 = vec![vec![1.0, 2.0, 3.0], vec![4.0, 5.0, 6.0]];
/// let mat2 = vec![ /// let mat2 = vec![

View File

@@ -1,11 +1,12 @@
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::assignments::assignment09::matmul::*;
use approx::*; use approx::*;
use itertools::Itertools; use itertools::Itertools;
use ndarray::prelude::*; use ndarray::prelude::*;
use ndarray_rand::{rand_distr::Uniform, RandomExt}; use ndarray_rand::rand_distr::Uniform;
use ndarray_rand::RandomExt;
use crate::assignments::assignment09::matmul::*;
#[test] #[test]
fn vec_add_test() { fn vec_add_test() {

View File

@@ -2,8 +2,8 @@
//! //!
//! The primary goal of this assignment is to get used to iterators. //! The primary goal of this assignment is to get used to iterators.
//! //!
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 9` works fine. //! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 9` works
//! See `assignment09/*_grade.rs` and `/scripts/grade.sh 9` for the test script. //! fine. See `assignment09/*_grade.rs` and `/scripts/grade.sh 9` for the test script.
//! //!
//! To submit, run //! To submit, run
//! ```bash //! ```bash

View File

@@ -2,14 +2,17 @@
use std::collections::HashMap; use std::collections::HashMap;
/// Returns whether the given sequence is a fibonacci sequence starts from the given sequence's first two terms. use itertools::Itertools;
/// Returns whether the given sequence is a fibonacci sequence starts from the given sequence's
/// first two terms.
/// ///
/// Returns `true` if the length of sequence is less or equal than 2. /// Returns `true` if the length of sequence is less or equal than 2.
/// ///
/// # Exmample /// # Exmample
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment09::is_fibonacci; /// use cs220::assignments::assignment09::small_exercises::*;
/// ///
/// assert_eq!(is_fibonacci([1, 1, 2, 3, 5, 8, 13].into_iter()), true); /// assert_eq!(is_fibonacci([1, 1, 2, 3, 5, 8, 13].into_iter()), true);
/// assert_eq!(is_fibonacci([1, 1, 2, 3, 5, 8, 14].into_iter()), false); /// assert_eq!(is_fibonacci([1, 1, 2, 3, 5, 8, 14].into_iter()), false);
@@ -20,10 +23,10 @@ pub fn is_fibonacci(inner: impl Iterator<Item = i64>) -> bool {
/// Returns the sum of `f(v)` for all element `v` the given array. /// Returns the sum of `f(v)` for all element `v` the given array.
/// ///
/// # Exmaple /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment09::sigma; /// use cs220::assignments::assignment09::small_exercises::*;
/// ///
/// assert_eq!(sigma([1, 2].into_iter(), |x| x + 2), 7); /// assert_eq!(sigma([1, 2].into_iter(), |x| x + 2), 7);
/// assert_eq!(sigma([1, 2].into_iter(), |x| x * 4), 12); /// assert_eq!(sigma([1, 2].into_iter(), |x| x * 4), 12);
@@ -39,7 +42,7 @@ pub fn sigma<T, F: Fn(T) -> i64>(inner: impl Iterator<Item = T>, f: F) -> i64 {
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment09::interleave3; /// use cs220::assignments::assignment09::small_exercises::*;
/// ///
/// assert_eq!( /// assert_eq!(
/// interleave3([1, 2].into_iter(), [3, 4].into_iter(), [5, 6].into_iter()), /// interleave3([1, 2].into_iter(), [3, 4].into_iter(), [5, 6].into_iter()),
@@ -61,7 +64,7 @@ pub fn interleave3<T>(
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment09::interleave_n; /// use cs220::assignments::assignment09::small_exercises::*;
/// ///
/// assert_eq!( /// assert_eq!(
/// interleave_n(&mut [[1, 2].into_iter(), [3, 4].into_iter(), [5, 6].into_iter()]), /// interleave_n(&mut [[1, 2].into_iter(), [3, 4].into_iter(), [5, 6].into_iter()]),
@@ -80,7 +83,7 @@ pub fn interleave_n<T, const N: usize>(
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment09::k_smallest_mean; /// use cs220::assignments::assignment09::small_exercises::*;
/// ///
/// assert_eq!( /// assert_eq!(
/// k_smallest_mean(vec![1, 3, 2].into_iter(), 2), /// k_smallest_mean(vec![1, 3, 2].into_iter(), 2),
@@ -97,10 +100,10 @@ pub fn k_smallest_mean(inner: impl Iterator<Item = i64>, k: usize) -> f64 {
/// Returns mean for each class. /// Returns mean for each class.
/// ///
/// # Exmaple /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment09::calculate_mean; /// use cs220::assignments::assignment09::small_exercises::*;
/// ///
/// assert_eq!( /// assert_eq!(
/// calculate_mean( /// calculate_mean(
@@ -135,7 +138,7 @@ pub fn calculate_mean(inner: impl Iterator<Item = (String, i64)>) -> HashMap<Str
/// Among these sets, the number of sets whose sum is 4 is 2, which is [1, 3] and [2, 2]. /// Among these sets, the number of sets whose sum is 4 is 2, which is [1, 3] and [2, 2].
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment09::sum_is_n; /// use cs220::assignments::assignment09::small_exercises::*;
/// ///
/// assert_eq!(sum_is_n(vec![vec![1, 2, 3], vec![2, 3]], 3), 1); /// assert_eq!(sum_is_n(vec![vec![1, 2, 3], vec![2, 3]], 3), 1);
/// assert_eq!(sum_is_n(vec![vec![1, 2, 3], vec![2, 3]], 4), 2); /// assert_eq!(sum_is_n(vec![vec![1, 2, 3], vec![2, 3]], 4), 2);
@@ -147,12 +150,13 @@ pub fn sum_is_n(inner: Vec<Vec<i64>>, n: i64) -> usize {
todo!() todo!()
} }
/// Returns a new vector that contains the item that appears `n` times in the input vector in increasing order. /// Returns a new vector that contains the item that appears `n` times in the input vector in
/// increasing order.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment09::find_count_n; /// use cs220::assignments::assignment09::small_exercises::*;
/// ///
/// assert_eq!(find_count_n(vec![1, 2], 1), vec![1, 2]); /// assert_eq!(find_count_n(vec![1, 2], 1), vec![1, 2]);
/// assert_eq!(find_count_n(vec![1, 3, 3], 1), vec![1]); /// assert_eq!(find_count_n(vec![1, 3, 3], 1), vec![1]);
@@ -175,10 +179,10 @@ pub fn find_count_n(inner: Vec<usize>, n: usize) -> Vec<usize> {
/// - If the list is empty, returns `None`. /// - If the list is empty, returns `None`.
/// - If several elements are equally median, the position of the first of them is returned. /// - If several elements are equally median, the position of the first of them is returned.
/// ///
/// # Exmaple /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment09::position_median; /// use cs220::assignments::assignment09::small_exercises::*;
/// ///
/// assert_eq!(position_median(vec![1, 3, 3, 6, 7, 8, 9]), Some(3)); /// assert_eq!(position_median(vec![1, 3, 3, 6, 7, 8, 9]), Some(3));
/// assert_eq!(position_median(vec![1, 3, 3, 3]), Some(1)); /// assert_eq!(position_median(vec![1, 3, 3, 3]), Some(1));
@@ -191,6 +195,8 @@ pub fn position_median<T: Ord>(inner: Vec<T>) -> Option<usize> {
/// ///
/// # Example /// # Example
/// ``` /// ```
/// use cs220::assignments::assignment09::small_exercises::*;
///
/// assert_eq!( /// assert_eq!(
/// two_dimensional_sum([[1, 2, 3].into_iter(), [4, 5, 6].into_iter()].into_iter()), /// two_dimensional_sum([[1, 2, 3].into_iter(), [4, 5, 6].into_iter()].into_iter()),
/// 21 /// 21
@@ -202,8 +208,10 @@ pub fn two_dimensional_sum(inner: impl Iterator<Item = impl Iterator<Item = i64>
/// Returns whether the given string is palindrome or not. /// Returns whether the given string is palindrome or not.
/// ///
/// A palindrome is a word, number, phrase, or other sequence of characters which reads the same backward as forward. /// A palindrome is a word, number, phrase, or other sequence of characters which reads the same
/// We consider the empty string is palindrome. /// backward as forward.
///
/// We consider the empty string as a palindrome.
/// ///
/// Consult <https://en.wikipedia.org/wiki/Palindrome>. /// Consult <https://en.wikipedia.org/wiki/Palindrome>.
pub fn is_palindrome(s: String) -> bool { pub fn is_palindrome(s: String) -> bool {

View File

@@ -1,11 +1,11 @@
//! Labyrinth //! Labyrinth
//! //!
//! Look at the `labyrinth_grade.rs` below before you start. //! Look at `labyrinth_grade.rs` below before you start.
//! HINT: <https://en.wikipedia.org/wiki/100_prisoners_problem> //! HINT: <https://en.wikipedia.org/wiki/100_prisoners_problem>
//! //!
//! NOTE: You will have to implement a probabilistic algorithm, which means, the algorithm can fail //! NOTE: You will have to implement a probabilistic algorithm, which means, the algorithm can fail
//! even if you have implemented the solution. We recommend running multiple times (at least 5 times) to check your //! even if you have implemented the solution. We recommend running multiple times (at least 5
//! solution works well. //! times) to check your solution works well.
use std::cell::RefCell; use std::cell::RefCell;
@@ -26,8 +26,8 @@ impl Husband {
Strategy { husband: self } Strategy { husband: self }
} }
/// Based on the information about currently visited room number and someone's wife ID trapped inside, /// Based on the information about currently visited room number and someone's wife ID trapped
/// what the husband should do next? /// inside, what the husband should do next?
pub fn carefully_checks_whos_inside(&self, room: usize, wife: usize) { pub fn carefully_checks_whos_inside(&self, room: usize, wife: usize) {
todo!() todo!()
} }

View File

@@ -1,5 +1,6 @@
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
use rand::thread_rng; use rand::thread_rng;
@@ -38,12 +39,13 @@ mod test {
(0..WIVES).all(|his_wife| { (0..WIVES).all(|his_wife| {
// A new husband steps into the labyrinth to rescue his wife...! // A new husband steps into the labyrinth to rescue his wife...!
let husband = Box::new(Husband::seeking(his_wife /*👩*/)); let husband = Box::new(Husband::seeking(his_wife /* 👩 */));
let strategy = Box::new(husband.has_devised_a_strategy()); let strategy = Box::new(husband.has_devised_a_strategy());
#[allow(clippy::all)] // (Allow for better storytelling.)
/* The Minotaur🐂 will arrive in */ #[allow(clippy::search_is_some)]
(0..50) /* steps... */ // The Minotaur🐂 will arrive in
(0..50) // steps...
.zip(strategy) .zip(strategy)
.find(|(_, room)| { .find(|(_, room)| {
// The husband contemplates his next move... 🤔 // The husband contemplates his next move... 🤔

View File

@@ -1,8 +1,8 @@
//! Assignment 10: Iterators (2/2). //! Assignment 10: Iterators (2/2).
//! The primary goal of this assignment is to get used to iterators. //! The primary goal of this assignment is to get used to iterators.
//! //!
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 10` works fine. //! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 10` works
//! See `assignment10/*_grade.rs` and `/scripts/grade.sh 10` for the test script. //! fine. See `assignment10/*_grade.rs` and `/scripts/grade.sh 10` for the test script.
//! //!
//! To submit, run //! To submit, run
//! ```bash //! ```bash

View File

@@ -1,10 +1,13 @@
//! Small exercises. //! Small exercises.
use std::collections::HashSet;
use itertools::*; use itertools::*;
/// Returns the pairs of `(i, j)` where `i < j` and `inner[i] > inner[j]` in increasing order. /// Returns the pairs of `(i, j)` where `i < j` and `inner[i] > inner[j]` in increasing order.
/// ///
/// For example, the inversions of `[3, 5, 1, 2, 4]` is `[(0, 2), (0, 3), (1, 2), (1, 3), (1, 4)]` because as follows: /// For example, the inversions of `[3, 5, 1, 2, 4]` is `[(0, 2), (0, 3), (1, 2), (1, 3), (1, 4)]`
/// because as follows:
/// ///
/// - `0 < 2`, `inner[0] = 3 > 1 = inner[2]` /// - `0 < 2`, `inner[0] = 3 > 1 = inner[2]`
/// - `0 < 3`, `inner[0] = 3 > 2 = inner[3]` /// - `0 < 3`, `inner[0] = 3 > 2 = inner[3]`
@@ -108,7 +111,8 @@ pub enum File {
/// |__c (Data, size: 8) /// |__c (Data, size: 8)
/// ``` /// ```
/// ///
/// Output: `[("a1", 1), ("a2", 3), ("b1", 3), ("a", 4), ("c", 8), ("b2", 15), ("b", 18), ("root", 30)]` /// Output: `[("a1", 1), ("a2", 3), ("b1", 3), ("a", 4), ("c", 8), ("b2", 15), ("b", 18), ("root",
/// 30)]`
pub fn du_sort(root: &File) -> Vec<(&str, usize)> { pub fn du_sort(root: &File) -> Vec<(&str, usize)> {
todo!() todo!()
} }
@@ -118,12 +122,11 @@ pub fn du_sort(root: &File) -> Vec<(&str, usize)> {
/// of returning a new vector. /// of returning a new vector.
/// ///
/// # Example /// # Example
/// ``` /// ```ignore
/// let mut vec = vec![1, 2, 3, 4, 5]; /// let mut vec = vec![1, 2, 3, 4, 5];
/// remove_even(&mut vec); /// remove_even(&mut vec);
/// assert_eq!(*vec, vec![1, 3, 5]); /// assert_eq!(*vec, vec![1, 3, 5]);
/// ``` /// ```
#[allow(clippy::ptr_arg)]
pub fn remove_even(inner: &mut Vec<i64>) { pub fn remove_even(inner: &mut Vec<i64>) {
todo!() todo!()
} }
@@ -135,12 +138,11 @@ pub fn remove_even(inner: &mut Vec<i64>) {
/// Also, note that the order does not matter. /// Also, note that the order does not matter.
/// ///
/// # Example /// # Example
/// ``` /// ```ignore
/// let mut vec = vec![1, 2, 1, 1, 3, 7, 5, 7]; /// let mut vec = vec![1, 2, 1, 1, 3, 7, 5, 7];
/// remove_duplicate(&mut vec); /// remove_duplicate(&mut vec);
/// assert_eq!(*vec, vec![1, 2, 3, 7, 5]); /// assert_eq!(*vec, vec![1, 2, 3, 7, 5]);
/// ``` /// ```
#[allow(clippy::ptr_arg)]
pub fn remove_duplicate(inner: &mut Vec<i64>) { pub fn remove_duplicate(inner: &mut Vec<i64>) {
todo!() todo!()
} }
@@ -153,6 +155,7 @@ pub fn remove_duplicate(inner: &mut Vec<i64>) {
/// ///
/// # Example /// # Example
/// ///
/// ```text
/// table1 table2 /// table1 table2
/// ---------------------- ---------------------- /// ---------------------- ----------------------
/// 20230001 | Jack 20230001 | CS /// 20230001 | Jack 20230001 | CS
@@ -165,11 +168,12 @@ pub fn remove_duplicate(inner: &mut Vec<i64>) {
/// 20230001 | Jack | CS /// 20230001 | Jack | CS
/// 20230001 | Jack | EE /// 20230001 | Jack | EE
/// 20231234 | Mike | ME /// 20231234 | Mike | ME
/// /// ```
pub fn natural_join(table1: Vec<Vec<String>>, table2: Vec<Vec<String>>) -> Vec<Vec<String>> { pub fn natural_join(table1: Vec<Vec<String>>, table2: Vec<Vec<String>>) -> Vec<Vec<String>> {
todo!() todo!()
} }
/// You can freely add more fields.
struct Pythagorean; struct Pythagorean;
impl Pythagorean { impl Pythagorean {
@@ -187,7 +191,8 @@ impl Iterator for Pythagorean {
} }
/// Generates sequence of unique [primitive Pythagorean triples](https://en.wikipedia.org/wiki/Pythagorean_triple), /// Generates sequence of unique [primitive Pythagorean triples](https://en.wikipedia.org/wiki/Pythagorean_triple),
/// i.e. (a,b,c) such that a² + b² = c², a and b are coprimes, and a < b. Generate in the increasing order of c. /// i.e. (a,b,c) such that a² + b² = c², a and b are coprimes, and a < b. Generate in the increasing
/// order of c.
pub fn pythagorean() -> impl Iterator<Item = (u64, u64, u64)> { pub fn pythagorean() -> impl Iterator<Item = (u64, u64, u64)> {
Pythagorean::new() Pythagorean::new()
} }

View File

@@ -322,17 +322,11 @@ mod test {
(68, 285, 293), (68, 285, 293),
]; ];
let mut pythagorean_iter = pythagorean(); for (i, (a, b, c)) in pythagorean().enumerate().take(1000) {
for i in 0..1000 {
let t = pythagorean_iter.next();
assert!(t.is_some());
let (a, b, c) = t.unwrap();
assert_eq!(a * a + b * b, c * c);
if i < pythagoreans.len() { if i < pythagoreans.len() {
assert_eq!(pythagoreans[i], (a, b, c)) assert_eq!(pythagoreans[i], (a, b, c))
} }
assert_eq!(a * a + b * b, c * c);
} }
} }
} }

View File

@@ -12,6 +12,10 @@
//! //!
//! Refer `graph_grade.rs` for test cases. //! Refer `graph_grade.rs` for test cases.
use std::cell::RefCell;
use std::collections::HashSet;
use std::rc::Rc;
#[derive(PartialEq, Eq, Debug)] #[derive(PartialEq, Eq, Debug)]
enum VisitStatus { enum VisitStatus {
Unvisited, Unvisited,
@@ -20,11 +24,12 @@ enum VisitStatus {
} }
/// 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
/// node. That is, there can be multiple handles to the same node. /// node. That is, there can be multiple handles to the same node.
/// The user can access the node through a handle if it does not violate Rust's aliasing rules. /// The user can access the node through a handle if it does not violate Rust's aliasing rules.
/// ///
/// TODO: 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;
@@ -34,7 +39,7 @@ pub struct GraphError;
/// Subgraph /// Subgraph
/// ///
/// TODO: 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;
@@ -45,23 +50,24 @@ impl NodeHandle {
} }
/// Adds an edge to `to`. /// Adds an edge to `to`.
/// If the modification cannot be done, e.g. because of aliasing issues, returns `Err(GraphError)`. /// If the modification cannot be done, e.g. because of aliasing issues, returns
/// 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!() todo!()
} }
/// Removes the edge to `to`. /// Removes the edge to `to`.
/// If the modification cannot be done, e.g. because of aliasing issues, returns `Err(GraphError)`. /// If the modification cannot be done, e.g. because of aliasing issues, returns
/// 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!() todo!()
} }
/// Removes all edges. /// Removes all edges.
/// If the modification cannot be done, e.g. because of aliasing issues, returns `Err(GraphError)`. /// If the modification cannot be done, e.g. because of aliasing issues, returns
/// `Err(GraphError)`.
pub fn clear_edges(&self) -> Result<(), GraphError> { pub fn clear_edges(&self) -> Result<(), GraphError> {
todo!() todo!()
} }
@@ -84,7 +90,7 @@ impl SubGraph {
todo!() todo!()
} }
/// Removes a node from the subgraph. Returns true iff the node is successfully removed. /// Adds a node to 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!() todo!()
} }

View File

@@ -1,6 +1,7 @@
//! TV Room Simulator. //! TV Room Simulator.
//! //!
//! People can come to the TV room and watch TV. There are two types of TV watchers, manager and guest. //! People can come to the TV room and watch TV. There are two types of TV watchers, manager and
//! guest.
//! //!
//! The rule of the TV room is as follows: //! The rule of the TV room is as follows:
//! //!
@@ -9,8 +10,9 @@
//! - Manager can leave the TV room earlier than guests. //! - Manager can leave the TV room earlier than guests.
//! - The TV room closes when the last person left the TV room. //! - The TV room closes when the last person left the TV room.
//! //!
//! Both `Manager` and `Guest` have `Rc<Watcher>` as a field, and its reference count indicates the number of people in //! Both `Manager` and `Guest` have `Rc<Watcher>` as a field, and its reference count indicates the
//! the TV room. When the 'Manager' and 'Guest' object is dropped, it means that the person leaves the TV room. //! number of people in the TV room. When the 'Manager' and 'Guest' object is dropped, it means that
//! the person leaves the TV room.
//! //!
//! Consult the following documentations: //! Consult the following documentations:
//! - <https://doc.rust-lang.org/book/ch15-04-rc.html#rct-the-reference-counted-smart-pointer> //! - <https://doc.rust-lang.org/book/ch15-04-rc.html#rct-the-reference-counted-smart-pointer>
@@ -18,7 +20,8 @@
//! //!
//! Refer `tv_room_grade.rs` for test cases. //! Refer `tv_room_grade.rs` for test cases.
use std::{cell::RefCell, rc::Rc}; use std::cell::RefCell;
use std::rc::Rc;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
enum TVRoomState { enum TVRoomState {

View File

@@ -8,10 +8,8 @@
//! //!
//! Have fun! //! Have fun!
use std::{ use std::collections::HashMap;
collections::HashMap, use std::sync::{Arc, Mutex};
sync::{Arc, Mutex},
};
/// Color represents the color of the card. /// Color represents the color of the card.
/// The color of a card can be either Blue or White. /// The color of a card can be either Blue or White.

View File

@@ -2,13 +2,13 @@
#[cfg(test)] #[cfg(test)]
mod test_card { mod test_card {
use crate::assignments::assignment12::card::*;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Barrier, Mutex}; use std::sync::{Arc, Barrier, Mutex};
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use crate::assignments::assignment12::card::*;
const NUM_CARDS: usize = 10000; const NUM_CARDS: usize = 10000;
const DURATION: u64 = 20; const DURATION: u64 = 20;
const NUM_ENEMIES: usize = 25; const NUM_ENEMIES: usize = 25;
@@ -60,7 +60,7 @@ mod test_card {
fn play() { fn play() {
let ground = Ground::new(); let ground = Ground::new();
let barrier = Arc::new(Barrier::new( let barrier = Arc::new(Barrier::new(
NUM_ENEMIES + 1 /*Player*/ + 1, /*Referee*/ NUM_ENEMIES + 1 /*Player*/ + 1, /* Referee */
)); ));
let playing = Arc::new(AtomicBool::new(true)); let playing = Arc::new(AtomicBool::new(true));

View File

@@ -1,6 +1,7 @@
//! Demultiplexing sender //! Demultiplexing sender
//! //!
//! Implement demultiplexing sender //! Implement a demultiplexing sender.
//!
//! Demultiplexer, `Demux` in short, is a device that has one input and many outputs. //! Demultiplexer, `Demux` in short, is a device that has one input and many outputs.
//! It distributes the input to the outputs according to the control signal. //! It distributes the input to the outputs according to the control signal.
//! It is used when a circuit wishes to send a signal to one of many devices. //! It is used when a circuit wishes to send a signal to one of many devices.

View File

@@ -2,12 +2,13 @@
#[cfg(test)] #[cfg(test)]
mod test_demux { mod test_demux {
use crate::assignments::assignment12::demux::*;
use ntest::timeout;
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
use std::thread; use std::thread;
use ntest::timeout;
use crate::assignments::assignment12::demux::*;
#[test] #[test]
#[timeout(5000)] #[timeout(5000)]
fn test_demux() { fn test_demux() {

View File

@@ -1,17 +1,19 @@
//! Funnel //! Funnel
//! //!
//! Spawn a thread that executes a funnel. //! Spawn a thread that executes a funnel.
//! Funnel will receive data from multiple receivers and send it to a single sender.
//! Also, the funnel will filter out data that does not pass the filter function.
//! //!
//! Refer `funnel_grade.rs` for test cases //! Funnel will receive data from multiple receivers and send it to a single sender. Also, the
//! funnel will filter out data that does not pass the filter function.
//!
//! Refer to `funnel_grade.rs` for test cases.
use std::sync::mpsc::{channel, Receiver, Sender}; use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::Arc; use std::sync::Arc;
use std::thread; use std::thread;
use std::thread::JoinHandle; use std::thread::JoinHandle;
/// Spawn a thread that concurrently receive datas from `rxs`, send it to `tx` if it makes `f` true. Returns its handle. /// Spawn a thread that concurrently receive datas from `rxs`, send it to `tx` if it makes `f` true.
/// Returns its handle.
pub fn spawn_funnel<T, F>(rxs: Vec<Receiver<T>>, tx: Sender<T>, f: F) -> JoinHandle<()> pub fn spawn_funnel<T, F>(rxs: Vec<Receiver<T>>, tx: Sender<T>, f: F) -> JoinHandle<()>
where where
T: Send + 'static, T: Send + 'static,

View File

@@ -2,12 +2,13 @@
#[cfg(test)] #[cfg(test)]
mod test_funnel { mod test_funnel {
use crate::assignments::assignment12::funnel::*;
use ntest::timeout;
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
use std::thread; use std::thread;
use ntest::timeout;
use crate::assignments::assignment12::funnel::*;
#[test] #[test]
#[timeout(5000)] #[timeout(5000)]
fn test_funnel_concurrent() { fn test_funnel_concurrent() {

View File

@@ -2,8 +2,8 @@
//! //!
//! The primary goal of this assignment is to get used to concurrency. //! The primary goal of this assignment is to get used to concurrency.
//! //!
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 12` works fine. //! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 12` works
//! See `assignment12/*_grade.rs` and `/scripts/grade.sh 12` for the test script. //! fine. See `assignment12/*_grade.rs` and `/scripts/grade.sh 12` for the test script.
//! //!
//! To submit, run //! To submit, run
//! ```bash //! ```bash

View File

@@ -1,5 +1,3 @@
#![allow(single_use_lifetimes)]
//! Small exercises //! Small exercises
//! //!
//! Refer `small_exercises_grade.rs` for test cases //! Refer `small_exercises_grade.rs` for test cases
@@ -12,16 +10,18 @@ use etrace::*;
/// The "pong" function /// The "pong" function
/// ///
/// Data will be sent and received through `rx` and `tx`. /// Data will be sent and received through `rx` and `tx`.
/// Read the `test_ping_pong` function in `small_exercises_grade.rs` to figure out what it should do. /// Read the `test_ping_pong` function in `small_exercises_grade.rs` to figure out what it should
/// do.
pub fn pong(rx1: &mut Receiver<u32>, tx2: &mut Sender<u32>) -> bool { pub fn pong(rx1: &mut Receiver<u32>, tx2: &mut Sender<u32>) -> bool {
todo!() todo!()
} }
/// Executes the given functions (f1, f2) in concurrent and returns the results. /// Executes the given functions (f1, f2) in concurrent and returns the results.
/// ///
/// Read the `test_scoped_thread` function in `small_exercises_grade.rs` to figure out what it should do. /// Read the `test_scoped_thread` function in `small_exercises_grade.rs` to figure out what it
pub fn use_scoped_thread<'scope, 'env, T1, T2, F1, F2>( /// should do.
s: &'scope thread::Scope<'scope, 'env>, pub fn use_scoped_thread<'scope, T1, T2, F1, F2>(
s: &'scope thread::Scope<'scope, '_>,
f1: F1, f1: F1,
f2: F2, f2: F2,
) -> (T1, T2) ) -> (T1, T2)

View File

@@ -2,12 +2,13 @@
#[cfg(test)] #[cfg(test)]
mod test_pingpong { mod test_pingpong {
use crate::assignments::assignment12::small_exercises::*;
use ntest::timeout;
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
use std::thread; use std::thread;
use ntest::timeout;
use crate::assignments::assignment12::small_exercises::*;
#[test] #[test]
fn test_ping_pong() { fn test_ping_pong() {
let (tx1, mut rx1) = channel(); let (tx1, mut rx1) = channel();

View File

@@ -2,9 +2,10 @@
//! //!
//! The primary goal of this assignment is to get used to data 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. //! Refer to your solution for assignment 09. You will implement the parallelized version of
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 13` works fine. //! assignment 09. You should fill out the `todo!()` placeholders in such a way that
//! See `assignment13/small_exercises_grade.rs` and `/scripts/grade.sh 13` for the test script. //! `/scripts/grade.sh 13` works fine. See `assignment13/small_exercises_grade.rs` and
//! `/scripts/grade.sh 13` for the test script.
//! //!
//! To submit, run //! To submit, run
//! ```bash //! ```bash

View File

@@ -1,19 +1,15 @@
//! Assignment 13: Parallelism. //! Assignment 13: Parallelism.
//! //!
//! If you did well on assignment 09, you will do well on this assignment. //! If you did well on assignment 09, you will do well on this assignment. Take it easy!
//! Take it easy!
use rayon::prelude::*; use rayon::prelude::*;
// Use this function if you want.
use crate::assignments::assignment09::matmul::dot_product;
/// Returns the sum of `f(v)` for all element `v` the given array. /// Returns the sum of `f(v)` for all element `v` the given array.
/// ///
/// # Exmaple /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment13::sigma; /// use cs220::assignments::assignment13::small_exercises::*;
/// use rayon::iter::IntoParallelIterator; /// use rayon::iter::IntoParallelIterator;
/// ///
/// assert_eq!(sigma_par([1, 2].into_par_iter(), |x| x + 2), 7); /// assert_eq!(sigma_par([1, 2].into_par_iter(), |x| x + 2), 7);
@@ -31,7 +27,7 @@ pub fn sigma_par<T, F: Fn(T) -> i64 + Sync + Send>(
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment13::interleave3; /// use cs220::assignments::assignment13::small_exercises::*;
/// use rayon::iter::IntoParallelIterator; /// use rayon::iter::IntoParallelIterator;
/// ///
/// assert_eq!( /// assert_eq!(
@@ -49,10 +45,10 @@ pub fn interleave3_par<T: Send>(
/// Parallel vector addition /// Parallel vector addition
/// ///
/// # Exmaple /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment13::vec_add_par; /// use cs220::assignments::assignment13::small_exercises::*;
/// ///
/// let vec1 = vec![1.0, 2.0, 3.0, 4.0, 5.0]; /// let vec1 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
/// let vec2 = vec![1.0, 2.0, 3.0, 4.0, 5.0]; /// let vec2 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
@@ -68,10 +64,10 @@ pub fn vec_add_par(lhs: &[f64], rhs: &[f64]) -> Vec<f64> {
/// You don't know how to calculate dot product? /// You don't know how to calculate dot product?
/// See <https://mathinsight.org/dot_product_examples> /// See <https://mathinsight.org/dot_product_examples>
/// ///
/// # Exmaple /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment13::dot_product_par; /// use cs220::assignments::assignment13::small_exercises::*;
/// ///
/// let vec1 = vec![1.0, 2.0, 3.0, 4.0, 5.0]; /// let vec1 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
/// let vec2 = vec![1.0, 2.0, 3.0, 4.0, 5.0]; /// let vec2 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
@@ -93,10 +89,10 @@ pub fn dot_product_par(lhs: &[f64], rhs: &[f64]) -> f64 {
/// - rhs: (p, n) /// - rhs: (p, n)
/// - output: (m, p) /// - output: (m, p)
/// ///
/// # Exmaple /// # Example
/// ///
/// ``` /// ```
/// use cs220::assignments::assignment13::matmul_par; /// use cs220::assignments::assignment13::small_exercises::*;
/// ///
/// let mat1 = vec![vec![1.0, 2.0, 3.0], vec![4.0, 5.0, 6.0]]; /// let mat1 = vec![vec![1.0, 2.0, 3.0], vec![4.0, 5.0, 6.0]];
/// let mat2 = vec![ /// let mat2 = vec![

View File

@@ -1,13 +1,17 @@
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::assignments::assignment09::matmul::*; use std::hint;
use crate::assignments::assignment13::small_exercises::*; use std::time::Instant;
use approx::*; use approx::*;
use itertools::Itertools; use itertools::Itertools;
use ndarray::prelude::*; use ndarray::prelude::*;
use ndarray_rand::{rand_distr::Uniform, RandomExt}; use ndarray_rand::rand_distr::Uniform;
use ndarray_rand::RandomExt;
use rayon::prelude::IntoParallelIterator; use rayon::prelude::IntoParallelIterator;
use std::time::Instant;
use crate::assignments::assignment09::matmul::*;
use crate::assignments::assignment13::small_exercises::*;
#[test] #[test]
fn test_sigma_par() { fn test_sigma_par() {
@@ -72,72 +76,66 @@ mod test {
} }
#[test] #[test]
fn vec_add_correctness() { fn vec_add_test() {
// small test
let vec1 = vec![1.0, 2.0, 3.0, 4.0, 5.0]; let vec1 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let vec2 = vec![1.0, 2.0, 3.0, 4.0, 5.0]; let vec2 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let res = vec_add_par(&vec1, &vec2); let res = vec_add(&vec1, &vec2);
assert_eq!(res, vec![2.0, 4.0, 6.0, 8.0, 10.0]); assert_eq!(res, vec![2.0, 4.0, 6.0, 8.0, 10.0]);
// random test for _ in 0..5 {
let vec1 = Array::random(1000, Uniform::new(0., 10.)); let vec1 = hint::black_box(Array::random(5_000_000, Uniform::new(0., 10.)));
let vec2 = Array::random(1000, Uniform::new(0., 10.)); let vec2 = hint::black_box(Array::random(5_000_000, Uniform::new(0., 10.)));
let res_par = vec_add_par(vec1.as_slice().unwrap(), vec2.as_slice().unwrap());
let ans = vec1 + vec2;
assert_eq!(Array::from_vec(res_par), ans);
}
#[test]
fn vec_add_test_performance() {
for _ in 0..2 {
let vec1 = Array::random(500000, Uniform::new(0., 10.));
let vec2 = Array::random(500000, Uniform::new(0., 10.));
let now_seq = Instant::now(); let now_seq = Instant::now();
let res_seq = vec_add(vec1.as_slice().unwrap(), vec2.as_slice().unwrap()); let res_seq = hint::black_box(vec_add(
hint::black_box(vec1.as_slice().unwrap()),
hint::black_box(vec2.as_slice().unwrap()),
));
let elapsed_seq = now_seq.elapsed(); let elapsed_seq = now_seq.elapsed();
let now_par = Instant::now(); let now_par = Instant::now();
let res_par = vec_add_par(vec1.as_slice().unwrap(), vec2.as_slice().unwrap()); let res_par = hint::black_box(vec_add_par(
hint::black_box(vec1.as_slice().unwrap()),
hint::black_box(vec2.as_slice().unwrap()),
));
let elapsed_par = now_par.elapsed(); let elapsed_par = now_par.elapsed();
let ans = vec1 + vec2;
assert_eq!(Array::from_vec(res_seq), ans);
assert_eq!(Array::from_vec(res_par), ans);
assert!(elapsed_par < elapsed_seq); assert!(elapsed_par < elapsed_seq);
} }
} }
#[test] #[test]
fn dot_product_correctness() { fn dot_product_test() {
// small test
let vec1 = vec![1.0, 2.0, 3.0, 4.0, 5.0]; let vec1 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let vec2 = vec![1.0, 2.0, 3.0, 4.0, 5.0]; let vec2 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
let res_seq = dot_product(&vec1, &vec2);
let res_par = dot_product_par(&vec1, &vec2); let res_par = dot_product_par(&vec1, &vec2);
assert_eq!(res_seq, 55.0);
assert_eq!(res_par, 55.0); assert_eq!(res_par, 55.0);
// random test for _ in 0..5 {
let vec1 = Array::random(1000, Uniform::new(0., 10.)); let vec1 = Array::random(500_000, Uniform::new(0., 10.));
let vec2 = Array::random(1000, Uniform::new(0., 10.)); let vec2 = Array::random(500_000, Uniform::new(0., 10.));
let res_par = dot_product_par(vec1.as_slice().unwrap(), vec2.as_slice().unwrap());
let _res = relative_eq!(res_par, vec1.dot(&vec2), epsilon = f64::EPSILON);
}
#[test]
fn dot_product_performance() {
for _ in 0..2 {
let vec1 = Array::random(1000000, Uniform::new(0., 10.));
let vec2 = Array::random(1000000, Uniform::new(0., 10.));
let now_seq = Instant::now(); let now_seq = Instant::now();
let res_seq = dot_product(vec1.as_slice().unwrap(), vec2.as_slice().unwrap()); let res_seq = hint::black_box(dot_product(
hint::black_box(vec1.as_slice().unwrap()),
hint::black_box(vec2.as_slice().unwrap()),
));
let elapsed_seq = now_seq.elapsed(); let elapsed_seq = now_seq.elapsed();
let now_par = Instant::now(); let now_par = Instant::now();
let res_par = dot_product_par(vec1.as_slice().unwrap(), vec2.as_slice().unwrap()); let res_par = hint::black_box(dot_product_par(
hint::black_box(vec1.as_slice().unwrap()),
hint::black_box(vec2.as_slice().unwrap()),
));
let elapsed_par = now_par.elapsed(); let elapsed_par = now_par.elapsed();
let _res = relative_eq!(res_seq, vec1.dot(&vec2), epsilon = f64::EPSILON);
let _res = relative_eq!(res_par, vec1.dot(&vec2), epsilon = f64::EPSILON);
assert!(elapsed_par < elapsed_seq); assert!(elapsed_par < elapsed_seq);
} }
} }
@@ -163,8 +161,7 @@ mod test {
} }
#[test] #[test]
fn matmul_correctness() { fn matmul_test() {
// small case
let mat1 = vec![vec![1.0, 2.0, 3.0], vec![4.0, 5.0, 6.0]]; let mat1 = vec![vec![1.0, 2.0, 3.0], vec![4.0, 5.0, 6.0]];
let mat2 = vec![ let mat2 = vec![
vec![7.0, 8.0, 9.0], vec![7.0, 8.0, 9.0],
@@ -176,72 +173,68 @@ mod test {
vec![50.0, 68.0, 86.0, 104.0], vec![50.0, 68.0, 86.0, 104.0],
vec![122.0, 167.0, 212.0, 257.0], vec![122.0, 167.0, 212.0, 257.0],
]; ];
let res_seq = matmul(&mat1, &mat2);
let res_par = matmul_par(&mat1, &mat2); let res_par = matmul_par(&mat1, &mat2);
assert_eq!(ans, res_seq);
assert_eq!(ans, res_par); assert_eq!(ans, res_par);
let mat1 = Array::random((10, 10), Uniform::new(0., 10.)); for _ in 0..5 {
let mat2 = Array::random((10, 10), Uniform::new(0., 10.));
let ans = mat1.dot(&mat2);
let mat2_transposed = mat2.t();
// Run parallel matrix multiplication
let now_par = Instant::now();
let res_par = matmul_par(
mat1.axis_iter(Axis(0))
.map(|row| row.to_vec())
.collect::<Vec<_>>()
.as_slice(),
mat2_transposed
.axis_iter(Axis(0))
.map(|row| row.to_vec())
.collect::<Vec<_>>()
.as_slice(),
);
let elapsed_par = now_par.elapsed();
for it in ans.iter().zip(vec_to_array(res_par).iter()) {
let (ans, par) = it;
let _res = relative_eq!(ans, par);
}
}
#[test]
fn matmul_performance() {
for _ in 0..2 {
let mat1 = Array::random((500, 500), Uniform::new(0., 10.)); let mat1 = Array::random((500, 500), Uniform::new(0., 10.));
let mat2 = Array::random((500, 500), Uniform::new(0., 10.)); let mat2 = Array::random((500, 500), Uniform::new(0., 10.));
let ans = mat1.dot(&mat2);
let mat2_transposed = mat2.t(); let mat2_transposed = mat2.t();
// Run sequential matrix multiplication // Run sequential matrix multiplication
let now_seq = Instant::now(); let now_seq = Instant::now();
let res_seq = matmul( let res_seq = hint::black_box(matmul(
mat1.axis_iter(Axis(0)) hint::black_box(
.map(|row| row.to_vec()) mat1.axis_iter(Axis(0))
.collect::<Vec<_>>() .map(|row| row.to_vec())
.as_slice(), .collect::<Vec<_>>()
mat2_transposed .as_slice(),
.axis_iter(Axis(0)) ),
.map(|row| row.to_vec()) hint::black_box(
.collect::<Vec<_>>() mat2_transposed
.as_slice(), .axis_iter(Axis(0))
); .map(|row| row.to_vec())
.collect::<Vec<_>>()
.as_slice(),
),
));
let elapsed_seq = now_seq.elapsed(); let elapsed_seq = now_seq.elapsed();
// Run parallel matrix multiplication // Run parallel matrix multiplication
let now_par = Instant::now(); let now_par = Instant::now();
let res_par = matmul_par( let res_par = hint::black_box(matmul_par(
mat1.axis_iter(Axis(0)) hint::black_box(
.map(|row| row.to_vec()) mat1.axis_iter(Axis(0))
.collect::<Vec<_>>() .map(|row| row.to_vec())
.as_slice(), .collect::<Vec<_>>()
mat2_transposed .as_slice(),
.axis_iter(Axis(0)) ),
.map(|row| row.to_vec()) hint::black_box(
.collect::<Vec<_>>() mat2_transposed
.as_slice(), .axis_iter(Axis(0))
); .map(|row| row.to_vec())
.collect::<Vec<_>>()
.as_slice(),
),
));
let elapsed_par = now_par.elapsed(); let elapsed_par = now_par.elapsed();
// Check answer
for it in ans.iter().zip(vec_to_array(res_seq).iter()) {
let (ans, seq) = it;
let _res = relative_eq!(ans, seq);
}
for it in ans.iter().zip(vec_to_array(res_par).iter()) {
let (ans, par) = it;
let _res = relative_eq!(ans, par);
}
// Check time
// println!("Sequential: {:?}", elapsed_seq);
// println!("Parallel: {:?}", elapsed_par);
assert!(elapsed_par < elapsed_seq); assert!(elapsed_par < elapsed_seq);
} }
} }

View File

@@ -3,7 +3,6 @@ use std::io::{self, BufRead, Read};
use anyhow::Result; use anyhow::Result;
use clap::Parser; use clap::Parser;
use cs220::assignments::assignment04::*; use cs220::assignments::assignment04::*;
struct Input<'a> { struct Input<'a> {

View File

@@ -1,31 +1,57 @@
//! KAIST CS220: Programming Principles //! KAIST CS220: Programming Principles
// # Tries to deny all lints (`rustc -W help`).
#![deny(absolute_paths_not_starting_with_crate)]
#![deny(anonymous_parameters)]
// #![deny(box_pointers)]
#![deny(deprecated_in_future)]
#![deny(explicit_outlives_requirements)]
#![deny(keyword_idents)]
#![deny(macro_use_extern_crate)]
#![deny(missing_debug_implementations)]
#![deny(non_ascii_idents)]
#![deny(rust_2018_idioms)]
#![deny(trivial_numeric_casts)]
// #![deny(unused_crate_dependencies)] // TODO: uncomment
#![deny(unused_extern_crates)]
#![deny(unused_import_braces)]
#![deny(unused_qualifications)]
#![deny(unused_results)]
#![deny(variant_size_differences)]
#![deny(warnings)] #![deny(warnings)]
#![deny(rustdoc::invalid_html_tags)]
// #![deny(rustdoc::missing_doc_code_examples)]
#![deny(missing_docs)]
#![deny(rustdoc::all)] #![deny(rustdoc::all)]
#![deny(unreachable_pub)] // # Tries to deny all lints (`rustc -W help`).
#![deny(single_use_lifetimes)] #![deny(
#![deny(unused_lifetimes)] absolute_paths_not_starting_with_crate,
#![deny(unstable_features)] // box_pointers,
deprecated_safe,
elided_lifetimes_in_paths,
explicit_outlives_requirements,
ffi_unwind_calls,
// fuzzy_provenance_casts,
// impl_trait_overcaptures,
keyword_idents,
keyword_idents_2018,
keyword_idents_2024,
let_underscore_drop,
// lossy_provenance_casts,
macro_use_extern_crate,
meta_variable_misuse,
missing_abi,
// missing_copy_implementations,
missing_debug_implementations,
missing_docs,
missing_unsafe_on_extern,
// multiple_supertrait_upcastable,
// must_not_suspend,
non_ascii_idents,
// non_exhaustive_omitted_patterns,
non_local_definitions,
redundant_lifetimes,
rust_2021_incompatible_closure_captures,
rust_2021_incompatible_or_patterns,
rust_2021_prefixes_incompatible_syntax,
rust_2021_prelude_collisions,
// rust_2024_incompatible_pat,
single_use_lifetimes,
trivial_casts,
trivial_numeric_casts,
unit_bindings,
unnameable_types,
unreachable_pub,
unsafe_code,
unsafe_op_in_unsafe_fn,
unstable_features,
// unused_crate_dependencies,
unused_extern_crates,
unused_import_braces,
unused_lifetimes,
unused_macro_rules,
unused_qualifications,
unused_results,
variant_size_differences
)]
pub mod assignments; pub mod assignments;

View File