ruby - hamming
This commit is contained in:
parent
1b675cccc5
commit
0e9c386087
66
ruby/hamming/README.md
Normal file
66
ruby/hamming/README.md
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# Hamming
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
* * * *
|
||||||
|
|
||||||
|
For installation and learning resources, refer to the
|
||||||
|
[exercism help page](http://exercism.io/languages/ruby).
|
||||||
|
|
||||||
|
For running the tests provided, you will need the Minitest gem. Open a
|
||||||
|
terminal window and run the following command to install minitest:
|
||||||
|
|
||||||
|
gem install minitest
|
||||||
|
|
||||||
|
If you would like color output, you can `require 'minitest/pride'` in
|
||||||
|
the test file, or note the alternative instruction, below, for running
|
||||||
|
the test file.
|
||||||
|
|
||||||
|
Run the tests from the exercise directory using the following command:
|
||||||
|
|
||||||
|
ruby hamming_test.rb
|
||||||
|
|
||||||
|
To include color from the command line:
|
||||||
|
|
||||||
|
ruby -r minitest/pride hamming_test.rb
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
The Calculating Point Mutations problem at Rosalind [http://rosalind.info/problems/hamm/](http://rosalind.info/problems/hamm/)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
56
ruby/hamming/RUNNING_TESTS.md
Normal file
56
ruby/hamming/RUNNING_TESTS.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# Running Tests
|
||||||
|
|
||||||
|
In order to complete this exercise, and all of the subsequent exercises, you
|
||||||
|
will need to pass multiple tests.
|
||||||
|
|
||||||
|
## Understanding Test Results
|
||||||
|
|
||||||
|
After you have created and saved `hamming.rb`, run the test suite. You should
|
||||||
|
see output like the following:
|
||||||
|
|
||||||
|
# Running:
|
||||||
|
|
||||||
|
SSSSSSESSSSSSSSS
|
||||||
|
|
||||||
|
Finished in 0.002593s, 6170.4588 runs/s, 0.0000 assertions/s.
|
||||||
|
|
||||||
|
1) Error:
|
||||||
|
HammingTest#test_identical_strands:
|
||||||
|
NameError: uninitialized constant HammingTest::Hamming
|
||||||
|
Did you mean? HammingTest
|
||||||
|
../hamming/hamming_test.rb:9:in `test_identical_strands'
|
||||||
|
|
||||||
|
16 runs, 0 assertions, 0 failures, 1 errors, 15 skips
|
||||||
|
|
||||||
|
You have skipped tests. Run with --verbose for details.
|
||||||
|
|
||||||
|
|
||||||
|
The letters `SSSSSSESSSSSSSSS` show that there are sixteen tests altogether,
|
||||||
|
that one of them has an error (`E`), and that the rest of them are skipped (all
|
||||||
|
the `S` letters).
|
||||||
|
|
||||||
|
The tests are run in randomized order, which will cause the letters to display
|
||||||
|
in random order as well.
|
||||||
|
|
||||||
|
The goal is to have all passing tests, which will show in two places:
|
||||||
|
|
||||||
|
1. `SSSSSSESSSSSSSSS` will become a series dots: `................`,
|
||||||
|
|
||||||
|
2. The line at the bottom will read `16 runs, 16 assertions, 0 failures, 0
|
||||||
|
errors, 0 skips`.
|
||||||
|
|
||||||
|
## Passing Tests
|
||||||
|
|
||||||
|
Write enough code to change the Error to Failure, and finally to Passing.
|
||||||
|
|
||||||
|
Open `hamming_test.rb`, and find the word "skip". All but the first test start
|
||||||
|
with "skip", which tells Minitest to ignore the test. This is so that you don't
|
||||||
|
have to deal with all the failures at once.
|
||||||
|
|
||||||
|
To activate the next test, delete the "skip", or comment it out, and run the
|
||||||
|
test suite again.
|
||||||
|
|
||||||
|
## Wash, Rinse, Repeat
|
||||||
|
|
||||||
|
Delete one "skip" at a time, and make each test pass before you move to the
|
||||||
|
next one.
|
15
ruby/hamming/hamming.rb
Normal file
15
ruby/hamming/hamming.rb
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
class Hamming
|
||||||
|
def self.compute(a, b)
|
||||||
|
if a.length != b.length
|
||||||
|
raise ArgumentError
|
||||||
|
end
|
||||||
|
|
||||||
|
distance = 0
|
||||||
|
0.upto(a.length - 1) do |i|
|
||||||
|
if a[i] != b[i]
|
||||||
|
distance += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
distance
|
||||||
|
end
|
||||||
|
end
|
84
ruby/hamming/hamming_test.rb
Normal file
84
ruby/hamming/hamming_test.rb
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
require 'minitest/autorun'
|
||||||
|
require_relative 'hamming'
|
||||||
|
|
||||||
|
# Common test data version: 2.1.0 b5d154b
|
||||||
|
class HammingTest < Minitest::Test
|
||||||
|
def test_empty_strands
|
||||||
|
# skip
|
||||||
|
assert_equal 0, Hamming.compute('', '')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_identical_strands
|
||||||
|
# skip
|
||||||
|
assert_equal 0, Hamming.compute('A', 'A')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_long_identical_strands
|
||||||
|
# skip
|
||||||
|
assert_equal 0, Hamming.compute('GGACTGA', 'GGACTGA')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_complete_distance_in_single_nucleotide_strands
|
||||||
|
# skip
|
||||||
|
assert_equal 1, Hamming.compute('A', 'G')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_complete_distance_in_small_strands
|
||||||
|
# skip
|
||||||
|
assert_equal 2, Hamming.compute('AG', 'CT')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_small_distance_in_small_strands
|
||||||
|
# skip
|
||||||
|
assert_equal 1, Hamming.compute('AT', 'CT')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_small_distance
|
||||||
|
# skip
|
||||||
|
assert_equal 1, Hamming.compute('GGACG', 'GGTCG')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_small_distance_in_long_strands
|
||||||
|
# skip
|
||||||
|
assert_equal 2, Hamming.compute('ACCAGGG', 'ACTATGG')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_non_unique_character_in_first_strand
|
||||||
|
# skip
|
||||||
|
assert_equal 1, Hamming.compute('AAG', 'AAA')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_non_unique_character_in_second_strand
|
||||||
|
# skip
|
||||||
|
assert_equal 1, Hamming.compute('AAA', 'AAG')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_same_nucleotides_in_different_positions
|
||||||
|
# skip
|
||||||
|
assert_equal 2, Hamming.compute('TAG', 'GAT')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_large_distance
|
||||||
|
# skip
|
||||||
|
assert_equal 4, Hamming.compute('GATACA', 'GCATAA')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_large_distance_in_off_by_one_strand
|
||||||
|
# skip
|
||||||
|
assert_equal 9, Hamming.compute('GGACGGATTCTG', 'AGGACGGATTCT')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_disallow_first_strand_longer
|
||||||
|
# skip
|
||||||
|
assert_raises(ArgumentError) do
|
||||||
|
Hamming.compute('AATG', 'AAA')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_disallow_second_strand_longer
|
||||||
|
# skip
|
||||||
|
assert_raises(ArgumentError) do
|
||||||
|
Hamming.compute('ATA', 'AGTG')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user