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

# Eggman's solution

## to Pascal's Triangle in the Elixir Track

Published at Apr 15 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(num) when is_integer(num) and num > 0 do
1..num
|> Enum.reduce([], fn row, acc -> [generate_row(row, List.first(acc)) | acc] end)
|> Enum.reverse
end

# -----

# A row has as many columns as it's ordinal row number
# i.e. the 4th row has 4 columns, the 9th row has 9 columns, etc

defp generate_row(1, _), do: [1]

defp generate_row(row_num, previous_row) do
0..row_num - 1
|> Enum.map( &(add_neighbors(&1, previous_row)) )
end

# -----

defp add_neighbors(col_index, prev_row) do
value_at(prev_row, col_index - 1) + value_at(prev_row, col_index)
end

# -----

defp value_at(num_list, index) when index < 0 or index > length(num_list) -1, do: 0

defp value_at(num_list, index), do: Enum.at(num_list, index)

end``````