From d8ea42b79501f888fa05befd1ef5d0ac17087cee Mon Sep 17 00:00:00 2001 From: lilymonade Date: Thu, 13 Mar 2025 22:24:34 +0100 Subject: [PATCH] finifini --- practical.yml | 4 ++ subject_source/tests/vec_compute.rs | 20 +++++++++ subject_text/tree | 3 +- subject_text/vec/compute.md | 64 +++++++++++++++++++++++++++++ subject_text/vec/index.md | 4 +- 5 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 subject_text/vec/compute.md diff --git a/practical.yml b/practical.yml index ee99515..10cf0d5 100644 --- a/practical.yml +++ b/practical.yml @@ -59,3 +59,7 @@ exercises: - "compute_division_by_zero_push" - "compute_division_by_zero_operation" - "compute_all_ops" + - "compute_add" + - "compute_sub" + - "compute_mul" + - "compute_div" diff --git a/subject_source/tests/vec_compute.rs b/subject_source/tests/vec_compute.rs index aa7f26f..4d613dc 100644 --- a/subject_source/tests/vec_compute.rs +++ b/subject_source/tests/vec_compute.rs @@ -56,3 +56,23 @@ pub fn compute_all_ops() { Ok(3.0), ); } + +#[test] +pub fn compute_add() { + assert_eq!(compute(&[Operation::Push(1.0), Operation::Push(2.0), Operation::Binary(Binary::Add)]), Ok(3.0)); +} + +#[test] +pub fn compute_sub() { + assert_eq!(compute(&[Operation::Push(1.0), Operation::Push(2.0), Operation::Binary(Binary::Sub)]), Ok(-1.0)); +} + +#[test] +pub fn compute_mul() { + assert_eq!(compute(&[Operation::Push(3.0), Operation::Push(2.0), Operation::Binary(Binary::Mul)]), Ok(6.0)); +} + +#[test] +pub fn compute_div() { + assert_eq!(compute(&[Operation::Push(42.0), Operation::Push(7.0), Operation::Binary(Binary::Div)]), Ok(6.0)); +} diff --git a/subject_text/tree b/subject_text/tree index 3f6193c..94956a0 100644 --- a/subject_text/tree +++ b/subject_text/tree @@ -6,6 +6,7 @@    │   └── result.rs    ├── errors.rs    ├── vec -    │   └── access.rs +    │   ├── access.rs +    │   └── compute.rs    ├── vec.rs    └── lib.rs diff --git a/subject_text/vec/compute.md b/subject_text/vec/compute.md new file mode 100644 index 0000000..2cd0460 --- /dev/null +++ b/subject_text/vec/compute.md @@ -0,0 +1,64 @@ +--- +name = "Compute simple Forth expressions" +file = "src/vec/compute.rs" +--- + +[Forth](https://en.wikipedia.org/wiki/Forth_(programming_language)) is a stack based programming language based on the [Reverse Polish Notation](https://en.wikipedia.org/wiki/Reverse_Polish_notation). In this language, a program is expressed as a stream of words, each word representing an instruction. For example, this expression: + +``` +1.0 2.0 + +``` + +represent a program made of 3 words: `1.0` meaning "push the number 1.0" on the stack, `2.0` meaning push 2.0 on the stack, and `+` meaning "pop the two highest numbers off the stack, and push their sum". We will first define some types to represent such program, and then implement the `compute` function, taking a `slice` of operations and giving the result of computing these operations. + +```rust +/// Possible operations +pub enum Operation { + Push(f32), + Binary(Binary), +} + +/// Different binary operators +pub enum Binary { + /// + + Add, + /// - + Sub, + /// * + Mul, + /// / + Div, +} + +/// What could go wrong when computing a Forth expression +#[derive(PartialEq, Debug)] +pub enum ComputeError { + NotEnoughData, + DivisionByZero, +} +``` + +```prototype +pub fn compute(operations: &[Operation]) -> Result { + unimplemented!() +} +``` + +```example +fn main() { + // 1 2 3 * + + // gives the result 7 because it's computed as 1 + 2 * 3 + assert_eq!( + compute(&[ + Operation::Push(1.0), + Operation::Push(2.0), + Operation::Push(3.0), + Operation::Binary(Binary::Mul), + Operation::Binary(Binary::Add), + ]), + Ok(7.0) + ); + + assert_eq!(compute(&[Operation::Binary(Binary::Add)), Err(ComputeError::NotEnoughData)); +} +``` diff --git a/subject_text/vec/index.md b/subject_text/vec/index.md index 4d4f5cf..4aa491d 100644 --- a/subject_text/vec/index.md +++ b/subject_text/vec/index.md @@ -1,7 +1,7 @@ --- name = "Vecs and slices" -difficulty = 2 -exercises = ["access.md"] +difficulty = 5 +exercises = ["access.md", "compute.md"] --- Let's now look at some functions on [`slice`](https://doc.rust-lang.org/std/primitive.slice.html)s and [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html)s. Instead of manualy checking things we will follow the type system using `Option`s and `Result`s we saw earlier.