From 6b27c260e5484bb088a54b1cf32520f15421dbb0 Mon Sep 17 00:00:00 2001 From: Angelika Cathor Date: Wed, 28 Aug 2024 10:41:45 +0200 Subject: [PATCH] Lucas numbers: swap steps to avoid infinite recursion (#1512) --- .../concept/lucas-numbers/.docs/hints.md | 12 ++--- .../lucas-numbers/.docs/instructions.md | 24 +++++----- .../lucas-numbers/test/lucas_numbers_test.exs | 48 +++++++++---------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/exercises/concept/lucas-numbers/.docs/hints.md b/exercises/concept/lucas-numbers/.docs/hints.md index 3642792394..51f5ad735e 100644 --- a/exercises/concept/lucas-numbers/.docs/hints.md +++ b/exercises/concept/lucas-numbers/.docs/hints.md @@ -5,21 +5,21 @@ - Use the built-in [(linked) list type][list]. - Use the built-in [`Stream`][stream] module functions to create a stream -## 1. Generate the base cases +## 1. Catch bad arguments + +- Use a [guard][guards] to catch the cases when an integer isn't passed as an argument to `generate/1`. + +## 2. Generate the base cases - You can use multiple [function clauses][multiple-fn-clauses] and [pattern-matching][pattern-matching] to create the base case functions. -## 2. Create the generalized case +## 3. Create the generalized case - Use the [`Stream.iterate/2`][stream-iterate] function to generate a sequence of numbers, with the next being created from the previous. - The starting numbers are `2` then `1`, which you can pass in together using a tuple to make a pair `{2, 1}` - Make sure the next number is the sum of the two numbers previous to it. - To evaluate the stream to a list, use an [`Enum`][enum] function. -## 3. Catch bad arguments - -- Use a [guard][guards] to catch the cases when an integer isn't passed as an argument to `generate/1`. - [enum]: https://hexdocs.pm/elixir/Enum.html#content [guards]: https://hexdocs.pm/elixir/patterns-and-guards.html#guards [list]: https://hexdocs.pm/elixir/lists-and-tuples.html#linked-lists diff --git a/exercises/concept/lucas-numbers/.docs/instructions.md b/exercises/concept/lucas-numbers/.docs/instructions.md index 268dda22f6..fd424ddd32 100644 --- a/exercises/concept/lucas-numbers/.docs/instructions.md +++ b/exercises/concept/lucas-numbers/.docs/instructions.md @@ -2,9 +2,18 @@ You are a huge fan of the [Numberphile Youtube channel](https://www.youtube.com/watch?v=PeUbRXnbmms) and you just saw a cool video about the _Lucas Number Sequence_. You want to create this sequence using Elixir. -While designing your function, you want to make use of _lazy evaluation_, so that you can generate as many numbers as you want, but only if you need to -- So you decide to use a stream: +While designing your function, you want to make use of _lazy evaluation_, so that you can generate as many numbers as you want, but only if you need to -- So you decide to use a stream. -## 1. Generate the base cases +## 1. Catch bad arguments + +Add a guard clause to raise an error if a non-integer or an integer less than 1 is used to generate the sequence. Doing this as the first step will prevent infinite recursion bugs in later steps. + +```elixir +LucasNumbers.generate("Hello World") +# => ** (ArgumentError) count must be specified as an integer >= 1 +``` + +## 2. Generate the base cases You know that the sequence has two starting numbers which don't follow the same rule. Write two base case clauses to return these numbers: @@ -16,7 +25,7 @@ LucasNumbers.generate(2) # => [2, 1] ``` -## 2. Create the generalized case +## 3. Create the generalized case For any sequence longer than 2, you know that you need to add the previous two numbers to get the next number and so on. Write the generalized case. @@ -27,12 +36,3 @@ LucasNumbers.generate(3) LucasNumbers.generate(4) # => [2, 1, 3, 4] ``` - -## 3. Catch bad arguments - -Later, you find someone is using your function and having problems because they are using incorrect arguments. Add a guard clause to raise an error if a non-integer or an integer less than 1 is used to generate the sequence: - -```elixir -LucasNumbers.generate("Hello World") -# => ** (ArgumentError) count must be specified as an integer >= 1 -``` diff --git a/exercises/concept/lucas-numbers/test/lucas_numbers_test.exs b/exercises/concept/lucas-numbers/test/lucas_numbers_test.exs index af15c089a5..40ce9c7f7b 100644 --- a/exercises/concept/lucas-numbers/test/lucas_numbers_test.exs +++ b/exercises/concept/lucas-numbers/test/lucas_numbers_test.exs @@ -2,68 +2,82 @@ defmodule LucasNumbersTest do use ExUnit.Case @tag task_id: 1 + test "catch incorrect non-integer arguments" do + assert_raise ArgumentError, "count must be specified as an integer >= 1", fn -> + LucasNumbers.generate("Hello world!") + end + end + + @tag task_id: 1 + test "catch incorrect integer arguments" do + assert_raise ArgumentError, "count must be specified as an integer >= 1", fn -> + LucasNumbers.generate(-1) + end + end + + @tag task_id: 2 test "generates a sequence of length 1" do assert LucasNumbers.generate(1) == [2] end - @tag task_id: 1 + @tag task_id: 2 test "generates a sequence of length 2" do assert LucasNumbers.generate(2) == [2, 1] end - @tag task_id: 2 + @tag task_id: 3 test "generates a sequence of length 3" do assert LucasNumbers.generate(3) == [2, 1, 3] end - @tag task_id: 2 + @tag task_id: 3 test "generates a sequence of length 4" do assert LucasNumbers.generate(4) == [2, 1, 3, 4] end - @tag task_id: 2 + @tag task_id: 3 test "generates a sequence of length 5" do sequence = [2, 1, 3, 4, 7] assert LucasNumbers.generate(5) == sequence end - @tag task_id: 2 + @tag task_id: 3 test "generates a sequence of length 6" do sequence = [2, 1, 3, 4, 7, 11] assert LucasNumbers.generate(6) == sequence end - @tag task_id: 2 + @tag task_id: 3 test "generates a sequence of length 7" do sequence = [2, 1, 3, 4, 7, 11, 18] assert LucasNumbers.generate(7) == sequence end - @tag task_id: 2 + @tag task_id: 3 test "generates a sequence of length 8" do sequence = [2, 1, 3, 4, 7, 11, 18, 29] assert LucasNumbers.generate(8) == sequence end - @tag task_id: 2 + @tag task_id: 3 test "generates a sequence of length 9" do sequence = [2, 1, 3, 4, 7, 11, 18, 29, 47] assert LucasNumbers.generate(9) == sequence end - @tag task_id: 2 + @tag task_id: 3 test "generates a sequence of length 10" do sequence = [2, 1, 3, 4, 7, 11, 18, 29, 47, 76] assert LucasNumbers.generate(10) == sequence end - @tag task_id: 2 + @tag task_id: 3 test "generates a sequence of length 25" do sequence = [ 2, @@ -95,18 +109,4 @@ defmodule LucasNumbersTest do assert LucasNumbers.generate(25) == sequence end - - @tag task_id: 3 - test "catch incorrect non-integer arguments" do - assert_raise ArgumentError, "count must be specified as an integer >= 1", fn -> - LucasNumbers.generate("Hello world!") - end - end - - @tag task_id: 3 - test "catch incorrect integer arguments" do - assert_raise ArgumentError, "count must be specified as an integer >= 1", fn -> - LucasNumbers.generate(-1) - end - end end