diff --git a/elixir/bracket-push/README.md b/elixir/bracket-push/README.md new file mode 100644 index 0000000..78d8f30 --- /dev/null +++ b/elixir/bracket-push/README.md @@ -0,0 +1,45 @@ +# Bracket Push + +Given a string containing brackets `[]`, braces `{}` and parentheses `()`, +verify that all the pairs are matched and nested correctly. + +## Running tests + +Execute the tests with: + +```bash +$ elixir bracket_push_test.exs +``` + +### 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: + +```elixir +# @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. + +```elixir +# ExUnit.configure exclude: :pending, trace: true +``` + +For more detailed information about the Elixir track, please +see the [help page](http://exercism.io/languages/elixir). + +## Source + +Ginna Baker + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/elixir/bracket-push/bracket_push.exs b/elixir/bracket-push/bracket_push.exs new file mode 100644 index 0000000..052e7b2 --- /dev/null +++ b/elixir/bracket-push/bracket_push.exs @@ -0,0 +1,22 @@ +defmodule BracketPush do + @doc """ + Checks that all the brackets and braces in the string are matched correctly, and nested correctly + """ + @spec check_brackets(String.t()) :: boolean + def check_brackets(str) do + check(String.graphemes(str), []) + end + + String.graphemes("{}()[]<>") + |> Enum.chunk_every(2) + |> Enum.each(fn pair -> + [o, c] = pair + defp check([unquote(o) | tail], stack), do: check(tail, [unquote(o) | stack]) + defp check([unquote(c) | tail], [unquote(o) | stack]), do: check(tail, stack) + defp check([unquote(c) | _], _), do: false + end) + + defp check([_head | tail], stack), do: check(tail, stack) + defp check([], []), do: true + defp check([], _), do: false +end diff --git a/elixir/bracket-push/bracket_push_test.exs b/elixir/bracket-push/bracket_push_test.exs new file mode 100644 index 0000000..2b9accd --- /dev/null +++ b/elixir/bracket-push/bracket_push_test.exs @@ -0,0 +1,82 @@ +if !System.get_env("EXERCISM_TEST_EXAMPLES") do + Code.load_file("bracket_push.exs", __DIR__) +end + +ExUnit.start() +ExUnit.configure(trace: true) + +defmodule BracketPushTest do + use ExUnit.Case + + @tag :pending + test "paired square brackets" do + assert BracketPush.check_brackets("[]") + end + + @tag :pending + test "empty string" do + assert BracketPush.check_brackets("") + end + + @tag :pending + test "unpaired brackets" do + refute BracketPush.check_brackets("[[") + end + + @tag :pending + test "wrong ordered brackets" do + refute BracketPush.check_brackets("}{") + end + + @tag :pending + test "wrong closing bracket" do + refute BracketPush.check_brackets("{]") + end + + @tag :pending + test "paired with whitespace" do + assert BracketPush.check_brackets("{ }") + end + + @tag :pending + test "simple nested brackets" do + assert BracketPush.check_brackets("{[]}") + end + + @tag :pending + test "several paired brackets" do + assert BracketPush.check_brackets("{}[]") + end + + @tag :pending + test "paired and nested brackets" do + assert BracketPush.check_brackets("([{}({}[])])") + end + + @tag :pending + test "unopened closing brackets" do + refute BracketPush.check_brackets("{[)][]}") + end + + @tag :pending + test "unpaired and nested brackets" do + refute BracketPush.check_brackets("([{])") + end + + @tag :pending + test "paired and wrong nested brackets" do + refute BracketPush.check_brackets("[({]})") + end + + @tag :pending + test "math expression" do + assert BracketPush.check_brackets("(((185 + 223.85) * 15) - 543)/2") + end + + @tag :pending + test "complex latex expression" do + assert BracketPush.check_brackets( + "\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)" + ) + end +end diff --git a/elixir/matrix/matrix.exs b/elixir/matrix/matrix.exs index dc499c0..43a9b00 100644 --- a/elixir/matrix/matrix.exs +++ b/elixir/matrix/matrix.exs @@ -7,6 +7,10 @@ defmodule Matrix do """ @spec from_string(input :: String.t()) :: %Matrix{} def from_string(input) do + input + |> String.split("\n") + |> Enum.map(&String.split(&1, " ")) + |> Enum.map(fn row -> Enum.map(row, &String.to_integer/1) end) end @doc """ @@ -15,33 +19,39 @@ defmodule Matrix do """ @spec to_string(matrix :: %Matrix{}) :: String.t() def to_string(matrix) do + Enum.join(Enum.map(matrix, &Enum.join(&1, " ")), "\n") end @doc """ Given a `matrix`, return its rows as a list of lists of integers. """ @spec rows(matrix :: %Matrix{}) :: list(list(integer)) - def rows(matrix) do - end + def rows(matrix), do: matrix @doc """ Given a `matrix` and `index`, return the row at `index`. """ @spec row(matrix :: %Matrix{}, index :: integer) :: list(integer) - def row(matrix, index) do - end + def row([head | _tail], 0), do: head + def row([_head | tail], index), do: row(tail, index - 1) @doc """ Given a `matrix`, return its columns as a list of lists of integers. """ @spec columns(matrix :: %Matrix{}) :: list(list(integer)) - def columns(matrix) do - end + def columns(matrix), do: rows(transpose(matrix)) @doc """ Given a `matrix` and `index`, return the column at `index`. """ @spec column(matrix :: %Matrix{}, index :: integer) :: list(integer) - def column(matrix, index) do + def column(matrix, index), do: row(transpose(matrix), index) + + @doc """ + swap rows and columns of a matrix + inspired by: http://exercism.io/submissions/dc8f7aff89864956b59d6077477ce9ce + """ + defp transpose(matrix) do + Enum.map(List.zip(matrix), &Tuple.to_list/1) end end diff --git a/elixir/phone-number/README.md b/elixir/phone-number/README.md new file mode 100644 index 0000000..9df6492 --- /dev/null +++ b/elixir/phone-number/README.md @@ -0,0 +1,70 @@ +# Phone Number + +Clean up user-entered phone numbers so that they can be sent SMS messages. + +The **North American Numbering Plan (NANP)** is a telephone numbering system used by many countries in North America like the United States, Canada or Bermuda. All NANP-countries share the same international country code: `1`. + +NANP numbers are ten-digit numbers consisting of a three-digit Numbering Plan Area code, commonly known as *area code*, followed by a seven-digit local number. The first three digits of the local number represent the *exchange code*, followed by the unique four-digit number which is the *subscriber number*. + +The format is usually represented as + +```text +(NXX)-NXX-XXXX +``` + +where `N` is any digit from 2 through 9 and `X` is any digit from 0 through 9. + +Your task is to clean up differently formatted telephone numbers by removing punctuation and the country code (1) if present. + +For example, the inputs +- `+1 (613)-995-0253` +- `613-995-0253` +- `1 613 995 0253` +- `613.995.0253` + +should all produce the output + +`6139950253` + +**Note:** As this exercise only deals with telephone numbers used in NANP-countries, only 1 is considered a valid country code. + +## Running tests + +Execute the tests with: + +```bash +$ elixir phone_number_test.exs +``` + +### 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: + +```elixir +# @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. + +```elixir +# ExUnit.configure exclude: :pending, trace: true +``` + +For more detailed information about the Elixir track, please +see the [help page](http://exercism.io/languages/elixir). + +## Source + +Event Manager by JumpstartLab [http://tutorials.jumpstartlab.com/projects/eventmanager.html](http://tutorials.jumpstartlab.com/projects/eventmanager.html) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/elixir/phone-number/phone_number.exs b/elixir/phone-number/phone_number.exs new file mode 100644 index 0000000..1ec6425 --- /dev/null +++ b/elixir/phone-number/phone_number.exs @@ -0,0 +1,76 @@ +defmodule Phone do + @doc """ + Remove formatting from a phone number. + + Returns "0000000000" if phone number is not valid + (10 digits or "1" followed by 10 digits) + + ## Examples + + iex> Phone.number("212-555-0100") + "2125550100" + + iex> Phone.number("+1 (212) 555-0100") + "2125550100" + + iex> Phone.number("+1 (212) 055-0100") + "0000000000" + + iex> Phone.number("(212) 555-0100") + "2125550100" + + iex> Phone.number("867.5309") + "0000000000" + """ + @spec number(String.t()) :: String.t() + def number(raw) do + end + + @doc """ + Extract the area code from a phone number + + Returns the first three digits from a phone number, + ignoring long distance indicator + + ## Examples + + iex> Phone.area_code("212-555-0100") + "212" + + iex> Phone.area_code("+1 (212) 555-0100") + "212" + + iex> Phone.area_code("+1 (012) 555-0100") + "000" + + iex> Phone.area_code("867.5309") + "000" + """ + @spec area_code(String.t()) :: String.t() + def area_code(raw) do + end + + @doc """ + Pretty print a phone number + + Wraps the area code in parentheses and separates + exchange and subscriber number with a dash. + + ## Examples + + iex> Phone.pretty("212-555-0100") + "(212) 555-0100" + + iex> Phone.pretty("212-155-0100") + "(000) 000-0000" + + iex> Phone.pretty("+1 (303) 555-1212") + "(303) 555-1212" + + iex> Phone.pretty("867.5309") + "(000) 000-0000" + """ + @spec pretty(String.t()) :: String.t() + def pretty(raw) do + end +end diff --git a/elixir/phone-number/phone_number_test.exs b/elixir/phone-number/phone_number_test.exs new file mode 100644 index 0000000..8c0b3d0 --- /dev/null +++ b/elixir/phone-number/phone_number_test.exs @@ -0,0 +1,109 @@ +if !System.get_env("EXERCISM_TEST_EXAMPLES") do + Code.load_file("phone_number.exs", __DIR__) +end + +ExUnit.start() +ExUnit.configure(exclude: :pending, trace: true) + +defmodule PhoneTest do + use ExUnit.Case + + test "cleans number" do + assert Phone.number("(212) 555-0100") == "2125550100" + end + + @tag :pending + test "cleans number with dots" do + assert Phone.number("212.555.0100") == "2125550100" + end + + @tag :pending + test "valid when 11 digits and first is 1" do + assert Phone.number("12125550100") == "2125550100" + end + + @tag :pending + test "valid when 11 digits and some decorations" do + assert Phone.number("+1 (212) 555-0100") == "2125550100" + end + + @tag :pending + test "invalid when country calling code is not 1" do + assert Phone.number("22125550100") == "0000000000" + end + + @tag :pending + test "invalid when 9 digits" do + assert Phone.number("212555010") == "0000000000" + end + + @tag :pending + test "invalid when proper number of digits but letters mixed in" do + assert Phone.number("2a1a2a5a5a5a0a1a0a0a") == "0000000000" + end + + @tag :pending + test "invalid with correct number of characters but some are letters" do + assert Phone.number("2a1a2a5a5a") == "0000000000" + end + + @tag :pending + test "invalid when area code begins with 1" do + assert Phone.number("1125550100") == "0000000000" + end + + @tag :pending + test "invalid when area code begins with 0" do + assert Phone.number("0125550100") == "0000000000" + end + + @tag :pending + test "invalid when exchange code begins with 1" do + assert Phone.number("2121550100") == "0000000000" + end + + @tag :pending + test "invalid when exchange code begins with 0" do + assert Phone.number("2120550100") == "0000000000" + end + + @tag :pending + test "area code" do + assert Phone.area_code("2125550100") == "212" + end + + @tag :pending + test "area code with full US phone number" do + assert Phone.area_code("12125550100") == "212" + end + + @tag :pending + test "invalid area code" do + assert Phone.area_code("(100) 555-1234") == "000" + end + + @tag :pending + test "no area code" do + assert Phone.area_code("867.5309") == "000" + end + + @tag :pending + test "pretty print" do + assert Phone.pretty("2125550100") == "(212) 555-0100" + end + + @tag :pending + test "pretty print with full US phone number" do + assert Phone.pretty("+1 (303) 555-1212") == "(303) 555-1212" + end + + @tag :pending + test "pretty print invalid US phone number" do + assert Phone.pretty("212-155-0100") == "(000) 000-0000" + end + + @tag :pending + test "pretty print invalid, short US phone number" do + assert Phone.pretty("867.5309") == "(000) 000-0000" + end +end diff --git a/elixir/rna-transcription/README.md b/elixir/rna-transcription/README.md new file mode 100644 index 0000000..4691431 --- /dev/null +++ b/elixir/rna-transcription/README.md @@ -0,0 +1,60 @@ +# RNA Transcription + +Given a DNA strand, return its RNA complement (per RNA transcription). + +Both DNA and RNA strands are a sequence of nucleotides. + +The four nucleotides found in DNA are adenine (**A**), cytosine (**C**), +guanine (**G**) and thymine (**T**). + +The four nucleotides found in RNA are adenine (**A**), cytosine (**C**), +guanine (**G**) and uracil (**U**). + +Given a DNA strand, its transcribed RNA strand is formed by replacing +each nucleotide with its complement: + +* `G` -> `C` +* `C` -> `G` +* `T` -> `A` +* `A` -> `U` + +## Running tests + +Execute the tests with: + +```bash +$ elixir rna_transcription_test.exs +``` + +### 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: + +```elixir +# @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. + +```elixir +# ExUnit.configure exclude: :pending, trace: true +``` + +For more detailed information about the Elixir track, please +see the [help page](http://exercism.io/languages/elixir). + +## Source + +Rosalind [http://rosalind.info/problems/rna](http://rosalind.info/problems/rna) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/elixir/rna-transcription/rna_transcription.exs b/elixir/rna-transcription/rna_transcription.exs new file mode 100644 index 0000000..b98fdf4 --- /dev/null +++ b/elixir/rna-transcription/rna_transcription.exs @@ -0,0 +1,21 @@ +defmodule RNATranscription do + @doc """ + Transcribes a character list representing DNA nucleotides to RNA + + ## Examples + + iex> RNATranscription.to_rna('ACTG') + 'UGAC' + """ + @spec to_rna([char]) :: [char] + def to_rna(dna) do + Enum.map(dna, fn d -> + case d do + ?G -> ?C + ?C -> ?G + ?T -> ?A + ?A -> ?U + end + end) + end +end diff --git a/elixir/rna-transcription/rna_transcription_test.exs b/elixir/rna-transcription/rna_transcription_test.exs new file mode 100644 index 0000000..8d0ed3b --- /dev/null +++ b/elixir/rna-transcription/rna_transcription_test.exs @@ -0,0 +1,35 @@ +if !System.get_env("EXERCISM_TEST_EXAMPLES") do + Code.load_file("rna_transcription.exs", __DIR__) +end + +ExUnit.start() +ExUnit.configure(trace: true) + +defmodule RNATranscriptionTest do + use ExUnit.Case + + @tag :pending + test "transcribes guanine to cytosine" do + assert RNATranscription.to_rna('G') == 'C' + end + + @tag :pending + test "transcribes cytosine to guanine" do + assert RNATranscription.to_rna('C') == 'G' + end + + @tag :pending + test "transcribes thymidine to adenine" do + assert RNATranscription.to_rna('T') == 'A' + end + + @tag :pending + test "transcribes adenine to uracil" do + assert RNATranscription.to_rna('A') == 'U' + end + + @tag :pending + test "it transcribes all dna nucleotides to rna equivalents" do + assert RNATranscription.to_rna('ACGTGGTCTTAA') == 'UGCACCAGAAUU' + end +end