| @@ -0,0 +1,26 @@ | |||
| module NucleotideCount | |||
| let isValidNucleotide nucleotide = | |||
| nucleotide = 'A' | |||
| || nucleotide = 'C' | |||
| || nucleotide = 'G' | |||
| || nucleotide = 'T' | |||
| let validInput (strand: string) = | |||
| String.collect (fun c -> if isValidNucleotide c then string (c) else "") strand = strand | |||
| let nucleotideCounts (strand: string): Option<Map<char, int>> = | |||
| if validInput strand then | |||
| let mutable counts = | |||
| Map.empty.Add('A', 0).Add('C', 0).Add('G', 0).Add('T', 0) | |||
| Seq.iter (fun c -> | |||
| if counts.ContainsKey c then | |||
| let current = counts.Item c | |||
| counts <- counts.Remove(c) | |||
| counts <- counts.Add(c, current + 1) | |||
| else | |||
| counts <- counts.Add(c, 1)) strand | |||
| Some(counts) | |||
| else | |||
| None | |||
| @@ -0,0 +1,21 @@ | |||
| <Project Sdk="Microsoft.NET.Sdk"> | |||
| <PropertyGroup> | |||
| <TargetFramework>netcoreapp3.0</TargetFramework> | |||
| <IsPackable>false</IsPackable> | |||
| </PropertyGroup> | |||
| <ItemGroup> | |||
| <Compile Include="NucleotideCount.fs" /> | |||
| <Compile Include="NucleotideCountTests.fs" /> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" /> | |||
| <PackageReference Include="xunit" Version="2.4.1" /> | |||
| <PackageReference Include="xunit.runner.visualstudio" Version="2.4.2" /> | |||
| <PackageReference Include="FsUnit.xUnit" Version="3.8.1" /> | |||
| </ItemGroup> | |||
| </Project> | |||
| @@ -0,0 +1,63 @@ | |||
| // This file was auto-generated based on version 1.3.0 of the canonical data. | |||
| module NucleotideCountTests | |||
| open FsUnit.Xunit | |||
| open Xunit | |||
| open NucleotideCount | |||
| [<Fact>] | |||
| let ``Empty strand`` () = | |||
| let strand = "" | |||
| let expected = | |||
| [ ('A', 0); | |||
| ('C', 0); | |||
| ('G', 0); | |||
| ('T', 0) ] | |||
| |> Map.ofList | |||
| |> Some | |||
| nucleotideCounts strand |> should equal expected | |||
| [<Fact>] | |||
| let ``Can count one nucleotide in single-character input`` () = | |||
| let strand = "G" | |||
| let expected = | |||
| [ ('A', 0); | |||
| ('C', 0); | |||
| ('G', 1); | |||
| ('T', 0) ] | |||
| |> Map.ofList | |||
| |> Some | |||
| nucleotideCounts strand |> should equal expected | |||
| [<Fact>] | |||
| let ``Strand with repeated nucleotide`` () = | |||
| let strand = "GGGGGGG" | |||
| let expected = | |||
| [ ('A', 0); | |||
| ('C', 0); | |||
| ('G', 7); | |||
| ('T', 0) ] | |||
| |> Map.ofList | |||
| |> Some | |||
| nucleotideCounts strand |> should equal expected | |||
| [<Fact>] | |||
| let ``Strand with multiple nucleotides`` () = | |||
| let strand = "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC" | |||
| let expected = | |||
| [ ('A', 20); | |||
| ('C', 12); | |||
| ('G', 17); | |||
| ('T', 21) ] | |||
| |> Map.ofList | |||
| |> Some | |||
| nucleotideCounts strand |> should equal expected | |||
| [<Fact>] | |||
| let ``Strand with invalid nucleotides`` () = | |||
| let strand = "AGXXACT" | |||
| let expected = None | |||
| nucleotideCounts strand |> should equal expected | |||
| @@ -0,0 +1,33 @@ | |||
| # 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 the tests | |||
| To run the tests, run the command `dotnet test` from within the exercise directory. | |||
| ## Autoformatting the code | |||
| F# source code can be formatted with the [Fantomas](https://github.com/fsprojects/fantomas) tool. | |||
| After installing it with `dotnet tool restore`, run `dotnet fantomas .` to format code within the current directory. | |||
| ## Further information | |||
| For more detailed information about the F# track, including how to get help if | |||
| you're having trouble, please visit the exercism.io [F# language page](http://exercism.io/languages/fsharp/resources). | |||
| ## Source | |||
| The Calculating DNA Nucleotides_problem at Rosalind [http://rosalind.info/problems/dna/](http://rosalind.info/problems/dna/) | |||