Hello rusty rusters, I've got a small exercise that could use some more experienced eyes. Any and all suggestions welcome. Below I briefly describe the exercise, my solution, and specific questions.
My code is posted at the end (lib.rs
) as well as the tests included from Exercism, which can be placed in the tests
cargo project folder for usage with cargo test
. Note that if you do this, be sure to run all tests with cargo test -- --ignored
.
The Exercise
Create a function which takes a u32
parameter and returns a struct
called PascalsTriangle
. The struct must have two functions built in, each with predetermined parameters and return types:
pub struct PascalsTriangle {}
impl PascalsTraingle {
pub fn new(row_count: u32) -> Self {
}
pub fn rows(&self) -> Vec<Vec<u32>> {
}
}
My Solution
This code basically works by creating a new vector for each row, and populating that row by adding the two values in the previous row.
Questions
- Is this the right way to go about using rust for this problem?
- Are there useful things from the standard library I'm missing?
- Any other rust-style things I should be replacing
for
loops with? I'm still having trouble knowing when to applywhile let
,if let
,match
, and using iterators rather thanfor
loops.
Anything else you think might improve this code is totally welcome. Thanks for looking!
src/lib.rs
pub struct PascalsTriangle {
row_count: u32,
triangle: Vec<Vec<u32>>,
}
impl PascalsTriangle {
pub fn new(row_count: u32) -> Self {
let mut triangle: Vec<Vec<u32>> = vec![];
let mut new_triangle = PascalsTriangle {
row_count,
triangle,
};
triangle = new_triangle.rows();
new_triangle.triangle = triangle;
new_triangle
}
// Create Pascals Triangle vector of vectors
// First make containing vector, then populate first two rows as edge cases.
// For remaining rows, create a new vector for each row, use members of previous
// row to make members of new row.
pub fn rows(&self) -> Vec<Vec<u32>> {
let mut triangle: Vec<Vec<u32>> =
Vec::with_capacity(self.row_count as usize);
if self.row_count == 0 {
return triangle
} else if self.row_count >= 1 {
let apex: Vec<u32> = vec![1];
triangle.push(apex);
}
if self.row_count >= 2 {
let second_row: Vec<u32> = vec![1, 1];
triangle.push(second_row);
}
if self.row_count > 2 {
for index in 2..(self.row_count as usize) {
let mut row: Vec<u32> = Vec::with_capacity(index + 1);
row.push(1);
for last_index in 0..=((triangle[index - 1].len() - 2) as usize) {
row.push(triangle[index - 1][last_index]
+ triangle[index - 1][last_index+1]);
}
row.push(1);
triangle.push(row);
}
}
triangle
}
}
tests/pascals-triangle.rs
use pascals_triangle::*;
#[test]
fn no_rows() {
let pt = PascalsTriangle::new(0);
let expected: Vec<Vec<u32>> = Vec::new();
assert_eq!(expected, pt.rows());
}
#[test]
#[ignore]
fn one_row() {
let pt = PascalsTriangle::new(1);
let expected: Vec<Vec<u32>> = vec![vec![1]];
assert_eq!(expected, pt.rows());
}
#[test]
#[ignore]
fn two_rows() {
let pt = PascalsTriangle::new(2);
let expected: Vec<Vec<u32>> = vec![vec![1], vec![1, 1]];
assert_eq!(expected, pt.rows());
}
#[test]
#[ignore]
fn three_rows() {
let pt = PascalsTriangle::new(3);
let expected: Vec<Vec<u32>> = vec![vec![1], vec![1, 1], vec![1, 2, 1]];
assert_eq!(expected, pt.rows());
}
#[test]
#[ignore]
fn last_of_four_rows() {
let pt = PascalsTriangle::new(4);
let expected: Vec<u32> = vec![1, 3, 3, 1];
assert_eq!(Some(expected), pt.rows().pop());
}
#[test]
#[ignore]
fn five_rows() {
let pt = PascalsTriangle::new(5);
let expected: Vec<Vec<u32>> = vec![
vec![1],
vec![1, 1],
vec![1, 2, 1],
vec![1, 3, 3, 1],
vec![1, 4, 6, 4, 1],
];
assert_eq!(expected, pt.rows());
}
#[test]
#[ignore]
fn six_rows() {
let pt = PascalsTriangle::new(6);
let expected: Vec<Vec<u32>> = vec![
vec![1],
vec![1, 1],
vec![1, 2, 1],
vec![1, 3, 3, 1],
vec![1, 4, 6, 4, 1],
vec![1, 5, 10, 10, 5, 1],
];
assert_eq!(expected, pt.rows());
}
#[test]
#[ignore]
fn seven_rows() {
let pt = PascalsTriangle::new(7);
let expected: Vec<Vec<u32>> = vec![
vec![1],
vec![1, 1],
vec![1, 2, 1],
vec![1, 3, 3, 1],
vec![1, 4, 6, 4, 1],
vec![1, 5, 10, 10, 5, 1],
vec![1, 6, 15, 20, 15, 6, 1],
];
assert_eq!(expected, pt.rows());
}
#[test]
#[ignore]
fn ten_rows() {
let pt = PascalsTriangle::new(10);
let expected: Vec<Vec<u32>> = vec![
vec![1],
vec![1, 1],
vec![1, 2, 1],
vec![1, 3, 3, 1],
vec![1, 4, 6, 4, 1],
vec![1, 5, 10, 10, 5, 1],
vec![1, 6, 15, 20, 15, 6, 1],
vec![1, 7, 21, 35, 35, 21, 7, 1],
vec![1, 8, 28, 56, 70, 56, 28, 8, 1],
vec![1, 9, 36, 84, 126, 126, 84, 36, 9, 1],
];
assert_eq!(expected, pt.rows());
}