mirror of
https://github.com/kmc7468/cs220.git
synced 2025-12-14 22:18:46 +00:00
copy-paste assignment 2~5
This commit is contained in:
@@ -135,6 +135,39 @@ pub fn fibonacci(n: u64) -> u64 {
|
||||
(FIBONACCI_MAT.power(n) * FIBONACCI_VEC).get_upper()
|
||||
}
|
||||
|
||||
/// 2x2 floating-point matrix of the following configuration:
|
||||
///
|
||||
/// a, b
|
||||
/// c, d
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FMat2 {
|
||||
/// row 1, column 1
|
||||
pub a: f64,
|
||||
/// row 1, column 2
|
||||
pub b: f64,
|
||||
/// row 2, column 1
|
||||
pub c: f64,
|
||||
/// row 2, column 2
|
||||
pub d: f64,
|
||||
}
|
||||
|
||||
impl FMat2 {
|
||||
/// Returns the inverse of the given matrix. (We assume the given matrix is always invertible.)
|
||||
/// Hint: https://www.cuemath.com/algebra/inverse-of-2x2-matrix/
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// 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}
|
||||
/// );
|
||||
/// ```
|
||||
pub fn inverse(self) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes down the lyrics of "twelve days of christmas".
|
||||
///
|
||||
/// Hint: Google the song title for lyrics and look at the test code for the expected result.
|
||||
|
||||
@@ -149,6 +149,48 @@ 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!(
|
||||
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
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
FMat2 {
|
||||
a: 2.0,
|
||||
b: 3.0,
|
||||
c: 5.0,
|
||||
d: 7.0
|
||||
}
|
||||
.inverse(),
|
||||
FMat2 {
|
||||
a: -7.0,
|
||||
b: 3.0,
|
||||
c: 5.0,
|
||||
d: -2.0
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lyrics() {
|
||||
assert_eq!(twelve_days_of_christmas_lyrics(), LYRICS)
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
//! Assignment 3: Mastering common programming concepts (2/2).
|
||||
//!
|
||||
//! The primary goal of this assignment is to re-learn the common programming concepts in Rust, especially those in the Rust Book chapters 6, 7, 8, and 9.
|
||||
//! Please make sure you're comfortable with the concepts to proceed on to the next assignments.
|
||||
//! Assignment 3: Mastering common programming concepts (2/2)
|
||||
//!
|
||||
//! You should fill out the `todo!()` placeholders in such a way that `/scripts/grade-03.sh` works fine.
|
||||
//! See `assignment03_grade.rs` and `/scripts/grade-03.sh` for the test script.
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt;
|
||||
|
||||
/// Day of week.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -166,3 +164,125 @@ pub fn piglatin(input: String) -> String {
|
||||
pub fn organize(commands: Vec<String>) -> HashMap<String, HashSet<String>> {
|
||||
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`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// 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));
|
||||
/// ```
|
||||
pub fn option_op_or<T, F: FnOnce(T, T) -> T>(v1: Option<T>, v2: Option<T>, f: F) -> Option<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Events in a text editor.
|
||||
#[derive(Debug)]
|
||||
pub enum TypeEvent {
|
||||
/// A character is typed.
|
||||
Type(char),
|
||||
/// The last character is removed.
|
||||
Backspace,
|
||||
/// The whole string is copied to the clipboard.
|
||||
Copy,
|
||||
/// The string in the clipboard is appended.
|
||||
Paste,
|
||||
}
|
||||
|
||||
/// Starting from an empty string and an empty clipboard,
|
||||
/// processes the given `events` in order and returns the resulting string.
|
||||
///
|
||||
/// See the test function `test_editor` for examples.
|
||||
pub fn use_editor(events: Vec<TypeEvent>) -> String {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// 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.
|
||||
/// ```text
|
||||
/// ls 'VirtualBox VMs' --> ["ls", 'VirtualBox VMs']
|
||||
/// ls VirtualBox' 'VMs --> ["ls", 'VirtualBox VMs']
|
||||
/// ```
|
||||
///
|
||||
/// For simplicity, you may assume that the string only contains alphanumeric characters, spaces
|
||||
/// (" "), and single quotes ("'").
|
||||
///
|
||||
/// See `test_shell` for more examples.
|
||||
pub fn parse_shell_command(command: &str) -> Vec<String> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Represents a JSON value. See https://en.wikipedia.org/wiki/JSON.
|
||||
///
|
||||
/// For simplicity, you may assume that numbers are of type `i64`, and strings do not contain
|
||||
/// special characters that need to be escaped (e.g. '"', '\n', ...).
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum JsonValue {
|
||||
/// null
|
||||
Null,
|
||||
/// true, false
|
||||
Boolean(bool),
|
||||
/// integers
|
||||
Number(i64),
|
||||
/// strings
|
||||
String(String),
|
||||
/// array of JSON values
|
||||
Array(Vec<JsonValue>),
|
||||
/// objects
|
||||
Object(HashMap<String, JsonValue>),
|
||||
}
|
||||
|
||||
/// Parse a string into a JSON value. Returns `Err(())` if it contains syntax errors.
|
||||
///
|
||||
/// See `test_json` for examples.
|
||||
pub fn parse_json(json_string: &str) -> Result<JsonValue, String> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
impl fmt::Display for JsonValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
JsonValue::Null => write!(f, "null"),
|
||||
JsonValue::Boolean(b) => write!(f, "{}", b),
|
||||
JsonValue::Number(n) => write!(f, "{}", n),
|
||||
JsonValue::String(s) => write!(f, "\"{}\"", s),
|
||||
JsonValue::Array(arr) => {
|
||||
write!(f, "[")?;
|
||||
let mut iter = arr.iter();
|
||||
if let Some(item) = iter.next() {
|
||||
write!(f, "{}", item)?;
|
||||
for item in iter {
|
||||
write!(f, ", {}", item)?;
|
||||
}
|
||||
}
|
||||
write!(f, "]")
|
||||
}
|
||||
JsonValue::Object(obj) => {
|
||||
write!(f, "{{")?;
|
||||
let mut iter = obj.iter();
|
||||
if let Some((key, value)) = iter.next() {
|
||||
write!(f, "\"{}\": {}", key, value)?;
|
||||
for (key, value) in iter {
|
||||
write!(f, ", \"{}\": {}", key, value)?;
|
||||
}
|
||||
}
|
||||
write!(f, "}}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,4 +165,162 @@ mod test {
|
||||
.into()
|
||||
);
|
||||
}
|
||||
|
||||
fn product(a: i32, b: i32) -> i32 {
|
||||
a * b
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_option_op_or() {
|
||||
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(None, Some(5), product), Some(5));
|
||||
assert_eq!(option_op_or(Some(3), Some(5), product), Some(15));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_editor() {
|
||||
assert_eq!(
|
||||
use_editor(vec![
|
||||
TypeEvent::Type('a'),
|
||||
TypeEvent::Backspace,
|
||||
TypeEvent::Backspace,
|
||||
TypeEvent::Type('b'),
|
||||
TypeEvent::Type('c')
|
||||
]),
|
||||
"bc"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
use_editor(vec![
|
||||
TypeEvent::Type('a'),
|
||||
TypeEvent::Copy,
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Type('b'),
|
||||
TypeEvent::Copy,
|
||||
TypeEvent::Paste
|
||||
]),
|
||||
"aaabaaab"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
use_editor(vec![
|
||||
TypeEvent::Paste, // clipboard starts empty
|
||||
TypeEvent::Type('a'),
|
||||
TypeEvent::Type('n'),
|
||||
TypeEvent::Copy,
|
||||
TypeEvent::Backspace,
|
||||
TypeEvent::Backspace,
|
||||
TypeEvent::Type('b'),
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Backspace
|
||||
]),
|
||||
"banana"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
use_editor(vec![
|
||||
TypeEvent::Copy,
|
||||
TypeEvent::Backspace,
|
||||
TypeEvent::Backspace,
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Paste,
|
||||
TypeEvent::Copy,
|
||||
TypeEvent::Backspace
|
||||
]),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shell() {
|
||||
assert_eq!(
|
||||
parse_shell_command("cat file"),
|
||||
vec!["cat".to_string(), "file".to_string()]
|
||||
);
|
||||
assert_eq!(
|
||||
parse_shell_command("ls 'VirtualBox VMs'"),
|
||||
vec!["ls".to_string(), "VirtualBox VMs".to_string()]
|
||||
);
|
||||
assert_eq!(
|
||||
parse_shell_command("ls VirtualBox' 'VMs"),
|
||||
vec!["ls".to_string(), "VirtualBox VMs".to_string()]
|
||||
);
|
||||
assert_eq!(
|
||||
parse_shell_command("echo once upon a midnight dreary"),
|
||||
vec![
|
||||
"echo".to_string(),
|
||||
"once".to_string(),
|
||||
"upon".to_string(),
|
||||
"a".to_string(),
|
||||
"midnight".to_string(),
|
||||
"dreary".to_string(),
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
parse_shell_command("echo 'once upon a midnight dreary'"),
|
||||
vec![
|
||||
"echo".to_string(),
|
||||
"once upon a midnight dreary".to_string(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_json() {
|
||||
use std::collections::HashMap;
|
||||
let json_str = r#"{
|
||||
"name": "John Doe",
|
||||
"age": 30,
|
||||
"city": "New York",
|
||||
"active": true,
|
||||
"address": {
|
||||
"street": "123 Main St",
|
||||
"zipCode": "10001"
|
||||
},
|
||||
"skills": ["Rust", "Python", "JavaScript"],
|
||||
"organization": null
|
||||
}"#;
|
||||
println!("{}", parse_json(json_str).unwrap());
|
||||
assert_eq!(
|
||||
parse_json(json_str),
|
||||
Ok(JsonValue::Object(HashMap::from([
|
||||
(
|
||||
"name".to_string(),
|
||||
JsonValue::String("John Doe".to_string())
|
||||
),
|
||||
("age".to_string(), JsonValue::Number(30)),
|
||||
(
|
||||
"city".to_string(),
|
||||
JsonValue::String("New York".to_string())
|
||||
),
|
||||
("active".to_string(), JsonValue::Boolean(true)),
|
||||
(
|
||||
"address".to_string(),
|
||||
JsonValue::Object(HashMap::from([
|
||||
(
|
||||
"street".to_string(),
|
||||
JsonValue::String("123 Main St".to_string())
|
||||
),
|
||||
(
|
||||
"zipCode".to_string(),
|
||||
JsonValue::String("10001".to_string())
|
||||
)
|
||||
]))
|
||||
),
|
||||
(
|
||||
"skills".to_string(),
|
||||
JsonValue::Array(vec![
|
||||
JsonValue::String("Rust".to_string()),
|
||||
JsonValue::String("Python".to_string()),
|
||||
JsonValue::String("JavaScript".to_string())
|
||||
])
|
||||
),
|
||||
("organization".to_string(), JsonValue::Null),
|
||||
])))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
//! Singly linked list.
|
||||
//!
|
||||
//! Hint: Consult <https://doc.rust-lang.org/book/ch15-01-box.html>.
|
||||
//!
|
||||
//! Refer `linked_list_grade.rs` for test cases.
|
||||
//! Consult <https://doc.rust-lang.org/book/ch15-01-box.html>.
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
@@ -61,4 +59,82 @@ impl<T: Debug> SinglyLinkedList<T> {
|
||||
pub fn pop_back(&mut self) -> Option<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Create a new list from the given vector `vec`.
|
||||
pub fn from_vec(vec: Vec<T>) -> Self {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Convert the current list into a vector.
|
||||
pub fn as_vec(&self) -> Vec<T> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Return the length (i.e., number of nodes) of the list.
|
||||
pub fn length(&self) -> usize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Apply function `f` on every element of the list.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// `self`: `[1, 2]`, `f`: `|x| x + 1` ==> `[2, 3]`
|
||||
pub fn map<F: Fn(T) -> T>(&mut self, f: F) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Insert given list `another` at the specified index `idx`.
|
||||
/// If `idx` is out-of-bound of `self`, append `another` at the end of `self`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// `self`: `[1, 2]`, `another`: `[3, 4]`, `idx`: `1` ==> `[1, 3, 4, 2]`
|
||||
/// `self`: `[1, 2]`, `another`: `[3, 4]`, `idx`: `5` ==> `[1, 2, 3, 4]`
|
||||
pub fn insert(&mut self, another: &Self, idx: usize) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Reverse the list in a chunk of size `n`.
|
||||
/// If `n == 0`, do nothing.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// `self`: `[1, 2, 3, 4, 5, 6, 7, 8, 9]`, `n`: `3`
|
||||
/// // each chunk of size `3`: `[1, 2, 3]`, `[4, 5, 6]`, `[7, 8, 9]`
|
||||
/// // reversed sequence of chunks: `[7, 8, 9]`, `[4, 5, 6]`, `[1, 2, 3]`
|
||||
/// ==> `[7, 8, 9, 4, 5, 6, 1, 2, 3]`,
|
||||
///
|
||||
/// `self`: `[1, 2, 3, 4, 5, 6, 7, 8, 9]`, `n`: `4`
|
||||
/// // each chunk of size `4`: `[1, 2, 3, 4]`, `[5, 6, 7, 8]`, `[9]`
|
||||
/// // reversed sequence of chunks: `[9]`, `[5, 6, 7, 8]`, `[1, 2, 3, 4]`
|
||||
/// ==> `[9, 5, 6, 7, 8, 1, 2, 3, 4]`
|
||||
pub fn chunk_reverse(&mut self, n: usize) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Apply given function `f` for each adjacent pair of elements in the list.
|
||||
/// If `self.length() < 2`, do nothing.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// `self`: `[1, 2, 3, 4]`, `f`: `|x, y| x + y`
|
||||
/// // each adjacent pair of elements: `(1, 2)`, `(2, 3)`, `(3, 4)`
|
||||
/// // apply `f` to each pair: `f(1, 2) == 3`, `f(2, 3) == 5`, `f(3, 4) == 7`
|
||||
/// ==> `[3, 5, 7]`
|
||||
pub fn pair_map<F: Fn(T, T) -> T>(&mut self, f: F) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
// A list of lists.
|
||||
impl<T: Debug> SinglyLinkedList<SinglyLinkedList<T>> {
|
||||
/// Flatten the list of lists into a single list.
|
||||
///
|
||||
/// # Examples
|
||||
/// `self`: `[[1, 2, 3], [4, 5, 6], [7, 8]]`
|
||||
/// ==> `[1, 2, 3, 4, 5, 6, 7, 8]`
|
||||
pub fn flatten(self) -> SinglyLinkedList<T> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
//! Test cases for assignment11/linked_list.rs
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_linked_list {
|
||||
use super::super::linked_list::*;
|
||||
use crate::assignments::assignment11::linked_list::*;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct V(usize);
|
||||
|
||||
#[test]
|
||||
fn test_linked_list() {
|
||||
fn test_push_pop() {
|
||||
let mut list = SinglyLinkedList::new();
|
||||
list.push_back(V(3));
|
||||
list.push_front(V(2));
|
||||
@@ -24,4 +22,101 @@ mod test_linked_list {
|
||||
assert_eq!(list.pop_back(), None);
|
||||
assert_eq!(list.pop_front(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_as_vec() {
|
||||
assert_eq!(SinglyLinkedList::<i32>::new().as_vec(), vec![]);
|
||||
assert_eq!(
|
||||
SinglyLinkedList::from_vec(vec![1, 2, 3]).as_vec(),
|
||||
vec![1, 2, 3]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_length() {
|
||||
let list = SinglyLinkedList::from_vec(vec![1, 2, 3]);
|
||||
assert_eq!(list.length(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_map() {
|
||||
let mut list = SinglyLinkedList::from_vec(vec![1, 2, 3]);
|
||||
let incr = |x: i32| x + 1;
|
||||
list.map(incr);
|
||||
assert_eq!(list.as_vec(), vec![2, 3, 4]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert() {
|
||||
let mut list1 = SinglyLinkedList::from_vec(vec![1, 2, 3]);
|
||||
let mut list2 = SinglyLinkedList::from_vec(vec![1, 2, 3]);
|
||||
let mut list3 = SinglyLinkedList::from_vec(vec![1, 2, 3]);
|
||||
let list4 = SinglyLinkedList::from_vec(vec![4, 5, 6]);
|
||||
|
||||
list1.insert(&list4, 0);
|
||||
assert_eq!(list1.as_vec(), vec![4, 5, 6, 1, 2, 3]);
|
||||
|
||||
list2.insert(&list4, 1);
|
||||
assert_eq!(list2.as_vec(), vec![1, 4, 5, 6, 2, 3]);
|
||||
|
||||
list3.insert(&list4, 4);
|
||||
assert_eq!(list3.as_vec(), vec![1, 2, 3, 4, 5, 6]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_chunk_reverse() {
|
||||
let mut list1 = SinglyLinkedList::from_vec(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
list1.chunk_reverse(3);
|
||||
assert_eq!(list1.as_vec(), vec![7, 8, 9, 3, 4, 5, 1, 2, 3]);
|
||||
|
||||
let mut list2 = SinglyLinkedList::from_vec(vec![1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
list2.chunk_reverse(3);
|
||||
assert_eq!(list2.as_vec(), vec![7, 8, 4, 5, 6, 1, 2, 3]);
|
||||
|
||||
let mut list3 = SinglyLinkedList::from_vec(vec![1, 2, 3]);
|
||||
list3.chunk_reverse(4);
|
||||
assert_eq!(list3.as_vec(), vec![1, 2, 3]);
|
||||
|
||||
let mut list4 = SinglyLinkedList::from_vec(vec![1, 2, 3, 4]);
|
||||
list4.chunk_reverse(1);
|
||||
assert_eq!(list4.as_vec(), vec![4, 3, 2, 1]);
|
||||
|
||||
let mut list5 = SinglyLinkedList::from_vec(vec![1, 2, 3, 4]);
|
||||
list4.chunk_reverse(0);
|
||||
assert_eq!(list4.as_vec(), vec![1, 2, 3, 4]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pair_map() {
|
||||
let mut list = SinglyLinkedList::from_vec(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
let add = |x: i32, y: i32| x + y;
|
||||
|
||||
list.pair_map(add);
|
||||
assert_eq!(list.as_vec(), vec![3, 5, 7, 9, 11, 13, 15, 17]);
|
||||
|
||||
list.pair_map(add);
|
||||
assert_eq!(list.as_vec(), vec![8, 12, 16, 20, 24, 28, 32]);
|
||||
|
||||
list.pair_map(add);
|
||||
assert_eq!(list.as_vec(), vec![20, 28, 36, 44, 52, 60]);
|
||||
|
||||
list.pair_map(add);
|
||||
assert_eq!(list.as_vec(), vec![48, 64, 80, 96, 112]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flatten() {
|
||||
let list1 = SinglyLinkedList::from_vec(vec![1, 2]);
|
||||
let list2 = SinglyLinkedList::from_vec(vec![3]);
|
||||
let list3 = SinglyLinkedList::from_vec(vec![4, 5, 6, 7]);
|
||||
let list4 = SinglyLinkedList::<i32>::new();
|
||||
let list5 = SinglyLinkedList::from_vec(vec![8, 9, 10]);
|
||||
|
||||
let list_list = SinglyLinkedList::from_vec(vec![list1, list2, list3, list4, list5]);
|
||||
|
||||
assert_eq!(
|
||||
list_list.flatten().as_vec(),
|
||||
vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,26 @@
|
||||
//! See `assignment11_grade.rs` and `/scripts/grade-11.sh` for the test script.
|
||||
//! Run `/scripts/prepare-submissions.sh` and submit `/target/assignment11.zip` to <https://gg.kaist.ac.kr>.
|
||||
|
||||
pub mod bst;
|
||||
pub mod bst_grade;
|
||||
pub mod doubly_linked_list;
|
||||
pub mod doubly_linked_list_grade;
|
||||
pub mod graph;
|
||||
pub mod graph_grade;
|
||||
pub mod linked_list;
|
||||
mod linked_list_grade;
|
||||
|
||||
pub mod peano_nat;
|
||||
mod peano_nat_grade;
|
||||
|
||||
pub mod bst;
|
||||
mod bst_grade;
|
||||
|
||||
pub mod doubly_linked_list;
|
||||
mod doubly_linked_list_grade;
|
||||
|
||||
pub mod graph;
|
||||
mod graph_grade;
|
||||
|
||||
pub mod mock_storage;
|
||||
pub mod mock_storage_grade;
|
||||
pub mod turing_machine;
|
||||
pub mod turing_machine_grade;
|
||||
|
||||
pub mod tv_room;
|
||||
pub mod tv_room_grade;
|
||||
|
||||
pub mod turing_machine;
|
||||
pub mod turing_machine_grade;
|
||||
|
||||
56
src/assignments/assignment11/peano_nat.rs
Normal file
56
src/assignments/assignment11/peano_nat.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
//! Peano natural number.
|
||||
|
||||
/// We can represent any natural number using only two symbols: 0 and S.
|
||||
///
|
||||
/// E.g.
|
||||
/// O == 0
|
||||
/// S(O) == 1
|
||||
/// S(S(O)) == 2
|
||||
/// ... so on.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Nat {
|
||||
/// Zero
|
||||
O,
|
||||
/// Plus one
|
||||
S(Box<Nat>),
|
||||
}
|
||||
|
||||
impl Nat {
|
||||
/// Create `Nat` from `usize`
|
||||
pub fn from_usize(n: usize) -> Nat {
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Convert `Nat` into nonnegative integer
|
||||
pub fn as_usize(&self) -> usize {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
// Implement `Add` operator (i.e. `+`) for `Nat`.
|
||||
impl std::ops::Add for Nat {
|
||||
type Output = Nat;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
// Implement `Sub` operator (i.e. `-`) for `Nat`.
|
||||
// If the result is negative, return `Nat::O`.
|
||||
impl std::ops::Sub for Nat {
|
||||
type Output = Nat;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
// Implement `Mul` operator (i.e. `*`) for `Nat`.
|
||||
impl std::ops::Mul for Nat {
|
||||
type Output = Nat;
|
||||
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
38
src/assignments/assignment11/peano_nat_grade.rs
Normal file
38
src/assignments/assignment11/peano_nat_grade.rs
Normal file
@@ -0,0 +1,38 @@
|
||||
#[cfg(test)]
|
||||
mod test_peano_nat {
|
||||
use crate::assignments::assignment11::peano_nat::*;
|
||||
|
||||
#[test]
|
||||
fn test_from_as_usize() {
|
||||
assert_eq!(Nat::from_usize(0), Nat::O);
|
||||
assert_eq!(
|
||||
Nat::from_usize(2),
|
||||
Nat::S(Box::new(Nat::S(Box::new(Nat::O))))
|
||||
);
|
||||
|
||||
for n in 0..100 {
|
||||
assert_eq!(Nat::from_usize(n).as_usize(), n);
|
||||
}
|
||||
}
|
||||
|
||||
fn safe_sub(i: usize, j: usize) -> usize {
|
||||
if i > j {
|
||||
i - j
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_sub_mul() {
|
||||
for i in 0..30 {
|
||||
let n = Nat::from_usize(i);
|
||||
for j in 0..30 {
|
||||
let m = Nat::from_usize(j);
|
||||
assert_eq!((n.clone() + m.clone()).as_usize(), i + j);
|
||||
assert_eq!((n.clone() - m.clone()).as_usize(), safe_sub(i, j));
|
||||
assert_eq!((n.clone() * m.clone()).as_usize(), i * j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user