Принудительный выход из рекурсии в случае, если ответ уже найден
От: Lazytech Ниоткуда  
Дата: 20.11.20 14:21
Оценка:
Опять я со своими нескончаемыми дилетантскими вопросами...

Простенькая задача: Merged String Checker | Codewars

  Мое решение на JavaScript
function isMerge(s, part1, part2) {
  if (s.length !== part1.length + part2.length) {
    return false;    
  }
  
  const last = s.length - 1;
  let mergeConfirmed = false;
  
  const tryMerge = (pos1=0, pos2=0) => {
    if (mergeConfirmed) {
      return;
    }
    
    const pos = pos1 + pos2;
    
    if (pos > last) {
      mergeConfirmed = true;
      return;
    }

    if (part1[pos1] === s[pos]) {
      tryMerge(pos1 + 1, pos2);
    }

    if (part2[pos2] === s[pos]) {
      tryMerge(pos1, pos2 + 1);
    }
  }  
  
  tryMerge();
  return mergeConfirmed;
}

Обратите внимание на проверку в самом начале рекурсивной функции tryMerge:
    if (mergeConfirmed) {
      return;
    }

Наверное, любой бывалый программист скажет, что подобные фрагменты в подавляющем большинстве случаев лишь засоряют код (поправьте, если это не так). Однако, как мне кажется, в некоторых (редких?) случаях они могут быть полезны.

  Немного модифицированное решение
function isMerge(s, part1, part2) {
  console.log("s =", s)
  console.log("part1 =", part1)
  console.log("part2 =", part2)
  
  if (s.length !== part1.length + part2.length) {
    return false;    
  }
  
  const last = s.length - 1;
  let mergeConfirmed = false;
  
  const tryMerge = (pos1=0, pos2=0) => {
    console.log("pos1, pos2, mergeConfirmed =", pos1, pos2, mergeConfirmed)
    
    if (mergeConfirmed) {
      // return;
      console.log("PREVENTIVE EXIT COULD BE HERE!")
    }
    
    const pos = pos1 + pos2;
    
    if (pos > last) {
      mergeConfirmed = true;
      return;
    }

    if (part1[pos1] === s[pos]) {
      tryMerge(pos1 + 1, pos2);
    }

    if (part2[pos2] === s[pos]) {
      tryMerge(pos1, pos2 + 1);
    }
  }  
  
  tryMerge();
  console.log("mergeConfirmed =", mergeConfirmed)
  
  return mergeConfirmed;
}

  Один из логов модифицированного решения
s = <!qTG<<!qoi3ndI
part1 = <!qoi
part2 = <!qTG<3ndI
pos1, pos2, mergeConfirmed = 0 0 false
pos1, pos2, mergeConfirmed = 1 0 false
pos1, pos2, mergeConfirmed = 2 0 false
pos1, pos2, mergeConfirmed = 3 0 false
pos1, pos2, mergeConfirmed = 0 1 false
pos1, pos2, mergeConfirmed = 0 2 false
pos1, pos2, mergeConfirmed = 0 3 false
pos1, pos2, mergeConfirmed = 0 4 false
pos1, pos2, mergeConfirmed = 0 5 false
pos1, pos2, mergeConfirmed = 1 5 false
pos1, pos2, mergeConfirmed = 1 6 false
pos1, pos2, mergeConfirmed = 2 6 false
pos1, pos2, mergeConfirmed = 3 6 false
pos1, pos2, mergeConfirmed = 4 6 false
pos1, pos2, mergeConfirmed = 5 6 false
pos1, pos2, mergeConfirmed = 5 7 false
pos1, pos2, mergeConfirmed = 5 8 false
pos1, pos2, mergeConfirmed = 5 9 false
pos1, pos2, mergeConfirmed = 5 10 false
pos1, pos2, mergeConfirmed = 0 6 true
PREVENTIVE EXIT COULD BE HERE!
pos1, pos2, mergeConfirmed = 1 6 true
PREVENTIVE EXIT COULD BE HERE!
pos1, pos2, mergeConfirmed = 2 6 true
PREVENTIVE EXIT COULD BE HERE!
pos1, pos2, mergeConfirmed = 3 6 true
PREVENTIVE EXIT COULD BE HERE!
pos1, pos2, mergeConfirmed = 4 6 true
PREVENTIVE EXIT COULD BE HERE!
pos1, pos2, mergeConfirmed = 5 6 true
PREVENTIVE EXIT COULD BE HERE!
pos1, pos2, mergeConfirmed = 5 7 true
PREVENTIVE EXIT COULD BE HERE!
pos1, pos2, mergeConfirmed = 5 8 true
PREVENTIVE EXIT COULD BE HERE!
pos1, pos2, mergeConfirmed = 5 9 true
PREVENTIVE EXIT COULD BE HERE!
pos1, pos2, mergeConfirmed = 5 10 true
PREVENTIVE EXIT COULD BE HERE!
mergeConfirmed = true

Что скажете, имеет ли такой подход с превентивным выходом из рекурсии право на существование? Оговорюсь, что вышеприведенный лог относится к единственному подвернувшемуся мне тестовому случаю, в котором этот подход мог быть мало-мальски полезен. Вполне возможно, что я чего-то недопонимаю...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.