Решение на Matrix 4 от Димитър Георгиев

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

Към профила на Димитър Георгиев

Резултати

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

Код

#[derive(Debug)]
pub struct Matrix<T: Clone> {
matrix: Vec<Cell<T> >,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Cell<T>(pub T);
impl<T: Clone> Matrix<T> {
pub fn new(data: &[T; 4]) -> Matrix<T> {
let mut matrix = vec![];
for t in data {
matrix.push(Cell(t.clone()));
}
Matrix { matrix }
}
pub fn by_row(&self) -> Vec<Cell<T>> {
self.matrix.clone()
}
pub fn by_col(&self) -> Vec<Cell<T>> {
let mut first_col: Vec<Cell<T>> = vec![];
let mut second_col: Vec<Cell<T>> = vec![];
for (i, cell) in self.matrix.iter().enumerate() {
if i % 2 == 0 {
first_col.push(cell.clone());
} else {
second_col.push(cell.clone());
}
}
first_col.append(&mut second_col);
first_col
}
}
use std::ops::Add;
impl Add<Cell<String> > for Cell<i32> {
type Output = Cell<String>; // искаме винаги да връщаме Cell<String>
fn add(self, rhs: Cell<String>) -> Cell<String> {
if self.0 >= 0 {
let result = format!("{} {}", self.0.to_string(), rhs.0);
return Cell(result);
} else {
let rhs_reverse = rhs.0.chars().rev().collect::<String>();
let result = format!("{} {}", rhs_reverse, (self.0).abs().to_string());
return Cell(result);
}
}
}
impl Add<Matrix<String> > for Matrix<i32> {
type Output = Matrix<String>;
fn add(self, rhs: Matrix<String>) -> Matrix<String> {
let mut result : Vec<Cell<String> > = vec![];
let mut iter = self.by_row().into_iter().zip(rhs.by_row());
while let Some((a, b)) = iter.next() {
result.push(a+b);
}
Matrix { matrix : result}
}
}
use std::ops::Mul;
impl Mul<Cell<String> > for Cell<i32> {
type Output = Cell<String>;
fn mul(self, rhs: Cell<String>) -> Cell<String> {
let repeater = (self.0).abs() as usize;
if self.0 >= 0 {
let result = rhs.0.repeat(repeater); // не съм сигурен дали е най-удачното решение заради usize cast-a

// не съм сигурен дали е най-удачното решение заради usize cast-a

Разумно е -- все пак горе му викаш .abs(). В идеален свят, може би този метод би върнал unsigned варианта на входа си, но не мисля че има как да се изрази с типовата система generically.

return Cell(result);
} else {
let rhs_reverse = rhs.0.chars().rev().collect::<String>();
let result = rhs_reverse.repeat(repeater);
return Cell(result);
}
}
}
impl Mul<Matrix<String> > for Matrix<i32> {
type Output = String;
fn mul(self, rhs: Matrix<String>) -> String {
let mut result = String::from("");
let mut iter = self.by_row().into_iter().zip(rhs.by_col());
while let Some((a, b)) = iter.next() {
result.push_str(&(a*b).0);
result.push(' ');
}
result.pop();
result
}
}
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>>>()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_matrix_row_col_test() {
let matrix1 = Matrix::new(&[3, 4, 6, 120]);
let matrix2 = Matrix::new(&[
String::from("one"),
String::from("two"),
String::from("three"),
String::from("four"),
]);
assert_eq!(matrix1.by_row()[0], Cell(3));
assert_eq!(matrix1.by_row()[1], Cell(4));
assert_eq!(matrix1.by_row()[3], Cell(120));
assert_eq!(matrix1.by_col()[0], Cell(3));
assert_eq!(matrix1.by_col()[1], Cell(6));
assert_eq!(matrix1.by_col()[2], Cell(4));
assert_eq!(matrix1.matrix[0], Cell(3)); // да видим дали случайно някъде не сменям ownership
assert_eq!(matrix1.matrix[3], Cell(120));
assert_eq!(matrix2.by_row()[0], Cell(String::from("one")));
assert_eq!(matrix2.by_row()[3], Cell(String::from("four")));
assert_eq!(matrix2.by_col()[0], Cell(String::from("one")));
assert_eq!(matrix2.by_col()[1], Cell(String::from("three")));
assert_eq!(matrix2.matrix[0], Cell(String::from("one"))); // да видим дали случайно някъде не сменям ownership
assert_eq!(matrix2.matrix[3], Cell(String::from("four")));
}
#[test]
#[should_panic]
fn new_matrix_row_col_test_panic() {
let matrix1 = Matrix::new(&[3, 4, 6, 120]);
let matrix2 = Matrix::new(&[
String::from("one"),
String::from("two"),
String::from("three"),
String::from("four"),
]);
assert_eq!(matrix1.by_row()[0], Cell(4));
assert_eq!(matrix1.by_row()[3], Cell(6));
assert_eq!(matrix1.by_col()[1], Cell(120));
assert_eq!(matrix1.by_col()[2], Cell(4));
assert_eq!(matrix2.by_row()[0], Cell(String::from("two")));
assert_eq!(matrix2.by_row()[3], Cell(String::from("two")));
assert_eq!(matrix2.by_col()[1], Cell(String::from("two")));
assert_eq!(matrix2.by_col()[1], Cell(String::from("one")));
}
#[test]
fn test_add_cells() {
assert_eq!((Cell(4) + Cell(String::from("badger"))).0, String::from("4 badger"));
assert_eq!((Cell(7) + Cell(String::from("Pi"))).0, String::from("7 Pi"));
assert_eq!(Cell(-4) + Cell(String::from("xirtam")), Cell(String::from("matrix 4")));
assert_eq!(Cell(-2) + Cell(String::from("alucard")), Cell(String::from("dracula 2")));
assert_eq!(Cell(0) + Cell(String::from("")), Cell(String::from("0 "))); // empty string test
}
#[test]
#[should_panic]
fn test_add_cells_panic() {
assert_eq!((Cell(3) + Cell(String::from("badger"))).0, String::from("4 badger"));
assert_eq!((Cell(7) + Cell(String::from("Pi"))).0, String::from("6 Pi"));
assert_eq!(Cell(-3) + Cell(String::from("xirtam")), Cell(String::from("matrix 4")));
assert_eq!(Cell(-2) + Cell(String::from("alucard")), Cell(String::from("dracula 3")));
}

Тестовете, в които проверяваш, че нещо ще panic-не са малко странни. Кода panic-ва просто защото assertion-а не е правилен, което не е нещо, което има смисъл да тестваш (допълнително, когато първия ред panic-не, останалите изобщо няма да се извикат). Ако искаш да валидираш, че Cell(3) + Cell(...) не е равно на нещо, можеш спокойно да напишеш assert_ne! ("not equal"). Но в този случай, защо не напишеш на какво очакваш да е равно? Ако провериш, че събирането на 3 и badger е 3 badger, тогава е ясно, че няма да бъде 4 badger.

#[test]
fn test_mul_cells() {
assert_eq!((Cell(2) * Cell(String::from("mushroom"))).0, String::from("mushroommushroom"));
assert_eq!((Cell(3) * Cell(String::from("Pile"))).0, String::from("PilePilePile"));
assert_eq!(Cell(-3) * Cell(String::from(",regdab")), Cell(String::from("badger,badger,badger,")));
assert_eq!(Cell(0) * Cell(String::from("Krusha")), Cell(String::from(""))); //0 multiplication test
}
#[test]
#[should_panic]
fn test_mul_cells_panic() {
assert_eq!((Cell(5) * Cell(String::from("mushroom"))).0, String::from("mushroommushroom"));
assert_eq!((Cell(2) * Cell(String::from("Pile"))).0, String::from("PilePilePile"));
assert_eq!(Cell(-1) * Cell(String::from(",regdab")), Cell(String::from("badger,badger,badger,")));
assert_eq!(Cell(0) * Cell(String::from("Krusha")), Cell(String::from("Krusha")));
}
#[test]
fn test_add_matrices() {
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("1 one", "2 two", "3 three", "4 four")
);
}
#[test]
#[should_panic]
fn test_add_matrices_panic() {
let matrix1 = Matrix::new(&[2, 3, 4, 1]);
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("1 one", "2 two", "3 three", "4 four")
);
}
#[test]
fn test_mul_matrices() {
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"));
let matrix3 = Matrix::new(&[2, 1, 4, 3]);
let matrix4 = Matrix::new(&[
String::from("one"), String::from("two"),
String::from("three"), String::from("four")
]);
assert_eq!(matrix3 * matrix4, String::from("oneone three twotwotwotwo fourfourfour"));
let matrix5 = Matrix::new(&[0, 0, 0, 0]);
let matrix6 = Matrix::new(&[
String::from("one"), String::from("two"),
String::from("three"), String::from("four")
]);
assert_eq!(matrix5 * matrix6, String::from(" "));
}
#[test]
#[should_panic]
fn test_mul_matrices_panic() {
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("on three two four"));
let matrix3 = Matrix::new(&[2, 1, 4, 3]);
let matrix4 = Matrix::new(&[
String::from("one"), String::from("two"),
String::from("three"), String::from("four")
]);
assert_eq!(matrix3 * matrix4, String::from("oneone two threethreethreethree fourfourfour "));
let matrix5 = Matrix::new(&[0, 0, 0, 0]);
let matrix6 = Matrix::new(&[
String::from("one"), String::from("two"),
String::from("three"), String::from("four")
]);
assert_eq!(matrix5 * matrix6, String::from("one "));
}
}

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

