summaryrefslogtreecommitdiff
path: root/go/hamming
diff options
context:
space:
mode:
Diffstat (limited to 'go/hamming')
-rw-r--r--go/hamming/README.md54
-rw-r--r--go/hamming/cases_test.go81
-rw-r--r--go/hamming/hamming.go18
-rw-r--r--go/hamming/hamming_test.go36
4 files changed, 189 insertions, 0 deletions
diff --git a/go/hamming/README.md b/go/hamming/README.md
new file mode 100644
index 0000000..83c017d
--- /dev/null
+++ b/go/hamming/README.md
@@ -0,0 +1,54 @@
+# Hamming
+
+Write a program that can calculate the Hamming difference between two DNA strands.
+
+A mutation is simply a mistake that occurs during the creation or
+copying of a nucleic acid, in particular DNA. Because nucleic acids are
+vital to cellular functions, mutations tend to cause a ripple effect
+throughout the cell. Although mutations are technically mistakes, a very
+rare mutation may equip the cell with a beneficial attribute. In fact,
+the macro effects of evolution are attributable by the accumulated
+result of beneficial microscopic mutations over many generations.
+
+The simplest and most common type of nucleic acid mutation is a point
+mutation, which replaces one base with another at a single nucleotide.
+
+By counting the number of differences between two homologous DNA strands
+taken from different genomes with a common ancestor, we get a measure of
+the minimum number of point mutations that could have occurred on the
+evolutionary path between the two strands.
+
+This is called the 'Hamming distance'.
+
+It is found by comparing two DNA strands and counting how many of the
+nucleotides are different from their equivalent in the other string.
+
+ GAGCCTACTAACGGGAT
+ CATCGTAATGACGGCCT
+ ^ ^ ^ ^ ^ ^^
+
+The Hamming distance between these two DNA strands is 7.
+
+# Implementation notes
+
+The Hamming distance is only defined for sequences of equal length. This means
+that based on the definition, each language could deal with getting sequences
+of equal length differently.
+
+To run the tests simply run the command `go test` in the exercise directory.
+
+If the test suite contains benchmarks, you can run these with the `-bench`
+flag:
+
+ go test -bench .
+
+For more detailed info about the Go track see the [help
+page](http://exercism.io/languages/go).
+
+## Source
+
+The Calculating Point Mutations problem at Rosalind [http://rosalind.info/problems/hamm/](http://rosalind.info/problems/hamm/)
+
+## Submitting Incomplete Problems
+It's possible to submit an incomplete solution so you can see how others have completed the exercise.
+
diff --git a/go/hamming/cases_test.go b/go/hamming/cases_test.go
new file mode 100644
index 0000000..fc808b5
--- /dev/null
+++ b/go/hamming/cases_test.go
@@ -0,0 +1,81 @@
+package hamming
+
+// Source: exercism/x-common
+// Commit: c84e435 Merge pull request #51 from soniakeys/master
+
+var testCases = []struct {
+ s1 string
+ s2 string
+ want int
+}{
+ { // identical strands
+ "A",
+ "A",
+ 0,
+ },
+ { // long identical strands
+ "GGACTGA",
+ "GGACTGA",
+ 0,
+ },
+ { // complete distance in single nucleotide strands
+ "A",
+ "G",
+ 1,
+ },
+ { // complete distance in small strands
+ "AG",
+ "CT",
+ 2,
+ },
+ { // small distance in small strands
+ "AT",
+ "CT",
+ 1,
+ },
+ { // small distance
+ "GGACG",
+ "GGTCG",
+ 1,
+ },
+ { // small distance in long strands
+ "ACCAGGG",
+ "ACTATGG",
+ 2,
+ },
+ { // non-unique character in first strand
+ "AGA",
+ "AGG",
+ 1,
+ },
+ { // non-unique character in second strand
+ "AGG",
+ "AGA",
+ 1,
+ },
+ { // large distance
+ "GATACA",
+ "GCATAA",
+ 4,
+ },
+ { // large distance in off-by-one strand
+ "GGACGGATTCTG",
+ "AGGACGGATTCT",
+ 9,
+ },
+ { // empty strands
+ "",
+ "",
+ 0,
+ },
+ { // disallow first strand longer
+ "AATG",
+ "AAA",
+ -1,
+ },
+ { // disallow second strand longer
+ "ATA",
+ "AGTG",
+ -1,
+ },
+}
diff --git a/go/hamming/hamming.go b/go/hamming/hamming.go
new file mode 100644
index 0000000..88dca1e
--- /dev/null
+++ b/go/hamming/hamming.go
@@ -0,0 +1,18 @@
+package hamming
+
+import "errors"
+
+const testVersion = 4
+
+func Distance(a, b string) (int, error) {
+ if len(a) != len(b) {
+ return 0, errors.New("same length required")
+ }
+ var n int
+ for i := 0; i < len(a); i++ {
+ if a[i] != b[i] {
+ n++
+ }
+ }
+ return n, nil
+}
diff --git a/go/hamming/hamming_test.go b/go/hamming/hamming_test.go
new file mode 100644
index 0000000..bfee705
--- /dev/null
+++ b/go/hamming/hamming_test.go
@@ -0,0 +1,36 @@
+package hamming
+
+import "testing"
+
+const targetTestVersion = 4
+
+func TestHamming(t *testing.T) {
+ if testVersion != targetTestVersion {
+ t.Errorf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
+ }
+ for _, tc := range testCases {
+ switch got, err := Distance(tc.s1, tc.s2); {
+ case err != nil:
+ var _ error = err
+ if tc.want >= 0 {
+ t.Fatalf("Distance(%q, %q) returned error: %v",
+ tc.s1, tc.s2, err)
+ }
+ case tc.want < 0:
+ t.Fatalf("Distance(%q, %q) = %d. Expected error.",
+ tc.s1, tc.s2, got)
+ case got != tc.want:
+ t.Fatalf("Distance(%q, %q) = %d, want %d.",
+ tc.s1, tc.s2, got, tc.want)
+ }
+ }
+}
+
+func BenchmarkHamming(b *testing.B) {
+ // bench combined time to run through all test cases
+ for i := 0; i < b.N; i++ {
+ for _, tc := range testCases {
+ Distance(tc.s1, tc.s2)
+ }
+ }
+}