Решение на Matrix 4 от Диана Маркова

Обратно към всички решения

Към профила на Диана Маркова

Резултати

  • 20 точки от тестове
  • 0 бонус точки
  • 20 точки общо
  • 15 успешни тест(а)
  • 0 неуспешни тест(а)

Код

use std::ops::Add;
use std::ops::Mul;
#[derive(Debug)]
pub struct Matrix<T: Clone> {
elements: Vec<T>
}
#[derive(Debug, Clone, PartialEq)]
pub struct Cell<T>(pub T);
impl Add<Cell<String>> for Cell<i32> {
type Output = Cell<String>;
fn add(self, other: Cell<String>) -> Self::Output
{
let mut result = String::new();
if self.0 >= 0
{
result.push_str(&self.0.to_string());
result.push(' ');
result.push_str(&other.0);
}
else
{
result.push_str(&other.0.chars().rev().collect::<String>());
result.push(' ');
result.push_str(&(-self.0).to_string());
}
Cell(result)
}
}
impl Mul<Cell<String>> for Cell<i32> {
type Output = Cell<String>;
fn mul(self, other: Cell<String>) -> Self::Output
{
let mut result = String::new();
if self.0 >= 0
{
for i in 0..self.0
{ result.push_str(&other.0); }
}
else
{
let rev = other.0.chars().rev().collect::<String>();
for i in 0..(-self.0)
{ result.push_str(&rev); }
}
Cell(result)
}
}
impl<T: Clone> Matrix<T> {
/// Данните се очаква да бъдат подадени със статичен масив -- вижте по-долу за примери за
/// конструиране. Какви може да са елементите? Ще тестваме само с два типа: String и i32.
///
/// Очаква се да бъдат подадени по редове, от ляво надясно. Тоест, ако подадем като вход списък
/// с елементи: 1, 2, 3, 4, се очаква конструираната матрица:
///
/// | 1 2 |
/// | 3 4 |
///
/// Забележете, че подаваме като вход някакъв slice -- reference тип. Не очакваме матрицата да
/// държи reference, клонирайте си данните, за да имате ownership.
///
pub fn new(data: &[T; 4]) -> Matrix<T> {
Matrix{
elements: data.into_iter().
map(|x| x.clone()).
collect::<Vec<T>>(),
}
}
/// Връща вектор, който съдържа в себе си всички 4 елемента на матрицата, наредени по редове,
/// от ляво надясно и от горе надолу, обвити в `Cell`. Тоест, ако матрицата изглежда така:
///
/// | 1 2 |
/// | 3 4 |
///
/// Очакваме `.by_row` да върне елементите в ред: 1, 2, 3, 4
///
pub fn by_row(&self) -> Vec<Cell<T>> {
self.elements.iter().
map(|x| Cell(x.clone())).
collect::<Vec<_>>()
}
/// Връща вектор, който съдържа в себе си всички 4 елемента на матрицата, наредени по колони,
/// от горе надолу и от ляво надясно, Обвити в `Cell`. Тоест, ако матрицата изглежда така:
///
/// | 1 2 |
/// | 3 4 |
///
/// Очакваме `.by_col` да върне елементите в ред: 1, 3, 2, 4
///
pub fn by_col(&self) -> Vec<Cell<T>> {
let mut temp = self.elements.clone();
temp.swap(1,2);
temp.iter().
map(|x| Cell(x.clone())).
collect::<Vec<_>>()
}
}
impl Add<Matrix<String>> for Matrix<i32> {
type Output = Matrix<String>;
fn add(self, other: Matrix<String>) -> Self::Output
{
let mut result = Vec::<Cell::<String>>::new();
for i in 0..4
{ result.push(Cell(self.elements[i]) + Cell(other.elements[i].clone())) }
Matrix
{
elements: result.iter().
map(|x| x.0.clone()).
collect::<Vec<_>>()
}
}
}
impl Mul<Matrix<String>> for Matrix<i32> {
type Output = String;
fn mul(self, other: Matrix<String>) -> Self::Output
{
let rows = self.by_row();
let cols = other.by_col();
let mut after_muliplication = Vec::<String>::new();
for i in 0..4
{ after_muliplication.push((rows[i].clone() * cols[i].clone()).0); }
let mut result = String::new();
for j in 0..3
{
result.push_str(&after_muliplication[j]);
result.push(' ');
}
result.push_str(&after_muliplication[3]);
result
}
}
#[cfg(test)]
mod tests {
use super::*;
fn string_cell_vec(s1: &str, s2: &str, s3: &str, s4: &str) -> Vec<Cell<String>> {
[s1, s2, s3, s4].into_iter().map(String::from).map(Cell).collect::<Vec<Cell<String>>>()
}
#[test]
// the basic test given
fn basic_test()
{
assert_eq!((Cell(4) + Cell(String::from("badger"))).0, String::from("4 badger"));
assert_eq!((Cell(2) * Cell(String::from("mushroom"))).0, String::from("mushroommushroom"));
let matrix1 = Matrix::new(&[1, 2, 3, 4]);
let matrix2 = Matrix::new(&[
String::from("one"), String::from("two"),
String::from("three"), String::from("four")
]);
assert_eq!(matrix1.by_row()[0], Cell(1));
assert_eq!(matrix1.by_col()[0], Cell(1));
assert_eq!(
(matrix1 + matrix2).by_row(),
string_cell_vec("1 one", "2 two", "3 three", "4 four")
);
let matrix1 = Matrix::new(&[1, 1, 1, 1]);
let matrix2 = Matrix::new(&[
String::from("one"), String::from("two"),
String::from("three"), String::from("four")
]);
assert_eq!(matrix1 * matrix2, String::from("one three two four"));
}
#[test]
fn test_cell_addition()
{
assert_eq!(Cell(22) + Cell(String::from("years ago")), Cell(String::from("22 years ago")));
assert_eq!((Cell(4) + Cell(String::from("badger"))).0, String::from("4 badger"));
assert_eq!((Cell(5) + Cell(String::from("little piggies"))).0, String::from("5 little piggies"));
assert_eq!((Cell(0) + Cell(String::from("whatever"))).0, String::from("0 whatever"));
assert_eq!((Cell(0) + Cell(String::from(""))).0, String::from("0 "));
assert_eq!((Cell(5) + Cell(String::from(""))).0, String::from("5 "));
assert_eq!((Cell(-5) + Cell(String::from(""))).0, String::from(" 5"));
assert_eq!((Cell(-1) + Cell(String::from("азобичаммачибоза"))).0, String::from("азобичаммачибоза 1"));
assert_eq!((Cell(-2) + Cell(String::from("tsafrabitralS"))).0, String::from("Slartibarfast 2"));
}
#[test]
fn test_cell_multiplication()
{
assert_eq!(Cell(3) * Cell(String::from("woah!")), Cell(String::from("woah!woah!woah!")));
assert_eq!(Cell(0) * Cell(String::from("woah?")), Cell(String::from("")));
assert_eq!(Cell(-3) * Cell(String::from(",regdab")), Cell(String::from("badger,badger,badger,")));
assert_eq!(Cell(-3) * Cell(String::from(",regdab")), Cell(String::from("badger,badger,badger,")));
assert_eq!((Cell(-1) * Cell(String::from("азобичаммачибоза"))).0, String::from("азобичаммачибоза"));
assert_eq!((Cell(-2) * Cell(String::from("азобичаммачибоза"))).0, String::from("азобичаммачибозаазобичаммачибоза"));
}
#[test]
fn test_row_getter()
{
let matrix1 = Matrix::new(&[1, 2, 3, 4]);
let matrix2 = Matrix::new(&[
String::from("едно"), String::from("две"),
String::from("три"), String::from("four")
]);
assert_eq!(matrix1.by_row()[0], Cell(1));
assert_eq!(matrix1.by_row()[1], Cell(2));
assert_eq!(matrix1.by_row()[2], Cell(3));
assert_eq!(matrix1.by_row()[3], Cell(4));
assert_eq!(matrix2.by_row()[0], Cell(String::from("едно")));
assert_eq!(matrix2.by_row()[1], Cell(String::from("две")));
assert_eq!(matrix2.by_row()[2], Cell(String::from("три")));
assert_eq!(matrix2.by_row()[3], Cell(String::from("four")));
}
#[test]
fn test_column_getter()
{
let matrix1 = Matrix::new(&[1, 2, 3, 4]);
let matrix2 = Matrix::new(&[
String::from("едно"), String::from("две"),
String::from("три"), String::from("четири")
]);
assert_eq!(matrix1.by_col()[0], Cell(1));
assert_eq!(matrix1.by_col()[1], Cell(3));
assert_eq!(matrix1.by_col()[2], Cell(2));
assert_eq!(matrix1.by_col()[3], Cell(4));
assert_eq!(matrix2.by_col()[0], Cell(String::from("едно")));
assert_eq!(matrix2.by_col()[1], Cell(String::from("три")));
assert_eq!(matrix2.by_col()[2], Cell(String::from("две")));
assert_eq!(matrix2.by_col()[3], Cell(String::from("четири")));
}
#[test]
fn test_matrix_addition()
{
let matrix1 = Matrix::new(&[1, 2, -3, 4]);
let matrix2 = Matrix::new(&[
String::from("one"), String::from("two"),
String::from("eerht"), String::from("four")
]);
let res = matrix1 + matrix2;
assert_eq!(res.by_row()[0].0, "1 one");
assert_eq!(res.by_row()[1].0, "2 two");
assert_eq!(res.by_row()[2].0, "three 3");
assert_eq!(res.by_row()[3].0, "4 four");
}
#[test]
fn test_matrix_multiplication()
{
let matrix1 = Matrix::new(&[1, -2, -3, 4]);
let matrix2 = Matrix::new(&[
String::from("one"), String::from("owt"),
String::from("eerht"), String::from("four")
]);
let res = matrix1 * matrix2;
let mut iter = res.split_whitespace();
assert_eq!(Some("one"), iter.next());
assert_eq!(Some("threethree"), iter.next());
assert_eq!(Some("twotwotwo"), iter.next());
assert_eq!(Some("fourfourfourfour"), iter.next());
}
}

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20220112-2706256-sb5rv2/solution)
warning: unused variable: `i`
  --> src/lib.rs:40:17
   |
