mirror of
https://github.com/kmc7468/cs220.git
synced 2025-12-12 21:08:45 +00:00
Assignment 3 Done
This commit is contained in:
@@ -26,7 +26,10 @@ pub enum MyOption<T> {
|
||||
/// assert_eq!(my_map(MyOption::MyNone, len), MyOption::MyNone);
|
||||
/// ```
|
||||
pub fn my_map<T, U, F: FnOnce(T) -> U>(v: MyOption<T>, f: F) -> MyOption<U> {
|
||||
todo!()
|
||||
match v {
|
||||
MyOption::MySome(value) => MyOption::MySome(f(value)),
|
||||
_ => MyOption::MyNone,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `MyNone` if the option is `MyNone`, otherwise calls `f` with the wrapped value and
|
||||
@@ -52,7 +55,10 @@ pub fn my_map<T, U, F: FnOnce(T) -> U>(v: MyOption<T>, f: F) -> MyOption<U> {
|
||||
/// assert_eq!(my_and_then(MyOption::MyNone, pos_then_to_string), MyOption::MyNone);
|
||||
/// ```
|
||||
pub fn my_and_then<T, U, F: FnOnce(T) -> MyOption<U>>(v: MyOption<T>, f: F) -> MyOption<U> {
|
||||
todo!()
|
||||
match v {
|
||||
MyOption::MySome(value) => f(value),
|
||||
_ => MyOption::MyNone,
|
||||
}
|
||||
}
|
||||
|
||||
/// Custom operator: `option_op_or(v1, v2, f)`. If neither `v1` nor `v2` is `Some`, returns `None`.
|
||||
@@ -76,5 +82,10 @@ pub fn my_option_op_or<T, F: FnOnce(T, T) -> T>(
|
||||
v2: MyOption<T>,
|
||||
f: F,
|
||||
) -> MyOption<T> {
|
||||
todo!()
|
||||
match (v1, v2) {
|
||||
(MyOption::MySome(value1), MyOption::MySome(value2)) => MyOption::MySome(f(value1, value2)),
|
||||
(MyOption::MySome(value1), _) => MyOption::MySome(value1),
|
||||
(_, MyOption::MySome(value2)) => MyOption::MySome(value2),
|
||||
(_, _) => MyOption::MyNone,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,5 +27,30 @@
|
||||
///
|
||||
/// See `test_shell` for more examples.
|
||||
pub fn parse_shell_command(command: &str) -> Vec<String> {
|
||||
todo!()
|
||||
let mut result: Vec<String> = Vec::new();
|
||||
let mut is_quote_open = false;
|
||||
|
||||
for word in command.split_ascii_whitespace() {
|
||||
let old_is_quote_open = is_quote_open;
|
||||
|
||||
let content = if let Some(other) = word.strip_prefix("'") {
|
||||
is_quote_open = !is_quote_open;
|
||||
other
|
||||
} else if let Some(other) = word.strip_suffix("'") {
|
||||
is_quote_open = !is_quote_open;
|
||||
other
|
||||
} else {
|
||||
word
|
||||
};
|
||||
|
||||
if old_is_quote_open {
|
||||
let last = result.last_mut().unwrap();
|
||||
last.push(' ');
|
||||
last.push_str(content);
|
||||
} else {
|
||||
result.push(content.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
|
||||
/// Day of week.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -26,7 +27,13 @@ pub enum DayOfWeek {
|
||||
///
|
||||
/// `next_weekday(Thu)` is `Fri`; and `next_weekday(Fri)` is `Mon`.
|
||||
pub fn next_weekday(day: DayOfWeek) -> DayOfWeek {
|
||||
todo!()
|
||||
match day {
|
||||
DayOfWeek::Mon => DayOfWeek::Tue,
|
||||
DayOfWeek::Tue => DayOfWeek::Wed,
|
||||
DayOfWeek::Wed => DayOfWeek::Thu,
|
||||
DayOfWeek::Thu => DayOfWeek::Fri,
|
||||
_ => DayOfWeek::Mon,
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a list of integers, returns its median (when sorted, the value in the middle position).
|
||||
@@ -52,7 +59,14 @@ pub fn next_weekday(day: DayOfWeek) -> DayOfWeek {
|
||||
///
|
||||
/// Returns `None` if the list is empty.
|
||||
pub fn median(values: Vec<isize>) -> Option<isize> {
|
||||
todo!()
|
||||
if values.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut values = values.to_vec();
|
||||
values.sort();
|
||||
|
||||
Some(values[values.len() / 2])
|
||||
}
|
||||
|
||||
/// Given a list of integers, returns its smallest mode (the value that occurs most often; a hash
|
||||
@@ -60,7 +74,32 @@ pub fn median(values: Vec<isize>) -> Option<isize> {
|
||||
///
|
||||
/// Returns `None` if the list is empty.
|
||||
pub fn mode(values: Vec<isize>) -> Option<isize> {
|
||||
todo!()
|
||||
if values.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut map: HashMap<isize, i32> = HashMap::new();
|
||||
|
||||
for value in values {
|
||||
*map.entry(value).or_insert(0) += 1;
|
||||
}
|
||||
|
||||
let mut mode: Option<isize> = None;
|
||||
let mut mode_count = 0;
|
||||
|
||||
for (key, value) in map {
|
||||
if let Some(mode_value) = mode {
|
||||
if mode_count < value || (mode_count == value && mode_value > key) {
|
||||
mode = Some(key);
|
||||
mode_count = value;
|
||||
}
|
||||
} else {
|
||||
mode = Some(key);
|
||||
mode_count = value;
|
||||
}
|
||||
}
|
||||
|
||||
mode
|
||||
}
|
||||
|
||||
/// Converts the given string to Pig Latin. Use the rules below to translate normal English into Pig
|
||||
@@ -83,7 +122,25 @@ pub fn mode(values: Vec<isize>) -> Option<isize> {
|
||||
///
|
||||
/// You may assume the string only contains lowercase alphabets, and it contains at least one vowel.
|
||||
pub fn piglatin(input: String) -> String {
|
||||
todo!()
|
||||
let is_vowel = |c: u8| matches!(c, b'a' | b'e' | b'i' | b'o' | b'u');
|
||||
let input_bytes = input.as_bytes();
|
||||
|
||||
if is_vowel(input_bytes[0]) {
|
||||
input + "hay"
|
||||
} else if is_vowel(input_bytes[1]) {
|
||||
let mut result = input[1..].to_string();
|
||||
result.push(input_bytes[0] as char);
|
||||
result.push_str("ay");
|
||||
|
||||
result
|
||||
} else {
|
||||
for i in 1..input.len() {
|
||||
if is_vowel(input_bytes[i]) {
|
||||
return input[i..].to_string() + &input[0..i] + "ay";
|
||||
}
|
||||
}
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts HR commands to the organization table.
|
||||
@@ -109,7 +166,42 @@ pub fn piglatin(input: String) -> String {
|
||||
///
|
||||
/// See the test function for more details.
|
||||
pub fn organize(commands: Vec<String>) -> HashMap<String, HashSet<String>> {
|
||||
todo!()
|
||||
let mut result: HashMap<String, HashSet<String>> = HashMap::new();
|
||||
|
||||
for command in commands {
|
||||
if let Some(other) = command.strip_prefix("Add ") {
|
||||
let args: Vec<String> = other.split(" to ").map(String::from).collect();
|
||||
_ = result
|
||||
.entry(args[1].clone())
|
||||
.or_default()
|
||||
.insert(args[0].clone());
|
||||
} else if let Some(other) = command.strip_prefix("Remove ") {
|
||||
let args: Vec<String> = other.split(" from ").map(String::from).collect();
|
||||
if let Some(set) = result.get_mut(&args[1]) {
|
||||
_ = set.remove(&args[0]);
|
||||
if set.is_empty() {
|
||||
let _unused = result.remove(&args[1]);
|
||||
}
|
||||
}
|
||||
} else if let Some(other) = command.strip_prefix("Move ") {
|
||||
let args1: Vec<String> = other.split(" from ").map(String::from).collect();
|
||||
let args2: Vec<String> = args1[1].split(" to ").map(String::from).collect();
|
||||
|
||||
if let Some(set) = result.get_mut(&args2[0]) {
|
||||
if set.remove(&args1[0]) {
|
||||
if set.is_empty() {
|
||||
let _unused = result.remove(&args2[0]);
|
||||
}
|
||||
_ = result
|
||||
.entry(args2[1].clone())
|
||||
.or_default()
|
||||
.insert(args1[0].clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Events in a text editor.
|
||||
@@ -130,5 +222,17 @@ pub enum TypeEvent {
|
||||
///
|
||||
/// See the test function `test_editor` for examples.
|
||||
pub fn use_editor(events: Vec<TypeEvent>) -> String {
|
||||
todo!()
|
||||
let mut result = String::new();
|
||||
let mut clipboard = String::new();
|
||||
|
||||
for event in events {
|
||||
match event {
|
||||
TypeEvent::Type(value) => result.push(value),
|
||||
TypeEvent::Backspace => _ = result.pop(),
|
||||
TypeEvent::Copy => clipboard = result.clone(),
|
||||
TypeEvent::Paste => result.push_str(&clipboard),
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user