summary refs log tree commit diff stats
path: root/go/nucleotide-count
diff options
context:
space:
mode:
Diffstat (limited to 'go/nucleotide-count')
-rw-r--r--go/nucleotide-count/README.md64
-rw-r--r--go/nucleotide-count/cases_test.go39
-rw-r--r--go/nucleotide-count/go.mod3
-rw-r--r--go/nucleotide-count/nucleotide_count.go19
-rw-r--r--go/nucleotide-count/nucleotide_count_test.go27
5 files changed, 152 insertions, 0 deletions
diff --git a/go/nucleotide-count/README.md b/go/nucleotide-count/README.md
new file mode 100644
index 0000000..be96783
--- /dev/null
+++ b/go/nucleotide-count/README.md
@@ -0,0 +1,64 @@
+# 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...
+
+## Implementation
+
+You should define a custom type 'DNA' with a function 'Counts' that outputs two values: 
+
+- a frequency count for the given DNA strand
+- an error (if there are invalid nucleotides)
+
+Which is a good type for a DNA strand ? 
+
+Which is the best Go types to represent the output values ?
+
+Take a look at the test cases to get a hint about what could be the possible inputs.
+
+
+## note about the tests
+You may be wondering about the `cases_test.go` file. We explain it in the
+[leap exercise][leap-exercise-readme].
+
+[leap-exercise-readme]: https://github.com/exercism/go/blob/master/exercises/leap/README.md
+
+
+
+## Coding the solution
+
+Look for a stub file having the name nucleotide_count.go
+and place your solution code in that file.
+
+## Running the tests
+
+To run the tests run the command `go test` from within the exercise directory.
+
+If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
+flags:
+
+    go test -v --bench . --benchmem
+
+Keep in mind that each reviewer will run benchmarks on a different machine, with
+different specs, so the results from these benchmark tests may vary.
+
+## Further information
+
+For more detailed information about the Go track, including how to get help if
+you're having trouble, please visit the exercism.io [Go language page](http://exercism.io/languages/go/resources).
+
+## 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/go/nucleotide-count/cases_test.go b/go/nucleotide-count/cases_test.go
new file mode 100644
index 0000000..98d5cac
--- /dev/null
+++ b/go/nucleotide-count/cases_test.go
@@ -0,0 +1,39 @@
+package dna
+
+// Source: exercism/problem-specifications
+// Commit: 879a096 nucleotide-count: Apply new "input" policy
+// Problem Specifications Version: 1.3.0
+
+// count all nucleotides in a strand
+var testCases = []struct {
+	description   string
+	strand        string
+	expected      Histogram
+	errorExpected bool
+}{
+	{
+		description: "empty strand",
+		strand:      "",
+		expected:    Histogram{'A': 0, 'C': 0, 'G': 0, 'T': 0},
+	},
+	{
+		description: "can count one nucleotide in single-character input",
+		strand:      "G",
+		expected:    Histogram{'A': 0, 'C': 0, 'G': 1, 'T': 0},
+	},
+	{
+		description: "strand with repeated nucleotide",
+		strand:      "GGGGGGG",
+		expected:    Histogram{'A': 0, 'C': 0, 'G': 7, 'T': 0},
+	},
+	{
+		description: "strand with multiple nucleotides",
+		strand:      "AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC",
+		expected:    Histogram{'A': 20, 'C': 12, 'G': 17, 'T': 21},
+	},
+	{
+		description:   "strand with invalid nucleotides",
+		strand:        "AGXXACT",
+		errorExpected: true,
+	},
+}
diff --git a/go/nucleotide-count/go.mod b/go/nucleotide-count/go.mod
new file mode 100644
index 0000000..ee07bad
--- /dev/null
+++ b/go/nucleotide-count/go.mod
@@ -0,0 +1,3 @@
+module dna
+
+go 1.13
diff --git a/go/nucleotide-count/nucleotide_count.go b/go/nucleotide-count/nucleotide_count.go
new file mode 100644
index 0000000..1fb532c
--- /dev/null
+++ b/go/nucleotide-count/nucleotide_count.go
@@ -0,0 +1,19 @@
+package dna
+
+// Histogram is a mapping from nucleotide to its count in given DNA.
+// Choose a suitable data type.
+type Histogram
+
+// DNA is a list of nucleotides. Choose a suitable data type.
+type DNA
+
+// Counts generates a histogram of valid nucleotides in the given DNA.
+// Returns an error if d contains an invalid nucleotide.
+///
+// Counts is a method on the DNA type. A method is a function with a special receiver argument.
+// The receiver appears in its own argument list between the func keyword and the method name.
+// Here, the Counts method has a receiver of type DNA named d.
+func (d DNA) Counts() (Histogram, error) {
+	var h Histogram
+	return h, nil
+}
diff --git a/go/nucleotide-count/nucleotide_count_test.go b/go/nucleotide-count/nucleotide_count_test.go
new file mode 100644
index 0000000..247f8db
--- /dev/null
+++ b/go/nucleotide-count/nucleotide_count_test.go
@@ -0,0 +1,27 @@
+package dna
+
+import (
+	"reflect"
+	"testing"
+)
+
+func TestCounts(t *testing.T) {
+	for _, tc := range testCases {
+		dna := DNA(tc.strand)
+		s, err := dna.Counts()
+		switch {
+		case tc.errorExpected:
+			if err == nil {
+				t.Fatalf("FAIL: %s\nCounts(%q)\nExpected error\nActual: %#v",
+					tc.description, tc.strand, s)
+			}
+		case err != nil:
+			t.Fatalf("FAIL: %s\nCounts(%q)\nExpected: %#v\nGot error: %q",
+				tc.description, tc.strand, tc.expected, err)
+		case !reflect.DeepEqual(s, tc.expected):
+			t.Fatalf("FAIL: %s\nCounts(%q)\nExpected: %#v\nActual: %#v",
+				tc.description, tc.strand, tc.expected, s)
+		}
+		t.Logf("PASS: %s", tc.description)
+	}
+}