Я работаю над упражнениями по exercism.io, а третий просит нас сравнить две строки ДНК и вернуть разницу (расстояние Хэмминга) между ними.

Так, например:

GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^  ^ ^    ^^

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

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

    var diff = [];
    var same = [];
    function ham(dna1, dna2) {
      for (var i = 0; i < dna1.length; i++)
      for (var j = 0; j < dna2.length; i++){
        if (dna1[i] !== dna2[j]) {
          console.log(dna1[i]);
          diff.push(dna1[i]);
        }
        else {
          console.log(dna1[i]);
          same.push(dna1[i]);
        }
      return diff.length;
    }

    ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
    console.log("The Hamming distance between both DNA types is " +                 diff.length + ".");
0
davedeecoder 7 Янв 2017 в 20:42

7 ответов

Лучший ответ

Не используйте глобалы.

Не используйте вложенные циклы, если вам не нужно.

Не храните ненужные вещи в массивах.

function ham(dna1, dna2) {
  if (dna1.length !== dna2.length) throw new Error("Strings have different length.");
  var diff = 0;
  for (var i = 0; i < dna1.length; ++i) {
    if (dna1[i] !== dna2[i]) {
      ++diff;
    }
  }
  return diff;
}
var diff = ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
console.log("The Hamming distance between both DNA types is " + diff + ".");
1
Oriol 7 Янв 2017 в 18:04

Вам нужен только один цикл, как показано ниже:

var diff = [];
var same = [];

function ham(dna1, dna2) {
  for (var i = 0; i < dna1.length; i++) {
    if (dna1[i] !== dna2[i]) {
      console.log("not same");
      diff.push(dna1[i]);
    } else {
      console.log("same");
      same.push(dna1[i]);
    }


  }


  return diff.length;
}

ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
console.log("The Hamming distance between both DNA types is " + diff.length + ".");
0
Sandeep Nayak 7 Янв 2017 в 17:57

Я думаю, что вы хотели бы сделать что-то вроде этого:

var dna1 = "GAGCCTACTAACGGGAT";
var dna2 = "CATCGTAATGACGGCCT";
function ham(string1, string2) {
var counter = 0;
for (i = 0;i < string1.length;i++) {
if (string1.slice(i, i + 1) != string2.slice(i, i + 1)) {
counter++
};
};
return(counter);
};
console.log("insert text here " + ham(dna1, dna2));

Он проверяет каждый символ строки на соответствие символу другой строки и добавляет 1 к счетчику всякий раз, когда 2 символа не равны.

0
milesman34 7 Янв 2017 в 19:47

Расстояние редактирования не очень сложно рассчитать. Больше кода необходимо, чтобы охватить крайние случаи в значениях параметров.

function hamming(str1, str2) {
    var i, len, distance = 0;

    // argument validity check
    if (typeof str1 === "undefined" || typeof str2 === "undefined") return;
    if (str1 === null || str2 === null) return;

    // all other argument types are assumed to be meant as strings
    str1 = str1.toString();
    str2 = str2.toString();

    // the longer string governs the maximum edit distance
    len = str1.length > str2.length ? str1.length : str2.length;

    // now we can compare
    for (i = 0; i < len; i++) {
        if ( !(str1[i] === str2[i]) ) distance++;
    }

    return distance;
}
0
Tomalak 7 Янв 2017 в 18:20

Первая проблема в том, что вы пропускаете закрывающий }. Я думаю, что вы хотите это прямо до оператора return.

Во-вторых, есть проблема с вашим алгоритмом. Вы сравниваете каждый элемент в dna1 (i) с каждым элементом в dna2 вместо того, чтобы копировать элемент в той же позиции.

Чтобы использовать более короткий пример, чтобы мы могли пройти его, рассмотрите сравнение «CAT» и «CBT». Вы хотите сравнить символы в одинаковом положении в каждой строке. Таким образом, вы на самом деле не хотите 2 for циклов, вы хотите только 1. Вы сравнили бы C с C ([0]), A с B ([1]) и T с T ([2]), чтобы найти 1 различие в [1]. Теперь проделайте это с вашими 2 for циклами в своей голове, и вы увидите, что вы получите гораздо больше отличий, чем существует.

Как только вы используете одинаковое смещение для символов в каждой строке для сравнения, вам нужно беспокоиться о том, что один может быть короче другого. Вы получите ошибку, если попытаетесь использовать смещение в конце строки. Поэтому мы должны принять это во внимание и предположительно посчитать разницу между длиной строки как разницу. Но, возможно, это выходит за рамки вашей компетенции, и строки всегда будут одинаковыми.

0
Daniel Farrell 7 Янв 2017 в 17:55

Вы можете использовать Array#reduce итерировать первую строку, используя {{ X1}} и сравните каждую букву с буквой соответствующего индекса во 2-й строке.

function ham(dna1, dna2) {
  return [].reduce.call(dna1, function(count, l, i) {
    return l !== dna2[i] ? count + 1 : count;
  }, 0);
}

var diff =ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");
console.log("The Hamming distance between both DNA types is " + diff + ".");
0
Ori Drori 7 Янв 2017 в 20:31

Выполнение функции:

ham( "GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT" );

Следующего определения функции:

function ham(A,B){
   var D = [], i = 0;
   i = A.length > B.length ? A : B; 

   for( var x in i)
      A[x] == B[x] ? D.push(" ") : D.push("^");

   console.log( A + "\n" + B +"\n" + D.join("") );
}

Выведет журнал:

GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^  ^ ^    ^^ 

Может принимать строки различной длины, которые в зависимости от требований и сравнения представления данных могут быть изменены, чтобы заполнить пробел соответствующими стандартными символами и т. Д.

Демо-версия :

ham("GAGCCTACTAACGGGAT", "CATCGTAATGACGGCCT");

function ham(A, B) {
  var D = [],
    i = 0;
  i = A.length > B.length ? A : B;

  for (var x in i)
    A[x] == B[x] ? D.push(" ") : D.push("^");

  console.log(A + "\n" + B + "\n" + D.join(""));
};
0
Bekim Bacaj 7 Янв 2017 в 18:58