Skip to content

Commit f0f3388

Browse files
committed
Add nucleotide-count
1 parent 4ec5e8a commit f0f3388

File tree

7 files changed

+215
-0
lines changed

7 files changed

+215
-0
lines changed

nucleotide-count/README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Nucleotide Count
2+
3+
Given a single stranded DNA string, compute how many times each nucleotide occurs in the string.
4+
5+
The genetic language of every living thing on the planet is DNA.
6+
DNA is a large molecule that is built from an extremely long sequence of individual elements called nucleotides.
7+
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.
8+
9+
Here is an analogy:
10+
- twigs are to birds nests as
11+
- nucleotides are to DNA as
12+
- legos are to lego houses as
13+
- words are to sentences as...
14+
15+
16+
## Getting Started
17+
18+
Please refer to the [installation](https://exercism.io/tracks/haskell/installation)
19+
and [learning](https://exercism.io/tracks/haskell/learning) help pages.
20+
21+
## Running the tests
22+
23+
To run the test suite, execute the following command:
24+
25+
```bash
26+
stack test
27+
```
28+
29+
#### If you get an error message like this...
30+
31+
```
32+
No .cabal file found in directory
33+
```
34+
35+
You are probably running an old stack version and need
36+
to upgrade it.
37+
38+
#### Otherwise, if you get an error message like this...
39+
40+
```
41+
No compiler found, expected minor version match with...
42+
Try running "stack setup" to install the correct GHC...
43+
```
44+
45+
Just do as it says and it will download and install
46+
the correct compiler version:
47+
48+
```bash
49+
stack setup
50+
```
51+
52+
## Running *GHCi*
53+
54+
If you want to play with your solution in GHCi, just run the command:
55+
56+
```bash
57+
stack ghci
58+
```
59+
60+
## Feedback, Issues, Pull Requests
61+
62+
The [exercism/haskell](https://github.com/exercism/haskell) repository on
63+
GitHub is the home for all of the Haskell exercises.
64+
65+
If you have feedback about an exercise, or want to help implementing a new
66+
one, head over there and create an issue. We'll do our best to help you!
67+
68+
## Source
69+
70+
The Calculating DNA Nucleotides_problem at Rosalind [http://rosalind.info/problems/dna/](http://rosalind.info/problems/dna/)
71+
72+
## Submitting Incomplete Solutions
73+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
cabal-version: 1.12
2+
3+
-- This file has been generated from package.yaml by hpack version 0.33.0.
4+
--
5+
-- see: https://github.com/sol/hpack
6+
--
7+
-- hash: c85b93dcc5a9010c6db8d786cc1b90e30eb1c4a39356b7989c4d331b1f6af460
8+
9+
name: nucleotide-count
10+
version: 1.3.0.8
11+
build-type: Simple
12+
13+
library
14+
exposed-modules:
15+
DNA
16+
other-modules:
17+
Paths_nucleotide_count
18+
hs-source-dirs:
19+
src
20+
ghc-options: -Wall
21+
build-depends:
22+
base
23+
, containers
24+
default-language: Haskell2010
25+
26+
test-suite test
27+
type: exitcode-stdio-1.0
28+
main-is: Tests.hs
29+
other-modules:
30+
Paths_nucleotide_count
31+
hs-source-dirs:
32+
test
33+
build-depends:
34+
base
35+
, containers
36+
, hspec
37+
, nucleotide-count
38+
default-language: Haskell2010

nucleotide-count/package.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: nucleotide-count
2+
version: 1.3.0.8
3+
4+
dependencies:
5+
- base
6+
- containers
7+
8+
library:
9+
exposed-modules: DNA
10+
source-dirs: src
11+
ghc-options: -Wall
12+
# dependencies:
13+
# - foo # List here the packages you
14+
# - bar # want to use in your solution.
15+
16+
tests:
17+
test:
18+
main: Tests.hs
19+
source-dirs: test
20+
dependencies:
21+
- nucleotide-count
22+
- hspec

nucleotide-count/src/DNA.hs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module DNA (nucleotideCounts, Nucleotide(..)) where
2+
3+
import Data.Map (Map)
4+
import qualified Data.Map as Map
5+
6+
data Nucleotide = A | C | G | T deriving (Eq, Ord, Show)
7+
8+
dnaMap :: Map Nucleotide Int
9+
dnaMap = foldl (\acc c -> Map.insert c 0 acc) Map.empty [A, C, G, T]
10+
11+
nucleotideCounts :: String -> Either String (Map Nucleotide Int)
12+
nucleotideCounts xs = foldl addToMap (Right dnaMap) xs
13+
where
14+
addToMap (Left a) _ = Left a
15+
addToMap (Right a) c
16+
| c == 'A' = Right (Map.insertWith (+) A 1 a)
17+
| c == 'C' = Right (Map.insertWith (+) C 1 a)
18+
| c == 'G' = Right (Map.insertWith (+) G 1 a)
19+
| c == 'T' = Right (Map.insertWith (+) T 1 a)
20+
| otherwise = Left xs

nucleotide-count/stack.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
resolver: lts-15.8

nucleotide-count/stack.yaml.lock

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# This file was autogenerated by Stack.
2+
# You should not edit this file by hand.
3+
# For more information, please see the documentation at:
4+
# https://docs.haskellstack.org/en/stable/lock_files
5+
6+
packages: []
7+
snapshots:
8+
- completed:
9+
size: 492015
10+
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/15/8.yaml
11+
sha256: 926bc3d70249dd0ba05277ff00943c0addb35b627cb641752669e7cf771310d0
12+
original: lts-15.8

nucleotide-count/test/Tests.hs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
2+
{-# language LambdaCase #-}
3+
4+
import Data.Either (isLeft)
5+
import Data.Map (findWithDefault)
6+
import Test.Hspec (Spec, describe, it, shouldSatisfy)
7+
import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
8+
9+
import DNA (nucleotideCounts, Nucleotide(..))
10+
11+
main :: IO ()
12+
main = hspecWith defaultConfig {configFastFail = True} specs
13+
14+
specs :: Spec
15+
specs = do
16+
17+
let x `matchesMap` y = shouldSatisfy x $ \case
18+
Right count -> and [ findWithDefault 0 n count == c | (n,c) <- y ]
19+
Left _ -> False
20+
21+
describe "nucleotideCounts" $ do
22+
23+
it "empty dna strand has no nucleotides" $
24+
nucleotideCounts "" `matchesMap` [ (A, 0)
25+
, (C, 0)
26+
, (G, 0)
27+
, (T, 0) ]
28+
29+
it "can count one nucleotide in single-character input" $
30+
nucleotideCounts "G" `matchesMap` [ (A, 0)
31+
, (C, 0)
32+
, (G, 1)
33+
, (T, 0) ]
34+
35+
it "repetitive-sequence-has-only-guanosine" $
36+
nucleotideCounts "GGGGGGGG" `matchesMap` [ (A, 0)
37+
, (C, 0)
38+
, (G, 8)
39+
, (T, 0) ]
40+
41+
it "counts all nucleotides" $
42+
nucleotideCounts "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC"
43+
`matchesMap` [ (A, 20)
44+
, (C, 12)
45+
, (G, 17)
46+
, (T, 21) ]
47+
48+
it "validates strand" $
49+
nucleotideCounts "AGXXACT" `shouldSatisfy` isLeft

0 commit comments

Comments
 (0)