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

2
.gitignore vendored
View File

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

10
Cargo.lock generated
View File

@@ -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"

View File

@@ -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"

View File

@@ -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 (?%)

View File

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

View File

@@ -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;

View File

@@ -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

View File

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

View File

@@ -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));;

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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!()
}

View File

@@ -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
}
}

View File

@@ -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!(

View File

@@ -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>,

View File

@@ -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() {

View File

@@ -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

View File

@@ -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']

View File

@@ -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.
///

View File

@@ -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
///

View File

@@ -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

View File

@@ -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")
}

View File

@@ -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

View File

@@ -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`.

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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();

View File

@@ -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

View File

@@ -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)>,

View File

@@ -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,

View File

@@ -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);

View File

@@ -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

View File

@@ -15,7 +15,8 @@ pub fn repeat<T, F: FnMut(T) -> T>(n: usize, mut f: F) -> impl FnMut(T) -> T {
///
/// Applies the given function `f` for `i` times for the `i`-th element of the given vector.
///
/// 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

View File

@@ -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!()

View File

@@ -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]

View File

@@ -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![

View File

@@ -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() {

View File

@@ -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

View File

@@ -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 {

View File

@@ -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!()
}

View File

@@ -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... 🤔

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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);
}
}
}

View File

@@ -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!()
}

View File

@@ -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 {

View File

@@ -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.

View File

@@ -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));

View File

@@ -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.

View File

@@ -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() {

View File

@@ -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,

View File

@@ -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() {

View File

@@ -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

View File

@@ -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)

View File

@@ -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();

View File

@@ -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

View File

@@ -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![

View File

@@ -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);
}
}

View File

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

View File

@@ -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;

View File