codingBat plusOut с использованием регулярных выражений

Это похоже на мои предыдущие усилия (wordEnds а также repeatEnd): как умственное упражнение, я хочу решить эту игрушечную проблему, используя только регулярные выражения.

Описание от codingbat.com:

Если задана строка и непустая строка слова, вернуть версию исходной строки, в которой все символы заменены на плюсы ("+"), за исключением появлений слова string, которые сохраняются без изменений.

plusOut("12xy34", "xy") → "++xy++"
plusOut("12xy34", "1") → "1+++++"
plusOut("12xy34xyabcxy", "xy") → "++xy++xy+++xy"

Нет упоминания о том, разрешать или нет перекрытие (например, что plusOut("+xAxAx+", "xAx")?), но мое решение без регулярных выражений не обрабатывает перекрытия, и оно проходит, поэтому я предполагаю, что мы можем предположить неперекрывающиеся вхождения word если это упрощает (бонусные баллы, если вы предлагаете решения для обоих вариантов!).

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

Итак, давайте посмотрим, что придумает сообщество stackru.

4 ответа

Решение

Это проходит все их тесты:

public String plusOut(String str, String word) {
  return str.replaceAll(
    String.format("(?<!(?=\\Q%s\\E).{0,%d}).", word, word.length()-1),
    "+"
  );  
}

Также я получаю:

plusOut("1xAxAx2", "xAx") → "+xAxAx+"

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

Это предоставлено здесь только для справки. Это по сути решение Алана, но с использованием replace вместо String.format,

public String plusOut(String str, String word) {
  return str.replaceAll(
    "(?<!(?=word).{0,M})."
      .replace("word", java.util.regex.Pattern.quote(word))
      .replace("M", String.valueOf(word.length()-1)),
    "+"
  );  
}

Очень простое решение, использующее \G:

word = java.util.regex.Pattern.quote(word);
return str.replaceAll("\\G((?:" + word + ")*+).", "$1+");

Однако есть одна оговорка. призвание plusOut("12xxxxx34", "xxx") с реализацией выше вернется ++xxx++++,

Во всяком случае, проблема не ясна в отношении поведения в таком случае для начала. Для такой ситуации даже нет тестовых случаев (так как моя программа прошла все тестовые случаи).

Регулярное выражение в основном совпадает с циклическим решением (которое также проходит все тестовые случаи):

StringBuilder out = new StringBuilder(str);

for (int i = 0; i < out.length(); ) {
    if (!str.startsWith(word, i))
        out.setCharAt(i++, '+');
    else
        i += word.length();
}

return out.toString();

Неоднократно пропускает word, затем заменить текущий символ, если он не является префиксом word,

Я думаю, что вы могли бы использовать отрицательный диапазон, чтобы сделать это. Так как это всего лишь подсказка, она еще не проверена!

Включи свой "xy" в регулярное выражение, как это: "[^xy]"

... и затем оберните это в регулярное выражение, которое заменяет строки, соответствующие этому выражению, на "+".

Другие вопросы по тегам