justinleveck
7/31/2013 - 8:31 PM

each_with_object.rb

require 'minitest/autorun'
require_relative 'dna'

class DNATest < MiniTest::Unit::TestCase

  def test_no_difference_between_empty_strands
    assert_equal 0, DNA.new('').hamming_distance('')
  end

  def test_no_difference_between_identical_strands
    assert_equal 0, DNA.new('GGACTGA').hamming_distance('GGACTGA')
  end

  def test_complete_hamming_distance_in_small_strand
    assert_equal 3, DNA.new('ACT').hamming_distance('GGA')
  end

  def test_hamming_distance_in_off_by_one_strand
    assert_equal 19, DNA.new('GGACGGATTCTGACCTGGACTAATTTTGGGG').hamming_distance('AGGACGGATTCTGACCTGGACTAATTTTGGGG')
  end

  def test_small_hamming_distance_in_middle_somewhere
    assert_equal 1, DNA.new('GGACG').hamming_distance('GGTCG')
  end

  def test_larger_distance
    assert_equal 2, DNA.new('ACCAGGG').hamming_distance('ACTATGG')
  end

  def test_ignores_extra_length_on_other_strand_when_longer
    assert_equal 3, DNA.new('AAACTAGGGG').hamming_distance('AGGCTAGCGGTAGGAC')
  end

  def test_ignores_extra_length_on_original_strand_when_longer
    assert_equal 5, DNA.new('GACTACGGACAGGGTAGGGAAT').hamming_distance('GACATCGCACACC')
  end

  def test_does_not_actually_shorten_original_strand
    assert_equal 1, DNA.new('AGACAACAGCCAGCCGCCGGATT').hamming_distance('AGGCAA')
    assert_equal 4, DNA.new('AGACAACAGCCAGCCGCCGGATT').hamming_distance('AGACATCTTTCAGCCGCCGGATTAGGCAA')
    assert_equal 1, DNA.new('AGACAACAGCCAGCCGCCGGATT').hamming_distance('AGG')
  end

end
class DNA
  attr_reader :strand

  def initialize(strand)
    @strand = strand
  end

  def hamming_distance(homologous_strand)
    nucleic_acid_indexes(homologous_strand).inject(0) do |differences_count, nucleic_acid_index|
      if nucleic_acids_differ?(nucleic_acid_index, homologous_strand)
        differences_count += 1
      end
      differences_count
    end
  end

  private

  def nucleic_acids_differ?(nucleic_acid_index, homologous_strand)
    strand[nucleic_acid_index].to_s != homologous_strand[nucleic_acid_index].to_s
  end

  def nucleic_acid_indexes(homologous_strand)
    0.upto([strand.length, homologous_strand.length].min - 1)
  end
end
class DNA
  attr_reader :strand

  def initialize(strand)
    @strand = strand
  end

  def hamming_distance(homologous_strand)
    nucleic_acid_indexes(homologous_strand).each_with_object(0) do |nucleic_acid_index, differences_count|
      if nucleic_acids_differ?(nucleic_acid_index, homologous_strand)
        differences_count += 1
      end
    end
  end

  private

  def nucleic_acids_differ?(nucleic_acid_index, homologous_strand)
    strand[nucleic_acid_index].to_s != homologous_strand[nucleic_acid_index].to_s
  end

  def nucleic_acid_indexes(homologous_strand)
    0.upto([strand.length, homologous_strand.length].min - 1)
  end
end