Решение на Matrix 4 от Георги Шавов
Резултати
- 20 точки от тестове
- 0 бонус точки
- 20 точки общо
- 15 успешни тест(а)
- 0 неуспешни тест(а)
Код
use std::ops::Add;
use std::ops::Mul;
#[derive(Debug)]
pub struct Matrix<T: Clone> {
row1: Vec<T>,
row2: 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: Cell<i32>, other: Cell<String>) -> Self::Output {
let Cell(num) = self;
let Cell(msg) = other;
if num < 0 {
return Cell(format!("{} {}", msg.chars().rev().collect::<String>(), num.abs()))
}
Cell(format!("{} {}", num, msg))
}
}
impl Mul<Cell<String>> for Cell<i32> {
type Output = Cell<String>;
fn mul(self: Cell<i32>, other: Cell<String>) -> Self::Output {
let Cell(num) = self;
let Cell(msg) = other;
let rev_msg = msg.chars().rev().collect::<String>();
let mut final_msg = String::from("");
let mut counter = 0;
while counter < num.abs() {
if num < 0 {
final_msg.push_str(rev_msg.as_str());
}
else {
final_msg.push_str(msg.as_str());
}
counter = counter + 1
}
Cell(final_msg.clone())
}
}
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> {
let mut v1 = Vec::new();
let mut v2 = Vec::new();
for (pos, item) in data.iter().enumerate() {
if pos < data.len() / 2 {
v1.push(item.clone())
}
else {
v2.push(item.clone())
}
}
Matrix {
row1: v1.clone(),
row2: v2.clone()
}
}
/// Връща вектор, който съдържа в себе си всички 4 елемента на матрицата, наредени по редове,
/// от ляво надясно и от горе надолу, обвити в `Cell`. Тоест, ако матрицата изглежда така:
///
/// | 1 2 |
/// | 3 4 |
///
/// Очакваме `.by_row` да върне елементите в ред: 1, 2, 3, 4
///
pub fn by_row(&self) -> Vec<Cell<T>> {
let mut v = Vec::new();
for item in self.row1.iter() {
v.push(Cell(item.clone()));
}
for item in self.row2.iter() {
v.push(Cell(item.clone()));
}
v.clone()
}
/// Връща вектор, който съдържа в себе си всички 4 елемента на матрицата, наредени по колони,
/// от горе надолу и от ляво надясно, Обвити в `Cell`. Тоест, ако матрицата изглежда така:
///
/// | 1 2 |
/// | 3 4 |
///
/// Очакваме `.by_col` да върне елементите в ред: 1, 3, 2, 4
///
pub fn by_col(&self) -> Vec<Cell<T>> {
let mut v = Vec::new();
let iter1 = self.row1.iter();
let iter2 = self.row2.iter();
for (item1, item2) in iter1.zip(iter2) {
v.push(Cell(item1.clone()));
v.push(Cell(item2.clone()));
}
v.clone()
}
}
impl Add<Matrix<String>> for Matrix<i32> {
type Output = Matrix<String>;
fn add(self: Matrix<i32>, other: Matrix<String>) -> Self::Output {
let self_rows = self.by_row();
let other_rows = other.by_row();
let mut result1 = Vec::new();
let mut result2 = Vec::new();
for (item1, (pos, item2)) in self_rows.iter().zip(other_rows.iter().enumerate()) {
let Cell(result_msg) = item1.clone() + item2.clone();
if pos < 2 {
result1.push(result_msg);
}
else {
result2.push(result_msg);
}
}
Matrix {
row1: result1,
row2: result2
}
}
}
impl Mul<Matrix<String>> for Matrix<i32> {
type Output = String;
fn mul(self: Matrix<i32>, other: Matrix<String>) -> Self::Output {
let self_rows = self.by_row();
let other_cols = other.by_col();
let mut result_msg = String::from("");
for (item1, (pos, item2)) in self_rows.iter().zip(other_cols.iter().enumerate()) {
let Cell(msg) = item1.clone() * item2.clone();
result_msg.push_str(msg.as_str());
if pos + 1 < self_rows.len() {
result_msg.push(' ');
}
}
result_msg.clone()
}
}
#[cfg(test)]
mod matrix_fns {
use super::{ Matrix, Cell };
#[test]
fn when_by_row(){
let matrix1 = Matrix::new(&[1, 2, 3, 4]);
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));
}
#[test]
fn when_by_col(){
let matrix1 = Matrix::new(&[1, 2, 3, 4]);
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));
}
}
#[cfg(test)]
mod cell_operations {
use super::Cell;
#[test]
fn when_add(){
assert_eq!(Cell(22) + Cell(String::from("years ago")), Cell(String::from("22 years ago")));
assert_eq!(Cell(0) + Cell(String::from("expectation")), Cell(String::from("0 expectation")));
}
#[test]
fn when_add_and_number_is_negative(){
assert_eq!(Cell(-4) + Cell(String::from("xirtam")), Cell(String::from("matrix 4")));
}
#[test]
fn when_mult(){
assert_eq!(Cell(3) * Cell(String::from("woah!")), Cell(String::from("woah!woah!woah!")));
}
#[test]
fn when_mult_and_number_is_negative(){
assert_eq!(Cell(-3) * Cell(String::from(",regdab")), Cell(String::from("badger,badger,badger,")))
}
#[test]
fn when_mult_and_number_is_zero(){
assert_eq!(Cell(0) * Cell(String::from("woah?")), Cell(String::from("")));
}
}
#[cfg(test)]
mod martix_operations {
use super::{ Matrix, Cell };
fn string_cell_vec_helper(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]
fn when_add(){
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 + matrix2).by_row(),
string_cell_vec_helper("1 one", "2 two", "3 three", "4 four")
);
}
#[test]
fn when_add_and_some_number_is_negative(){
let matrix1 = Matrix::new(&[1, -2, 0, -4]);
let matrix2 = Matrix::new(&[
String::from("one"), String::from("owt"),
String::from("zero"), String::from("ruof")
]);
assert_eq!(
(matrix1 + matrix2).by_row(),
string_cell_vec_helper("1 one", "two 2", "0 zero", "four 4")
);
}
#[test]
fn when_mul(){
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 * matrix2, String::from("one threethree twotwotwo fourfourfourfour"));
}
#[test]
fn when_mul_and_some_number_is_negative(){
let matrix1 = Matrix::new(&[1, 2, -3, 4]);
let matrix2 = Matrix::new(&[
String::from("one"), String::from("owt"),
String::from("three"), String::from("four")
]);
assert_eq!(matrix1 * matrix2, String::from("one threethree twotwotwo fourfourfourfour"));
}
#[test]
fn when_mul_and_all_numbers_are_zero(){
let matrix1 = Matrix::new(&[0, 0, 0, 0]);
let matrix2 = Matrix::new(&[
String::from("one"), String::from("two"),
String::from("three"), String::from("four")
]);
assert_eq!(matrix1 * matrix2, String::from(" "));
}
}
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20220112-2706256-19ddn1l/solution) Finished test [unoptimized + debuginfo] target(s) in 8.42s 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.00s
История (2 версии и 1 коментар)
Георги качи решение на 16.11.2021 18:45 (преди почти 4 години)
use std::ops::Add;
use std::ops::Mul;
#[derive(Debug)]
pub struct Matrix<T: Clone> {
row1: Vec<T>,
row2: 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: Cell<i32>, other: Cell<String>) -> Self::Output {
let Cell(num) = self;
let Cell(msg) = other;
if num < 0 {
return Cell(format!("{} {}", msg.chars().rev().collect::<String>(), num.abs()))
}
Cell(format!("{} {}", num, msg))
}
}
impl Mul<Cell<String>> for Cell<i32> {
type Output = Cell<String>;
fn mul(self: Cell<i32>, other: Cell<String>) -> Self::Output {
let Cell(num) = self;
let Cell(msg) = other;
let rev_msg = msg.chars().rev().collect::<String>();
let mut final_msg = String::from("");
let mut counter = 0;
while counter < num.abs() {
if num < 0 {
final_msg.push_str(rev_msg.as_str());
}
else {
final_msg.push_str(msg.as_str());
}
counter = counter + 1
}
Cell(final_msg.clone())
}
}
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> {
let mut v1 = Vec::new();
let mut v2 = Vec::new();
for (pos, item) in data.iter().enumerate() {
if pos < data.len() / 2 {
v1.push(item.clone())
}
else {
v2.push(item.clone())
}
}
Matrix {
row1: v1.clone(),
row2: v2.clone()
}
}
/// Връща вектор, който съдържа в себе си всички 4 елемента на матрицата, наредени по редове,
/// от ляво надясно и от горе надолу, обвити в `Cell`. Тоест, ако матрицата изглежда така:
///
/// | 1 2 |
/// | 3 4 |
///
/// Очакваме `.by_row` да върне елементите в ред: 1, 2, 3, 4
///
pub fn by_row(&self) -> Vec<Cell<T>> {
let mut v = Vec::new();
for item in self.row1.iter() {
v.push(Cell(item.clone()));
}
for item in self.row2.iter() {
v.push(Cell(item.clone()));
}
v.clone()
}
/// Връща вектор, който съдържа в себе си всички 4 елемента на матрицата, наредени по колони,
/// от горе надолу и от ляво надясно, Обвити в `Cell`. Тоест, ако матрицата изглежда така:
///
/// | 1 2 |
/// | 3 4 |
///
/// Очакваме `.by_col` да върне елементите в ред: 1, 3, 2, 4
///
pub fn by_col(&self) -> Vec<Cell<T>> {
let mut v = Vec::new();
let iter1 = self.row1.iter();
let iter2 = self.row2.iter();
for (item1, item2) in iter1.zip(iter2) {
v.push(Cell(item1.clone()));
v.push(Cell(item2.clone()));
}
v.clone()
}
}
impl Add<Matrix<String>> for Matrix<i32> {
type Output = Matrix<String>;
fn add(self: Matrix<i32>, other: Matrix<String>) -> Self::Output {
let self_rows = self.by_row();
let other_rows = other.by_row();
let mut result1 = Vec::new();
let mut result2 = Vec::new();
for (item1, (pos, item2)) in self_rows.iter().zip(other_rows.iter().enumerate()) {
let Cell(result_msg) = item1.clone() + item2.clone();
if pos < 2 {
result1.push(result_msg);
}
else {
result2.push(result_msg);
}
}
Matrix {
row1: result1,
row2: result2
}
}
}
impl Mul<Matrix<String>> for Matrix<i32> {
type Output = String;
fn mul(self: Matrix<i32>, other: Matrix<String>) -> Self::Output {
let self_rows = self.by_row();
let other_cols = other.by_col();
let mut result_msg = String::from("");
for (item1, (pos, item2)) in self_rows.iter().zip(other_cols.iter().enumerate()) {
let Cell(msg) = item1.clone() * item2.clone();
result_msg.push_str(msg.as_str());
- if pos + 1 < self_rows.len() && msg != "" {
+ if pos + 1 < self_rows.len() {
result_msg.push(' ');
}
}
result_msg.clone()
}
}
#[cfg(test)]
mod matrix_fns {
use super::{ Matrix, Cell };
#[test]
fn when_by_row(){
let matrix1 = Matrix::new(&[1, 2, 3, 4]);
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));
}
#[test]
fn when_by_col(){
let matrix1 = Matrix::new(&[1, 2, 3, 4]);
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));
}
}
#[cfg(test)]
mod cell_operations {
use super::Cell;
#[test]
fn when_add(){
assert_eq!(Cell(22) + Cell(String::from("years ago")), Cell(String::from("22 years ago")));
assert_eq!(Cell(0) + Cell(String::from("expectation")), Cell(String::from("0 expectation")));
}
#[test]
fn when_add_and_number_is_negative(){
assert_eq!(Cell(-4) + Cell(String::from("xirtam")), Cell(String::from("matrix 4")));
}
#[test]
fn when_mult(){
assert_eq!(Cell(3) * Cell(String::from("woah!")), Cell(String::from("woah!woah!woah!")));
}
#[test]
fn when_mult_and_number_is_negative(){
assert_eq!(Cell(-3) * Cell(String::from(",regdab")), Cell(String::from("badger,badger,badger,")))
}
#[test]
fn when_mult_and_number_is_zero(){
assert_eq!(Cell(0) * Cell(String::from("woah?")), Cell(String::from("")));
}
}
#[cfg(test)]
mod martix_operations {
use super::{ Matrix, Cell };
fn string_cell_vec_helper(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]
fn when_add(){
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 + matrix2).by_row(),
string_cell_vec_helper("1 one", "2 two", "3 three", "4 four")
);
}
#[test]
fn when_add_and_some_number_is_negative(){
let matrix1 = Matrix::new(&[1, -2, 0, -4]);
let matrix2 = Matrix::new(&[
String::from("one"), String::from("owt"),
String::from("zero"), String::from("ruof")
]);
assert_eq!(
(matrix1 + matrix2).by_row(),
string_cell_vec_helper("1 one", "two 2", "0 zero", "four 4")
);
}
#[test]
fn when_mul(){
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 * matrix2, String::from("one threethree twotwotwo fourfourfourfour"));
}
#[test]
fn when_mul_and_some_number_is_negative(){
let matrix1 = Matrix::new(&[1, 2, -3, 4]);
let matrix2 = Matrix::new(&[
String::from("one"), String::from("owt"),
String::from("three"), String::from("four")
]);
assert_eq!(matrix1 * matrix2, String::from("one threethree twotwotwo fourfourfourfour"));
}
#[test]
fn when_mul_and_all_numbers_are_zero(){
let matrix1 = Matrix::new(&[0, 0, 0, 0]);
let matrix2 = Matrix::new(&[
String::from("one"), String::from("two"),
String::from("three"), String::from("four")
]);
- assert_eq!(matrix1 * matrix2, String::from(""));
+ assert_eq!(matrix1 * matrix2, String::from(" "));
}
}
Имаш допълнителни тестове за някои по-интересни случаи (нула, отрицателни числа), това е добре. Но мисля, че нито веднъж не си тествал обръщане на unicode, примерно кирилица.