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

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

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

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

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

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

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

Итак, посмотрим, что возникает в сообществе stackoverflow.

Ответ 1

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

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

Ответ 2

Это описано здесь только для справки. Это по существу решение Алана, но с использованием 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)),
    "+"
  );  
}

Ответ 3

Чрезвычайно простое решение, используя \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.

Ответ 4

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

Поверните "xy" в регулярное выражение следующим образом: "[^xy]"

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