diff --git a/Dockerfile b/Dockerfile index 28cf2879..3faf0858 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ ### Test Image specific config -FROM rust:1.89-slim-bookworm +FROM rust:1.90-slim-trixie RUN apt-get update RUN apt-get -y install pkg-config libssl-dev moreutils diff --git a/solutions/border_cross/Cargo.toml b/solutions/border_cross/Cargo.toml index 14b91398..b5a2dbbe 100644 --- a/solutions/border_cross/Cargo.toml +++ b/solutions/border_cross/Cargo.toml @@ -2,7 +2,7 @@ name = "border_cross" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/border_cross/src/lib.rs b/solutions/border_cross/src/lib.rs index e290caec..acc266a2 100644 --- a/solutions/border_cross/src/lib.rs +++ b/solutions/border_cross/src/lib.rs @@ -1,10 +1,3 @@ -// Create the trait Vehicle with the model and year - -// In a border cross you want to keep a list of all the vehicles that -// are waiting to enter the country. You want to keep a waiting list -// of the vehicle but the vehicles can be of two types: Car or Truck -// With the following structure: -#[allow(dead_code)] pub struct Car<'a> { pub plate_nbr: &'a str, pub model: &'a str, @@ -12,7 +5,6 @@ pub struct Car<'a> { pub year: u32, } -#[allow(dead_code)] pub struct Truck<'a> { pub plate_nbr: &'a str, pub model: &'a str, @@ -27,135 +19,30 @@ pub trait Vehicle { } impl Vehicle for Truck<'_> { + #[inline] fn model(&self) -> &str { self.model } + #[inline] fn year(&self) -> u32 { self.year } } impl Vehicle for Car<'_> { + #[inline] fn model(&self) -> &str { self.model } + + #[inline] fn year(&self) -> u32 { self.year } } -// create a function that receives a vector of structures that -// implement the Vehicle trait - -#[allow(dead_code)] -pub fn all_models(list: Vec<&dyn Vehicle>) -> Vec<&str> { - let mut models = Vec::new(); - for ve in list { - models.push(ve.model()); - } - models -} - -#[cfg(test)] -mod tests { - use super::*; - - fn setup_cars<'a>() -> Vec<&'a dyn Vehicle> { - let cars: Vec<&dyn Vehicle> = vec![ - &Car { - plate_nbr: "A3D5C7", - model: "Model 3", - horse_power: 325, - year: 2010, - }, - &Car { - plate_nbr: "A785P7", - model: "S", - horse_power: 500, - year: 1980, - }, - &Car { - plate_nbr: "D325C7", - model: "300", - horse_power: 300, - year: 2000, - }, - &Car { - plate_nbr: "Z3KCH4", - model: "Montana", - horse_power: 325, - year: 2020, - }, - ]; - cars - } - - fn setup_trucks<'a>() -> Vec<&'a dyn Vehicle> { - let trucks: Vec<&dyn Vehicle> = vec![ - &Truck { - plate_nbr: "V3D5CT", - model: "Ranger", - horse_power: 325, - year: 2010, - load_tons: 40, - }, - &Truck { - plate_nbr: "V785PT", - model: "Silverado", - horse_power: 500, - year: 1980, - load_tons: 40, - }, - &Truck { - plate_nbr: "DE2SC7", - model: "Sierra", - horse_power: 300, - year: 2000, - load_tons: 40, - }, - &Truck { - plate_nbr: "3DH432", - model: "Cybertruck", - horse_power: 325, - year: 2020, - load_tons: 40, - }, - ]; - trucks - } - - #[test] - fn all_car_models() { - let cars = setup_cars(); - assert_eq!(all_models(cars), ["Model 3", "S", "300", "Montana"]); - } - - #[test] - fn all_truck_models() { - let trucks = setup_trucks(); - assert_eq!( - all_models(trucks), - ["Ranger", "Silverado", "Sierra", "Cybertruck"] - ); - } - - #[test] - fn cars_and_trucks_models() { - let mut vehicles = setup_cars(); - vehicles.extend(setup_trucks()); - assert_eq!( - all_models(vehicles), - [ - "Model 3", - "S", - "300", - "Montana", - "Ranger", - "Silverado", - "Sierra", - "Cybertruck" - ] - ); - } +#[inline] +pub fn all_models(list: [&dyn Vehicle; N]) -> [&str; N] { + list.map(Vehicle::model) } diff --git a/solutions/delete_prefix/Cargo.toml b/solutions/delete_prefix/Cargo.toml index 50d13545..df1a156d 100644 --- a/solutions/delete_prefix/Cargo.toml +++ b/solutions/delete_prefix/Cargo.toml @@ -2,7 +2,7 @@ name = "delete_prefix" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/delete_prefix/src/lib.rs b/solutions/delete_prefix/src/lib.rs index 0a23af41..7d94a392 100644 --- a/solutions/delete_prefix/src/lib.rs +++ b/solutions/delete_prefix/src/lib.rs @@ -1,41 +1,4 @@ -// Define the function `delete_prefix(prefix: &str, s: &str) -> Option<&str>` -// That takes 2 slices of string and returns the string of slice s -// with the `prefix` removed wrapped in Some -// If `prefix ` is not contained in `s` return None - -// Example: -// delete_prefix("hello, ", "hello, world")? == "world" -// delete_prefix("not", "win"); - -pub fn delete_prefix<'a, 'b>(prefix: &'b str, s: &'a str) -> Option<&'a str> { - if prefix.len() > s.len() { - return None; - } - let mut char_s = s.chars(); - - for char_prefix in prefix.chars() { - if char_prefix != char_s.next()? { - return None; - } - } - Some(&s[prefix.len()..]) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_delete_prefix() { - assert_eq!( - delete_prefix("augusto", "augusto ornelas"), - Some(" ornelas") - ); - - assert_eq!(delete_prefix("ab", "b"), None); - - assert_eq!(delete_prefix("aa", "ab"), None); - - assert_eq!(delete_prefix("á©", "á©ab"), Some("ab")); - } +#[inline] +pub fn delete_prefix<'a>(prefix: &str, s: &'a str) -> Option<&'a str> { + s.strip_prefix(prefix) } diff --git a/solutions/events/Cargo.toml b/solutions/events/Cargo.toml index 1902fa7a..9258c3a5 100644 --- a/solutions/events/Cargo.toml +++ b/solutions/events/Cargo.toml @@ -2,10 +2,9 @@ name = "events" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -chrono = "0.4" -colored = "2.0.4" +colored = "3.0.0" diff --git a/solutions/events/src/lib.rs b/solutions/events/src/lib.rs index 5cc482e6..6d43c876 100644 --- a/solutions/events/src/lib.rs +++ b/solutions/events/src/lib.rs @@ -1,69 +1,14 @@ -// You're have to design a notification system for a platform -// This events are Remainders, Registrations, Appointments, Holidays -// Create an event handler that depending of the type of event creates -// different notification: different color, different size and -// different position - -// The possible positions are Top, Bottom and Center: Create and Enum -// `Position` with those values - -// Create a struct called `Notification` with the fields -// size: u32, -// color: (u8, u8, u8), -// position: Position, -// content: String, - -// The event that you have to handle are -// enum Event { -// Remainder(&str), -// Registration(Duration), -// Appointment(&str), -// Holiday, -// } - -// Create a method called `notify` -// fn notify(&self) -> Notification -// That returns a notification with the following caracteristics for -// each -// Remainder: -// size= 50, -// color= (50, 50, 50), -// position= Bottom, -// content= the slice associated to the enum value - -// Registration(chrono::Duration), -// size = 30, -// color = (255, 2, 22), -// position = Top, -// content = "You have `duration` left before the registration ends", -// `durations` must be displayed in the form of -// {hours}:{minutes}:{seconds} left for the beginning of the event -// for example if there is two hours 32 minutes and 3 seconds left -// before the registration then the content will be `You have 2:32:2 left before the registration ends` - -// Appointment(text) -// size: 100 -// color: (200, 200, 3) -// position: Center -// content: text associated to the value - -// Holiday -// size: 25 -// color: (0, 255, 0) -// position: Top -// content: "Enjoy your holiday" - -use chrono::Duration; use colored::*; +use std::{fmt, time::Duration}; -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum Position { Top, Bottom, Center, } -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub struct Notification { pub size: u32, pub color: (u8, u8, u8), @@ -71,7 +16,7 @@ pub struct Notification { pub content: String, } -#[derive(Debug)] +#[derive(Clone, Copy)] pub enum Event<'a> { Remainder(&'a str), Registration(Duration), @@ -79,24 +24,20 @@ pub enum Event<'a> { Holiday, } -use std::fmt; - -#[derive(Debug)] -struct DurationInHours { - hours: i64, - minutes: i64, - seconds: i64, +#[derive(Clone, Copy)] +struct ReadableDuration { + hours: u64, + minutes: u64, + seconds: u64, } -impl From<&Duration> for DurationInHours { - fn from(duration: &Duration) -> DurationInHours { - let mut left = duration.num_seconds(); - let hours = left / 3600; - left %= 3600; - let minutes = left / 60; - left %= 60; - let seconds = left; - DurationInHours { +impl From for ReadableDuration { + fn from(duration: Duration) -> Self { + let total_secs = duration.as_secs(); + let hours = total_secs / 3600; + let minutes = (total_secs % 3600) / 60; + let seconds = total_secs % 60; + Self { hours, minutes, seconds, @@ -104,13 +45,15 @@ impl From<&Duration> for DurationInHours { } } -impl fmt::Display for DurationInHours { +impl fmt::Display for ReadableDuration { + #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}H:{}M:{}S", self.hours, self.minutes, self.seconds) } } impl fmt::Display for Notification { + #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, @@ -123,107 +66,36 @@ impl fmt::Display for Notification { } } -use Event::*; - -impl<'a> Event<'a> { - pub fn notify(&self) -> Notification { +impl Event<'_> { + pub fn notify(self) -> Notification { match self { - Remainder(text) => Notification { + Event::Remainder(text) => Notification { size: 50, color: (50, 50, 50), position: Position::Bottom, - content: text.to_string(), + content: text.to_owned(), }, - Registration(time_left) => Notification { + Event::Registration(time_left) => Notification { size: 30, color: (255, 2, 22), position: Position::Top, content: format!( "You have {} left before the registration ends", - DurationInHours::from(time_left) + ReadableDuration::from(time_left) ), }, - Appointment(text) => Notification { + Event::Appointment(text) => Notification { size: 100, color: (200, 200, 3), position: Position::Center, - content: text.to_string(), + content: text.to_owned(), }, - Holiday => Notification { + Event::Holiday => Notification { size: 25, color: (0, 255, 0), position: Position::Top, - content: String::from("Enjoy your holiday"), + content: "Enjoy your holiday".to_owned(), }, } } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn remainder_notification() { - let remainder = Remainder("Go to the doctor"); - let notification = remainder.notify(); - println!("{}", ¬ification); - assert_eq!( - notification, - Notification { - size: 50, - color: (50, 50, 50), - position: Position::Bottom, - content: "Go to the doctor".to_string(), - } - ); - } - - #[test] - fn registration_notification() { - let registration = Registration(Duration::seconds(49094)); - let notification = registration.notify(); - println!("{}", registration.notify()); - assert_eq!( - notification, - Notification { - size: 30, - color: (255, 2, 22), - position: Position::Top, - content: "You have 13H:38M:14S left before the registration ends".to_string(), - } - ); - } - - #[test] - fn appointment_notification() { - let appointment = Appointment("Go to the doctor"); - let notification = appointment.notify(); - println!("{}", ¬ification); - assert_eq!( - notification, - Notification { - size: 100, - color: (200, 200, 3), - position: Position::Center, - content: "Go to the doctor".to_string(), - } - ); - } - - #[test] - fn holiday_notification() { - let holiday = Holiday; - let notification = Holiday.notify(); - println!("{}", holiday.notify()); - assert_eq!( - notification, - Notification { - size: 25, - color: (0, 255, 0), - position: Position::Top, - content: String::from("Enjoy your holiday"), - } - ); - } -} diff --git a/solutions/lifetimes/Cargo.toml b/solutions/lifetimes/Cargo.toml index c2ce271a..114d398e 100644 --- a/solutions/lifetimes/Cargo.toml +++ b/solutions/lifetimes/Cargo.toml @@ -2,7 +2,7 @@ name = "lifetimes" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/lifetimes/src/lib.rs b/solutions/lifetimes/src/lib.rs index 9c17816f..409017a5 100644 --- a/solutions/lifetimes/src/lib.rs +++ b/solutions/lifetimes/src/lib.rs @@ -1,44 +1,11 @@ -// Create a struct called Person that has two fields: name of type -// string slice (&str) and age of type u8 -// and create the associated function new which creates a new person -// with age 0 and with the name given - -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Person<'a> { pub name: &'a str, - pub age: u8, + pub age: u32, } impl<'a> Person<'a> { - pub fn new(name: &str) -> Person { - Person { name, age: 0 } - } -} - -// fn main() { -// let person = Person::new("Leo"); - -// println!("Person = {:?}", person); -// } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn fields() { - let person = Person { - name: "Dijkstra", - age: 10, - }; - assert_eq!(person.age, 10); - assert_eq!(person.name, "Dijkstra"); - } - - #[test] - fn create_person() { - let person = Person::new("Leo"); - assert_eq!(person.age, 0); - assert_eq!(person.name, "Leo"); + pub const fn new(name: &'a str) -> Self { + Self { name, age: 0 } } } diff --git a/solutions/macro_map/Cargo.toml b/solutions/macro_map/Cargo.toml index 7d97414b..74883c07 100644 --- a/solutions/macro_map/Cargo.toml +++ b/solutions/macro_map/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "macro_map" version = "0.1.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/solutions/macro_map/src/lib.rs b/solutions/macro_map/src/lib.rs index 3e6c02e4..62e5a72d 100644 --- a/solutions/macro_map/src/lib.rs +++ b/solutions/macro_map/src/lib.rs @@ -1,17 +1,14 @@ #[macro_export] macro_rules! hash_map { - () => {{ - crate::HashMap::new() - }}; - - ($($k:expr => $v:expr),+ $(,)?) => {{ - use crate::HashMap; - let mut hm = HashMap::new(); + () => { + ::std::collections::HashMap::new() + }; + ($($key:expr => $value:expr),+ $(,)?) => {{ + let mut map = ::std::collections::HashMap::new(); $( - hm.insert($k, $v); + map.insert($key, $value); )+ - - hm + map }}; } diff --git a/solutions/matrix/Cargo.toml b/solutions/matrix/Cargo.toml index 34e531c2..5d7f1ccf 100644 --- a/solutions/matrix/Cargo.toml +++ b/solutions/matrix/Cargo.toml @@ -2,9 +2,9 @@ name = "matrix" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -lalgebra_scalar = { path = "../lalgebra_scalar"} \ No newline at end of file +lalgebra_scalar = { path = "../lalgebra_scalar" } diff --git a/solutions/matrix/src/lib.rs b/solutions/matrix/src/lib.rs index e47b62e7..b4f0ee18 100644 --- a/solutions/matrix/src/lib.rs +++ b/solutions/matrix/src/lib.rs @@ -1,90 +1,21 @@ -// First exercise - -// # Instructions -// Define a data structure to represent a matrix of any size and -// implement the basic operations for this you will need to follow the -// next steps: - -// You can use a 2 dimensional Vec's -// We will consider a matrix as a rectangular arrangements of scalars -// You can use the definition of scalars done in the last exercise: -// `lalgebra_scalar` - -// Then define the associated function `identity` that returns the identity matrix -// of size n -// Ex: -// Matrix::identity(3) == [[1,0,0], [0,1,0], [0,0,1]] - -// And the associated function `zero` that returns a matrix of size -// `row x col` with all the positions filled by zeroes -// Ex: -// Matrix::zero(3, 3) == [[0,0,0],[0,0,0],[0,0,0]] - -// Resources: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html - use lalgebra_scalar::Scalar; -mod mult; -mod ops; -#[derive(Debug, Eq, PartialEq, Clone)] -pub struct Matrix(pub Vec>); +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub struct Matrix(pub [[T; W]; H]); -impl> Matrix { - pub fn new() -> Matrix { - Matrix(vec![Vec::new()]) - } - // It returns the zero matrix of the size given by the row and - // column parameters - pub fn zero(row: usize, col: usize) -> Matrix { - let mut matrix = Matrix(Vec::new()); - for _ in 0..row { - matrix.0.push(vec![T::zero(); col]); - } - matrix +impl> Matrix { + #[inline] + pub fn zero() -> Self { + Matrix([[T::zero(); W]; H]) } +} - pub fn identity(n: usize) -> Matrix { - let mut matrix = Matrix::new(); - for y in 0..n { - if y > 0 { - matrix.0.push(Vec::new()); - } - for x in 0..n { - if y == x { - matrix.0[y].push(T::one()); - } else { - matrix.0[y].push(T::zero()); - } - } +impl> Matrix { + pub fn identity() -> Self { + let mut matrix = Matrix::zero(); + for i in 0..S { + matrix.0[i][i] = T::one(); } matrix } } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn zero_property() { - let matrix: Matrix = Matrix::zero(3, 4); - let expected: Matrix = - Matrix(vec![vec![0, 0, 0, 0], vec![0, 0, 0, 0], vec![0, 0, 0, 0]]); - assert_eq!(matrix, expected); - - let matrix: Matrix = Matrix::zero(2, 2); - let expected: Matrix = Matrix(vec![vec![0, 0], vec![0, 0]]); - assert_eq!(matrix, expected); - } - - #[test] - fn identy_matrix() { - let matrix: Matrix = Matrix::identity(2); - let expected: Matrix = Matrix(vec![vec![1, 0], vec![0, 1]]); - assert_eq!(matrix, expected); - - let matrix: Matrix = Matrix::identity(3); - let expected: Matrix = Matrix(vec![vec![1, 0, 0], vec![0, 1, 0], vec![0, 0, 1]]); - assert_eq!(matrix, expected); - } -} diff --git a/solutions/matrix/src/mult.rs b/solutions/matrix/src/mult.rs deleted file mode 100644 index b50c5451..00000000 --- a/solutions/matrix/src/mult.rs +++ /dev/null @@ -1,88 +0,0 @@ -// Now define the matrix multiplication by implementing the -// std::ops::Mul for the type matrix - -use crate::Matrix; -use crate::Scalar; -use std::ops::Mul; - -impl> Matrix { - pub fn number_of_cols(&self) -> usize { - self.0[0].len() - } - - pub fn number_of_rows(&self) -> usize { - self.0.len() - } - - pub fn row(&self, n: usize) -> Vec { - self.0[n].clone() - } - - pub fn col(&self, n: usize) -> Vec { - let mut column = Vec::new(); - for row in &self.0 { - for (i, v) in row.iter().enumerate() { - if i == n { - column.push(v.clone()); - } - } - } - column - } -} - -impl + std::iter::Sum<::Output>> Mul for Matrix { - type Output = Option; - fn mul(self, rhs: Self) -> Self::Output { - // If the number of columns of self match don't match the number of - // number_of_rows of self don't match return None - let row_lenght = self.number_of_rows(); - let col_lenght = rhs.number_of_cols(); - if self.number_of_cols() != rhs.number_of_rows() { - return None; - } - let mut result: Matrix = Matrix::zero(row_lenght, col_lenght); - for j in 0..result.number_of_rows() { - for i in 0..result.number_of_cols() { - result.0[j][i] = self - .row(j) - .iter() - .zip(rhs.col(i).iter()) - .map(|(x, y)| x.clone() * y.clone()) - .sum(); - } - } - Some(result) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn get_row() { - let matrix: Matrix = Matrix(vec![vec![3, 6], vec![8, 0]]); - assert_eq!(vec![3u32, 6], matrix.row(0)); - assert_eq!(vec![8u32, 0], matrix.row(1)); - } - - #[test] - fn get_col() { - let matrix: Matrix = Matrix(vec![vec![3, 6], vec![8, 0]]); - assert_eq!(matrix.col(0), vec![3u32, 8]); - assert_eq!(vec![6u32, 0], matrix.col(1)); - } - - #[test] - fn matrix_multiplication() { - let matrix_1: Matrix = Matrix(vec![vec![0, 1], vec![0, 0]]); - let matrix_2: Matrix = Matrix(vec![vec![0, 0], vec![1, 0]]); - let expected: Matrix = Matrix(vec![vec![1, 0], vec![0, 0]]); - assert_eq!(matrix_1 * matrix_2, Some(expected)); - - let matrix_1: Matrix = Matrix(vec![vec![0, 1], vec![0, 0]]); - let matrix_2: Matrix = Matrix(vec![vec![0, 0, 0], vec![1, 0, 0], vec![1, 1, 1]]); - assert_eq!(matrix_1 * matrix_2, None); - } -} diff --git a/solutions/matrix/src/ops.rs b/solutions/matrix/src/ops.rs deleted file mode 100644 index 0d72442a..00000000 --- a/solutions/matrix/src/ops.rs +++ /dev/null @@ -1,85 +0,0 @@ -// In this exercise you will define the basic operations with a matrix -// starting by implementing the `std::ops::Add` trait - -// Define the operation + (by defining the trait std::ops::Add) for -// two matrices remember that two matrices can only be added if they -// have the same size. Therefore the add method must handle the -// possibility of failure by returning an Option - -use crate::{Matrix, Scalar}; -use std::ops::Add; - -impl + std::ops::Add> Add for Matrix { - type Output = Option; - - fn add(self, other: Self) -> Self::Output { - if self.0[0].len() != other.0[0].len() || self.0.len() != other.0.len() { - return None; - } - - let mut matrix = Matrix::new(); - for (j, row) in self.0.iter().enumerate() { - if j > 0 { - matrix.0.push(Vec::new()); - } - for (i, v) in row.iter().enumerate() { - matrix.0[j].push(v.clone() + other.0[j][i].clone()); - } - } - - Some(matrix) - } -} - -use std::ops::Sub; - -impl + Sub> Sub for Matrix { - type Output = Option; - - fn sub(self, other: Self) -> Self::Output { - if self.0[0].len() != other.0[0].len() || self.0.len() != other.0.len() { - return None; - } - - let mut matrix = Matrix::new(); - for (j, row) in self.0.iter().enumerate() { - if j > 0 { - matrix.0.push(Vec::new()); - } - for (i, v) in row.iter().enumerate() { - matrix.0[j].push(v.clone() - other.0[j][i].clone()); - } - } - - Some(matrix) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn addition() { - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1], vec![1, 1]]); - let expected = Matrix(vec![vec![2, 2], vec![2, 2]]); - assert_eq!(matrix + matrix_2, Some(expected)); - - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1, 3], vec![1, 1]]); - assert_eq!(matrix + matrix_2, None); - } - - #[test] - fn subtraction() { - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1], vec![1, 1]]); - let expected = Matrix(vec![vec![0, 0], vec![0, 0]]); - assert_eq!(matrix - matrix_2, Some(expected)); - - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1, 3], vec![1, 1]]); - assert_eq!(matrix - matrix_2, None); - } -} diff --git a/solutions/matrix_ops/Cargo.toml b/solutions/matrix_ops/Cargo.toml index 3d18584a..3606af54 100644 --- a/solutions/matrix_ops/Cargo.toml +++ b/solutions/matrix_ops/Cargo.toml @@ -2,9 +2,10 @@ name = "matrix_ops" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -lalgebra_scalar = { path = "../lalgebra_scalar"} \ No newline at end of file +lalgebra_scalar = { path = "../lalgebra_scalar" } +matrix = { path = "../matrix" } diff --git a/solutions/matrix_ops/src/lib.rs b/solutions/matrix_ops/src/lib.rs index e47b62e7..db3fc53c 100644 --- a/solutions/matrix_ops/src/lib.rs +++ b/solutions/matrix_ops/src/lib.rs @@ -1,90 +1,46 @@ -// First exercise - -// # Instructions -// Define a data structure to represent a matrix of any size and -// implement the basic operations for this you will need to follow the -// next steps: - -// You can use a 2 dimensional Vec's -// We will consider a matrix as a rectangular arrangements of scalars -// You can use the definition of scalars done in the last exercise: -// `lalgebra_scalar` - -// Then define the associated function `identity` that returns the identity matrix -// of size n -// Ex: -// Matrix::identity(3) == [[1,0,0], [0,1,0], [0,0,1]] - -// And the associated function `zero` that returns a matrix of size -// `row x col` with all the positions filled by zeroes -// Ex: -// Matrix::zero(3, 3) == [[0,0,0],[0,0,0],[0,0,0]] - -// Resources: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html +use std::ops::{Add, Mul, Sub}; use lalgebra_scalar::Scalar; -mod mult; -mod ops; +use matrix::Matrix; -#[derive(Debug, Eq, PartialEq, Clone)] -pub struct Matrix(pub Vec>); +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub struct Wrapper(pub Matrix); -impl> Matrix { - pub fn new() -> Matrix { - Matrix(vec![Vec::new()]) - } - // It returns the zero matrix of the size given by the row and - // column parameters - pub fn zero(row: usize, col: usize) -> Matrix { - let mut matrix = Matrix(Vec::new()); - for _ in 0..row { - matrix.0.push(vec![T::zero(); col]); - } - matrix +impl From<[[T; W]; H]> for Wrapper { + #[inline] + fn from(array: [[T; W]; H]) -> Self { + Wrapper(Matrix(array)) } +} - pub fn identity(n: usize) -> Matrix { - let mut matrix = Matrix::new(); - for y in 0..n { - if y > 0 { - matrix.0.push(Vec::new()); - } - for x in 0..n { - if y == x { - matrix.0[y].push(T::one()); - } else { - matrix.0[y].push(T::zero()); - } +macro_rules! impl_binary_op { + ($trait:ident, $method:ident, $op:tt) => { + impl + $trait> $trait for Wrapper { + type Output = Self; + + #[inline] + fn $method(self, other: Self) -> Self::Output { + std::array::from_fn(|j| { + std::array::from_fn(|i| self.0.0[j][i] $op other.0.0[j][i]) + }).into() } } - matrix - } + }; } -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn zero_property() { - let matrix: Matrix = Matrix::zero(3, 4); - let expected: Matrix = - Matrix(vec![vec![0, 0, 0, 0], vec![0, 0, 0, 0], vec![0, 0, 0, 0]]); - assert_eq!(matrix, expected); - - let matrix: Matrix = Matrix::zero(2, 2); - let expected: Matrix = Matrix(vec![vec![0, 0], vec![0, 0]]); - assert_eq!(matrix, expected); - } +impl_binary_op!(Add, add, +); +impl_binary_op!(Sub, sub, -); - #[test] - fn identy_matrix() { - let matrix: Matrix = Matrix::identity(2); - let expected: Matrix = Matrix(vec![vec![1, 0], vec![0, 1]]); - assert_eq!(matrix, expected); +impl + std::iter::Sum<::Output>> Mul + for Wrapper +{ + type Output = Self; - let matrix: Matrix = Matrix::identity(3); - let expected: Matrix = Matrix(vec![vec![1, 0, 0], vec![0, 1, 0], vec![0, 0, 1]]); - assert_eq!(matrix, expected); + #[inline] + fn mul(self, rhs: Self) -> Self::Output { + std::array::from_fn(|j| { + std::array::from_fn(|i| (0..S).map(|k| self.0.0[j][k] * rhs.0.0[k][i]).sum()) + }) + .into() } } diff --git a/solutions/matrix_ops/src/mult.rs b/solutions/matrix_ops/src/mult.rs deleted file mode 100644 index b50c5451..00000000 --- a/solutions/matrix_ops/src/mult.rs +++ /dev/null @@ -1,88 +0,0 @@ -// Now define the matrix multiplication by implementing the -// std::ops::Mul for the type matrix - -use crate::Matrix; -use crate::Scalar; -use std::ops::Mul; - -impl> Matrix { - pub fn number_of_cols(&self) -> usize { - self.0[0].len() - } - - pub fn number_of_rows(&self) -> usize { - self.0.len() - } - - pub fn row(&self, n: usize) -> Vec { - self.0[n].clone() - } - - pub fn col(&self, n: usize) -> Vec { - let mut column = Vec::new(); - for row in &self.0 { - for (i, v) in row.iter().enumerate() { - if i == n { - column.push(v.clone()); - } - } - } - column - } -} - -impl + std::iter::Sum<::Output>> Mul for Matrix { - type Output = Option; - fn mul(self, rhs: Self) -> Self::Output { - // If the number of columns of self match don't match the number of - // number_of_rows of self don't match return None - let row_lenght = self.number_of_rows(); - let col_lenght = rhs.number_of_cols(); - if self.number_of_cols() != rhs.number_of_rows() { - return None; - } - let mut result: Matrix = Matrix::zero(row_lenght, col_lenght); - for j in 0..result.number_of_rows() { - for i in 0..result.number_of_cols() { - result.0[j][i] = self - .row(j) - .iter() - .zip(rhs.col(i).iter()) - .map(|(x, y)| x.clone() * y.clone()) - .sum(); - } - } - Some(result) - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn get_row() { - let matrix: Matrix = Matrix(vec![vec![3, 6], vec![8, 0]]); - assert_eq!(vec![3u32, 6], matrix.row(0)); - assert_eq!(vec![8u32, 0], matrix.row(1)); - } - - #[test] - fn get_col() { - let matrix: Matrix = Matrix(vec![vec![3, 6], vec![8, 0]]); - assert_eq!(matrix.col(0), vec![3u32, 8]); - assert_eq!(vec![6u32, 0], matrix.col(1)); - } - - #[test] - fn matrix_multiplication() { - let matrix_1: Matrix = Matrix(vec![vec![0, 1], vec![0, 0]]); - let matrix_2: Matrix = Matrix(vec![vec![0, 0], vec![1, 0]]); - let expected: Matrix = Matrix(vec![vec![1, 0], vec![0, 0]]); - assert_eq!(matrix_1 * matrix_2, Some(expected)); - - let matrix_1: Matrix = Matrix(vec![vec![0, 1], vec![0, 0]]); - let matrix_2: Matrix = Matrix(vec![vec![0, 0, 0], vec![1, 0, 0], vec![1, 1, 1]]); - assert_eq!(matrix_1 * matrix_2, None); - } -} diff --git a/solutions/matrix_ops/src/ops.rs b/solutions/matrix_ops/src/ops.rs deleted file mode 100644 index 0d72442a..00000000 --- a/solutions/matrix_ops/src/ops.rs +++ /dev/null @@ -1,85 +0,0 @@ -// In this exercise you will define the basic operations with a matrix -// starting by implementing the `std::ops::Add` trait - -// Define the operation + (by defining the trait std::ops::Add) for -// two matrices remember that two matrices can only be added if they -// have the same size. Therefore the add method must handle the -// possibility of failure by returning an Option - -use crate::{Matrix, Scalar}; -use std::ops::Add; - -impl + std::ops::Add> Add for Matrix { - type Output = Option; - - fn add(self, other: Self) -> Self::Output { - if self.0[0].len() != other.0[0].len() || self.0.len() != other.0.len() { - return None; - } - - let mut matrix = Matrix::new(); - for (j, row) in self.0.iter().enumerate() { - if j > 0 { - matrix.0.push(Vec::new()); - } - for (i, v) in row.iter().enumerate() { - matrix.0[j].push(v.clone() + other.0[j][i].clone()); - } - } - - Some(matrix) - } -} - -use std::ops::Sub; - -impl + Sub> Sub for Matrix { - type Output = Option; - - fn sub(self, other: Self) -> Self::Output { - if self.0[0].len() != other.0[0].len() || self.0.len() != other.0.len() { - return None; - } - - let mut matrix = Matrix::new(); - for (j, row) in self.0.iter().enumerate() { - if j > 0 { - matrix.0.push(Vec::new()); - } - for (i, v) in row.iter().enumerate() { - matrix.0[j].push(v.clone() - other.0[j][i].clone()); - } - } - - Some(matrix) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn addition() { - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1], vec![1, 1]]); - let expected = Matrix(vec![vec![2, 2], vec![2, 2]]); - assert_eq!(matrix + matrix_2, Some(expected)); - - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1, 3], vec![1, 1]]); - assert_eq!(matrix + matrix_2, None); - } - - #[test] - fn subtraction() { - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1], vec![1, 1]]); - let expected = Matrix(vec![vec![0, 0], vec![0, 0]]); - assert_eq!(matrix - matrix_2, Some(expected)); - - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1, 3], vec![1, 1]]); - assert_eq!(matrix - matrix_2, None); - } -} diff --git a/tests/border_cross_test/Cargo.toml b/tests/border_cross_test/Cargo.toml index 1f593e25..492e4772 100644 --- a/tests/border_cross_test/Cargo.toml +++ b/tests/border_cross_test/Cargo.toml @@ -2,7 +2,7 @@ name = "border_cross_test" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/border_cross_test/src/lib.rs b/tests/border_cross_test/src/lib.rs new file mode 100644 index 00000000..ae89e05d --- /dev/null +++ b/tests/border_cross_test/src/lib.rs @@ -0,0 +1,105 @@ +#[cfg(test)] +mod tests { + use border_cross::*; + + const CARS: [&dyn Vehicle; 4] = [ + &Car { + plate_nbr: "A3D5C7", + model: "Model 3", + horse_power: 325, + year: 2010, + }, + &Car { + plate_nbr: "A785P7", + model: "S", + horse_power: 500, + year: 1980, + }, + &Car { + plate_nbr: "D325C7", + model: "300", + horse_power: 300, + year: 2000, + }, + &Car { + plate_nbr: "Z3KCH4", + model: "Montana", + horse_power: 325, + year: 2020, + }, + ]; + + const TRUCKS: [&dyn Vehicle; 4] = [ + &Truck { + plate_nbr: "V3D5CT", + model: "Ranger", + horse_power: 325, + year: 2010, + load_tons: 40, + }, + &Truck { + plate_nbr: "V785PT", + model: "Silverado", + horse_power: 500, + year: 1980, + load_tons: 40, + }, + &Truck { + plate_nbr: "DE2SC7", + model: "Sierra", + horse_power: 300, + year: 2000, + load_tons: 40, + }, + &Truck { + plate_nbr: "3DH432", + model: "Cybertruck", + horse_power: 325, + year: 2020, + load_tons: 40, + }, + ]; + + #[test] + fn all_car_models() { + assert_eq!(all_models(CARS), ["Model 3", "S", "300", "Montana"]); + } + + #[test] + fn all_truck_models() { + assert_eq!( + all_models(TRUCKS), + ["Ranger", "Silverado", "Sierra", "Cybertruck"] + ); + } + + // because `generic_const_exprs` isn't stable yet we need to give the specific case + fn flatten_3x2(input: [[T; 4]; 2]) -> [T; 8] { + let mut out = [input[0][0]; 8]; + let mut i = 0; + for row in &input { + for &item in row { + out[i] = item; + i += 1; + } + } + out + } + + #[test] + fn cars_and_trucks_models() { + assert_eq!( + all_models(flatten_3x2([CARS, TRUCKS])), + [ + "Model 3", + "S", + "300", + "Montana", + "Ranger", + "Silverado", + "Sierra", + "Cybertruck" + ] + ); + } +} diff --git a/tests/border_cross_test/src/main.rs b/tests/border_cross_test/src/main.rs deleted file mode 100644 index dc631516..00000000 --- a/tests/border_cross_test/src/main.rs +++ /dev/null @@ -1,131 +0,0 @@ -// Create the trait Vehicle with the model and year - -// In a border cross you want to keep a list of all the vehicles that -// are waiting to enter the country. You want to keep a waiting list -// of the vehicle but the vehicles can be of two types: Car or Truck -// With the following structure: - -// create a function that receives a vector of structures that -// implement the Vehicle trait - -use border_cross::{all_models, Car, Truck, Vehicle}; - -#[allow(dead_code)] -fn main() { - let vehicles: Vec<&dyn Vehicle> = vec![ - &Car { - plate_nbr: "A3D5C7", - model: "Model 3", - horse_power: 325, - year: 2010, - }, - &Truck { - plate_nbr: "V3D5CT", - model: "Ranger", - horse_power: 325, - year: 2010, - load_tons: 40, - }, - ]; - println!("{:?}", all_models(vehicles)); -} - -#[allow(dead_code)] -fn setup_cars<'a>() -> Vec<&'a dyn Vehicle> { - let cars: Vec<&dyn Vehicle> = vec![ - &Car { - plate_nbr: "A3D5C7", - model: "Model 3", - horse_power: 325, - year: 2010, - }, - &Car { - plate_nbr: "A785P7", - model: "S", - horse_power: 500, - year: 1980, - }, - &Car { - plate_nbr: "D325C7", - model: "300", - horse_power: 300, - year: 2000, - }, - &Car { - plate_nbr: "Z3KCH4", - model: "Montana", - horse_power: 325, - year: 2020, - }, - ]; - cars -} - -#[allow(dead_code)] -fn setup_trucks<'a>() -> Vec<&'a dyn Vehicle> { - let trucks: Vec<&dyn Vehicle> = vec![ - &Truck { - plate_nbr: "V3D5CT", - model: "Ranger", - horse_power: 325, - year: 2010, - load_tons: 40, - }, - &Truck { - plate_nbr: "V785PT", - model: "Silverado", - horse_power: 500, - year: 1980, - load_tons: 40, - }, - &Truck { - plate_nbr: "DE2SC7", - model: "Sierra", - horse_power: 300, - year: 2000, - load_tons: 40, - }, - &Truck { - plate_nbr: "3DH432", - model: "Cybertruck", - horse_power: 325, - year: 2020, - load_tons: 40, - }, - ]; - trucks -} - -#[test] -fn all_car_models() { - let cars = setup_cars(); - assert_eq!(all_models(cars), ["Model 3", "S", "300", "Montana"]); -} - -#[test] -fn all_truck_models() { - let trucks = setup_trucks(); - assert_eq!( - all_models(trucks), - ["Ranger", "Silverado", "Sierra", "Cybertruck"] - ); -} - -#[test] -fn cars_and_trucks_models() { - let mut vehicles = setup_cars(); - vehicles.extend(setup_trucks()); - assert_eq!( - all_models(vehicles), - [ - "Model 3", - "S", - "300", - "Montana", - "Ranger", - "Silverado", - "Sierra", - "Cybertruck" - ] - ); -} diff --git a/tests/delete_prefix_test/Cargo.toml b/tests/delete_prefix_test/Cargo.toml index e7918073..3bd39080 100644 --- a/tests/delete_prefix_test/Cargo.toml +++ b/tests/delete_prefix_test/Cargo.toml @@ -2,7 +2,7 @@ name = "delete_prefix_test" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/delete_prefix_test/src/lib.rs b/tests/delete_prefix_test/src/lib.rs new file mode 100644 index 00000000..c13a232c --- /dev/null +++ b/tests/delete_prefix_test/src/lib.rs @@ -0,0 +1,15 @@ +#[cfg(test)] +mod tests { + use delete_prefix::*; + + #[test] + fn test_delete_prefix() { + assert_eq!(delete_prefix("john", "john wick"), Some(" wick")); + + assert_eq!(delete_prefix("ab", "b"), None); + + assert_eq!(delete_prefix("aa", "ab"), None); + + assert_eq!(delete_prefix("á©", "á©ab"), Some("ab")); + } +} diff --git a/tests/delete_prefix_test/src/main.rs b/tests/delete_prefix_test/src/main.rs deleted file mode 100644 index 38bee342..00000000 --- a/tests/delete_prefix_test/src/main.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Define the function `delete_prefix(prefix: &str, s: &str) -> Option<&str>` -// That takes 2 slices of string and returns the string of slice s -// with the `prefix` removed wrapped in Some -// If `prefix ` is not contained in `s` return None - -// Example: -// delete_prefix("hello, ", "hello, world")? == "world" -// delete_prefix("not", "win"); - -use delete_prefix::*; - -#[allow(dead_code)] -fn main() { - println!("{:?}", delete_prefix("ab", "abcdefghijklmnop")); - println!("{:?}", delete_prefix("x", "abcdefghijklmnop")); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_delete_prefix() { - assert_eq!(delete_prefix("john", "john wick"), Some(" wick")); - - assert_eq!(delete_prefix("ab", "b"), None); - - assert_eq!(delete_prefix("aa", "ab"), None); - - assert_eq!(delete_prefix("á©", "á©ab"), Some("ab")); - } -} diff --git a/tests/events_test/Cargo.toml b/tests/events_test/Cargo.toml index 38ace202..667824cf 100644 --- a/tests/events_test/Cargo.toml +++ b/tests/events_test/Cargo.toml @@ -2,10 +2,10 @@ name = "events_test" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -chrono = "0.4" -events = { path = "../../solutions/events"} +events = { path = "../../solutions/events" } +colored = "3.0.0" diff --git a/tests/events_test/src/lib.rs b/tests/events_test/src/lib.rs new file mode 100644 index 00000000..d077c65b --- /dev/null +++ b/tests/events_test/src/lib.rs @@ -0,0 +1,78 @@ +#[cfg(test)] +mod tests { + use colored::Colorize; + use events::*; + use std::time::Duration; + + #[test] + fn remainder_notification() { + assert_eq!( + Event::Remainder("Go to the doctor").notify(), + Notification { + size: 50, + color: (50, 50, 50), + position: Position::Bottom, + content: "Go to the doctor".to_owned(), + } + ); + } + + #[test] + fn registration_notification() { + assert_eq!( + Event::Registration(Duration::from_secs(49094)).notify(), + Notification { + size: 30, + color: (255, 2, 22), + position: Position::Top, + content: "You have 13H:38M:14S left before the registration ends".to_owned(), + } + ); + } + + #[test] + fn appointment_notification() { + assert_eq!( + Event::Appointment("Go to the doctor").notify(), + Notification { + size: 100, + color: (200, 200, 3), + position: Position::Center, + content: "Go to the doctor".to_owned(), + } + ); + } + + #[test] + fn holiday_notification() { + assert_eq!( + Event::Holiday.notify(), + Notification { + size: 25, + color: (0, 255, 0), + position: Position::Top, + content: "Enjoy your holiday".to_owned(), + } + ); + } + + #[test] + fn test_notification_display() { + let notification = Notification { + size: 30, + color: (255, 2, 22), + position: Position::Top, + content: "You have 13H:38M:14S left before the registration ends".to_owned(), + }; + + let (r, g, b) = notification.color; + let formatted_content = notification.content.truecolor(r, g, b); + + let expected = format!( + "({:?}, {}, {})", + notification.position, notification.size, formatted_content + ); + + assert_eq!(notification.to_string(), expected); + } +} diff --git a/tests/events_test/src/main.rs b/tests/events_test/src/main.rs deleted file mode 100644 index ec2efed7..00000000 --- a/tests/events_test/src/main.rs +++ /dev/null @@ -1,86 +0,0 @@ -use chrono::Duration; -use events::Event::*; -#[allow(unused_imports)] -use events::{Notification, Position}; - -#[allow(dead_code)] -fn main() { - let remainder = Remainder("Go to the doctor"); - println!("{}", remainder.notify()); - let registration = Registration(Duration::seconds(49094)); - println!("{}", registration.notify()); - let appointment = Appointment("Go to the doctor"); - println!("{}", appointment.notify()); - let holiday = Holiday; - println!("{}", holiday.notify()); -} - -#[cfg(test)] -mod tests { - - use super::*; - - #[test] - fn remainder_notification() { - let remainder = Remainder("Go to the doctor"); - let notification = remainder.notify(); - println!("{}", ¬ification); - assert_eq!( - notification, - Notification { - size: 50, - color: (50, 50, 50), - position: Position::Bottom, - content: "Go to the doctor".to_string(), - } - ); - } - - #[test] - fn registration_notification() { - let registration = Registration(Duration::seconds(49094)); - let notification = registration.notify(); - println!("{}", registration.notify()); - assert_eq!( - notification, - Notification { - size: 30, - color: (255, 2, 22), - position: Position::Top, - content: "You have 13H:38M:14S left before the registration ends".to_string(), - } - ); - } - - #[test] - fn appointment_notification() { - let appointment = Appointment("Go to the doctor"); - let notification = appointment.notify(); - println!("{}", ¬ification); - assert_eq!( - notification, - Notification { - size: 100, - color: (200, 200, 3), - position: Position::Center, - content: "Go to the doctor".to_string(), - } - ); - } - - #[test] - fn holiday_notification() { - let holiday = Holiday; - let notification = Holiday.notify(); - println!("{}", holiday.notify()); - assert_eq!( - notification, - Notification { - size: 25, - color: (0, 255, 0), - position: Position::Top, - content: String::from("Enjoy your holiday"), - } - ); - } -} diff --git a/tests/lifetimes_test/Cargo.toml b/tests/lifetimes_test/Cargo.toml index 811ec731..c38429a4 100644 --- a/tests/lifetimes_test/Cargo.toml +++ b/tests/lifetimes_test/Cargo.toml @@ -2,10 +2,9 @@ name = "lifetimes_test" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] lifetimes = { path = "../../solutions/lifetimes"} -lib = { path = "../lib" } diff --git a/tests/lifetimes_test/src/lib.rs b/tests/lifetimes_test/src/lib.rs new file mode 100644 index 00000000..88f7d2a5 --- /dev/null +++ b/tests/lifetimes_test/src/lib.rs @@ -0,0 +1,17 @@ +#[cfg(test)] +mod tests { + use lifetimes::*; + + #[test] + fn create_person() { + let person = Person::new("Leo"); + + assert_eq!( + person, + Person { + age: 0, + name: "Leo" + } + ); + } +} diff --git a/tests/lifetimes_test/src/main.rs b/tests/lifetimes_test/src/main.rs deleted file mode 100644 index e3f9e704..00000000 --- a/tests/lifetimes_test/src/main.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Create a struct called Person that has two fields: name of type -// string slice (&str) and age of type u8 -// and create the associated function new which creates a new person -// with age 0 and with the name given - -use lifetimes::Person; - -fn main() { - let person = Person::new("Leo"); - - println!("Person = {:?}", person); -} - -#[cfg(test)] -mod tests { - use super::*; - use lib::{Kind, TestProperties}; - - #[test] - fn fields() { - let person = Person { - name: "Dijkstra", - age: 10, - }; - let test = TestProperties { - kind: Kind::Value, - name: "age", - }; - test.assert_with_message(&[Box::new(person.clone())], person.age, 10); - let test = TestProperties { - kind: Kind::Value, - name: "name", - }; - test.assert_with_message(&[Box::new(person.clone())], person.name, "Dijkstra"); - } - - #[test] - fn create_person() { - let person = Person::new("Leo"); - let test = TestProperties { - kind: Kind::Value, - name: "age", - }; - test.assert_with_message(&[Box::new(person.clone())], person.age, 0); - let test = TestProperties { - kind: Kind::Value, - name: "name", - }; - test.assert_with_message(&[Box::new(person.clone())], person.name, "Leo"); - } -} diff --git a/tests/macro_map_test/Cargo.toml b/tests/macro_map_test/Cargo.toml index 463bcb78..45ccfe4a 100644 --- a/tests/macro_map_test/Cargo.toml +++ b/tests/macro_map_test/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "macro_map_test" version = "0.1.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/macro_map_test/src/lib.rs b/tests/macro_map_test/src/lib.rs new file mode 100644 index 00000000..a1771ec6 --- /dev/null +++ b/tests/macro_map_test/src/lib.rs @@ -0,0 +1,42 @@ +#[cfg(test)] +mod tests { + use macro_map::hash_map; + use std::collections::HashMap; + + #[test] + fn empty() { + let expected = HashMap::::new(); + let computed = hash_map!(); + + assert_eq!(computed, expected); + } + + #[test] + fn one_element() { + let expected = HashMap::from([("my name", 10)]); + let computed = hash_map!("my name" => 10); + + assert_eq!(computed, expected); + } + + #[test] + fn multiple_elements_one_line() { + let expected = HashMap::from([("my name", 10), ("another name", 22)]); + let computed = hash_map!("my name" => 10, "another name" => 22); + + assert_eq!(computed, expected); + } + + #[test] + fn multiple_elements_multiple_lines() { + let expected = + HashMap::from([("my name", 10), ("another name", 22), ("the third one", 33)]); + let computed = hash_map!( + "my name" => 10, + "another name" => 22, + "the third one" => 33, + ); + + assert_eq!(computed, expected); + } +} diff --git a/tests/macro_map_test/src/main.rs b/tests/macro_map_test/src/main.rs deleted file mode 100644 index e699ff97..00000000 --- a/tests/macro_map_test/src/main.rs +++ /dev/null @@ -1,65 +0,0 @@ -use macro_map::hash_map; -use std::collections::HashMap; - -fn main() { - let empty: HashMap = hash_map!(); - let new = hash_map!('a' => 22, 'b' => 1, 'c' => 10); - let nested = hash_map!( - "first" => hash_map!( - "Rob" => 32.2, - "Gen" => 44.1, - "Chris" => 10., - ), - "second" => hash_map!() - ); - println!("{:?}", empty); - println!("{:?}", new); - println!("{:?}", nested); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn empty() { - let expected: HashMap = HashMap::new(); - let computed = hash_map!(); - - assert_eq!(computed, expected); - } - - #[test] - fn one_element() { - let mut expected = HashMap::new(); - expected.insert("my name", 10); - let computed = hash_map!("my name" => 10); - - assert_eq!(computed, expected); - } - - #[test] - fn multiple_elements_one_line() { - let mut expected = HashMap::new(); - expected.insert("my name", 10); - expected.insert("another name", 22); - let computed = hash_map!("my name" => 10, "another name" => 22); - - assert_eq!(computed, expected); - } - - #[test] - fn multiple_elements_multiple_lines() { - let mut expected = HashMap::new(); - expected.insert("my name", 10); - expected.insert("another name", 22); - expected.insert("the third one", 33); - let computed = hash_map!( - "my name" => 10, - "another name" => 22, - "the third one" => 33, - ); - - assert_eq!(computed, expected); - } -} diff --git a/tests/matrix_ops_test/Cargo.toml b/tests/matrix_ops_test/Cargo.toml index 77dfbd0a..6d594e7d 100644 --- a/tests/matrix_ops_test/Cargo.toml +++ b/tests/matrix_ops_test/Cargo.toml @@ -2,7 +2,7 @@ name = "matrix_test" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/matrix_ops_test/src/lib.rs b/tests/matrix_ops_test/src/lib.rs new file mode 100644 index 00000000..abde45b8 --- /dev/null +++ b/tests/matrix_ops_test/src/lib.rs @@ -0,0 +1,28 @@ +#[cfg(test)] +mod tests { + use matrix_ops::Wrapper; + + #[test] + fn add() { + assert_eq!( + Wrapper::from([[1, 1], [1, 1]]) + Wrapper::from([[1, 1], [1, 1]]), + Wrapper::from([[2, 2], [2, 2]]) + ); + } + + #[test] + fn sub() { + assert_eq!( + Wrapper::from([[1, 1], [1, 1]]) - Wrapper::from([[1, 1], [1, 1]]), + Wrapper::from([[0, 0], [0, 0]]) + ); + } + + #[test] + fn mul() { + assert_eq!( + Wrapper::from([[1, 2], [3, 4]]) * Wrapper::from([[5, 6], [7, 8]]), + Wrapper::from([[19, 22], [43, 50]]) + ); + } +} diff --git a/tests/matrix_ops_test/src/main.rs b/tests/matrix_ops_test/src/main.rs deleted file mode 100644 index 94aaf0f5..00000000 --- a/tests/matrix_ops_test/src/main.rs +++ /dev/null @@ -1,51 +0,0 @@ -// In this exercise you will define the basic operations with a matrix -// starting by implementing the `std::ops::Add` trait - -// Define the operation + (by defining the trait std::ops::Add) for -// two matrices remember that two matrices can only be added if they -// have the same size. Therefore the add method must handle the -// possibility of failure by returning an Option - -use matrix_ops::Matrix; - -fn main() { - let matrix = Matrix(vec![vec![8, 1], vec![9, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1], vec![1, 1]]); - println!("{:?}", matrix + matrix_2); - - let matrix = Matrix(vec![vec![1, 3], vec![2, 5]]); - let matrix_2 = Matrix(vec![vec![3, 1], vec![1, 1]]); - println!("{:?}", matrix - matrix_2); - - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1, 3], vec![1, 1]]); - println!("{:?}", matrix - matrix_2); - - let matrix = Matrix(vec![vec![1, 3], vec![9, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1, 3], vec![1, 1]]); - println!("{:?}", matrix + matrix_2); -} - -#[test] -fn addition() { - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1], vec![1, 1]]); - let expected = Matrix(vec![vec![2, 2], vec![2, 2]]); - assert_eq!(matrix + matrix_2, Some(expected)); - - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1, 3], vec![1, 1]]); - assert_eq!(matrix + matrix_2, None); -} - -#[test] -fn subtraction() { - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1], vec![1, 1]]); - let expected = Matrix(vec![vec![0, 0], vec![0, 0]]); - assert_eq!(matrix - matrix_2, Some(expected)); - - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1, 3], vec![1, 1]]); - assert_eq!(matrix - matrix_2, None); -} diff --git a/tests/matrix_test/Cargo.toml b/tests/matrix_test/Cargo.toml index 36aa7894..251b8f0c 100644 --- a/tests/matrix_test/Cargo.toml +++ b/tests/matrix_test/Cargo.toml @@ -2,7 +2,7 @@ name = "matrix_test" version = "0.1.0" authors = ["Augusto "] -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/tests/matrix_test/src/lib.rs b/tests/matrix_test/src/lib.rs new file mode 100644 index 00000000..bc2c9800 --- /dev/null +++ b/tests/matrix_test/src/lib.rs @@ -0,0 +1,26 @@ +#[cfg(test)] +mod tests { + use matrix::Matrix; + + #[test] + fn zero_property() { + let matrix = Matrix::zero(); + let expected = Matrix([[0; 4]; 3]); + assert_eq!(matrix, expected); + + let matrix = Matrix::zero(); + let expected = Matrix([[0; 2]; 2]); + assert_eq!(matrix, expected); + } + + #[test] + fn identity_matrix() { + let matrix = Matrix::identity(); + let expected = Matrix([[1, 0], [0, 1]]); + assert_eq!(matrix, expected); + + let matrix = Matrix::identity(); + let expected = Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]]); + assert_eq!(matrix, expected); + } +} diff --git a/tests/matrix_test/src/main.rs b/tests/matrix_test/src/main.rs deleted file mode 100644 index 2afefb34..00000000 --- a/tests/matrix_test/src/main.rs +++ /dev/null @@ -1,55 +0,0 @@ -// First exercise - -// # Instructions -// Define a data structure to represent a matrix of any size and -// implement the basic operations for this you will need to follow the -// next steps: - -// You can use a 2 dimensional Vec's -// We will consider a matrix as a rectangular arrangements of scalars -// You can use the definition of scalars done in the last exercise: -// `lalgebra_scalar` - -// Then define the associated function `identity` that returns the identity matrix -// of size n -// Ex: -// Matrix::identity(3) == [[1,0,0], [0,1,0], [0,0,1]] - -// And the associated function `zero` that returns a matrix of size -// `row x col` with all the positions filled by zeroes -// Ex: -// Matrix::zero(3, 3) == [[0,0,0],[0,0,0],[0,0,0]] - -// Resources: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html - -use matrix::Matrix; - -#[allow(dead_code)] -fn main() { - let m: Matrix = Matrix(vec![vec![0, 0, 0, 0], vec![0, 0, 0, 0], vec![0, 0, 0, 0]]); - println!("{:?}", m); - println!("{:?}", Matrix::::identity(4)); - println!("{:?}", Matrix::::zero(3, 4)); -} - -#[test] -fn zero_property() { - let matrix: Matrix = Matrix::zero(3, 4); - let expected: Matrix = Matrix(vec![vec![0, 0, 0, 0], vec![0, 0, 0, 0], vec![0, 0, 0, 0]]); - assert_eq!(matrix, expected); - - let matrix: Matrix = Matrix::zero(2, 2); - let expected: Matrix = Matrix(vec![vec![0, 0], vec![0, 0]]); - assert_eq!(matrix, expected); -} - -#[test] -fn identity_matrix() { - let matrix: Matrix = Matrix::identity(2); - let expected: Matrix = Matrix(vec![vec![1, 0], vec![0, 1]]); - assert_eq!(matrix, expected); - - let matrix: Matrix = Matrix::identity(3); - let expected: Matrix = Matrix(vec![vec![1, 0, 0], vec![0, 1, 0], vec![0, 0, 1]]); - assert_eq!(matrix, expected); -}