ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

nilvon9wo's solution

to Pascal's Triangle in the Elixir Track

Published at May 08 2020 · 0 comments
Instructions
Test suite
Solution

Compute Pascal's triangle up to a given number of rows.

In Pascal's Triangle each number is computed by adding the numbers to the right and left of the current position in the previous row.

``````    1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
# ... etc
``````

Running tests

Execute the tests with:

``````\$ mix test
``````

Pending tests

In the test suites, all but the first test have been skipped.

Once you get a test passing, you can unskip the next one by commenting out the relevant `@tag :pending` with a `#` symbol.

For example:

``````# @tag :pending
test "shouting" do
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
end
``````

Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the test suite.

``````# ExUnit.configure exclude: :pending, trace: true
``````

If you're stuck on something, it may help to look at some of the available resources out there where answers might be found.

Source

Pascal's Triangle at Wolfram Math World http://mathworld.wolfram.com/PascalsTriangle.html

Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

pascals_triangle_test.exs

``````defmodule PascalsTriangleTest do
use ExUnit.Case

# @tag pending
test "one row" do
assert PascalsTriangle.rows(1) == [[1]]
end

@tag :pending
test "two rows" do
assert PascalsTriangle.rows(2) == [[1], [1, 1]]
end

@tag :pending
test "three rows" do
assert PascalsTriangle.rows(3) == [[1], [1, 1], [1, 2, 1]]
end

@tag :pending
test "fourth row" do
assert List.last(PascalsTriangle.rows(4)) == [1, 3, 3, 1]
end

@tag :pending
test "fifth row" do
assert List.last(PascalsTriangle.rows(5)) == [1, 4, 6, 4, 1]
end

@tag :pending
test "twentieth row" do
expected = [
1,
19,
171,
969,
3876,
11_628,
27_132,
50_388,
75_582,
92_378,
92_378,
75_582,
50_388,
27_132,
11_628,
3876,
969,
171,
19,
1
]

assert List.last(PascalsTriangle.rows(20)) == expected
end
end``````

test_helper.exs

``````ExUnit.start()
ExUnit.configure(exclude: :pending, trace: true)``````
``````defmodule PascalsTriangle do
@doc """
Calculates the rows of a pascal triangle
with the given height
"""
@spec rows(integer) :: [[integer]]
def rows(1),
do: [[1]]

def rows(height),
do: rows(height, _accumulator = [[1, 1] | rows(1)])

defp rows(height, accumulator)
when height === length(accumulator),
do: Enum.reverse(accumulator)

defp rows(height, [bottom_row | _] = accumulator),
do: rows(height, [make_next_row(bottom_row) | accumulator])

defp make_next_row(previous_row),
do: make_next_row(previous_row, _accumulator = [1])

defp make_next_row([penultimate, 1] = _previous_row, accumulator),
do: [1 | [penultimate + 1 | accumulator]]

defp make_next_row([head | [second | tail]] = _previous_row, accumulator),
do: make_next_row([second | tail], [head + second | accumulator])
end``````