рекурсивно добавлять символы в конец строки - PullRequest
1 голос
/ 20 марта 2020

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

Если слово начинается с гласной, вы просто добавляете «путь» в конец.

Если слово или группа слов это не содержит гласную, просто добавьте «ay» в конец.

Например: translatePigLatin («california») должен вернуть «aliforniacay».

translatePigLatin («glove») должен вернуть «oveglay» ".

translatePigLatin (" алгоритм ") должен возвращать" путь алгоритма ".

function translatePigLatin(str) {
  var changed = true;

  if (!["a", "e", "i", "o", "u"].includes(str[0])) {

    return translatePigLatin(str.substring(1, str.length) + str[0])

  }
  else {
    return str + "ay"
  }
}

console.log(translatePigLatin("glove"));

Ответы [ 5 ]

1 голос
/ 20 марта 2020

Почему бы просто не использовать флаг, похожий на этот, чтобы отличить первый вызов от другого рекурсивного вызова

function translatePigLatin(str, isStart = false) {
  var changed = true;
  
  // to handle case when there's any vowels at start
  if(/^[aeiou]/i.test(str) && isStart){
    return str + 'way'
  }
  
  // to handle case when there's no vowels in string
  if(!/[aeiou]/i.test(str) && isStart){
    return str + 'ay'
  }
 
  if (!["a", "e", "i", "o", "u"].includes(str[0]) ) {
    return translatePigLatin(str.substring(1, str.length) + str[0])
  }
  else {
    return str + "ay"
  }
}

console.log(translatePigLatin("glove", true));
console.log(translatePigLatin("california", true));
console.log(translatePigLatin("algorithm", true));
console.log(translatePigLatin("gypsy", true));
1 голос
/ 20 марта 2020

Обновление

Хорошо, рекурсивная версия не так уж и плоха. И на самом деле, он может быть почти таким же чистым, как оригинальное нерекурсивное решение ниже.

const toPigLatin = (str, prefix) =>
  (!str) || 'aeiou' .includes (str [0]) 
    ? str + prefix + (prefix.length ? '' : 'w') + 'ay'
    : toPigLatin (str.slice(1), prefix + str[0])

const translatePigLatin = (str) => toPigLatin (str, '')
                            

console .log (['california', 'glove', 'algorithm', 'gypsy'] .map (translatePigLatin))

Хотя это также можно записать без вспомогательной функции, используя параметр по умолчанию, например:

const translatePigLatin = (str, prefix = '') =>
  (!str) || 'aeiou' .includes (str [0]) 
    ? str + prefix + (prefix.length ? '' : 'w') + 'ay'
    : translatePigLatin (str.slice(1), prefix + str[0])

, это может иметь некоторые странные эффекты, если кто-то передал дополнительные параметры, как при вызове map.

console .log (['california', 'glove', 'algorithm', 'gypsy'] .map (translatePigLatin))
//=> ["alifornia0cay","ove1glay","algorithm2way","3gypsyay"]

Обойти это можно, заключив параметр в лямбду в map, например:

console .log (['california', 'glove', 'algorithm', 'gypsy'] .map (s => translatePigLatin(s)))
//=> ["aliforniacay","oveglay","algorithmway","gypsyay"]

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

Обновление до обновления

Эта альтернатива может быть немного чище:

const toPigLatin = (base, prefix, suffix) =>
  base .length == 0 || 'aeiou' .includes (base [0])
    ? base + prefix + suffix
    : toPigLatin (base .slice (1), prefix + base [0], 'ay')

const translatePigLatin = (str) => toPigLatin (str, '', 'way')

Оригинальный ответ

(Это быстро устарело!)

Этот нерекурсивный ответ кажется более простым и прямым, чем любой рекурсивный ответ:

const translatePigLatin = str => {
  const idx = str .split ('') .findIndex (c => 'aeiou' .includes (c))
  return idx == 0
    ? str + 'way'
  : idx < 0
    ? str + 'ay'
  : // else 
    str .slice (idx) + str .slice (0, idx) + 'ay'
}

console .log (['california', 'glove', 'algorithm', 'gypsy'] .map (translatePigLatin))

(нам также может понадобиться .toLowerCase() там.)

Вы ищете рекурсивное решение, потому что думаете, что оно будет проще или потому что это кажется центральной проблемой?

1 голос
/ 20 марта 2020

Попробуйте это:

function translatePigLatin(str) {
  const vowels = ['a', 'e', 'i', 'o', 'u'];
  const chars = str.split('');
  const firstVowel = chars.findIndex(c => vowels.includes(c));
  // words beginning with a vowel are treated differently
  if (firstVowel === 0) {
    return str + 'way';
  } else {
    const start = str.substring(0, firstVowel);
    return str.substring(firstVowel) + start + 'ay';
  } 
}

console.log('glove:', translatePigLatin('glove'));
console.log('california:', translatePigLatin('california'));
console.log('algorithm:', translatePigLatin('algorithm'));
0 голосов
/ 25 марта 2020

Вы можете подойти к задаче с помощью скользящего курсора; все слева от этого курсора еще не обработано, а справа все согласные. Есть два состояния терминала:

  1. Левая сторона начинается с гласной
  2. Левая сторона пуста (слово состоит только из согласных)

В противном случае , согласный перемещается слева направо, и танец начинается заново.

Реализация

Внутренняя (именованная) функция является рекурсивной, в то время как внешняя функция просто настраивает начальное состояние для первого вызова.

function translatePigLatin(s) {
  const vowels = 'aeiou'.split('')

  return function _translate(head, tail) {
    if (head == '' || vowels.includes(head[0])) {
      // head is empty for words without vowels
      // tail is empty on the first pass
      return head + tail + (tail ? 'ay' : 'way');
    }
    // move consonant to the tail
    return _translate(head.slice(1), tail + head[0]);
  }(s, '');
}

const words = [
  'california',
  'glove',
  'algorithm',
  'gypsy'
]
words.forEach(word => console.log(translatePigLatin(word)))
0 голосов
/ 23 марта 2020

Вот чистая рекурсия (имеется в виду, что функция использует только один параметр), но с уловкой, что возвращаемое значение является кортежем трех упорядоченных секций результата: префикс, возможно начальные согласные, которые перемещаются в суффикс и окончательный суффикс.

function f(s){
  if (s.length == 1){
    if (["a", "e", "i", "o", "u"].includes(s[0]))
      return [s[0], "", "way"];
    else
      return ["", s[0], "ay"];
  }
      
  const n = s.length;
  const [pfx, sfx1, sfx2] = f(s.slice(0, n-1));
  const last = s[n-1];
  
  if (pfx)
    return [pfx + last, sfx1, sfx2];
  else if (["a", "e", "i", "o", "u"].includes(last))
    return [pfx + last, sfx1, sfx2];
  else
    return [pfx, sfx1 + last, sfx2];
}

var strs = [
  "california",
  "glove",
  "algorithm",
  "gypsy"
];

for (let s of strs)
  console.log(s + ": " + JSON.stringify(f(s)));
...