diff --git a/elixir/nucleotide-count/README.md b/elixir/nucleotide-count/README.md new file mode 100644 index 0000000..4782c89 --- /dev/null +++ b/elixir/nucleotide-count/README.md @@ -0,0 +1,55 @@ +# Nucleotide Count + +Given a single stranded DNA string, compute how many times each nucleotide occurs in the string. + +The genetic language of every living thing on the planet is DNA. +DNA is a large molecule that is built from an extremely long sequence of individual elements called nucleotides. +4 types exist in DNA and these differ only slightly and can be represented as the following symbols: 'A' for adenine, 'C' for cytosine, 'G' for guanine, and 'T' thymine. + +Here is an analogy: +- twigs are to birds nests as +- nucleotides are to DNA as +- legos are to lego houses as +- words are to sentences as... + +## Running tests + +Execute the tests with: + +```bash +$ elixir nucleotide_count_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 +``` + +If you're stuck on something, it may help to look at some of +the [available resources](https://exercism.io/tracks/elixir/resources) +out there where answers might be found. + +## Source + +The Calculating DNA Nucleotides_problem at Rosalind [http://rosalind.info/problems/dna/](http://rosalind.info/problems/dna/) + +## 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/nucleotide-count/nucleotide_count.exs b/elixir/nucleotide-count/nucleotide_count.exs new file mode 100644 index 0000000..902359f --- /dev/null +++ b/elixir/nucleotide-count/nucleotide_count.exs @@ -0,0 +1,32 @@ +defmodule NucleotideCount do + @nucleotides [?A, ?C, ?G, ?T] + + @doc """ + Counts individual nucleotides in a DNA strand. + + ## Examples + + iex> NucleotideCount.count('AATAA', ?A) + 4 + + iex> NucleotideCount.count('AATAA', ?T) + 1 + """ + @spec count([char], char) :: non_neg_integer + def count(strand, nucleotide) do + Enum.count(strand, fn n -> n == nucleotide end) + end + + @doc """ + Returns a summary of counts by nucleotide. + + ## Examples + + iex> NucleotideCount.histogram('AATAA') + %{?A => 4, ?T => 1, ?C => 0, ?G => 0} + """ + @spec histogram([char]) :: map + def histogram(strand) do + Map.new(@nucleotides, fn n -> {n, count(strand, n)} end) + end +end diff --git a/elixir/nucleotide-count/nucleotide_count_test.exs b/elixir/nucleotide-count/nucleotide_count_test.exs new file mode 100644 index 0000000..b30b76e --- /dev/null +++ b/elixir/nucleotide-count/nucleotide_count_test.exs @@ -0,0 +1,44 @@ +if !System.get_env("EXERCISM_TEST_EXAMPLES") do + Code.load_file("nucleotide_count.exs", __DIR__) +end + +ExUnit.start() +ExUnit.configure(exclude: :pending, trace: true) + +defmodule NucleotideCountTest do + use ExUnit.Case + + # @tag :pending + test "empty dna string has no adenine" do + assert NucleotideCount.count('', ?A) == 0 + end + + # @tag :pending + test "repetitive cytosine gets counted" do + assert NucleotideCount.count('CCCCC', ?C) == 5 + end + + # @tag :pending + test "counts only thymine" do + assert NucleotideCount.count('GGGGGTAACCCGG', ?T) == 1 + end + + # @tag :pending + test "empty dna string has no nucleotides" do + expected = %{?A => 0, ?T => 0, ?C => 0, ?G => 0} + assert NucleotideCount.histogram('') == expected + end + + # @tag :pending + test "repetitive sequence has only guanine" do + expected = %{?A => 0, ?T => 0, ?C => 0, ?G => 8} + assert NucleotideCount.histogram('GGGGGGGG') == expected + end + + # @tag :pending + test "counts all nucleotides" do + s = 'AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC' + expected = %{?A => 20, ?T => 21, ?C => 12, ?G => 17} + assert NucleotideCount.histogram(s) == expected + end +end