diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..8456ad6 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "RustOOP" +version = "0.1.0" +dependencies = [ + "text_io", +] + +[[package]] +name = "text_io" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f0c8eb2ad70c12a6a69508f499b3051c924f4b1cfeae85bfad96e6bc5bba46" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..88fa3e0 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "RustOOP" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[profile.release] +opt-level = 'z' # Optimize for size +lto = true # Enable link-time optimization +codegen-units = 1 # Reduce number of codegen units to increase optimizations +panic = 'abort' # Abort on panic +strip = true # Strip symbols from binary* + +[dependencies] +text_io = "0.1.12" diff --git a/src/bin/lab-1.rs b/src/bin/lab-1.rs new file mode 100644 index 0000000..4bbd930 --- /dev/null +++ b/src/bin/lab-1.rs @@ -0,0 +1,22 @@ +fn protected_read(variable_name: &str) -> i32 { + use text_io::try_read; + loop { + print!("Enter {}: ", variable_name); + let read_result: Result = try_read!(); + match read_result { + Ok(read_integer) => return read_integer, + Err(_e) => eprintln!("{} must be an integer!", variable_name.to_uppercase()), + } + } +} + +fn main() { + let n: i32 = protected_read("n"); + let m: i32 = protected_read("m"); + let a: i32 = protected_read("a"); + let b: i32 = protected_read("b"); + + let s: f32 = ((b + m) as f32 / 2f32) * ((m - b + 1) * (n - a + 1)) as f32; + + println!("S = {}", s); +} diff --git a/src/bin/lab-2.rs b/src/bin/lab-2.rs new file mode 100644 index 0000000..39043d4 --- /dev/null +++ b/src/bin/lab-2.rs @@ -0,0 +1,146 @@ +// #[allow(dead_code)] +use format as f; + +fn capitalise(s: &str) -> String { + let mut c = s.chars(); + match c.next() { + None => String::new(), + Some(f) => f.to_uppercase().collect::() + c.as_str(), + } +} + +fn read_row(row_number: u16) -> Vec { + loop { + print!("Row #{row_number} (separated by spaces): "); + let raw_row: String = text_io::read!("{}\n"); + let trimmed_row: &str = raw_row.trim(); + match trimmed_row.split(' ').all(|value| { + !value.is_empty() + && value.chars().all(|char| char.is_numeric() || char == '-') + && value.parse::().unwrap() <= i16::MAX as i128 + && value.parse::().unwrap() >= i16::MIN as i128 + }) { + true => { + return trimmed_row + .split(' ') + .map(|value| value.parse::().unwrap()) + .collect::>() + } + false => eprintln!("[Error] The row must consist of short integers separated by space, try again."), + } + } +} + +fn generate_row(row_index: u16, length: u16) -> Vec { + (0..length) + .map(|element_index| (element_index as i16 + 1) * (row_index as i16 + 1)) + .collect() +} + +fn read_matrix() -> Vec> { + let rows: u16 = protected_u16_read("the number of rows"); + loop { + print!("Generate [s]quare or [r]ectangle matrix or [i]nput manually [s/r/i]: "); + let option: String = text_io::read!(); + match option.to_lowercase().as_str() { + "s" => return (0..rows).map(|i| generate_row(i, rows)).collect(), + "r" => { + let columns: u16 = protected_u16_read("the number of columns"); + return (0..rows).map(|i| generate_row(i, columns)).collect(); + } + "i" => return (0..rows).map(read_row).collect(), + _ => eprintln!("[Error] Not an option, try again."), + } + } +} + +fn protected_u16_read(variable_name: &str) -> u16 { + use text_io::try_read; + loop { + print!("Enter {}: ", variable_name); + let read_result: Result = try_read!(); + match read_result { + Ok(read_integer) => return read_integer, + Err(_e) => eprintln!( + "[Error] {} must be a short integer, try again.", + capitalise(variable_name) + ), + } + } +} + +fn multiply_matrix_by_number(matrix: &[Vec], multiplier: u16) -> Vec> { + return matrix + .iter() + .map(|row| { + row.iter() + .map(|element| element * multiplier as i16) + .collect() + }) + .collect(); +} + +fn average_of_row(row: &Vec) -> f32 { + return row.iter().sum::() as f32 / row.len() as f32; +} + +fn format_matrix(matrix: &[Vec]) -> String { + let max_width = matrix + .iter() + .map(|row| { + row.iter() + .map(|element| element.to_string().len()) + .max() + .unwrap() + }) + .max() + .unwrap(); + + let mut formatted_matrix: String = matrix + .iter() + .map(|row| { + row.iter() + .map(|element| f!("| {:max_width$} ", element)) + .collect::>() + .join("") + }) + .collect::>() + .join("|\n"); + formatted_matrix.push('|'); + formatted_matrix +} + +fn format_column(column: &[f32]) -> String { + let max_width = column + .iter() + .map(|element| element.to_string().len()) + .max() + .unwrap(); + + return column + .iter() + .map(|element| f!("| {:max_width$} |", element)) + .collect::>() + .join("\n"); +} + +fn main() { + let full_vec_test: Vec> = read_matrix(); + println!("\nMatrix B:\n{}\n", format_matrix(&full_vec_test)); + + let multiplied_full_vec_test: Vec> = + multiply_matrix_by_number(&full_vec_test, protected_u16_read("matrix multiplier")); + println!( + "\nMatrix a×B:\n{}\n", + format_matrix(&multiplied_full_vec_test) + ); + + let row_averages: Vec = multiplied_full_vec_test + .iter() + .map(average_of_row) + .collect(); + println!( + "Averages for each row in a×B:\n{}", + format_column(&row_averages) + ); +}