Skip to content

Commit

Permalink
Lucas numbers: swap steps to avoid infinite recursion (#1512)
Browse files Browse the repository at this point in the history
  • Loading branch information
angelikatyborska authored Aug 28, 2024
1 parent 507231c commit 6b27c26
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 42 deletions.
12 changes: 6 additions & 6 deletions exercises/concept/lucas-numbers/.docs/hints.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 12 additions & 12 deletions exercises/concept/lucas-numbers/.docs/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand All @@ -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.

Expand All @@ -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
```
48 changes: 24 additions & 24 deletions exercises/concept/lucas-numbers/test/lucas_numbers_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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

0 comments on commit 6b27c26

Please sign in to comment.