mirror of
https://github.com/kmc7468/cs220.git
synced 2025-12-12 21:08:45 +00:00
Cleanups
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1,3 @@
|
||||
/target
|
||||
rustfmt.toml
|
||||
/.vscode
|
||||
|
||||
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -190,12 +190,10 @@ dependencies = [
|
||||
"ndarray",
|
||||
"ndarray-rand",
|
||||
"ntest",
|
||||
"num-traits",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
"rand",
|
||||
"rayon",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -210,9 +208,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.12.0"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
@@ -298,9 +296,9 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.7"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
|
||||
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
|
||||
|
||||
[[package]]
|
||||
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
|
||||
|
||||
[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]
|
||||
anyhow = "1.0.86"
|
||||
clap = { version = "4.5.11", features = ["derive"] }
|
||||
clap = { version = "4.5.11", features = ["derive"], optional = true }
|
||||
etrace = "1.1.1"
|
||||
itertools = "0.13.0"
|
||||
lazy_static = "1.5.0"
|
||||
pest = "2.7.11"
|
||||
pest_derive = "2.7.11"
|
||||
rayon = "1.10.0"
|
||||
thiserror = "1.0.63"
|
||||
ntest = "0.9.3"
|
||||
approx = "0.5.1"
|
||||
num-traits = "0.2.19"
|
||||
ndarray = "0.15.6"
|
||||
ndarray-rand = "0.14.0"
|
||||
rand = "0.8.5"
|
||||
|
||||
10
README.md
10
README.md
@@ -12,7 +12,7 @@
|
||||
- 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 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.
|
||||
If you want to come, do so by 9:15.
|
||||
See [below](https://github.com/kaist-cp/cs220#rules) for the office hour policy.
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
## Course description
|
||||
|
||||
This course will equip you with the programming concepts needed to effectively communicate your ideas to computers.
|
||||
This course will equip you with the programming concepts needed to effectively communicate your ideas to computers.
|
||||
For a detailed overview, please refer to the introduction in the Google Slides presentation.
|
||||
|
||||
### Outline
|
||||
@@ -162,7 +162,7 @@ Ensure you are proficient with the following development tools:
|
||||
- You can run the grading script with the following command:
|
||||
```bash
|
||||
$ ./scripts/grade.sh <assignment_number>
|
||||
|
||||
|
||||
# E.g. To grade `assignment09`, run the following command:
|
||||
$ ./scripts/grade.sh 9
|
||||
```
|
||||
@@ -181,8 +181,8 @@ Ensure you are proficient with the following development tools:
|
||||
Laptops can also be borrowed from the School of Computing Administration Team.
|
||||
|
||||
- We will use [Safe Exam Browser](https://safeexambrowser.org/) to prevent cheatings.
|
||||
- You should have your laptop configured with Safe Exam Browser before the exam.
|
||||
- TBA: Details will be announced later.
|
||||
- You should have your laptop configured with Safe Exam Browser before the exam.
|
||||
- TBA: Details will be announced later.
|
||||
|
||||
### Attendance (?%)
|
||||
|
||||
|
||||
@@ -19,5 +19,5 @@ module BinarySearch
|
||||
=
|
||||
(* IMPORTANT: DON'T MODIFY THE ABOVE LINES *)
|
||||
0 (* TODO *)
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
Given an array `a` of integers with length `n` greater than `0`,
|
||||
return `max_idx`, the index of the maximum element of that array.
|
||||
|
||||
|
||||
E.g. `max_idx [5, 12, 34, 10] 4` will return `2`
|
||||
E.g. `max_idx [4, 3, 2] 3` will return `0`
|
||||
E.g. `max_idx [1, 2, 3, 4] 4` will return `3`
|
||||
|
||||
|
||||
Prove the below program indeed follows the given specification,
|
||||
by giving an appropriate invariant.
|
||||
*)
|
||||
@@ -22,12 +22,13 @@ module Max
|
||||
requires { n = length a }
|
||||
ensures { 0 <= max_idx <= n-1 }
|
||||
ensures { forall i. 0 <= i <= n-1 -> a[i] <= a[max_idx] }
|
||||
=
|
||||
=
|
||||
let ref max_idx = 0 in
|
||||
for i = 0 to n-1 do
|
||||
invariant { 0 <= max_idx <= n-1 }
|
||||
(* 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 *)
|
||||
if a[max_idx] < a[i] then max_idx <- i;
|
||||
done;
|
||||
|
||||
@@ -17,9 +17,9 @@ module Pascal
|
||||
ensures { result >= 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. *)
|
||||
(* 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
|
||||
requires { n > 0 }
|
||||
ensures { forall i: int.
|
||||
@@ -28,16 +28,17 @@ module Pascal
|
||||
let ref row = Array.make 1 1 in
|
||||
for r = 1 to n do
|
||||
invariant { length row = r }
|
||||
invariant { forall c: int. 0 <= c < r -> row[c] = comb (r-1) c }
|
||||
invariant { forall c: int. 0 <= c < r -> row[c] = comb (r-1) c }
|
||||
let new_row = Array.make (r+1) 1 in
|
||||
for c = 1 to r-1 do
|
||||
(* 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 *)
|
||||
new_row[c] <- row[c-1] + row[c]
|
||||
done;
|
||||
row <- new_row
|
||||
done;
|
||||
row
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "1.80.0"
|
||||
components = [ "rustfmt", "clippy" ]
|
||||
components = ["rustfmt", "clippy"]
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# * RUNNERS: array of "cargo[_asan | _tsan] [--release]"
|
||||
# * TIMEOUT: default 10s
|
||||
|
||||
rustup toolchain update stable nightly
|
||||
rustup toolchain update stable
|
||||
|
||||
echo_err() {
|
||||
echo "$@" 1>&2
|
||||
@@ -37,27 +37,6 @@ 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]
|
||||
# example: _run_tests_with cargo_tsan --release
|
||||
# Echos number of failed tests to stdout.
|
||||
@@ -80,7 +59,7 @@ _run_tests_with() {
|
||||
# local NUM_TESTS=$(echo $TESTS | wc -w)
|
||||
for TEST in ${TESTS[@]}; do
|
||||
local TEST_CMD="$CARGO test $* --lib -- $TEST"
|
||||
# card_game in Assignment12 takes 20 seconds.
|
||||
# card_game in Assignment12 takes 20 seconds.
|
||||
timeout ${TIMEOUT:-22s} bash -c "$TEST_CMD 2> /dev/null" 1>&2
|
||||
case $? in
|
||||
0) PASSED=$((PASSED + 1));;
|
||||
|
||||
@@ -73,7 +73,6 @@ case $TEST_NAME in
|
||||
TESTS=(
|
||||
"assignments::assignment09::bigint_grade::test"
|
||||
"assignments::assignment09::small_exercises_grade::test"
|
||||
"assignments::assignment09::matmul_grade::test"
|
||||
)
|
||||
;;
|
||||
TEST10)
|
||||
|
||||
@@ -15,16 +15,6 @@ for i in {01..13} ; do
|
||||
zip -rj $BASEDIR/target/assignment05.zip $BASEDIR/assets/why3/assignment05
|
||||
continue
|
||||
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
|
||||
rm $BASEDIR/target/assignment$i.zip
|
||||
fi
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
//! 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.
|
||||
//! Please make sure you're comfortable with developing Rust programs before moving on to the next assignments.
|
||||
//! The primary goal of this assignment is bringing up SSH, VSCode, and all the other necessary
|
||||
//! 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.
|
||||
//! See `assigment01/small_exercises_grade.rs` and `/scripts/grade.sh 1` for the test script.
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 1` works
|
||||
//! fine. See `assigment01/small_exercises_grade.rs` and `/scripts/grade.sh 1` for the test script.
|
||||
//!
|
||||
//! To submit, run
|
||||
//! ```bash
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//! 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.
|
||||
//! See `small_problems_grade.rs` and `/scripts/grade.sh 1` for the test script.
|
||||
//! You should fill out `add()` and `sub()` function bodies in such a way that `/scripts/grade.sh 1`
|
||||
//! 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>
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
//! 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.
|
||||
//! Please make sure you're comfortable with the concepts to proceed on to the next assignments.
|
||||
//! 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. 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.
|
||||
//! See `assigment02/*_grade.rs` and `/scripts/grade.sh 2` for the test script.
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 2` works
|
||||
//! fine. See `assigment02/*_grade.rs` and `/scripts/grade.sh 2` for the test script.
|
||||
//!
|
||||
//! To submit, run
|
||||
//! ```bash
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//! Small problems.
|
||||
|
||||
use std::iter;
|
||||
|
||||
const FAHRENHEIT_OFFSET: f64 = 32.0;
|
||||
const FAHRENHEIT_SCALE: f64 = 5.0 / 9.0;
|
||||
|
||||
@@ -18,29 +20,33 @@ pub fn sum_array(input: &[u64]) -> u64 {
|
||||
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.)
|
||||
pub fn up3(n: u64) -> u64 {
|
||||
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 {
|
||||
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> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Returns the "zip" of two vectors.
|
||||
///
|
||||
/// For instance, `zip(vec![1, 2, 3], vec![4, 5])` equals to `vec![(1, 4), (2, 5)]`.
|
||||
/// Here, `3` is ignored because it doesn't have a partner.
|
||||
/// For instance, `zip(vec![1, 2, 3], vec![4, 5])` equals to `vec![(1, 4), (2, 5)]`. Here, `3` is
|
||||
/// ignored because it doesn't have a partner.
|
||||
pub fn zip(lhs: Vec<u64>, rhs: Vec<u64>) -> Vec<(u64, u64)> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
//!
|
||||
//! You will implement simple operations on vectors and matrices.
|
||||
|
||||
use std::cmp::PartialEq;
|
||||
use std::ops::Mul;
|
||||
|
||||
/// 2x2 matrix of the following configuration:
|
||||
@@ -112,13 +113,20 @@ impl FMat2 {
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// ```ignore
|
||||
/// assert_eq!(
|
||||
/// Mat2 { 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: 1.0, b: 1.0, c: 2.0, d: 3.0 }.inverse(),
|
||||
/// FMat2 { a: 3.0, b: -1.0, c: -2.0, d: 1.0 }
|
||||
/// );
|
||||
/// ```
|
||||
pub fn inverse(self) -> Self {
|
||||
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);
|
||||
}
|
||||
|
||||
// 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]
|
||||
fn test_inverse() {
|
||||
assert_eq!(
|
||||
|
||||
@@ -16,7 +16,7 @@ pub enum MyOption<T> {
|
||||
/// 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 {
|
||||
/// s.len()
|
||||
@@ -29,14 +29,15 @@ pub fn my_map<T, U, F: FnOnce(T) -> U>(v: MyOption<T>, f: F) -> MyOption<U> {
|
||||
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.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use cs220::assignments::assignment03::{MyOption, my_and_then};
|
||||
/// use cs220::assignments::assignment03::custom_operators::*;
|
||||
///
|
||||
/// fn pos_then_to_string(x: isize) -> MyOption<String> {
|
||||
/// 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!()
|
||||
}
|
||||
|
||||
/// Custom operator: `option_op_or(v1, v2, f)`
|
||||
/// 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 inside `Some` to `f` and wrap the resulting value inside `Some`.
|
||||
/// Custom operator: `option_op_or(v1, v2, f)`. 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
|
||||
/// inside `Some` to `f` and wrap the resulting value inside `Some`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use cs220::assignments::assignment03::custom_operators::*;
|
||||
/// fn product(a: i32, b: i32) -> i32 {
|
||||
/// a * b
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(option_op_or(None, None, product), None);
|
||||
/// assert_eq!(option_op_or(Some(3), None, product), Some(3));
|
||||
/// assert_eq!(option_op_or(Some(3), Some(5), product), Some(15));
|
||||
/// assert_eq!(my_option_op_or(MyOption::MyNone, MyOption::MyNone, product), MyOption::MyNone);
|
||||
/// assert_eq!(my_option_op_or(MyOption::MySome(3), MyOption::MyNone, product), MyOption::MySome(3));
|
||||
/// 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>(
|
||||
v1: MyOption<T>,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::assignments::assignment03::custom_operators::{MyOption::*, *};
|
||||
use crate::assignments::assignment03::custom_operators::MyOption::*;
|
||||
use crate::assignments::assignment03::custom_operators::*;
|
||||
|
||||
#[test]
|
||||
fn test_my_map() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! 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.
|
||||
//! See `assignment03/*_grade.rs` and `/scripts/grade.sh 3` for the test script.
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 3` works
|
||||
//! fine. See `assignment03/*_grade.rs` and `/scripts/grade.sh 3` for the test script.
|
||||
//!
|
||||
//! To submit, run
|
||||
//! ```bash
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
//! Parsing a shell command.
|
||||
//!
|
||||
//! 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.
|
||||
//! For example, you can use the `ls` command to list files in a directory.
|
||||
//! to interact with operating systems (e.g. Linux) and others. For example, you can use the `ls`
|
||||
//! command to list files in a directory.
|
||||
//!
|
||||
//! You will parse a given string consists of a small number of shell commands.
|
||||
|
||||
/// Parse the string as a shell command.
|
||||
///
|
||||
/// Usually, a shell command is whitespace-separated array of strings.
|
||||
///
|
||||
/// ```text
|
||||
/// 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
|
||||
/// 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!()
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub fn mode(values: Vec<isize>) -> Option<isize> {
|
||||
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"
|
||||
///
|
||||
@@ -99,7 +102,8 @@ pub fn piglatin(input: String) -> String {
|
||||
///
|
||||
/// - The result is a map from department to the list of its employees.
|
||||
/// - 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.
|
||||
/// - There is no space in the name of the person and department.
|
||||
///
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::*;
|
||||
use etrace::*;
|
||||
|
||||
use super::syntax::{Command, Expression};
|
||||
use super::syntax::{BinOp, Command, Expression};
|
||||
|
||||
/// Calculator's context.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
@@ -31,7 +32,8 @@ impl Context {
|
||||
|
||||
/// 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
|
||||
///
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
//! Assignment 4: Designing a calculator.
|
||||
//!
|
||||
//! The primary goal of this assignment is twofold:
|
||||
//! (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.
|
||||
//! - (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.
|
||||
//!
|
||||
//! For `pest`, read the following documentations (that contain 90% of the solution):
|
||||
//! - <https://pest.rs/>
|
||||
@@ -11,8 +12,9 @@
|
||||
//!
|
||||
//! 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.
|
||||
//! See `assignment04/grade.rs` and `/scripts/grade.sh 4` for the test script.
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 4` works
|
||||
//! 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>.
|
||||
//!
|
||||
//! To submit, run
|
||||
|
||||
@@ -2,8 +2,14 @@
|
||||
|
||||
//! 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 anyhow::Result;
|
||||
|
||||
#[allow(missing_docs)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
@@ -15,13 +21,16 @@ mod inner {
|
||||
pub(crate) struct SyntaxParser;
|
||||
}
|
||||
|
||||
use inner::*;
|
||||
|
||||
/// Parses command.
|
||||
///
|
||||
/// ## Operator Associativty
|
||||
///
|
||||
/// 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> {
|
||||
todo!("fill here")
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
//!
|
||||
//! 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.
|
||||
//! See `assignment06/*_grade.rs` and `/scripts/grade.sh 6` for the test script.
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 6` works
|
||||
//! fine. See `assignment06/*_grade.rs` and `/scripts/grade.sh 6` for the test script.
|
||||
//!
|
||||
//! To submit, run
|
||||
//! ```bash
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
//! Semiring
|
||||
|
||||
use std::{collections::HashMap, fmt::Debug};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
/// Semiring.
|
||||
///
|
||||
@@ -147,10 +150,8 @@ impl<C: Semiring> From<C> for Polynomial<C> {
|
||||
///
|
||||
/// Assumptions:
|
||||
/// - Each term is separated by ` + `.
|
||||
/// - Each term is one of the following form:
|
||||
/// `a`, `x`, `ax`, `x^n`, and `ax^n`,
|
||||
/// where `a` is a `usize` number and `n` is a `u64` number.
|
||||
/// This `a` should then be converted to a `C` type.
|
||||
/// - Each term is one of the following form: `a`, `x`, `ax`, `x^n`, and `ax^n`, 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 `ax` and `ax^n`, it is guaranteed that `a >= 2`.
|
||||
/// - In `x^n` and `ax^n`, it is guaranteed that `n >= 2`.
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::assignments::assignment06::semiring::*;
|
||||
use ntest::assert_about_eq;
|
||||
|
||||
use crate::assignments::assignment06::semiring::*;
|
||||
|
||||
fn test_from_str(s: &str, f: impl Fn(i64) -> i64) {
|
||||
let poly = s.parse::<Polynomial<i64>>().unwrap();
|
||||
for i in 0..10 {
|
||||
|
||||
@@ -5,10 +5,12 @@ use std::ops::*;
|
||||
|
||||
/// 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.
|
||||
/// See `normalize` for examples. As a corner case, 0 is represented by Rational { numerator: 0, demoninator: 0 }.
|
||||
/// Each Rational number should be normalized so that `demoninator` is nonnegative and `numerator`
|
||||
/// 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.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -96,9 +98,9 @@ pub enum SingletonPolynomial {
|
||||
Const(Rational),
|
||||
/// Non-const polynomial.
|
||||
Polynomial {
|
||||
/// coefficent of polynomial. Must be non-zero.
|
||||
/// Coefficent of polynomial. Must be non-zero.
|
||||
coeff: Rational,
|
||||
/// power of polynomial. Must be non-zero.
|
||||
/// Power of polynomial. Must be non-zero.
|
||||
power: Rational,
|
||||
},
|
||||
}
|
||||
@@ -156,7 +158,7 @@ pub enum Trignometric {
|
||||
/// Coefficent
|
||||
coeff: Rational,
|
||||
},
|
||||
/// Sine function.
|
||||
/// Cosine function.
|
||||
Cosine {
|
||||
/// Coefficent
|
||||
coeff: Rational,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::assignments::assignment06::symbolic_differentiation::*;
|
||||
use ntest::assert_about_eq;
|
||||
|
||||
use crate::assignments::assignment06::symbolic_differentiation::*;
|
||||
|
||||
// Constant rationals to use
|
||||
const TWO: Rational = Rational::new(2, 1);
|
||||
const FOUR: Rational = Rational::new(4, 1);
|
||||
@@ -172,7 +173,7 @@ mod test {
|
||||
// Mult
|
||||
//
|
||||
// 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 f2 = Trignometric::new_cosine(ONE);
|
||||
let f3 = Exp::new();
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
//!
|
||||
//! 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.
|
||||
//! See `assignment07/*_grade.rs` and `/scripts/grade.sh 7` for the test script.
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 7` works
|
||||
//! fine. See `assignment07/*_grade.rs` and `/scripts/grade.sh 7` for the test script.
|
||||
//!
|
||||
//! To submit, run
|
||||
//! ```bash
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
//! Implement your own minimal `itertools` crate.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::hash::Hash;
|
||||
|
||||
/// Iterator that iterates over the given iterator and returns only unique elements.
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[derive(Debug)]
|
||||
pub struct Unique<I: Iterator> {
|
||||
// TODO: remove `_marker` and add necessary fields as you want
|
||||
_marker: std::marker::PhantomData<I>,
|
||||
@@ -21,7 +22,7 @@ where
|
||||
}
|
||||
|
||||
/// Iterator that chains two iterators together.
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[derive(Debug)]
|
||||
pub struct Chain<I1: Iterator, I2: Iterator> {
|
||||
// TODO: remove `_marker` and add necessary fields as you want
|
||||
_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.
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[derive(Debug)]
|
||||
pub struct Enumerate<I: Iterator> {
|
||||
// TODO: remove `_marker` and add necessary fields as you want
|
||||
_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
|
||||
/// should be ignored.
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[derive(Debug)]
|
||||
pub struct Zip<I1: Iterator, I2: Iterator> {
|
||||
// TODO: remove `_marker` and add necessary fields as you want
|
||||
_marker: std::marker::PhantomData<(I1, I2)>,
|
||||
|
||||
@@ -47,7 +47,8 @@ where
|
||||
}
|
||||
|
||||
/// 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>
|
||||
where
|
||||
T: std::ops::Add<Output = T> + Copy,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
//! - <https://en.wikipedia.org/wiki/Church_encoding>
|
||||
//! - <https://opendsa-server.cs.vt.edu/OpenDSA/Books/PL/html/ChurchNumerals.html>
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
/// 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.
|
||||
/// 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,
|
||||
/// and then apply the Church numeral for `m` (the exponent) to the Church numeral for `n` (the base).
|
||||
/// Note: This function should be implemented *WITHOUT* using the `to_usize` or any `pow`-like method.
|
||||
/// and then apply the Church numeral for `m` (the exponent) to the Church numeral for `n` (the
|
||||
/// 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> {
|
||||
// ACTION ITEM: Uncomment the following lines and replace `todo!()` with your code.
|
||||
// let n = from_usize(n);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
//!
|
||||
//! 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.
|
||||
//! See `assignment08/*_grade.rs` and `/scripts/grade.sh 8` for the test script.
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 8` works
|
||||
//! fine. See `assignment08/*_grade.rs` and `/scripts/grade.sh 8` for the test script.
|
||||
//!
|
||||
//! To submit, run
|
||||
//! ```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.
|
||||
///
|
||||
/// 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.
|
||||
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
|
||||
///
|
||||
/// Returns the number of the elements of the set
|
||||
/// {x, f(x), f(f(x)), f(f(f(x))), ...}.
|
||||
/// You may assume that the answer is finite and small enough.
|
||||
/// Returns the number of the elements in the set {`x`, `f(x)`, `f(f(x))`, `f(f(f(x)))`, ...}. You
|
||||
/// may assume that the answer is finite and small enough.
|
||||
///
|
||||
/// 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
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
//! Big integer with infinite precision.
|
||||
|
||||
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.
|
||||
///
|
||||
@@ -15,15 +16,17 @@ use std::{iter::zip, ops::*};
|
||||
///
|
||||
/// 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.
|
||||
/// 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.
|
||||
/// Unlike standard fix-sized intergers in Rust where overflow will panic, the carrier is extended
|
||||
/// 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,
|
||||
/// 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.
|
||||
///
|
||||
/// 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)]
|
||||
pub struct BigInt {
|
||||
/// The carrier for `BigInt`.
|
||||
@@ -39,6 +42,10 @@ impl BigInt {
|
||||
}
|
||||
|
||||
/// Creates a new `BigInt` from a `Vec<u32>`.
|
||||
///
|
||||
/// # Panic
|
||||
///
|
||||
/// Panics if `carrier` is empty.
|
||||
pub fn new_large(carrier: Vec<u32>) -> Self {
|
||||
assert!(!carrier.is_empty());
|
||||
todo!()
|
||||
|
||||
@@ -43,7 +43,7 @@ mod test {
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_inf_prec_panic() {
|
||||
let _ = BigInt::new_large(vec![]);
|
||||
let _unused = BigInt::new_large(vec![]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -7,7 +7,7 @@ use itertools::*;
|
||||
/// # 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 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?
|
||||
/// 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 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)
|
||||
/// - 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 mat2 = vec![
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::assignments::assignment09::matmul::*;
|
||||
|
||||
use approx::*;
|
||||
use itertools::Itertools;
|
||||
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]
|
||||
fn vec_add_test() {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
//!
|
||||
//! 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.
|
||||
//! See `assignment09/*_grade.rs` and `/scripts/grade.sh 9` for the test script.
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 9` works
|
||||
//! fine. See `assignment09/*_grade.rs` and `/scripts/grade.sh 9` for the test script.
|
||||
//!
|
||||
//! To submit, run
|
||||
//! ```bash
|
||||
|
||||
@@ -2,14 +2,17 @@
|
||||
|
||||
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.
|
||||
///
|
||||
/// # 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, 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.
|
||||
///
|
||||
/// # 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 * 4), 12);
|
||||
@@ -39,7 +42,7 @@ pub fn sigma<T, F: Fn(T) -> i64>(inner: impl Iterator<Item = T>, f: F) -> i64 {
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use cs220::assignments::assignment09::interleave3;
|
||||
/// use cs220::assignments::assignment09::small_exercises::*;
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// interleave3([1, 2].into_iter(), [3, 4].into_iter(), [5, 6].into_iter()),
|
||||
@@ -61,7 +64,7 @@ pub fn interleave3<T>(
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use cs220::assignments::assignment09::interleave_n;
|
||||
/// use cs220::assignments::assignment09::small_exercises::*;
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// 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
|
||||
///
|
||||
/// ```
|
||||
/// use cs220::assignments::assignment09::k_smallest_mean;
|
||||
/// use cs220::assignments::assignment09::small_exercises::*;
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// 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.
|
||||
///
|
||||
/// # Exmaple
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use cs220::assignments::assignment09::calculate_mean;
|
||||
/// use cs220::assignments::assignment09::small_exercises::*;
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// 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].
|
||||
///
|
||||
/// ```
|
||||
/// 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]], 4), 2);
|
||||
@@ -147,12 +150,13 @@ pub fn sum_is_n(inner: Vec<Vec<i64>>, n: i64) -> usize {
|
||||
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
|
||||
///
|
||||
/// ```
|
||||
/// 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, 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 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, 3]), Some(1));
|
||||
@@ -191,6 +195,8 @@ pub fn position_median<T: Ord>(inner: Vec<T>) -> Option<usize> {
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use cs220::assignments::assignment09::small_exercises::*;
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// two_dimensional_sum([[1, 2, 3].into_iter(), [4, 5, 6].into_iter()].into_iter()),
|
||||
/// 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.
|
||||
///
|
||||
/// A palindrome is a word, number, phrase, or other sequence of characters which reads the same backward as forward.
|
||||
/// We consider the empty string is palindrome.
|
||||
/// A palindrome is a word, number, phrase, or other sequence of characters which reads the same
|
||||
/// backward as forward.
|
||||
///
|
||||
/// We consider the empty string as a palindrome.
|
||||
///
|
||||
/// Consult <https://en.wikipedia.org/wiki/Palindrome>.
|
||||
pub fn is_palindrome(s: String) -> bool {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
//! 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>
|
||||
//!
|
||||
//! 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
|
||||
//! solution works well.
|
||||
//! even if you have implemented the solution. We recommend running multiple times (at least 5
|
||||
//! times) to check your solution works well.
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
@@ -26,8 +26,8 @@ impl Husband {
|
||||
Strategy { husband: self }
|
||||
}
|
||||
|
||||
/// Based on the information about currently visited room number and someone's wife ID trapped inside,
|
||||
/// what the husband should do next?
|
||||
/// Based on the information about currently visited room number and someone's wife ID trapped
|
||||
/// inside, what the husband should do next?
|
||||
pub fn carefully_checks_whos_inside(&self, room: usize, wife: usize) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
|
||||
@@ -38,12 +39,13 @@ mod test {
|
||||
|
||||
(0..WIVES).all(|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());
|
||||
|
||||
#[allow(clippy::all)]
|
||||
/* The Minotaur🐂 will arrive in */
|
||||
(0..50) /* steps... */
|
||||
// (Allow for better storytelling.)
|
||||
#[allow(clippy::search_is_some)]
|
||||
// The Minotaur🐂 will arrive in
|
||||
(0..50) // steps...
|
||||
.zip(strategy)
|
||||
.find(|(_, room)| {
|
||||
// The husband contemplates his next move... 🤔
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//! Assignment 10: Iterators (2/2).
|
||||
//! 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.
|
||||
//! See `assignment10/*_grade.rs` and `/scripts/grade.sh 10` for the test script.
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 10` works
|
||||
//! fine. See `assignment10/*_grade.rs` and `/scripts/grade.sh 10` for the test script.
|
||||
//!
|
||||
//! To submit, run
|
||||
//! ```bash
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
//! Small exercises.
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use itertools::*;
|
||||
|
||||
/// 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 < 3`, `inner[0] = 3 > 2 = inner[3]`
|
||||
@@ -108,7 +111,8 @@ pub enum File {
|
||||
/// |__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)> {
|
||||
todo!()
|
||||
}
|
||||
@@ -118,12 +122,11 @@ pub fn du_sort(root: &File) -> Vec<(&str, usize)> {
|
||||
/// of returning a new vector.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// ```ignore
|
||||
/// let mut vec = vec![1, 2, 3, 4, 5];
|
||||
/// remove_even(&mut vec);
|
||||
/// assert_eq!(*vec, vec![1, 3, 5]);
|
||||
/// ```
|
||||
#[allow(clippy::ptr_arg)]
|
||||
pub fn remove_even(inner: &mut Vec<i64>) {
|
||||
todo!()
|
||||
}
|
||||
@@ -135,12 +138,11 @@ pub fn remove_even(inner: &mut Vec<i64>) {
|
||||
/// Also, note that the order does not matter.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// ```ignore
|
||||
/// let mut vec = vec![1, 2, 1, 1, 3, 7, 5, 7];
|
||||
/// remove_duplicate(&mut vec);
|
||||
/// assert_eq!(*vec, vec![1, 2, 3, 7, 5]);
|
||||
/// ```
|
||||
#[allow(clippy::ptr_arg)]
|
||||
pub fn remove_duplicate(inner: &mut Vec<i64>) {
|
||||
todo!()
|
||||
}
|
||||
@@ -153,6 +155,7 @@ pub fn remove_duplicate(inner: &mut Vec<i64>) {
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```text
|
||||
/// table1 table2
|
||||
/// ---------------------- ----------------------
|
||||
/// 20230001 | Jack 20230001 | CS
|
||||
@@ -165,11 +168,12 @@ pub fn remove_duplicate(inner: &mut Vec<i64>) {
|
||||
/// 20230001 | Jack | CS
|
||||
/// 20230001 | Jack | EE
|
||||
/// 20231234 | Mike | ME
|
||||
///
|
||||
/// ```
|
||||
pub fn natural_join(table1: Vec<Vec<String>>, table2: Vec<Vec<String>>) -> Vec<Vec<String>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// You can freely add more fields.
|
||||
struct 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),
|
||||
/// 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)> {
|
||||
Pythagorean::new()
|
||||
}
|
||||
|
||||
@@ -322,17 +322,11 @@ mod test {
|
||||
(68, 285, 293),
|
||||
];
|
||||
|
||||
let mut pythagorean_iter = pythagorean();
|
||||
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);
|
||||
|
||||
for (i, (a, b, c)) in pythagorean().enumerate().take(1000) {
|
||||
if i < pythagoreans.len() {
|
||||
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.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
enum VisitStatus {
|
||||
Unvisited,
|
||||
@@ -20,11 +24,12 @@ enum VisitStatus {
|
||||
}
|
||||
|
||||
/// Handle to a graph node.
|
||||
///
|
||||
/// `NodeHandle` should implement `Clone`, which clones the handle without cloning the underlying
|
||||
/// 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.
|
||||
///
|
||||
/// TODO: You can freely add fields to this struct.
|
||||
/// You can freely add fields to this struct.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NodeHandle;
|
||||
|
||||
@@ -34,7 +39,7 @@ pub struct GraphError;
|
||||
|
||||
/// Subgraph
|
||||
///
|
||||
/// TODO: You can freely add fields to this struct.
|
||||
/// You can freely add fields to this struct.
|
||||
#[derive(Debug)]
|
||||
pub struct SubGraph;
|
||||
|
||||
@@ -45,23 +50,24 @@ impl NodeHandle {
|
||||
}
|
||||
|
||||
/// Adds an edge to `to`.
|
||||
/// If the modification cannot be done, e.g. because of aliasing issues, returns `Err(GraphError)`.
|
||||
/// Returns `Ok(true)` if the edge is successfully added.
|
||||
/// If the modification cannot be done, e.g. because of aliasing issues, returns
|
||||
/// `Err(GraphError)`. Returns `Ok(true)` if the edge is successfully added.
|
||||
/// Returns `Ok(false)` if an edge to `to` already exits.
|
||||
pub fn add_edge(&self, to: NodeHandle) -> Result<bool, GraphError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Removes the edge to `to`.
|
||||
/// If the modification cannot be done, e.g. because of aliasing issues, returns `Err(GraphError)`.
|
||||
/// Returns `Ok(true)` if the edge is successfully removed.
|
||||
/// If the modification cannot be done, e.g. because of aliasing issues, returns
|
||||
/// `Err(GraphError)`. Returns `Ok(true)` if the edge is successfully removed.
|
||||
/// Returns `Ok(false)` if an edge to `to` does not exist.
|
||||
pub fn remove_edge(&self, to: &NodeHandle) -> Result<bool, GraphError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
todo!()
|
||||
}
|
||||
@@ -84,7 +90,7 @@ impl SubGraph {
|
||||
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 {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! 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:
|
||||
//!
|
||||
@@ -9,8 +10,9 @@
|
||||
//! - Manager can leave the TV room earlier than guests.
|
||||
//! - 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
|
||||
//! the TV room. When the 'Manager' and 'Guest' object is dropped, it means that the person leaves the TV room.
|
||||
//! Both `Manager` and `Guest` have `Rc<Watcher>` as a field, and its reference count indicates the
|
||||
//! 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:
|
||||
//! - <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.
|
||||
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum TVRoomState {
|
||||
|
||||
@@ -8,10 +8,8 @@
|
||||
//!
|
||||
//! Have fun!
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
/// Color represents the color of the card.
|
||||
/// The color of a card can be either Blue or White.
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_card {
|
||||
use crate::assignments::assignment12::card::*;
|
||||
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::assignments::assignment12::card::*;
|
||||
|
||||
const NUM_CARDS: usize = 10000;
|
||||
const DURATION: u64 = 20;
|
||||
const NUM_ENEMIES: usize = 25;
|
||||
@@ -60,7 +60,7 @@ mod test_card {
|
||||
fn play() {
|
||||
let ground = Ground::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));
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! Demultiplexing sender
|
||||
//!
|
||||
//! Implement demultiplexing sender
|
||||
//! Implement a demultiplexing sender.
|
||||
//!
|
||||
//! 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 is used when a circuit wishes to send a signal to one of many devices.
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_demux {
|
||||
use crate::assignments::assignment12::demux::*;
|
||||
use ntest::timeout;
|
||||
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread;
|
||||
|
||||
use ntest::timeout;
|
||||
|
||||
use crate::assignments::assignment12::demux::*;
|
||||
|
||||
#[test]
|
||||
#[timeout(5000)]
|
||||
fn test_demux() {
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
//! 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::Arc;
|
||||
use std::thread;
|
||||
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<()>
|
||||
where
|
||||
T: Send + 'static,
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_funnel {
|
||||
use crate::assignments::assignment12::funnel::*;
|
||||
use ntest::timeout;
|
||||
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread;
|
||||
|
||||
use ntest::timeout;
|
||||
|
||||
use crate::assignments::assignment12::funnel::*;
|
||||
|
||||
#[test]
|
||||
#[timeout(5000)]
|
||||
fn test_funnel_concurrent() {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
//!
|
||||
//! 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.
|
||||
//! See `assignment12/*_grade.rs` and `/scripts/grade.sh 12` for the test script.
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 12` works
|
||||
//! fine. See `assignment12/*_grade.rs` and `/scripts/grade.sh 12` for the test script.
|
||||
//!
|
||||
//! To submit, run
|
||||
//! ```bash
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#![allow(single_use_lifetimes)]
|
||||
|
||||
//! Small exercises
|
||||
//!
|
||||
//! Refer `small_exercises_grade.rs` for test cases
|
||||
@@ -12,16 +10,18 @@ use etrace::*;
|
||||
/// The "pong" function
|
||||
///
|
||||
/// 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 {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub fn use_scoped_thread<'scope, 'env, T1, T2, F1, F2>(
|
||||
s: &'scope thread::Scope<'scope, 'env>,
|
||||
/// Read the `test_scoped_thread` function in `small_exercises_grade.rs` to figure out what it
|
||||
/// should do.
|
||||
pub fn use_scoped_thread<'scope, T1, T2, F1, F2>(
|
||||
s: &'scope thread::Scope<'scope, '_>,
|
||||
f1: F1,
|
||||
f2: F2,
|
||||
) -> (T1, T2)
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_pingpong {
|
||||
use crate::assignments::assignment12::small_exercises::*;
|
||||
use ntest::timeout;
|
||||
|
||||
use std::sync::mpsc::channel;
|
||||
use std::thread;
|
||||
|
||||
use ntest::timeout;
|
||||
|
||||
use crate::assignments::assignment12::small_exercises::*;
|
||||
|
||||
#[test]
|
||||
fn test_ping_pong() {
|
||||
let (tx1, mut rx1) = channel();
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
//!
|
||||
//! The primary goal of this assignment is to get used to data parallelism.
|
||||
//!
|
||||
//! Refer to your solution for assignment 09. You will implement the parallelized version of assignment 09.
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade.sh 13` works fine.
|
||||
//! See `assignment13/small_exercises_grade.rs` and `/scripts/grade.sh 13` for the test script.
|
||||
//! Refer to your solution for assignment 09. You will implement the parallelized version of
|
||||
//! assignment 09. You should fill out the `todo!()` placeholders in such a way that
|
||||
//! `/scripts/grade.sh 13` works fine. See `assignment13/small_exercises_grade.rs` and
|
||||
//! `/scripts/grade.sh 13` for the test script.
|
||||
//!
|
||||
//! To submit, run
|
||||
//! ```bash
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
//! Assignment 13: Parallelism.
|
||||
//!
|
||||
//! If you did well on assignment 09, you will do well on this assignment.
|
||||
//! Take it easy!
|
||||
//! If you did well on assignment 09, you will do well on this assignment. Take it easy!
|
||||
|
||||
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.
|
||||
///
|
||||
/// # Exmaple
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use cs220::assignments::assignment13::sigma;
|
||||
/// use cs220::assignments::assignment13::small_exercises::*;
|
||||
/// use rayon::iter::IntoParallelIterator;
|
||||
///
|
||||
/// 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
|
||||
///
|
||||
/// ```
|
||||
/// use cs220::assignments::assignment13::interleave3;
|
||||
/// use cs220::assignments::assignment13::small_exercises::*;
|
||||
/// use rayon::iter::IntoParallelIterator;
|
||||
///
|
||||
/// assert_eq!(
|
||||
@@ -49,10 +45,10 @@ pub fn interleave3_par<T: Send>(
|
||||
|
||||
/// 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 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?
|
||||
/// 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 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)
|
||||
/// - 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 mat2 = vec![
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::assignments::assignment09::matmul::*;
|
||||
use crate::assignments::assignment13::small_exercises::*;
|
||||
use std::hint;
|
||||
use std::time::Instant;
|
||||
|
||||
use approx::*;
|
||||
use itertools::Itertools;
|
||||
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 std::time::Instant;
|
||||
|
||||
use crate::assignments::assignment09::matmul::*;
|
||||
use crate::assignments::assignment13::small_exercises::*;
|
||||
|
||||
#[test]
|
||||
fn test_sigma_par() {
|
||||
@@ -72,72 +76,66 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vec_add_correctness() {
|
||||
// small test
|
||||
fn vec_add_test() {
|
||||
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 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]);
|
||||
|
||||
// random test
|
||||
let vec1 = Array::random(1000, Uniform::new(0., 10.));
|
||||
let vec2 = Array::random(1000, 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.));
|
||||
for _ in 0..5 {
|
||||
let vec1 = hint::black_box(Array::random(5_000_000, Uniform::new(0., 10.)));
|
||||
let vec2 = hint::black_box(Array::random(5_000_000, Uniform::new(0., 10.)));
|
||||
|
||||
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 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 ans = vec1 + vec2;
|
||||
assert_eq!(Array::from_vec(res_seq), ans);
|
||||
assert_eq!(Array::from_vec(res_par), ans);
|
||||
assert!(elapsed_par < elapsed_seq);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dot_product_correctness() {
|
||||
// small test
|
||||
fn dot_product_test() {
|
||||
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 res_seq = dot_product(&vec1, &vec2);
|
||||
let res_par = dot_product_par(&vec1, &vec2);
|
||||
assert_eq!(res_seq, 55.0);
|
||||
assert_eq!(res_par, 55.0);
|
||||
|
||||
// random test
|
||||
let vec1 = Array::random(1000, Uniform::new(0., 10.));
|
||||
let vec2 = Array::random(1000, 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.));
|
||||
for _ in 0..5 {
|
||||
let vec1 = Array::random(500_000, Uniform::new(0., 10.));
|
||||
let vec2 = Array::random(500_000, Uniform::new(0., 10.));
|
||||
|
||||
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 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 _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);
|
||||
}
|
||||
}
|
||||
@@ -163,8 +161,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn matmul_correctness() {
|
||||
// small case
|
||||
fn matmul_test() {
|
||||
let mat1 = vec![vec![1.0, 2.0, 3.0], vec![4.0, 5.0, 6.0]];
|
||||
let mat2 = vec![
|
||||
vec![7.0, 8.0, 9.0],
|
||||
@@ -176,72 +173,68 @@ mod test {
|
||||
vec![50.0, 68.0, 86.0, 104.0],
|
||||
vec![122.0, 167.0, 212.0, 257.0],
|
||||
];
|
||||
let res_seq = matmul(&mat1, &mat2);
|
||||
let res_par = matmul_par(&mat1, &mat2);
|
||||
assert_eq!(ans, res_seq);
|
||||
assert_eq!(ans, res_par);
|
||||
|
||||
let mat1 = Array::random((10, 10), Uniform::new(0., 10.));
|
||||
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 {
|
||||
for _ in 0..5 {
|
||||
let mat1 = 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();
|
||||
|
||||
// Run sequential matrix multiplication
|
||||
let now_seq = Instant::now();
|
||||
let res_seq = matmul(
|
||||
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 res_seq = hint::black_box(matmul(
|
||||
hint::black_box(
|
||||
mat1.axis_iter(Axis(0))
|
||||
.map(|row| row.to_vec())
|
||||
.collect::<Vec<_>>()
|
||||
.as_slice(),
|
||||
),
|
||||
hint::black_box(
|
||||
mat2_transposed
|
||||
.axis_iter(Axis(0))
|
||||
.map(|row| row.to_vec())
|
||||
.collect::<Vec<_>>()
|
||||
.as_slice(),
|
||||
),
|
||||
));
|
||||
let elapsed_seq = now_seq.elapsed();
|
||||
|
||||
// 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 res_par = hint::black_box(matmul_par(
|
||||
hint::black_box(
|
||||
mat1.axis_iter(Axis(0))
|
||||
.map(|row| row.to_vec())
|
||||
.collect::<Vec<_>>()
|
||||
.as_slice(),
|
||||
),
|
||||
hint::black_box(
|
||||
mat2_transposed
|
||||
.axis_iter(Axis(0))
|
||||
.map(|row| row.to_vec())
|
||||
.collect::<Vec<_>>()
|
||||
.as_slice(),
|
||||
),
|
||||
));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ use std::io::{self, BufRead, Read};
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
|
||||
use cs220::assignments::assignment04::*;
|
||||
|
||||
struct Input<'a> {
|
||||
|
||||
76
src/lib.rs
76
src/lib.rs
@@ -1,31 +1,57 @@
|
||||
//! 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(rustdoc::invalid_html_tags)]
|
||||
// #![deny(rustdoc::missing_doc_code_examples)]
|
||||
#![deny(missing_docs)]
|
||||
#![deny(rustdoc::all)]
|
||||
#![deny(unreachable_pub)]
|
||||
#![deny(single_use_lifetimes)]
|
||||
#![deny(unused_lifetimes)]
|
||||
#![deny(unstable_features)]
|
||||
// # Tries to deny all lints (`rustc -W help`).
|
||||
#![deny(
|
||||
absolute_paths_not_starting_with_crate,
|
||||
// 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;
|
||||
|
||||
Reference in New Issue
Block a user