Add assignment 6

This commit is contained in:
Minseong Jang
2022-09-23 11:34:55 +09:00
parent 21c9c9ef02
commit 35aee8ecd4
4 changed files with 303 additions and 0 deletions

34
scripts/grade-06.sh Executable file
View File

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

View File

@@ -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 <https://en.wikipedia.org/wiki/Semiring>.
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<T: Semiring>(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<C: Semiring> {
coefficients: HashMap<u64, C>,
}
impl<C: Semiring> Semiring for Polynomial<C> {
fn zero() -> Self {
todo!()
}
fn one() -> Self {
todo!()
}
fn add(&self, rhs: &Self) -> Self {
todo!()
}
fn mul(&self, rhs: &Self) -> Self {
todo!()
}
}
impl<C: Semiring> From<C> for Polynomial<C> {
fn from(value: C) -> Self {
todo!()
}
}
impl<C: Semiring> Polynomial<C> {
/// 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<T: Eq> Iterator for FindIter<'_, T> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
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<Item = usize> {
FindIter {
query,
base,
curr: 0,
}
}

View File

@@ -0,0 +1,114 @@
#[cfg(test)]
mod test {
use super::super::assignment06::*;
fn test_polynomial<T: Semiring>() {
// x^2 + 5x + 6
let poly = Polynomial::add(
&Polynomial::add(
&Polynomial::mul(
&Polynomial::from(from_usize::<T>(1)),
&Polynomial::mul(&Polynomial::x(), &Polynomial::x()),
),
&Polynomial::mul(&Polynomial::from(from_usize::<T>(5)), &Polynomial::x()),
),
&Polynomial::from(from_usize::<T>(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::<u64>();
}
#[test]
fn test_polynomial_f64() {
test_polynomial::<f64>();
}
#[test]
fn test_polynomial_p_u64() {
test_polynomial::<Polynomial<u64>>();
}
#[test]
fn test_polynomial_xy() {
// (x+1)(y+2)
let poly: Polynomial<Polynomial<u64>> = Polynomial::mul(
&Polynomial::from(Polynomial::add(
&Polynomial::x(),
&Polynomial::from(from_usize::<u64>(1)),
)),
&(Polynomial::add(
&Polynomial::x(),
&Polynomial::from(Polynomial::from(from_usize::<u64>(2))),
)),
);
// poly with y = x+3
let value = poly.eval(Polynomial::add(
&Polynomial::x(),
&Polynomial::from(from_usize::<u64>(3)),
));
// x^2 + 6x + 5
let expected = Polynomial::add(
&Polynomial::add(
&Polynomial::mul(
&Polynomial::from(from_usize::<u64>(1)),
&Polynomial::mul(&Polynomial::x(), &Polynomial::x()),
),
&Polynomial::mul(&Polynomial::from(from_usize::<u64>(6)), &Polynomial::x()),
),
&Polynomial::from(from_usize::<u64>(5)),
);
assert_eq!(value, expected);
}
#[test]
fn test_zero_remove() {
// (x-1)(x+1)
let poly: Polynomial<i64> = 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<usize>>(),
vec![0, 4]
);
assert_eq!(
find("aaba".as_bytes(), "aabaacaadaabaaba".as_bytes()).collect::<Vec<usize>>(),
vec![0, 9, 12]
);
assert_eq!(
find("ababac".as_bytes(), "abababcabababcabababc".as_bytes()).collect::<Vec<usize>>(),
vec![]
);
assert_eq!(
find("ababc".as_bytes(), "abc".as_bytes()).collect::<Vec<usize>>(),
vec![]
);
}
}

View File

@@ -11,3 +11,5 @@ pub mod assignment03;
mod assignment03_grade;
pub mod assignment04;
mod assignment04_grade;
pub mod assignment06;
mod assignment06_grade;