mirror of
https://github.com/kmc7468/cs220.git
synced 2025-12-15 22:48:45 +00:00
Cleanups
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1,3 @@
|
|||||||
/target
|
/target
|
||||||
|
rustfmt.toml
|
||||||
|
/.vscode
|
||||||
|
|||||||
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -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"
|
||||||
|
|||||||
20
Cargo.toml
20
Cargo.toml
@@ -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"
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ module Max
|
|||||||
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;
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -32,7 +32,8 @@ module Pascal
|
|||||||
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;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "1.80.0"
|
channel = "1.80.0"
|
||||||
components = [ "rustfmt", "clippy" ]
|
components = ["rustfmt", "clippy"]
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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!()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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!(
|
||||||
|
|||||||
@@ -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>,
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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']
|
||||||
|
|||||||
@@ -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.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -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
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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`.
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)>,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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!()
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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![
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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!()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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... 🤔
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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!()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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![
|
||||||
|
|||||||
@@ -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(
|
||||||
|
hint::black_box(
|
||||||
mat1.axis_iter(Axis(0))
|
mat1.axis_iter(Axis(0))
|
||||||
.map(|row| row.to_vec())
|
.map(|row| row.to_vec())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.as_slice(),
|
.as_slice(),
|
||||||
|
),
|
||||||
|
hint::black_box(
|
||||||
mat2_transposed
|
mat2_transposed
|
||||||
.axis_iter(Axis(0))
|
.axis_iter(Axis(0))
|
||||||
.map(|row| row.to_vec())
|
.map(|row| row.to_vec())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.as_slice(),
|
.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(
|
||||||
|
hint::black_box(
|
||||||
mat1.axis_iter(Axis(0))
|
mat1.axis_iter(Axis(0))
|
||||||
.map(|row| row.to_vec())
|
.map(|row| row.to_vec())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.as_slice(),
|
.as_slice(),
|
||||||
|
),
|
||||||
|
hint::black_box(
|
||||||
mat2_transposed
|
mat2_transposed
|
||||||
.axis_iter(Axis(0))
|
.axis_iter(Axis(0))
|
||||||
.map(|row| row.to_vec())
|
.map(|row| row.to_vec())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.as_slice(),
|
.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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
76
src/lib.rs
76
src/lib.rs
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user