# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+# Error class for all exceptions to do with String.
+class StringError < StandardError; end
+
# Monkey patching Class String to add bitwise operators.
# Behaviour matching Perl's:
# http://perldoc.perl.org/perlop.html#Bitwise-String-Operators
class String
+ # Method to that returns the case senstive Hamming Distance between two strings.
+ # http://en.wikipedia.org/wiki/Hamming_distance
+ def self.hamming_dist(str1, str2)
+ raise StringError, "Uneven string lengths: #{str1.length} != #{str2.length}" if str1.length != str2.length
+ (str1 ^ str2 ).count("\x01-\xff")
+ end
+
# Method that performs bitwise AND operation where bits
# are copied if they exists in BOTH operands. If the operand
# sizes are different, the & operator methods acts as though
require 'pp'
class TestBits < Test::Unit::TestCase
+ def test_Bits_hamming_dist_with_uneven_lengths_raises
+ assert_raises(StringError) { String.hamming_dist("ATCG", "ATC") }
+ end
+
+ def test_Bits_hamming_dist_with_even_lengths_dont_raise
+ assert_nothing_raised { String.hamming_dist("ATCG", "ATCG") }
+ end
+
+ def test_Bits_hamming_dist_returns_correctly
+ assert_equal(0, String.hamming_dist("ATCG", "ATCG"))
+ assert_equal(1, String.hamming_dist("ATCX", "ATCG"))
+ assert_equal(2, String.hamming_dist("ATXX", "ATCG"))
+ assert_equal(2, String.hamming_dist("ATcg", "ATCG"))
+ assert_equal(3, String.hamming_dist("AXXX", "ATCG"))
+ assert_equal(4, String.hamming_dist("XXXX", "ATCG"))
+ end
+
def test_Bits_AND_with_equal_length_returns_correctly
assert_equal("ABCD", "abcd" & "____")
end