diff --git a/subject_source/src/vec.rs b/subject_source/src/vec.rs index ce652d9..32cd690 100644 --- a/subject_source/src/vec.rs +++ b/subject_source/src/vec.rs @@ -1 +1,2 @@ pub mod access; +pub mod compute; diff --git a/subject_source/src/vec/compute.rs b/subject_source/src/vec/compute.rs new file mode 100644 index 0000000..01cd4e3 --- /dev/null +++ b/subject_source/src/vec/compute.rs @@ -0,0 +1,48 @@ +pub enum Operation { + Push(f32), + Binary(Binary), +} + +pub enum Binary { + Add, + Sub, + Mul, + Div, +} + +#[derive(PartialEq, Debug)] +pub enum ComputeError { + NotEnoughData, + DivisionByZero, +} + +pub fn compute(operations: &[Operation]) -> Result { + let mut stack = vec![]; + for operation in operations { + match operation { + Operation::Push(n) => stack.push(*n), + Operation::Binary(op) => { + let b = stack.pop(); + let a = stack.pop(); + + let r = match (a, b) { + (Some(a), Some(b)) => match op { + Binary::Add => a + b, + Binary::Mul => a * b, + Binary::Div => { + if b == 0.0 { + return Err(ComputeError::DivisionByZero); + } + a / b + } + Binary::Sub => a - b, + }, + _ => return Err(ComputeError::NotEnoughData), + }; + stack.push(r); + } + } + } + + stack.pop().ok_or(ComputeError::NotEnoughData) +} diff --git a/subject_source/tests/vec_compute.rs b/subject_source/tests/vec_compute.rs new file mode 100644 index 0000000..aa7f26f --- /dev/null +++ b/subject_source/tests/vec_compute.rs @@ -0,0 +1,58 @@ +use subject_source::vec::compute::*; + +#[test] +pub fn compute_empty() { + assert_eq!(compute(&[]), Err(ComputeError::NotEnoughData)); +} + +#[test] +pub fn compute_too_many_ops() { + assert_eq!( + compute(&[Operation::Push(1.0), Operation::Binary(Binary::Add)]), + Err(ComputeError::NotEnoughData) + ); +} + +#[test] +pub fn compute_division_by_zero_push() { + assert_eq!( + compute(&[ + Operation::Push(1.0), + Operation::Push(0.0), + Operation::Binary(Binary::Div) + ]), + Err(ComputeError::DivisionByZero) + ); +} + +#[test] +pub fn compute_division_by_zero_operation() { + assert_eq!( + compute(&[ + Operation::Push(1.0), + Operation::Push(1.0), + Operation::Push(1.0), + Operation::Binary(Binary::Sub), + Operation::Binary(Binary::Div) + ]), + Err(ComputeError::DivisionByZero) + ); +} + +#[test] +pub fn compute_all_ops() { + assert_eq!( + compute(&[ + Operation::Push(1.0), + Operation::Push(3.0), + Operation::Push(2.0), + Operation::Binary(Binary::Sub), + Operation::Push(5.0), + Operation::Binary(Binary::Mul), + Operation::Binary(Binary::Add), + Operation::Push(2.0), + Operation::Binary(Binary::Div), + ]), + Ok(3.0), + ); +} diff --git a/subject_text/vec/access.md b/subject_text/vec/access.md index e782b1c..b272416 100644 --- a/subject_text/vec/access.md +++ b/subject_text/vec/access.md @@ -16,6 +16,14 @@ if vec.len() < 1 { Try to implement these functions using non-panicking methods like [`last`](https://doc.rust-lang.org/std/primitive.slice.html#method.last), [`last_chunk`](https://doc.rust-lang.org/std/primitive.slice.html#method.last_chunk), or [`get`](https://doc.rust-lang.org/std/primitive.slice.html#method.get). +```note +Don't be afraid of the `get` function prototype, look at the examples, they are fairly simple, it's just that `get` can work on multiple types, allowing for slice indexing as well as single element indexing. +``` + +```note +You may want to look at the [`sort`](https://doc.rust-lang.org/std/primitive.slice.html#method.sort) and [`to_vec`](https://doc.rust-lang.org/std/primitive.slice.html#method.to_vec) functions for the median. +``` + ```prototype /// Add the last two numbers of the input slice. ///