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