diff --git a/scripts/grade-06.sh b/scripts/grade-06.sh new file mode 100755 index 0000000..02ab6f0 --- /dev/null +++ b/scripts/grade-06.sh @@ -0,0 +1,34 @@ +#!/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. +cargo fmt --check +cargo clippy + +# Executes test for each runner. +for RUNNER in "${RUNNERS[@]}"; do + echo "Running with $RUNNER..." + + TESTS=("--lib assignment06_grade") + if [ $(run_tests) -ne 0 ]; then + exit 1 + fi +done + +exit 0 diff --git a/src/assignments/assignment06.rs b/src/assignments/assignment06.rs new file mode 100644 index 0000000..4fe740b --- /dev/null +++ b/src/assignments/assignment06.rs @@ -0,0 +1,153 @@ +//! Assignment 6: Mastering advanced types. +//! +//! 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-06.sh` works fine. +//! See `assignment06_grade.rs` and `/scripts/grade-06.sh` for the test script. + +use std::{collections::HashMap, fmt::Debug}; + +/// Semiring. +/// +/// Consult . +pub trait Semiring: Debug + Clone + PartialEq { + /// Additive identity. + fn zero() -> Self; + /// Multiplicative identity. + fn one() -> Self; + /// Addition operation. + fn add(&self, rhs: &Self) -> Self; + /// Multiplication operation. + fn mul(&self, rhs: &Self) -> Self; +} + +/// Converts integer to semiring value. +pub fn from_usize(value: usize) -> T { + let mut result = T::zero(); + let one = T::one(); + + for _ in 0..value { + result = T::add(&result, &one); + } + + result +} + +impl Semiring for u64 { + fn zero() -> Self { + todo!() + } + + fn one() -> Self { + todo!() + } + + fn add(&self, rhs: &Self) -> Self { + todo!() + } + + fn mul(&self, rhs: &Self) -> Self { + todo!() + } +} + +impl Semiring for i64 { + fn zero() -> Self { + todo!() + } + + fn one() -> Self { + todo!() + } + + fn add(&self, rhs: &Self) -> Self { + todo!() + } + + fn mul(&self, rhs: &Self) -> Self { + todo!() + } +} + +impl Semiring for f64 { + fn zero() -> Self { + todo!() + } + + fn one() -> Self { + todo!() + } + + fn add(&self, rhs: &Self) -> Self { + todo!() + } + + fn mul(&self, rhs: &Self) -> Self { + todo!() + } +} + +/// Polynomials with coefficient in `C`. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Polynomial { + coefficients: HashMap, +} + +impl Semiring for Polynomial { + fn zero() -> Self { + todo!() + } + + fn one() -> Self { + todo!() + } + + fn add(&self, rhs: &Self) -> Self { + todo!() + } + + fn mul(&self, rhs: &Self) -> Self { + todo!() + } +} + +impl From for Polynomial { + fn from(value: C) -> Self { + todo!() + } +} + +impl Polynomial { + /// The variable X. + pub fn x() -> Self { + todo!() + } + + /// Evaluates the polynomial with the given value. + pub fn eval(&self, value: C) -> C { + todo!() + } +} + +struct FindIter<'s, T: Eq> { + query: &'s [T], + base: &'s [T], + curr: usize, +} + +impl Iterator for FindIter<'_, T> { + type Item = usize; + + fn next(&mut self) -> Option { + todo!() + } +} + +/// Returns an iterator over substring query indexes in the base. +pub fn find<'s, T: Eq>(query: &'s [T], base: &'s [T]) -> impl 's + Iterator { + FindIter { + query, + base, + curr: 0, + } +} diff --git a/src/assignments/assignment06_grade.rs b/src/assignments/assignment06_grade.rs new file mode 100644 index 0000000..3f9cbae --- /dev/null +++ b/src/assignments/assignment06_grade.rs @@ -0,0 +1,114 @@ +#[cfg(test)] +mod test { + use super::super::assignment06::*; + + fn test_polynomial() { + // x^2 + 5x + 6 + let poly = Polynomial::add( + &Polynomial::add( + &Polynomial::mul( + &Polynomial::from(from_usize::(1)), + &Polynomial::mul(&Polynomial::x(), &Polynomial::x()), + ), + &Polynomial::mul(&Polynomial::from(from_usize::(5)), &Polynomial::x()), + ), + &Polynomial::from(from_usize::(6)), + ); + + // 13^2 + 5*13 + 6 + let value = poly.eval(from_usize(13)); + + assert_eq!(value, from_usize(13 * 13 + 5 * 13 + 6)); + } + + #[test] + fn test_polynomial_u64() { + test_polynomial::(); + } + + #[test] + fn test_polynomial_f64() { + test_polynomial::(); + } + + #[test] + fn test_polynomial_p_u64() { + test_polynomial::>(); + } + + #[test] + fn test_polynomial_xy() { + // (x+1)(y+2) + let poly: Polynomial> = Polynomial::mul( + &Polynomial::from(Polynomial::add( + &Polynomial::x(), + &Polynomial::from(from_usize::(1)), + )), + &(Polynomial::add( + &Polynomial::x(), + &Polynomial::from(Polynomial::from(from_usize::(2))), + )), + ); + + // poly with y = x+3 + let value = poly.eval(Polynomial::add( + &Polynomial::x(), + &Polynomial::from(from_usize::(3)), + )); + + // x^2 + 6x + 5 + let expected = Polynomial::add( + &Polynomial::add( + &Polynomial::mul( + &Polynomial::from(from_usize::(1)), + &Polynomial::mul(&Polynomial::x(), &Polynomial::x()), + ), + &Polynomial::mul(&Polynomial::from(from_usize::(6)), &Polynomial::x()), + ), + &Polynomial::from(from_usize::(5)), + ); + + assert_eq!(value, expected); + } + + #[test] + fn test_zero_remove() { + // (x-1)(x+1) + let poly: Polynomial = Polynomial::mul( + &Polynomial::add(&Polynomial::x(), &Polynomial::from(-1)), + &Polynomial::add(&Polynomial::x(), &Polynomial::from(1)), + ); + + // (x-1)(x+1) == x^2 - 1 + assert_eq!( + poly, + Polynomial::add( + &Polynomial::mul(&Polynomial::x(), &Polynomial::x()), + &Polynomial::from(-1) + ) + ); + } + + #[test] + fn test_find() { + assert_eq!( + find("abc".as_bytes(), "abcdabcd".as_bytes()).collect::>(), + vec![0, 4] + ); + + assert_eq!( + find("aaba".as_bytes(), "aabaacaadaabaaba".as_bytes()).collect::>(), + vec![0, 9, 12] + ); + + assert_eq!( + find("ababac".as_bytes(), "abababcabababcabababc".as_bytes()).collect::>(), + vec![] + ); + + assert_eq!( + find("ababc".as_bytes(), "abc".as_bytes()).collect::>(), + vec![] + ); + } +} diff --git a/src/assignments/mod.rs b/src/assignments/mod.rs index 79c93f5..e2c01b7 100644 --- a/src/assignments/mod.rs +++ b/src/assignments/mod.rs @@ -11,3 +11,5 @@ pub mod assignment03; mod assignment03_grade; pub mod assignment04; mod assignment04_grade; +pub mod assignment06; +mod assignment06_grade;