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