// #[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) ); }