From b40b19c2957c39d2bd5141c3d0254aa81e4f1786 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Wed, 9 Oct 2024 15:24:14 +0000 Subject: [PATCH 1/7] Setting up GitHub Classroom Feedback From 18bc5c4741af219549ad113e6e46deadd307754f Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Wed, 9 Oct 2024 15:24:16 +0000 Subject: [PATCH 2/7] add online IDE url --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3a518ad..77f0f15 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Open in Codespaces](https://classroom.github.com/assets/launch-codespace-2972f46106e565e64193e422d61a12cf1da4916b45550586e14ef0a7c637dd04.svg)](https://classroom.github.com/open-in-codespaces?assignment_repo_id=16450427) # Labs Please open each folder separately to benefit from Rust Analyzer. From 32834ea318852bf9bd60dbe80febd772a1ed7e5e Mon Sep 17 00:00:00 2001 From: mucel29 Date: Wed, 9 Oct 2024 19:04:35 +0300 Subject: [PATCH 3/7] lab 1 --- .../1-basic-syntax/src/bin/01.rs | 14 ++++++++----- .../1-basic-syntax/src/bin/02.rs | 20 ++++++++++++------- .../1-basic-syntax/src/bin/03.rs | 18 ++++++++++++++--- .../1-basic-syntax/src/bin/04.rs | 15 +++++++++----- .../1-basic-syntax/src/bin/05.rs | 13 +++++++----- 5 files changed, 55 insertions(+), 25 deletions(-) diff --git a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/01.rs b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/01.rs index 76cbeca..089a4fe 100644 --- a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/01.rs +++ b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/01.rs @@ -1,18 +1,22 @@ -fn main() { +fn main() +{ println!("{}", multiply(10, 20)); } -fn multiply(a: i32, b: i32) { - a * b +fn multiply(a: i32, b: i32) -> i32 +{ + return a * b; } // Tests; run with `cargo test --bin 01` #[cfg(test)] -mod tests { +mod tests +{ use super::*; #[test] - fn it_multiplies() { + fn it_multiplies() + { assert!(multiply(10, 10) == 100); assert!(multiply(2, 2) == 4); } diff --git a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/02.rs b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/02.rs index 8e677a5..a5106a4 100644 --- a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/02.rs +++ b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/02.rs @@ -1,21 +1,27 @@ -fn main() { - if (bigger(10, 20)) { +fn main() +{ + if (bigger(10, 20)) + { println!("10 is bigger than 20"); - } else { + } else + { println!("10 still isn't bigger than 20"); } } -fn bigger(a: i32, b: i32) -> i32 { - // TODO +fn bigger(a: i32, b: i32) -> bool +{ + return a > b } #[cfg(test)] -mod tests { +mod tests +{ use super::*; #[test] - fn it_biggers() { + fn it_biggers() + { assert!(bigger(20, 10)); assert!(!bigger(10, 20)); } diff --git a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/03.rs b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/03.rs index 365132e..82f5d27 100644 --- a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/03.rs +++ b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/03.rs @@ -1,7 +1,19 @@ -fn main() { +fn main() +{ let input = [23, 82, 16, 45, 21, 94, 12, 34]; - // TODO + let mut min: i32 = i32::MAX; + let mut max: i32 = i32::MIN; + for n in input + { + if n > max + { + max = n + } else if n < min + { + min = n + } + } - println!("{} is largest and {} is smallest"); + println!("{} is largest and {} is smallest", max, min); } diff --git a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/04.rs b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/04.rs index 8926e1d..2e0ef2c 100644 --- a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/04.rs +++ b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/04.rs @@ -1,9 +1,14 @@ -fn main() { - for (n in [10, 20, 30, 40]) { - let mult = if n < 25 { +fn main() +{ + + for n in [10, 20, 30, 40] + { + let mult = if n < 25 + { n * 4 - } else { - n * 3; + } else + { + n * 3 }; println!("{}", mult); } diff --git a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/05.rs b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/05.rs index faacb16..48e8c45 100644 --- a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/05.rs +++ b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/05.rs @@ -1,10 +1,13 @@ -fn main() { - let data = [22, 12, 13, 17, 18]; - for i in 0..5 { - data.i = floored_half(data.i); +fn main() +{ + let mut data = [22, 12, 13, 17, 18]; + for i in 0..5 + { + data[i] = floored_half(data[i]); } } -fn floored_half(data: i32) { +fn floored_half(data: i32) -> i32 +{ data / 2 } From 5f1ae1aacf22edbf7d47861997bb28a4364e374f Mon Sep 17 00:00:00 2001 From: mucel29 Date: Thu, 10 Oct 2024 12:18:31 +0300 Subject: [PATCH 4/7] fix: brackets placing --- .../1-basic-syntax/src/bin/01.rs | 12 ++++------- .../1-basic-syntax/src/bin/02.rs | 20 +++++++------------ .../1-basic-syntax/src/bin/03.rs | 12 ++++------- .../1-basic-syntax/src/bin/04.rs | 15 +++----------- .../1-basic-syntax/src/bin/05.rs | 9 +++------ 5 files changed, 21 insertions(+), 47 deletions(-) diff --git a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/01.rs b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/01.rs index 089a4fe..dc2b8c0 100644 --- a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/01.rs +++ b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/01.rs @@ -1,22 +1,18 @@ -fn main() -{ +fn main() { println!("{}", multiply(10, 20)); } -fn multiply(a: i32, b: i32) -> i32 -{ +fn multiply(a: i32, b: i32) -> i32 { return a * b; } // Tests; run with `cargo test --bin 01` #[cfg(test)] -mod tests -{ +mod tests { use super::*; #[test] - fn it_multiplies() - { + fn it_multiplies() { assert!(multiply(10, 10) == 100); assert!(multiply(2, 2) == 4); } diff --git a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/02.rs b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/02.rs index a5106a4..348d35c 100644 --- a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/02.rs +++ b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/02.rs @@ -1,27 +1,21 @@ -fn main() -{ - if (bigger(10, 20)) - { +fn main() { + if (bigger(10, 20)) { println!("10 is bigger than 20"); - } else - { + } else { println!("10 still isn't bigger than 20"); } } -fn bigger(a: i32, b: i32) -> bool -{ - return a > b +fn bigger(a: i32, b: i32) -> bool { + return a > b; } #[cfg(test)] -mod tests -{ +mod tests { use super::*; #[test] - fn it_biggers() - { + fn it_biggers() { assert!(bigger(20, 10)); assert!(!bigger(10, 20)); } diff --git a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/03.rs b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/03.rs index 82f5d27..1aec507 100644 --- a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/03.rs +++ b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/03.rs @@ -1,16 +1,12 @@ -fn main() -{ +fn main() { let input = [23, 82, 16, 45, 21, 94, 12, 34]; let mut min: i32 = i32::MAX; let mut max: i32 = i32::MIN; - for n in input - { - if n > max - { + for n in input { + if n > max { max = n - } else if n < min - { + } else if n < min { min = n } } diff --git a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/04.rs b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/04.rs index 2e0ef2c..20190fa 100644 --- a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/04.rs +++ b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/04.rs @@ -1,15 +1,6 @@ -fn main() -{ - - for n in [10, 20, 30, 40] - { - let mult = if n < 25 - { - n * 4 - } else - { - n * 3 - }; +fn main() { + for n in [10, 20, 30, 40] { + let mult = if n < 25 { n * 4 } else { n * 3 }; println!("{}", mult); } } diff --git a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/05.rs b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/05.rs index 48e8c45..dae2e55 100644 --- a/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/05.rs +++ b/2-foundations-of-rust/1-basic-syntax/1-basic-syntax/src/bin/05.rs @@ -1,13 +1,10 @@ -fn main() -{ +fn main() { let mut data = [22, 12, 13, 17, 18]; - for i in 0..5 - { + for i in 0..5 { data[i] = floored_half(data[i]); } } -fn floored_half(data: i32) -> i32 -{ +fn floored_half(data: i32) -> i32 { data / 2 } From 53ed79b0ce5b0c35565d09bc88dacf6ffbb080ea Mon Sep 17 00:00:00 2001 From: mucel29 Date: Wed, 23 Oct 2024 18:40:41 +0300 Subject: [PATCH 5/7] Laborator 2 Finished. Signed-off-by: mucel29 --- .../1-move-semantics/src/bin/02.rs | 3 +-- .../1-move-semantics/src/bin/03.rs | 6 +++--- .../1-move-semantics/src/bin/04.rs | 6 +++--- .../2-borrowing/src/bin/01.rs | 2 +- .../2-borrowing/src/bin/02.rs | 10 +++++----- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/2-foundations-of-rust/2-ownership-and-references/1-move-semantics/src/bin/02.rs b/2-foundations-of-rust/2-ownership-and-references/1-move-semantics/src/bin/02.rs index 02211b8..da4e311 100644 --- a/2-foundations-of-rust/2-ownership-and-references/1-move-semantics/src/bin/02.rs +++ b/2-foundations-of-rust/2-ownership-and-references/1-move-semantics/src/bin/02.rs @@ -5,11 +5,10 @@ fn main() { let s0 = String::from("Hello"); - let mut s1 = append_to_string(s0); - // Don't change the following line! println!("{} == `{}`", stringify!(s0), s0); + let mut s1 = append_to_string(s0); s1.push('!'); println!("{} == `{}`", stringify!(s1), s1); diff --git a/2-foundations-of-rust/2-ownership-and-references/1-move-semantics/src/bin/03.rs b/2-foundations-of-rust/2-ownership-and-references/1-move-semantics/src/bin/03.rs index 8473e69..379eaed 100644 --- a/2-foundations-of-rust/2-ownership-and-references/1-move-semantics/src/bin/03.rs +++ b/2-foundations-of-rust/2-ownership-and-references/1-move-semantics/src/bin/03.rs @@ -1,9 +1,9 @@ //! Make me compile without adding new lines-- just changing existing lines! fn main() { - let s0 = String::new(); + let mut s0 = String::new(); - let mut s1 = append_to_string(s0); + let s1 = append_to_string(&mut s0); println!("{} == `{}`", stringify!(s1), s1); @@ -12,7 +12,7 @@ fn main() { println!("{} == `{}`", stringify!(s1), s1); } -fn append_to_string(s: String) -> String { +fn append_to_string(s: &mut String) -> &mut String { s.push_str("Hello World"); s diff --git a/2-foundations-of-rust/2-ownership-and-references/1-move-semantics/src/bin/04.rs b/2-foundations-of-rust/2-ownership-and-references/1-move-semantics/src/bin/04.rs index 8631c1a..139b0ed 100644 --- a/2-foundations-of-rust/2-ownership-and-references/1-move-semantics/src/bin/04.rs +++ b/2-foundations-of-rust/2-ownership-and-references/1-move-semantics/src/bin/04.rs @@ -3,9 +3,9 @@ //! function. fn main() { - let s0 = String::new(); + // let s0 = String::new(); - let mut s1 = create_string(s0); + let mut s1 = create_string(); println!("{} == `{}`", stringify!(s1), s1); @@ -16,7 +16,7 @@ fn main() { ///`create_string()` no longer takes `s: String` as argument fn create_string() -> String { - let mut s = s; + let s = String::from("Hello"); s } diff --git a/2-foundations-of-rust/2-ownership-and-references/2-borrowing/src/bin/01.rs b/2-foundations-of-rust/2-ownership-and-references/2-borrowing/src/bin/01.rs index 76c3ddc..52c34a9 100644 --- a/2-foundations-of-rust/2-ownership-and-references/2-borrowing/src/bin/01.rs +++ b/2-foundations-of-rust/2-ownership-and-references/2-borrowing/src/bin/01.rs @@ -4,8 +4,8 @@ fn main() { let mut x = 100; let y = &mut x; - let z = &mut x; *y += 100; + let z = &mut x; *z += 1000; assert_eq!(x, 1200); } diff --git a/2-foundations-of-rust/2-ownership-and-references/2-borrowing/src/bin/02.rs b/2-foundations-of-rust/2-ownership-and-references/2-borrowing/src/bin/02.rs index 3e4f8a6..884fc5a 100644 --- a/2-foundations-of-rust/2-ownership-and-references/2-borrowing/src/bin/02.rs +++ b/2-foundations-of-rust/2-ownership-and-references/2-borrowing/src/bin/02.rs @@ -3,19 +3,19 @@ fn main() { let data = "Rust is great!".to_string(); - get_char(data); + get_char(&data); - string_uppercase(&data); + string_uppercase(data); } // Should not take ownership -fn get_char(data: String) -> char { +fn get_char(data: &String) -> char { data.chars().last().unwrap() } // Should take ownership -fn string_uppercase(mut data: &String) { - data = &data.to_uppercase(); +fn string_uppercase(mut data: String) { + data = data.to_uppercase(); println!("{}", data); } From 30699678b355e6bb8d2f9b4c1498fb5a66b11cf7 Mon Sep 17 00:00:00 2001 From: mucel29 Date: Wed, 6 Nov 2024 19:30:38 +0200 Subject: [PATCH 6/7] Laborator 3 --- .../1-error-propagation/src/main.rs | 12 ++-- .../2-error-handling/src/main.rs | 64 +++++++++++++------ .../3-advanced-syntax/3-slices/src/main.rs | 32 ++++++---- 3 files changed, 70 insertions(+), 38 deletions(-) diff --git a/2-foundations-of-rust/3-advanced-syntax/1-error-propagation/src/main.rs b/2-foundations-of-rust/3-advanced-syntax/1-error-propagation/src/main.rs index 5ded7bc..c10126a 100644 --- a/2-foundations-of-rust/3-advanced-syntax/1-error-propagation/src/main.rs +++ b/2-foundations-of-rust/3-advanced-syntax/1-error-propagation/src/main.rs @@ -19,15 +19,15 @@ use std::io::{self, BufRead, BufReader, Lines}; //change this into: //fn read_lines(filename: &str) -> Result>, io::Error> { -fn read_lines(filename: &str) -> Lines> { +fn read_lines(filename: &str) -> Result>, io::Error> { let file = File::open(filename).unwrap(); // this can easily fail - BufReader::new(file).lines() + Ok(BufReader::new(file).lines()) } //change this into: //fn count_bytes_and_lines(filename: &str) -> Result<(usize, usize, usize), io::Error> { -fn count_bytes_and_lines(filename: &str) -> (usize, usize, usize) { - let lines = read_lines(filename); +fn count_bytes_and_lines(filename: &str) -> Result<(usize, usize, usize), io::Error> { + let lines = read_lines(filename).unwrap(); let mut line_count = 0; let mut word_count = 0; let mut byte_count = 0; @@ -38,13 +38,13 @@ fn count_bytes_and_lines(filename: &str) -> (usize, usize, usize) { byte_count += text.len(); } - (line_count, word_count, byte_count) + Ok((line_count, word_count, byte_count)) } fn main() { let args: Vec = env::args().collect(); let filename = &args[1]; - let (lines, words, bytes) = count_bytes_and_lines(filename); + let (lines, words, bytes) = count_bytes_and_lines(filename).unwrap(); println!("{filename}: {lines} lines, {words} words, {bytes} bytes"); } diff --git a/2-foundations-of-rust/3-advanced-syntax/2-error-handling/src/main.rs b/2-foundations-of-rust/3-advanced-syntax/2-error-handling/src/main.rs index 0ebb167..a5c4456 100644 --- a/2-foundations-of-rust/3-advanced-syntax/2-error-handling/src/main.rs +++ b/2-foundations-of-rust/3-advanced-syntax/2-error-handling/src/main.rs @@ -1,6 +1,5 @@ /// While taking a first stab at programs, using panic!() is a quick-and-dirty way to do error handling; but panic!() has the obvious drawback /// that it is all-or-nothing: you cannot recover from it (in general). - // Consider this "interactive hello world" (that is a bit fussy about what is a valid name), where the intent is that the program repeats // the question if the user entered an invalid name. // @@ -20,35 +19,64 @@ // // NOTE: You will (hopefully) discover that "?" doesn't work in this context, and the resulting code // is a bit explicit about the errors --- we can solve that with traits, next week! - -use std::io::{BufRead, self, Write}; +use std::io::{self, BufRead, Error, ErrorKind, Write}; #[derive(Debug)] -enum MyError{ InvalidName,IOError( io::Error), +enum MyError { + InvalidName, + IOError(io::Error), } -fn get_username( ) --> String -{ +fn get_username() -> Result { print!("Username: "); - io::stdout().flush(); + match io::stdout().flush() { + Ok(_) => (), + Err(err) => { + return Err(MyError::IOError(Error::new( + ErrorKind::Other, + format!("{:?}", err).as_str(), + ))) + } + } - let mut input=String::new(); - io::stdin().lock().read_line(&mut input); input=input.trim().to_string(); + let mut input = String::new(); - for c in input.chars() - { - if !char::is_alphabetic(c) { panic!("that's not a valid name, try again"); } + match io::stdin().lock().read_line(&mut input) { + Ok(_) => (), + Err(_) => { + return Err(MyError::IOError(Error::new( + ErrorKind::Other, + "Could not read line!", + ))) + } } + input = input.trim().to_string(); -if input.is_empty() { -panic!("that's not a valid name, try again"); -} + for c in input.chars() { + if !char::is_alphabetic(c) { + return Err(MyError::InvalidName); + } + } - input + if input.is_empty() { + return Err(MyError::InvalidName); + } + + Ok(input) } fn main() { - let name=get_username(); + let name; + loop { + match get_username() { + Ok(val) => { + name = val; + break; + } + Err(MyError::IOError(err)) => panic!("{err}"), + _ => (), + } + } + println!("Hello {name}!") } diff --git a/2-foundations-of-rust/3-advanced-syntax/3-slices/src/main.rs b/2-foundations-of-rust/3-advanced-syntax/3-slices/src/main.rs index a4d5324..c4bab56 100644 --- a/2-foundations-of-rust/3-advanced-syntax/3-slices/src/main.rs +++ b/2-foundations-of-rust/3-advanced-syntax/3-slices/src/main.rs @@ -8,10 +8,10 @@ /// Merge two array slices (that have to be sorted) into a vector fn merge(a: &[i32], b: &[i32]) -> Vec { - let mut dest = Vec::new(); + let mut dest = Vec::::new(); - let a_idx = 0; - let b_idx = 0; + let mut a_idx = 0; + let mut b_idx = 0; while a_idx < a.len() && b_idx < b.len() { if a[a_idx] <= b[b_idx] { @@ -23,11 +23,11 @@ fn merge(a: &[i32], b: &[i32]) -> Vec { } } - for elem in a[a_idx..] { - dest.push(elem) + for elem in &a[a_idx..] { + dest.push(*elem) } - for elem in b[b_idx..] { - dest.push(elem) + for elem in &b[b_idx..] { + dest.push(*elem) } dest @@ -36,8 +36,9 @@ fn merge(a: &[i32], b: &[i32]) -> Vec { /// Take an array slice, and sort into a freshly constructed vector using the above function fn merge_sort(data: &[i32]) -> Vec { if data.len() > 1 { - // implement this - todo!() + let s1 = merge_sort(&data[..(data.len() / 2)]); + let s2 = merge_sort(&data[(data.len() / 2)..]); + merge(s1.as_slice(), s2.as_slice()) } else { data.to_vec() } @@ -73,10 +74,13 @@ mod test { #[test] fn test_sort() { - assert_eq!(merge_sort(&[]), vec![]); - assert_eq!(merge_sort(&[5]), vec![5]); - assert_eq!(merge_sort(&[1,2,3]), vec![1,2,3]); - assert_eq!(merge_sort(&[47,42,5,1]), vec![1,5,42,47]); - assert_eq!(merge_sort(&[6,47,42,5,1,123]), vec![1,5,6,42,47,123]); + assert_eq!(merge_sort(&[]), vec![]); + assert_eq!(merge_sort(&[5]), vec![5]); + assert_eq!(merge_sort(&[1, 2, 3]), vec![1, 2, 3]); + assert_eq!(merge_sort(&[47, 42, 5, 1]), vec![1, 5, 42, 47]); + assert_eq!( + merge_sort(&[6, 47, 42, 5, 1, 123]), + vec![1, 5, 6, 42, 47, 123] + ); } } From 0eaa803c87eb4ac2c71f32d8b93a3cc3fe6fe6a8 Mon Sep 17 00:00:00 2001 From: mucel29 Date: Fri, 13 Dec 2024 20:36:37 +0200 Subject: [PATCH 7/7] Laborator 4 & 5 --- .../4-ring-buffer/src/main.rs | 43 +- .../5-boxed-data/src/main.rs | 69 ++- .../1-local-storage-vec/src/lib.rs | 436 ++++++++++++------ 3 files changed, 382 insertions(+), 166 deletions(-) diff --git a/2-foundations-of-rust/3-advanced-syntax/4-ring-buffer/src/main.rs b/2-foundations-of-rust/3-advanced-syntax/4-ring-buffer/src/main.rs index 95d8475..41b1f06 100644 --- a/2-foundations-of-rust/3-advanced-syntax/4-ring-buffer/src/main.rs +++ b/2-foundations-of-rust/3-advanced-syntax/4-ring-buffer/src/main.rs @@ -19,15 +19,22 @@ // - add a method "peek" so that "queue.peek()" returns the same thing as "queue.read()", but leaves the element in the queue struct RingBuffer { - data: [u8; 16], + data: Box<[u8]>, start: usize, end: usize, } impl RingBuffer { - fn new() -> RingBuffer { + // fn new() -> RingBuffer { + // RingBuffer { + // data: make_box(16), + // start: 0, + // end: 0, + // } + // } + fn new(size: usize) -> RingBuffer { RingBuffer { - data: [0; 16], + data: make_box(size), start: 0, end: 0, } @@ -37,7 +44,12 @@ impl RingBuffer { /// it returns None if the queue was empty fn read(&mut self) -> Option { - todo!() + if self.start != self.end { + self.start += 1; + Some(self.data[self.start - 1]) + } else { + None + } } /// This function tries to put `value` on the queue; and returns true if this succeeds @@ -55,6 +67,18 @@ impl RingBuffer { true } } + + fn has_room(&self) -> bool { + self.end < self.data.len() - 1 + } + + fn peek(&self) -> Option { + if self.start != self.end { + Some(self.data[self.start]) + } else { + None + } + } } /// This function creates an "owned slice" a user-selectable size by allocating it as a vector (filled with zeros) using vec![], and then turning it @@ -75,12 +99,21 @@ impl Iterator for RingBuffer { } fn main() { - let mut queue = RingBuffer::new(); + let mut queue = RingBuffer::new(7); assert!(queue.write(1)); assert!(queue.write(2)); assert!(queue.write(3)); assert!(queue.write(4)); assert!(queue.write(5)); + + assert!(queue.has_room()); + println!("Queue still has room!"); + assert!(queue.write(6)); + assert!(!queue.has_room()); + println!("Queue is full!"); + + assert_eq!(queue.peek(), Some(1)); + queue.read(); for elem in queue { println!("{elem}"); } diff --git a/2-foundations-of-rust/3-advanced-syntax/5-boxed-data/src/main.rs b/2-foundations-of-rust/3-advanced-syntax/5-boxed-data/src/main.rs index 12d9f0e..b2a2b6e 100644 --- a/2-foundations-of-rust/3-advanced-syntax/5-boxed-data/src/main.rs +++ b/2-foundations-of-rust/3-advanced-syntax/5-boxed-data/src/main.rs @@ -6,7 +6,7 @@ /// - Add support for multiplication and division /// /// - We have added the form "Summation(Vec)", representing the sum of a list of expressions. -/// Question: why can we get away with Vec enough in that case, instead of Box> ? +/// Question: why can we get away with Vec enough in that case, instead of Box> ? /// /// - EXTRA: Since division can fail, the function eval needs to return an Option, where None indicates that a division by /// zero has occurred. Can you change the code so that that errors are propagated correctly? (hint: use the ? syntax). @@ -16,8 +16,11 @@ enum Expr { Const(i64), Add(Box, Box), Sub(Box, Box), + Mul(Box, Box), + Div(Box, Box), Var, Summation(Vec), + Sigma(i64, i64, Box), } // inject these two identifiers directly into the current namespace @@ -36,30 +39,52 @@ fn sub(x: Expr, y: Expr) -> Expr { } fn mul(x: Expr, y: Expr) -> Expr { - todo!() + Expr::Mul(Box::new(x), Box::new(y)) } fn div(x: Expr, y: Expr) -> Expr { - todo!() + Expr::Div(Box::new(x), Box::new(y)) +} + +fn sigma(x: i64, y: i64, z: Expr) -> Expr { + Expr::Sigma(x, y, Box::new(z)) } // ... -fn eval(expr: &Expr, var: i64) -> i64 { +fn eval(expr: &Expr, var: i64) -> Option { // this should return an Option use Expr::*; match expr { - Const(k) => *k, - Var => var, - Add(lhs, rhs) => eval(lhs, var) + eval(rhs, var), - Sub(lhs, rhs) => eval(lhs, var) - eval(rhs, var), + Const(k) => Some(*k), + Var => Some(var), + Add(lhs, rhs) => Some(eval(lhs, var).unwrap() + eval(rhs, var).unwrap()), + Sub(lhs, rhs) => Some(eval(lhs, var).unwrap() - eval(rhs, var).unwrap()), + + Mul(lhs, rhs) => Some(eval(lhs, var).unwrap() * eval(rhs, var).unwrap()), + Div(lhs, rhs) => { + if eval(rhs, var).unwrap() != 0 { + Some(eval(lhs, var).unwrap() / eval(rhs, var).unwrap()) + } else { + None + } + } Summation(exprs) => { let mut acc = 0; for e in exprs { - acc += eval(e, var); + acc += eval(e, var).unwrap(); } - acc + Some(acc) + } + + Sigma(from, to, expr) => { + let mut acc = 0; + for i in *from..=*to { + acc += eval(expr, i).unwrap(); + } + + Some(acc) } } } @@ -71,7 +96,7 @@ fn main() { "{:?} with Var = {} ==> {}", &expr, value, - eval(&expr, value) + eval(&expr, value).unwrap() ); }; @@ -81,6 +106,16 @@ fn main() { test(sub(Var, Var)); test(add(sub(Var, Const(5)), Const(5))); test(Summation(vec![Var, Const(1)])); + test(mul(Const(5), Const(7))); + test(div(Const(16), Const(4))); + //test(div(Var, Const(0))); + + //15 + test(sigma(1, 5, Var)); + // 30 + test(sigma(1, 5, mul(Const(2), Var))); + // (5 * 6 * 11) / 6 + test(sigma(1, 5, mul(Var, Var))); } #[cfg(test)] @@ -90,12 +125,12 @@ mod test { #[test] fn test_cases() { let x = 42; - assert_eq!(eval(&Const(5), x), 5); - assert_eq!(eval(&Var, x), 42); - assert_eq!(eval(&sub(Var, Const(5)), x), 37); - assert_eq!(eval(&sub(Var, Var), x), 0); - assert_eq!(eval(&add(sub(Var, Const(5)), Const(5)), x), 42); - assert_eq!(eval(&Summation(vec![Var, Const(1)]), x), 43); + assert_eq!(eval(&Const(5), x).unwrap(), 5); + assert_eq!(eval(&Var, x).unwrap(), 42); + assert_eq!(eval(&sub(Var, Const(5)), x).unwrap(), 37); + assert_eq!(eval(&sub(Var, Var), x).unwrap(), 0); + assert_eq!(eval(&add(sub(Var, Const(5)), Const(5)), x).unwrap(), 42); + assert_eq!(eval(&Summation(vec![Var, Const(1)]), x).unwrap(), 43); } } diff --git a/2-foundations-of-rust/4-traits-and-generics/1-local-storage-vec/src/lib.rs b/2-foundations-of-rust/4-traits-and-generics/1-local-storage-vec/src/lib.rs index 6d71caf..689bd71 100644 --- a/2-foundations-of-rust/4-traits-and-generics/1-local-storage-vec/src/lib.rs +++ b/2-foundations-of-rust/4-traits-and-generics/1-local-storage-vec/src/lib.rs @@ -1,10 +1,17 @@ +use std::{ + fmt::{Debug, Display}, + slice::{Iter, IterMut}, + usize, +}; + /// A growable, generic list that resides on the stack if it's small, /// but is moved to the heap to grow larger if needed. /// This list is generic over the items it contains as well as the /// size of its buffer if it's on the stack. pub enum LocalStorageVec { // TODO add some variants containing data - // to make the compiler happy + Stack { buf: [T; N], len: usize }, + Heap(Vec), // to make the compiler happy } // **Below `From` implementation is used in the tests and are therefore given. However, @@ -47,6 +54,146 @@ where } } +impl From> for LocalStorageVec +where + T: Default, +{ + fn from(v: Vec) -> Self { + Self::Heap(v) + } +} + +impl AsRef<[T]> for LocalStorageVec { + fn as_ref(&self) -> &[T] { + match self { + Self::Stack { buf, len } => &buf[..*len], + Self::Heap(v) => v.as_slice(), + } + } +} + +impl AsMut<[T]> for LocalStorageVec { + fn as_mut(&mut self) -> &mut [T] { + match self { + Self::Stack { buf, len } => &mut buf[..*len], + Self::Heap(v) => v.as_mut_slice(), + } + } +} + +impl Debug for LocalStorageVec +where + T: Debug, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Stack { buf, len } => f + .debug_struct("Stack") + .field("buf", buf) + .field("len", len) + .finish(), + Self::Heap(v) => f.debug_struct("Heap").field("v", v).finish(), + } + } +} + +impl LocalStorageVec { + pub fn new() -> Self { + LocalStorageVec::Stack { + buf: [T::default(); N], + len: 0, + } + } + + pub fn len(&self) -> usize { + match self { + Self::Stack { buf: _, len } => *len, + Self::Heap(v) => v.len(), + } + } + + pub fn push(&mut self, value: T) -> () { + match self { + Self::Stack { buf, len } => { + if *len < N { + buf[*len] = value; + *len = *len + 1; + } else { + *self = Self::from(buf.to_vec()); + self.push(value); + } + } + Self::Heap(v) => { + v.push(value); + } + } + } + + pub fn pop(&mut self) -> Option { + match self { + Self::Stack { buf, len } => { + if *len == 0 { + None + } else { + *len = *len - 1; + Some(buf[*len]) + } + } + Self::Heap(v) => v.pop(), + } + } + + pub fn insert(&mut self, pos: usize, value: T) -> () { + match self { + Self::Stack { buf, len } => { + if *len < N { + *len = *len + 1; + for i in (pos..*len).rev() { + buf[i] = buf[i - 1]; + } + buf[pos] = value; + } else { + *self = Self::from(buf.to_vec()); + self.insert(pos, value); + } + } + Self::Heap(v) => { + v.insert(pos, value); + } + } + } + + pub fn remove(&mut self, pos: usize) -> T { + match self { + Self::Stack { buf, len } => { + let value = buf[pos]; + for i in pos..*len { + buf[i] = buf[i + 1]; + } + *len = *len - 1; + value + } + Self::Heap(v) => v.remove(pos), + } + } + + pub fn clear(&mut self) -> () { + match self { + Self::Stack { buf, len } => { + *len = 0; + } + Self::Heap(v) => v.clear(), + } + } + + pub fn into_iter(&self) -> Iter<'_, T> { + match self { + Self::Stack { buf, len: _ } => buf.into_iter(), + Self::Heap(v) => v.into_iter(), + } + } +} + #[cfg(test)] mod test { use crate::LocalStorageVec; @@ -78,167 +225,168 @@ mod test { } // Uncomment me for part B - // #[test] - // fn it_from_vecs() { - // // The `vec!` macro creates a `Vec` in a way that resembles - // // array-initialization syntax. - // let vec: LocalStorageVec = LocalStorageVec::from(vec![1, 2, 3]); - // // Assert that the call to `from` indeed yields a `Heap` variant - // assert!(matches!(vec, LocalStorageVec::Heap(_))); - // - // let vec: LocalStorageVec = LocalStorageVec::from(vec![1, 2, 3]); - // - // assert!(matches!(vec, LocalStorageVec::Heap(_))); - // } + #[test] + fn it_from_vecs() { + // The `vec!` macro creates a `Vec` in a way that resembles + // array-initialization syntax. + let vec: LocalStorageVec = LocalStorageVec::from(vec![1, 2, 3]); + // Assert that the call to `from` indeed yields a `Heap` variant + assert!(matches!(vec, LocalStorageVec::Heap(_))); + + let vec: LocalStorageVec = LocalStorageVec::from(vec![1, 2, 3]); + + assert!(matches!(vec, LocalStorageVec::Heap(_))); + } // Uncomment me for part C - // #[test] - // fn it_as_refs() { - // let vec: LocalStorageVec = LocalStorageVec::from([0; 128]); - // let slice: &[i32] = vec.as_ref(); - // assert!(slice.len() == 128); - // let vec: LocalStorageVec = LocalStorageVec::from([0; 128]); - // let slice: &[i32] = vec.as_ref(); - // assert!(slice.len() == 128); - // - // let mut vec: LocalStorageVec = LocalStorageVec::from([0; 128]); - // let slice_mut: &[i32] = vec.as_mut(); - // assert!(slice_mut.len() == 128); - // let mut vec: LocalStorageVec = LocalStorageVec::from([0; 128]); - // let slice_mut: &[i32] = vec.as_mut(); - // assert!(slice_mut.len() == 128); - // } + #[test] + fn it_as_refs() { + let vec: LocalStorageVec = LocalStorageVec::from([0; 128]); + let slice: &[i32] = vec.as_ref(); + assert!(slice.len() == 128); + let vec: LocalStorageVec = LocalStorageVec::from([0; 128]); + let slice: &[i32] = vec.as_ref(); + assert!(slice.len() == 128); + + let mut vec: LocalStorageVec = LocalStorageVec::from([0; 128]); + let slice_mut: &[i32] = vec.as_mut(); + assert!(slice_mut.len() == 128); + let mut vec: LocalStorageVec = LocalStorageVec::from([0; 128]); + let slice_mut: &[i32] = vec.as_mut(); + assert!(slice_mut.len() == 128); + } // Uncomment me for part D - // #[test] - // fn it_constructs() { - // let vec: LocalStorageVec = LocalStorageVec::new(); - // // Assert that the call to `new` indeed yields a `Stack` variant with zero length - // assert!(matches!(vec, LocalStorageVec::Stack { buf: _, len: 0 })); - // } + #[test] + fn it_constructs() { + let vec: LocalStorageVec = LocalStorageVec::new(); + // Assert that the call to `new` indeed yields a `Stack` variant with zero length + assert!(matches!(vec, LocalStorageVec::Stack { buf: _, len: 0 })); + } // Uncomment me for part D - // #[test] - // fn it_lens() { - // let vec: LocalStorageVec<_, 3> = LocalStorageVec::from([0, 1, 2]); - // assert_eq!(vec.len(), 3); - // let vec: LocalStorageVec<_, 2> = LocalStorageVec::from([0, 1, 2]); - // assert_eq!(vec.len(), 3); - // } + #[test] + fn it_lens() { + let vec: LocalStorageVec<_, 3> = LocalStorageVec::from([0, 1, 2]); + assert_eq!(vec.len(), 3); + let vec: LocalStorageVec<_, 2> = LocalStorageVec::from([0, 1, 2]); + assert_eq!(vec.len(), 3); + } // Uncomment me for part D - // #[test] - // fn it_pushes() { - // let mut vec: LocalStorageVec<_, 128> = LocalStorageVec::new(); - // for value in 0..128 { - // vec.push(value); - // } - // assert!(matches!(vec, LocalStorageVec::Stack { len: 128, .. })); - // for value in 128..256 { - // vec.push(value); - // } - // assert!(matches!(vec, LocalStorageVec::Heap(v) if v.len() == 256)) - // } + #[test] + fn it_pushes() { + let mut vec: LocalStorageVec<_, 128> = LocalStorageVec::new(); + for value in 0..128 { + vec.push(value); + } + assert!(matches!(vec, LocalStorageVec::Stack { len: 128, .. })); + for value in 128..256 { + vec.push(value); + } + assert!(matches!(vec, LocalStorageVec::Heap(v) if v.len() == 256)) + } // Uncomment me for part D - // #[test] - // fn it_pops() { - // let mut vec: LocalStorageVec<_, 128> = LocalStorageVec::from([0; 128]); - // for _ in 0..128 { - // assert_eq!(vec.pop(), Some(0)) - // } - // assert_eq!(vec.pop(), None); - // - // let mut vec: LocalStorageVec<_, 128> = LocalStorageVec::from([0; 256]); - // for _ in 0..256 { - // assert_eq!(vec.pop(), Some(0)) - // } - // assert_eq!(vec.pop(), None); - // - // let mut vec: LocalStorageVec<_, 128> = LocalStorageVec::from(vec![0; 256]); - // for _ in 0..256 { - // assert_eq!(vec.pop(), Some(0)) - // } - // assert_eq!(vec.pop(), None); - // } + #[test] + fn it_pops() { + let mut vec: LocalStorageVec<_, 128> = LocalStorageVec::from([0; 128]); + for _ in 0..128 { + assert_eq!(vec.pop(), Some(0)) + } + assert_eq!(vec.pop(), None); + + let mut vec: LocalStorageVec<_, 128> = LocalStorageVec::from([0; 256]); + for _ in 0..256 { + assert_eq!(vec.pop(), Some(0)) + } + assert_eq!(vec.pop(), None); + + let mut vec: LocalStorageVec<_, 128> = LocalStorageVec::from(vec![0; 256]); + for _ in 0..256 { + assert_eq!(vec.pop(), Some(0)) + } + assert_eq!(vec.pop(), None); + } // Uncomment me for part D - // #[test] - // fn it_inserts() { - // let mut vec: LocalStorageVec<_, 4> = LocalStorageVec::from([0, 1, 2]); - // vec.insert(1, 3); - // assert!(matches!( - // vec, - // LocalStorageVec::Stack { - // buf: [0, 3, 1, 2], - // len: 4 - // } - // )); - // - // let mut vec: LocalStorageVec<_, 4> = LocalStorageVec::from([0, 1, 2, 3]); - // vec.insert(1, 3); - // assert!(matches!(vec, LocalStorageVec::Heap { .. })); - // assert_eq!(vec.as_ref(), &[0, 3, 1, 2, 3]); - // - // let mut vec: LocalStorageVec<_, 4> = LocalStorageVec::from([0, 1, 2, 3, 4]); - // vec.insert(1, 3); - // assert!(matches!(vec, LocalStorageVec::Heap { .. })); - // assert_eq!(vec.as_ref(), &[0, 3, 1, 2, 3, 4]) - // } + #[test] + fn it_inserts() { + let mut vec: LocalStorageVec<_, 4> = LocalStorageVec::from([0, 1, 2]); + vec.insert(1, 3); + + assert!(matches!( + vec, + LocalStorageVec::Stack { + buf: [0, 3, 1, 2], + len: 4 + } + )); + + let mut vec: LocalStorageVec<_, 4> = LocalStorageVec::from([0, 1, 2, 3]); + vec.insert(1, 3); + assert!(matches!(vec, LocalStorageVec::Heap { .. })); + assert_eq!(vec.as_ref(), &[0, 3, 1, 2, 3]); + + let mut vec: LocalStorageVec<_, 4> = LocalStorageVec::from([0, 1, 2, 3, 4]); + vec.insert(1, 3); + assert!(matches!(vec, LocalStorageVec::Heap { .. })); + assert_eq!(vec.as_ref(), &[0, 3, 1, 2, 3, 4]) + } // Uncomment me for part D - // #[test] - // fn it_removes() { - // let mut vec: LocalStorageVec<_, 4> = LocalStorageVec::from([0, 1, 2]); - // let elem = vec.remove(1); - // dbg!(&vec); - // assert!(matches!( - // vec, - // LocalStorageVec::Stack { - // buf: [0, 2, _, _], - // len: 2 - // } - // )); - // assert_eq!(elem, 1); - // - // let mut vec: LocalStorageVec<_, 2> = LocalStorageVec::from([0, 1, 2]); - // let elem = vec.remove(1); - // assert!(matches!(vec, LocalStorageVec::Heap(..))); - // assert_eq!(vec.as_ref(), &[0, 2]); - // assert_eq!(elem, 1); - // } + #[test] + fn it_removes() { + let mut vec: LocalStorageVec<_, 4> = LocalStorageVec::from([0, 1, 2]); + let elem = vec.remove(1); + dbg!(&vec); + assert!(matches!( + vec, + LocalStorageVec::Stack { + buf: [0, 2, _, _], + len: 2 + } + )); + assert_eq!(elem, 1); + + let mut vec: LocalStorageVec<_, 2> = LocalStorageVec::from([0, 1, 2]); + let elem = vec.remove(1); + assert!(matches!(vec, LocalStorageVec::Heap(..))); + assert_eq!(vec.as_ref(), &[0, 2]); + assert_eq!(elem, 1); + } // Uncomment me for part D - // #[test] - // fn it_clears() { - // let mut vec: LocalStorageVec<_, 10> = LocalStorageVec::from([0, 1, 2, 3]); - // assert!(matches!(vec, LocalStorageVec::Stack { buf: _, len: 4 })); - // vec.clear(); - // assert_eq!(vec.len(), 0); - // - // let mut vec: LocalStorageVec<_, 3> = LocalStorageVec::from([0, 1, 2, 3]); - // assert!(matches!(vec, LocalStorageVec::Heap(_))); - // vec.clear(); - // assert_eq!(vec.len(), 0); - // } + #[test] + fn it_clears() { + let mut vec: LocalStorageVec<_, 10> = LocalStorageVec::from([0, 1, 2, 3]); + assert!(matches!(vec, LocalStorageVec::Stack { buf: _, len: 4 })); + vec.clear(); + assert_eq!(vec.len(), 0); + + let mut vec: LocalStorageVec<_, 3> = LocalStorageVec::from([0, 1, 2, 3]); + assert!(matches!(vec, LocalStorageVec::Heap(_))); + vec.clear(); + assert_eq!(vec.len(), 0); + } // Uncomment me for part E - // #[test] - // fn it_iters() { - // let vec: LocalStorageVec<_, 128> = LocalStorageVec::from([0; 32]); - // let mut iter = vec.into_iter(); - // for item in &mut iter { - // assert_eq!(item, 0); - // } - // assert_eq!(iter.next(), None); - // - // let vec: LocalStorageVec<_, 128> = LocalStorageVec::from(vec![0; 128]); - // let mut iter = vec.into_iter(); - // for item in &mut iter { - // assert_eq!(item, 0); - // } - // assert_eq!(iter.next(), None); - // } + #[test] + fn it_iters() { + let vec: LocalStorageVec<_, 128> = LocalStorageVec::from([0; 32]); + let mut iter = vec.into_iter(); + for item in &mut iter { + assert_eq!(*item, 0); + } + assert_eq!(iter.next(), None); + + let vec: LocalStorageVec<_, 128> = LocalStorageVec::from(vec![0; 128]); + let mut iter = vec.into_iter(); + for item in &mut iter { + assert_eq!(*item, 0); + } + assert_eq!(iter.next(), None); + } // Uncomment me for part F // #[test]