diff --git a/scripts/grade-12.sh b/scripts/grade-12.sh new file mode 100755 index 0000000..6a87f98 --- /dev/null +++ b/scripts/grade-12.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +set -e +set -uo pipefail +IFS=$'\n\t' + +# Imports library. +BASEDIR=$(dirname "$0") +source $BASEDIR/grade-utils.sh + +RUNNERS=( + "cargo" + "cargo --release" + "cargo_asan" + "cargo_asan --release" + "cargo_tsan" + "cargo_tsan --release" +) + +# Lints. +run_linters || exit 1 + +# Executes test for each runner. +for RUNNER in "${RUNNERS[@]}"; do + echo "Running with $RUNNER..." + + TESTS=("--lib assignment12_grade") + if [ $(run_tests) -ne 0 ]; then + exit 1 + fi +done + +exit 0 diff --git a/scripts/grade-13.sh b/scripts/grade-13.sh new file mode 100755 index 0000000..6c180d4 --- /dev/null +++ b/scripts/grade-13.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +set -e +set -uo pipefail +IFS=$'\n\t' + +# Imports library. +BASEDIR=$(dirname "$0") +source $BASEDIR/grade-utils.sh + +RUNNERS=( + "cargo" + "cargo --release" + "cargo_asan" + "cargo_asan --release" + "cargo_tsan" + "cargo_tsan --release" +) + +# Lints. +run_linters || exit 1 + +# Executes test for each runner. +for RUNNER in "${RUNNERS[@]}"; do + echo "Running with $RUNNER..." + + TESTS=("--lib assignment13_grade") + if [ $(run_tests) -ne 0 ]; then + exit 1 + fi +done + +exit 0 diff --git a/src/assignments/assignment03.rs b/src/assignments/assignment03.rs index f30136a..f51b26c 100644 --- a/src/assignments/assignment03.rs +++ b/src/assignments/assignment03.rs @@ -50,6 +50,8 @@ pub enum MyOption { /// Converts an `MyOption` into an `MyOption`, consuming the original: /// /// ``` +/// use cs220::assignments::assignment03::{my_map, MyOption}; +/// /// fn len(s: String) -> usize { /// s.len() /// } @@ -68,6 +70,8 @@ pub fn my_map U>(v: MyOption, f: F) -> MyOption { /// # Examples /// /// ``` +/// use cs220::assignments::assignment03::{MyOption, my_and_then}; +/// /// fn pos_then_to_string(x: isize) -> MyOption { /// if x > 0 { /// MyOption::MySome(x.to_string()) @@ -93,13 +97,13 @@ pub fn my_and_then MyOption>(v: MyOption, f: F) -> M /// /// For example, the following list of seven numbers, /// -/// ``` +/// ```ignore /// vec![1, 3, 3, 6, 7, 8, 9] /// ``` /// /// has the median of 6, which is the fourth value. And for this data set of eight numbers, /// -/// ``` +/// ```ignore /// vec![1, 2, 3, 4, 5, 6, 8, 9] /// ``` /// @@ -142,13 +146,13 @@ pub fn piglatin(input: String) -> String { /// /// If the commands are as follows: /// -/// ``` +/// ```ignore /// vec!["Add Amir to Engineering", "Add Sally to Sales", "Remove Jeehoon from Sales", "Move Amir from Engineering to Sales"] /// ``` /// /// The return value should be: /// -/// ``` +/// ```ignore /// ["Sales" -> ["Amir", "Sally"]] /// ``` /// diff --git a/src/assignments/assignment06.rs b/src/assignments/assignment06.rs index 56a8168..e9a9646 100644 --- a/src/assignments/assignment06.rs +++ b/src/assignments/assignment06.rs @@ -91,7 +91,7 @@ impl Semiring for f64 { /// /// For example, polynomial `x^2 + 5x + 6` is represented in `Polynomial` as follows: /// -/// ``` +/// ```ignore /// Polynomial { /// coefficients: { /// 2: 1, diff --git a/src/assignments/assignment09.rs b/src/assignments/assignment09.rs index 2e31ab7..38dec0e 100644 --- a/src/assignments/assignment09.rs +++ b/src/assignments/assignment09.rs @@ -16,6 +16,8 @@ use itertools::*; /// # Exmample /// /// ``` +/// use cs220::assignments::assignment09::is_fibonacci; +/// /// 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); /// ``` @@ -28,6 +30,8 @@ pub fn is_fibonacci(inner: impl Iterator) -> bool { /// # Exmaple /// /// ``` +/// use cs220::assignments::assignment09::sigma; +/// /// assert_eq!(sigma([1, 2].into_iter(), |x| x + 2), 7); /// assert_eq!(sigma([1, 2].into_iter(), |x| x * 4), 12); /// ``` @@ -42,6 +46,8 @@ pub fn sigma i64>(inner: impl Iterator, f: F) -> i64 { /// # Example /// /// ``` +/// use cs220::assignments::assignment09::interleave3; +/// /// assert_eq!( /// interleave3([1, 2].into_iter(), [3, 4].into_iter(), [5, 6].into_iter()), /// vec![1, 3, 5, 2, 4, 6] @@ -60,6 +66,8 @@ pub fn interleave3( /// # Example /// /// ``` +/// use cs220::assignments::assignment09::k_smallest_mean; +/// /// assert_eq!( /// k_smallest_mean(vec![1, 3, 2].into_iter(), 2), /// ((1 + 2) as f64 / 2.0) @@ -78,6 +86,8 @@ pub fn k_smallest_mean(inner: impl Iterator, k: usize) -> f64 { /// # Exmaple /// /// ``` +/// use cs220::assignments::assignment09::calculate_mean; +/// /// assert_eq!( /// calculate_mean( /// [ @@ -111,6 +121,8 @@ pub fn calculate_mean(inner: impl Iterator) -> HashMap>, n: i64) -> usize { /// # Example /// /// ``` +/// use cs220::assignments::assignment09::find_count_n; +/// /// assert_eq!(find_count_n(vec![1, 2], 1), vec![1, 2]); /// assert_eq!(find_count_n(vec![1, 3, 3], 1), vec![1]); /// assert_eq!(find_count_n(vec![1, 3, 3], 2), vec![3]); @@ -150,6 +164,8 @@ pub fn find_count_n(inner: Vec, n: usize) -> Vec { /// # Exmaple /// /// ``` +/// use cs220::assignments::assignment09::position_median; +/// /// 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)); /// ``` diff --git a/src/assignments/assignment10.rs b/src/assignments/assignment10.rs index 37c8449..6a84161 100644 --- a/src/assignments/assignment10.rs +++ b/src/assignments/assignment10.rs @@ -47,7 +47,7 @@ pub enum Node { /// /// For example, the result of preorder traversal for the following tree /// -/// ``` +/// ```ignore /// 1 /// /|\ /// 2 3 4 @@ -57,7 +57,7 @@ pub enum Node { /// /// which can be represented as /// -/// ``` +/// ```ignore /// Node::NonLeaf(( /// 1, /// vec![ diff --git a/src/assignments/assignment12.rs b/src/assignments/assignment12.rs new file mode 100644 index 0000000..ec381ee --- /dev/null +++ b/src/assignments/assignment12.rs @@ -0,0 +1,33 @@ +#![allow(single_use_lifetimes)] + +//! Assignment 12: Concurrency. +//! +//! The primary goal of this assignment is to get used to concurrency. +//! +//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-12.sh` works fine. +//! See `assignment12_grade.rs` and `/scripts/grade-12.sh` for the test script. + +use std::sync::mpsc::{Receiver, RecvError, Sender}; +use std::thread; + +use etrace::*; + +/// The "pong" function (read the test script to figure out what it should do). +pub fn pong(rx1: &mut Receiver, tx2: &mut Sender) -> bool { + todo!() +} + +/// Executes the given functions (f1, f2) and returns the results. +pub fn use_scoped_thread<'scope, 'env, T1, T2, F1, F2>( + s: &'scope thread::Scope<'scope, 'env>, + f1: F1, + f2: F2, +) -> (T1, T2) +where + T1: Send + 'scope, + T2: Send + 'scope, + F1: Send + FnOnce() -> T1 + 'scope, + F2: Send + FnOnce() -> T2 + 'scope, +{ + todo!() +} diff --git a/src/assignments/assignment12_grade.rs b/src/assignments/assignment12_grade.rs new file mode 100644 index 0000000..332fe58 --- /dev/null +++ b/src/assignments/assignment12_grade.rs @@ -0,0 +1,44 @@ +#[cfg(test)] +mod test { + use super::super::assignment12::*; + + use std::sync::mpsc::channel; + use std::thread; + + #[test] + fn test_ping_pong() { + let (tx1, mut rx1) = channel(); + let (mut tx2, rx2) = channel(); + + let thread_ping = thread::spawn(move || { + for i in 0..100 { + tx1.send(i).unwrap(); + let x = rx2.recv().unwrap(); + assert_eq!(x, i + 1); + } + }); + + let thread_pong = thread::spawn(move || while pong(&mut rx1, &mut tx2) {}); + + thread_ping.join().unwrap(); + thread_pong.join().unwrap(); + } + + #[test] + fn test_scoped_thread() { + for i in 0..100 { + let v = (0..i).collect::>(); + + thread::scope(|s| { + let (r1, r2) = use_scoped_thread( + s, + || v.iter().sum::(), + || v.windows(2).map(|x| x[0] * x[1]).sum::(), + ); + + assert_eq!(r1, v.iter().sum()); + assert_eq!(r2, v.windows(2).map(|x| x[0] * x[1]).sum()); + }); + } + } +} diff --git a/src/assignments/assignment13.rs b/src/assignments/assignment13.rs new file mode 100644 index 0000000..bd91185 --- /dev/null +++ b/src/assignments/assignment13.rs @@ -0,0 +1,47 @@ +//! Assignment 13: Parallelism. +//! +//! The primary goal of this assignment is to get used to data parallelism. +//! +//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-13.sh` works fine. +//! See `assignment13_grade.rs` and `/scripts/grade-13.sh` for the test script. + +use rayon::prelude::*; + +/// Returns the sum of `f(v)` for all element `v` the given array. +/// +/// # Exmaple +/// +/// ``` +/// use cs220::assignments::assignment13::sigma; +/// use rayon::iter::IntoParallelIterator; +/// +/// assert_eq!(sigma([1, 2].into_par_iter(), |x| x + 2), 7); +/// assert_eq!(sigma([1, 2].into_par_iter(), |x| x * 4), 12); +/// ``` +pub fn sigma i64 + Sync + Send>( + inner: impl ParallelIterator, + f: F, +) -> i64 { + todo!() +} + +/// Alternate elements from three iterators until they have run out. +/// +/// # Example +/// +/// ``` +/// use cs220::assignments::assignment13::interleave3; +/// use rayon::iter::IntoParallelIterator; +/// +/// assert_eq!( +/// interleave3([1, 2].into_par_iter(), [3, 4].into_par_iter(), [5, 6].into_par_iter()), +/// vec![1, 3, 5, 2, 4, 6] +/// ); +/// ``` +pub fn interleave3( + list1: impl IndexedParallelIterator, + list2: impl IndexedParallelIterator, + list3: impl IndexedParallelIterator, +) -> Vec { + todo!() +} diff --git a/src/assignments/assignment13_grade.rs b/src/assignments/assignment13_grade.rs new file mode 100644 index 0000000..6f560c6 --- /dev/null +++ b/src/assignments/assignment13_grade.rs @@ -0,0 +1,67 @@ +#[cfg(test)] +mod test { + use super::super::assignment13::*; + use rayon::prelude::IntoParallelIterator; + + #[test] + fn test_sigma() { + assert_eq!(sigma([].into_par_iter(), |x: i64| x * 2), 0); + assert_eq!(sigma([1].into_par_iter(), |x| x * 3), 3); + assert_eq!(sigma([1, 2].into_par_iter(), |x| x + 2), 7); + assert_eq!(sigma([1, 2].into_par_iter(), |x| x * 4), 12); + assert_eq!(sigma([1, 2, 3].into_par_iter(), |x| x * 5), 30); + + assert_eq!( + sigma([-1.2, 3.0, 4.2, 5.8].into_par_iter(), |x: f64| x.floor() + as i64), + 10 + ); + assert_eq!( + sigma([-1.2, 3.0, 4.2, 5.8].into_par_iter(), |x: f64| x.ceil() + as i64), + 13 + ); + assert_eq!( + sigma([-1.2, 3.0, 4.2, 5.8].into_par_iter(), |x: f64| x.round() + as i64), + 12 + ); + + assert_eq!( + sigma(["Hello,", "World!"].into_par_iter(), |x| x.len() as i64), + 12 + ); + } + + #[test] + fn test_interleave3() { + assert_eq!( + interleave3( + [1, 2].into_par_iter(), + [3, 4].into_par_iter(), + [5, 6].into_par_iter() + ), + vec![1, 3, 5, 2, 4, 6] + ); + + assert_eq!( + interleave3( + [1, 2, 3].into_par_iter(), + [4, 5, 6].into_par_iter(), + [7, 8, 9].into_par_iter() + ), + vec![1, 4, 7, 2, 5, 8, 3, 6, 9] + ); + + assert_eq!( + interleave3( + ["a", "b", "c"].into_par_iter(), + ["d", "e", "f"].into_par_iter(), + ["g", "h", "i"].into_par_iter() + ) + .into_iter() + .collect::(), + "adgbehcfi" + ); + } +} diff --git a/src/assignments/mod.rs b/src/assignments/mod.rs index b69cbdb..74e67fe 100644 --- a/src/assignments/mod.rs +++ b/src/assignments/mod.rs @@ -26,3 +26,7 @@ pub mod assignment10; mod assignment10_grade; pub mod assignment11; mod assignment11_grade; +pub mod assignment12; +mod assignment12_grade; +pub mod assignment13; +mod assignment13_grade;