Compiling solution v0.1.0 (/tmp/d20220112-2706256-1bz7yh4/solution)
warning: function is never used: `string_cell_vec`
  --> src/lib.rs:95:4
   |
95 | fn string_cell_vec(s1: &str, s2: &str, s3: &str, s4: &str) -> Vec<Cell<String>> {
   |    ^^^^^^^^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

warning: `solution` (lib) generated 1 warning
    Finished test [unoptimized + debuginfo] target(s) in 7.68s
     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 версии и 2 коментара)

Димитър качи първо решение на 16.11.2021 11:06 (преди почти 4 години)

Димитър качи решение на 18.11.2021 16:40 (преди почти 4 години)

-use std::io::repeat;
-use std::vec;
-
#[derive(Debug)]
pub struct Matrix<T: Clone> {
matrix: Vec<Cell<T> >,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Cell<T>(pub T);
impl<T: Clone> Matrix<T> {
pub fn new(data: &[T; 4]) -> Matrix<T> {
- let mut _matrix = vec![];
+ let mut matrix = vec![];
for t in data {
- _matrix.push(Cell(t.clone()));
+ matrix.push(Cell(t.clone()));
}
- Matrix { matrix: _matrix }
+ Matrix { matrix }
}
pub fn by_row(&self) -> Vec<Cell<T>> {
- let mut result: Vec<Cell<T>> = self.matrix.clone();
- result
+ self.matrix.clone()
}
pub fn by_col(&self) -> Vec<Cell<T>> {
- let mut firstCol: Vec<Cell<T>> = vec![];
- let mut secondCol: Vec<Cell<T>> = vec![];
+ let mut first_col: Vec<Cell<T>> = vec![];
+ let mut second_col: Vec<Cell<T>> = vec![];
for (i, cell) in self.matrix.iter().enumerate() {
if i % 2 == 0 {
- firstCol.push(cell.clone());
+ first_col.push(cell.clone());
} else {
- secondCol.push(cell.clone());
+ second_col.push(cell.clone());
}
}
- firstCol.append(&mut secondCol);
- firstCol
+ first_col.append(&mut second_col);
+ first_col
}
}
use std::ops::Add;
impl Add<Cell<String> > for Cell<i32> {
type Output = Cell<String>; // искаме винаги да връщаме Cell<String>
fn add(self, rhs: Cell<String>) -> Cell<String> {
if self.0 >= 0 {
let result = format!("{} {}", self.0.to_string(), rhs.0);
return Cell(result);
} else {
- let rhsReverse = rhs.0.chars().rev().collect::<String>();
- let result = format!("{} {}", rhsReverse, (self.0).abs().to_string());
+ let rhs_reverse = rhs.0.chars().rev().collect::<String>();
+ let result = format!("{} {}", rhs_reverse, (self.0).abs().to_string());
return Cell(result);
}
}
}
impl Add<Matrix<String> > for Matrix<i32> {
type Output = Matrix<String>;
fn add(self, rhs: Matrix<String>) -> Matrix<String> {
let mut result : Vec<Cell<String> > = vec![];
let mut iter = self.by_row().into_iter().zip(rhs.by_row());
while let Some((a, b)) = iter.next() {
result.push(a+b);
}
Matrix { matrix : result}
}
}
use std::ops::Mul;
impl Mul<Cell<String> > for Cell<i32> {
type Output = Cell<String>;
fn mul(self, rhs: Cell<String>) -> Cell<String> {
let repeater = (self.0).abs() as usize;
if self.0 >= 0 {
let result = rhs.0.repeat(repeater); // не съм сигурен дали е най-удачното решение заради usize cast-a

// не съм сигурен дали е най-удачното решение заради usize cast-a

Разумно е -- все пак горе му викаш .abs(). В идеален свят, може би този метод би върнал unsigned варианта на входа си, но не мисля че има как да се изрази с типовата система generically.

return Cell(result);
} else {
- let rhsReverse = rhs.0.chars().rev().collect::<String>();
- let result = rhsReverse.repeat(repeater);
+ let rhs_reverse = rhs.0.chars().rev().collect::<String>();
+ let result = rhs_reverse.repeat(repeater);
return Cell(result);
}
}
}
impl Mul<Matrix<String> > for Matrix<i32> {
type Output = String;
fn mul(self, rhs: Matrix<String>) -> String {
let mut result = String::from("");
let mut iter = self.by_row().into_iter().zip(rhs.by_col());
while let Some((a, b)) = iter.next() {
result.push_str(&(a*b).0);
result.push(' ');
}
result.pop();
result
}
}
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>>>()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_matrix_row_col_test() {
let matrix1 = Matrix::new(&[3, 4, 6, 120]);
let matrix2 = Matrix::new(&[
String::from("one"),
String::from("two"),
String::from("three"),
String::from("four"),
]);
assert_eq!(matrix1.by_row()[0], Cell(3));
assert_eq!(matrix1.by_row()[1], Cell(4));
assert_eq!(matrix1.by_row()[3], Cell(120));
assert_eq!(matrix1.by_col()[0], Cell(3));
assert_eq!(matrix1.by_col()[1], Cell(6));
assert_eq!(matrix1.by_col()[2], Cell(4));
assert_eq!(matrix1.matrix[0], Cell(3)); // да видим дали случайно някъде не сменям ownership
assert_eq!(matrix1.matrix[3], Cell(120));
assert_eq!(matrix2.by_row()[0], Cell(String::from("one")));
assert_eq!(matrix2.by_row()[3], Cell(String::from("four")));
assert_eq!(matrix2.by_col()[0], Cell(String::from("one")));
assert_eq!(matrix2.by_col()[1], Cell(String::from("three")));
assert_eq!(matrix2.matrix[0], Cell(String::from("one"))); // да видим дали случайно някъде не сменям ownership
assert_eq!(matrix2.matrix[3], Cell(String::from("four")));
}
#[test]
#[should_panic]
fn new_matrix_row_col_test_panic() {
let matrix1 = Matrix::new(&[3, 4, 6, 120]);
let matrix2 = Matrix::new(&[
String::from("one"),
String::from("two"),
String::from("three"),
String::from("four"),
]);
assert_eq!(matrix1.by_row()[0], Cell(4));
assert_eq!(matrix1.by_row()[3], Cell(6));
assert_eq!(matrix1.by_col()[1], Cell(120));
assert_eq!(matrix1.by_col()[2], Cell(4));
assert_eq!(matrix2.by_row()[0], Cell(String::from("two")));
assert_eq!(matrix2.by_row()[3], Cell(String::from("two")));
assert_eq!(matrix2.by_col()[1], Cell(String::from("two")));
assert_eq!(matrix2.by_col()[1], Cell(String::from("one")));
}
#[test]
fn test_add_cells() {
assert_eq!((Cell(4) + Cell(String::from("badger"))).0, String::from("4 badger"));
assert_eq!((Cell(7) + Cell(String::from("Pi"))).0, String::from("7 Pi"));
assert_eq!(Cell(-4) + Cell(String::from("xirtam")), Cell(String::from("matrix 4")));
assert_eq!(Cell(-2) + Cell(String::from("alucard")), Cell(String::from("dracula 2")));
assert_eq!(Cell(0) + Cell(String::from("")), Cell(String::from("0 "))); // empty string test
-
- /*let x = Cell(4);
- let y = Cell(String::from("Pile"));
- let z = x + y;
- assert_eq!(z, Cell(String::from("4 Pile"))); // не съм сигурен дали трябва след извикване на оператор да сменяме ownership-а
- assert_eq!(x, Cell(4));
- assert_eq!(y, Cell(String::from("Pile")));*/
}
#[test]
#[should_panic]
fn test_add_cells_panic() {
assert_eq!((Cell(3) + Cell(String::from("badger"))).0, String::from("4 badger"));
assert_eq!((Cell(7) + Cell(String::from("Pi"))).0, String::from("6 Pi"));
assert_eq!(Cell(-3) + Cell(String::from("xirtam")), Cell(String::from("matrix 4")));
assert_eq!(Cell(-2) + Cell(String::from("alucard")), Cell(String::from("dracula 3")));
}

Тестовете, в които проверяваш, че нещо ще panic-не са малко странни. Кода panic-ва просто защото assertion-а не е правилен, което не е нещо, което има смисъл да тестваш (допълнително, когато първия ред panic-не, останалите изобщо няма да се извикат). Ако искаш да валидираш, че Cell(3) + Cell(...) не е равно на нещо, можеш спокойно да напишеш assert_ne! ("not equal"). Но в този случай, защо не напишеш на какво очакваш да е равно? Ако провериш, че събирането на 3 и badger е 3 badger, тогава е ясно, че няма да бъде 4 badger.

#[test]
fn test_mul_cells() {
assert_eq!((Cell(2) * Cell(String::from("mushroom"))).0, String::from("mushroommushroom"));
assert_eq!((Cell(3) * Cell(String::from("Pile"))).0, String::from("PilePilePile"));
assert_eq!(Cell(-3) * Cell(String::from(",regdab")), Cell(String::from("badger,badger,badger,")));
assert_eq!(Cell(0) * Cell(String::from("Krusha")), Cell(String::from(""))); //0 multiplication test
}
#[test]
#[should_panic]
fn test_mul_cells_panic() {
assert_eq!((Cell(5) * Cell(String::from("mushroom"))).0, String::from("mushroommushroom"));
assert_eq!((Cell(2) * Cell(String::from("Pile"))).0, String::from("PilePilePile"));
assert_eq!(Cell(-1) * Cell(String::from(",regdab")), Cell(String::from("badger,badger,badger,")));
assert_eq!(Cell(0) * Cell(String::from("Krusha")), Cell(String::from("Krusha")));
}
#[test]
fn test_add_matrices() {
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("1 one", "2 two", "3 three", "4 four")
);
}
#[test]
#[should_panic]
fn test_add_matrices_panic() {
let matrix1 = Matrix::new(&[2, 3, 4, 1]);
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("1 one", "2 two", "3 three", "4 four")
);
}
#[test]
fn test_mul_matrices() {
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"));
let matrix3 = Matrix::new(&[2, 1, 4, 3]);
let matrix4 = Matrix::new(&[
String::from("one"), String::from("two"),
String::from("three"), String::from("four")
]);
assert_eq!(matrix3 * matrix4, String::from("oneone three twotwotwotwo fourfourfour"));
let matrix5 = Matrix::new(&[0, 0, 0, 0]);
let matrix6 = Matrix::new(&[
String::from("one"), String::from("two"),
String::from("three"), String::from("four")
]);
assert_eq!(matrix5 * matrix6, String::from(" "));
}
#[test]
#[should_panic]
fn test_mul_matrices_panic() {
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("on three two four"));
let matrix3 = Matrix::new(&[2, 1, 4, 3]);
let matrix4 = Matrix::new(&[
String::from("one"), String::from("two"),
String::from("three"), String::from("four")
]);
assert_eq!(matrix3 * matrix4, String::from("oneone two threethreethreethree fourfourfour "));
let matrix5 = Matrix::new(&[0, 0, 0, 0]);
let matrix6 = Matrix::new(&[
String::from("one"), String::from("two"),
String::from("three"), String::from("four")
]);
assert_eq!(matrix5 * matrix6, String::from("one "));
}
}