| 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 |
| <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> |
| // 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 | |||||
| # 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/) | |||||