2015-01-29 2 views
2

Этот код my initial stab у проблемы с Хэмминг-Дистрибьюцией на Exercism.io, но это не так, когда строка a длиннее строки b, и я пытаюсь понять, почему.Почему отказ не отклоняется?

def self.compute(a, b) 
    a.split('').reject.with_index { |c, i| c == b[i] }.size 
end 

Я получил вокруг проблемы путем обрезки первую строку ...

def self.compute(a, b) 
    a[0...b.size].split('').reject.with_index { |c, i| c == b[i] }.size 
end 

... но я не понимаю, почему reject является в том числе и дополнительных символов. Когда я проверяю сравнения, они кажутся ложными, как и следовало ожидать, но все же включены в результат.

Может ли кто-нибудь сказать мне, почему?

+1

Это потому что, когда вы отклоняете, включается 'false' _means_. – matt

+0

'split ('')' такой же, как 'split'. Сделайте вашу жизнь проще и сохраните четырех персонажей. –

+1

Вот что я тоже подумал, «Оловянный человек», но, похоже, это не так. 'split', без аргументов, по умолчанию, по умолчанию разделяется на пробелы. http://www.ruby-doc.org/core-2.2.0/String.html#method-i-split –

ответ

5

Я не понимаю, почему отказ включает лишние символы. Когда я проверяю сравнения, они кажутся ложными

Исправить. И когда вы отказываетесь, false означает «принять» - противоположность отклонения.

Проблема заключается только в том, что вы не понимаете, что означает «отказ». Когда вы столкнулись с подобным вопросом, debug. В этом случае способ сделать это - устранить лишний материал и сосредоточиться на том, что вас сбивает с толку. Удалите size вызов и просто посмотреть на результаты reject вызова:

def compute(a, b) 
    a.split('').reject.with_index { |c, i| c == b[i] } 
end 
result = compute("hey", "ha") 
puts result 

Выход "e" и "y". И это имеет смысл:

  • На первом проходе, "h""h" == и отвергается.

  • На втором проходе "e"! = "a" и принимается.

  • На третьем проходе "y" не имеет к нему никакого отношения, поэтому он не может быть успешным; таким образом, мы отказываемся отклонить - и поэтому принимается "y". Это то, о чем вы просите.

1

Вот другой подход, который включает в себя много сортировки и, вероятно, неоптимальные, но может служить основой для более эффективного решения:

def ham(a,b) 
    [ a.length, b.length ].sort[1].times.reject do |i| 
    a[i] != b[i] 
    end.sort[-1] 
end 

pairs = [ 
    ['A', 'A'], 
    ['A','G'], 
    ['AG','CT'], 
    ['AT','CT'], 
    ['GGACG', 'GGTCG'], 
    ['AGAGACTTA', 'AAA'], 
    ['AGG', 'AAAACTGACCCACCCCAGG'], 
    ['GATACA', 'GCATAA'], 
    ['GGACGGATTCTG', 'AGGACGGATTCT'] 
] 

pairs.each do |pair| 
    puts '%s -> %s' % [ pair.inspect, ham(*pair).inspect ] 
end 

# ["A", "A"] -> 0 
# ["A", "G"] -> nil 
# ["AG", "CT"] -> nil 
# ["AT", "CT"] -> 1 
# ["GGACG", "GGTCG"] -> 4 
# ["AGAGACTTA", "AAA"] -> 2 
# ["AGG", "AAAACTGACCCACCCCAGG"] -> 0 
# ["GATACA", "GCATAA"] -> 5 
# ["GGACGGATTCTG", "AGGACGGATTCT"] -> 8 

Это выглядит как в вашей версии вы не сравниваете самая длинная строка до самой короткой, если есть разница в длине. Сортировка по длине устраняет эту проблему.

Смежные вопросы