From 871110175be04142faac6c6ef7c05354e796cab3 Mon Sep 17 00:00:00 2001 From: Minseong Jang Date: Thu, 20 Oct 2022 09:30:00 +0900 Subject: [PATCH] Add assignment 8 --- scripts/grade-08.sh | 33 ++++++++++++++++++ src/assignments/assignment08.rs | 48 +++++++++++++++++++++++++++ src/assignments/assignment08_grade.rs | 30 +++++++++++++++++ src/assignments/mod.rs | 2 ++ 4 files changed, 113 insertions(+) create mode 100755 scripts/grade-08.sh create mode 100644 src/assignments/assignment08.rs create mode 100644 src/assignments/assignment08_grade.rs diff --git a/scripts/grade-08.sh b/scripts/grade-08.sh new file mode 100755 index 0000000..99b7b27 --- /dev/null +++ b/scripts/grade-08.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 assignment08_grade") + if [ $(run_tests) -ne 0 ]; then + exit 1 + fi +done + +exit 0 diff --git a/src/assignments/assignment08.rs b/src/assignments/assignment08.rs new file mode 100644 index 0000000..05a3cdd --- /dev/null +++ b/src/assignments/assignment08.rs @@ -0,0 +1,48 @@ +//! Assignment 8: First-class functions. +//! +//! The primary goal of this assignment is to get used to first-class functions. +//! +//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-08.sh` works fine. +//! See `assignment08_grade.rs` and `/scripts/grade-08.sh` for the test script. + +/// Returns an anonymous function that applies the given function `f` for `n` times. +/// +/// For instance, `repeat(3, f)(x)` roughly translates to `f(f(f(x)))`. +pub fn repeat T>(n: usize, mut f: F) -> impl FnMut(T) -> T { + todo!() +} + +/// 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)))]`. +pub fn funny_map T>(f: F, vs: Vec) -> Vec { + todo!() +} + +/// Either `T1`, or `T2`. +#[derive(Debug, PartialEq, Eq)] +pub enum Either2 { + /// Case 1. + Case1 { + /// The inner value. + inner: T1, + }, + /// Case 1. + Case2 { + /// The inner value. + inner: T2, + }, +} + +impl Either2 { + /// Maps the inner value. + /// + /// If the inner value is case 1, apply `f1`, and if it is case 2, apply `f2`. + pub fn map(self, f1: F1, f2: F2) -> Either2 + where + F1: FnOnce(T1) -> U1, + F2: FnOnce(T2) -> U2, + { + todo!() + } +} diff --git a/src/assignments/assignment08_grade.rs b/src/assignments/assignment08_grade.rs new file mode 100644 index 0000000..e6299ed --- /dev/null +++ b/src/assignments/assignment08_grade.rs @@ -0,0 +1,30 @@ +#[cfg(test)] +mod test { + use super::super::assignment08::*; + + #[test] + fn test_repeat() { + for i in 0..10 { + assert_eq!(42 + 2 * i, repeat(i, |x| x + 2)(42)); + } + } + + #[test] + fn test_funny_map() { + assert_eq!( + vec![0, 3, 6, 9, 12], + funny_map(|x| x + 2, vec![0, 1, 2, 3, 4]) + ); + } + + #[test] + fn test_either2_map() { + let v1 = Either2::::Case1 { inner: 42 }; + let u1 = Either2::::Case1 { inner: 43 }; + assert_eq!(u1, v1.map(|i| i + 1, |f| f + 1.0)); + + let v2 = Either2::::Case2 { inner: 42.0 }; + let u2 = Either2::::Case2 { inner: 43.0 }; + assert_eq!(u2, v2.map(|i| i + 1, |f| f + 1.0)); + } +} diff --git a/src/assignments/mod.rs b/src/assignments/mod.rs index 5a663d6..0aeb881 100644 --- a/src/assignments/mod.rs +++ b/src/assignments/mod.rs @@ -15,3 +15,5 @@ pub mod assignment06; mod assignment06_grade; pub mod assignment07; mod assignment07_grade; +pub mod assignment08; +mod assignment08_grade;