40 |             for i in 0..self.0
   |                 ^ help: if this is intentional, prefix it with an underscore: `_i`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `i`
  --> src/lib.rs:46:17
   |
46 |             for i in 0..(-self.0)
   |                 ^ help: if this is intentional, prefix it with an underscore: `_i`

warning: `solution` (lib) generated 2 warnings
    Finished test [unoptimized + debuginfo] target(s) in 9.01s
     Running tests/solution_test.rs (target/debug/deps/solution_test-4c880d3f0adaac34)

running 15 tests
test solution_test::test_adding_int_and_string_negative ... ok
test solution_test::test_adding_int_and_string_positive ... ok
test solution_test::test_adding_int_and_string_unicode ... ok
test solution_test::test_adding_int_and_string_zero ... ok
test solution_test::test_adding_matrices_1 ... ok
test solution_test::test_adding_matrices_2 ... ok
test solution_test::test_blank_strings ... ok
test solution_test::test_iterating_i32s ... ok
test solution_test::test_iterating_strings ... ok
test solution_test::test_multiplying_int_and_string_negative ... ok
test solution_test::test_multiplying_int_and_string_positive ... ok
test solution_test::test_multiplying_int_and_string_unicode ... ok
test solution_test::test_multiplying_int_and_string_zero ... ok
test solution_test::test_multiplying_matrices_1 ... ok
test solution_test::test_multiplying_matrices_2 ... ok

test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s

История (1 версия и 1 коментар)

Диана качи първо решение на 13.11.2021 18:52 (преди почти 4 години)

Тестването със азобичаммачибоза е забавно, но технически погледнато, не тества обръщане заради симетрията 😅. Можеш да минеш този тест и без да обръщаш символите is what I'm saying. Имаш и други тестове, които обръщат, но никой от тях не тества обръщане на кирилица. Липсват ти и unicode тестове за матриците.

Все пак оценявам допълнителната работа, keep it up 👍