codingbat wordEnds usando regex

Estou tentando resolverwordEnds de codingbat.com usando regex.

Dada uma sequência de caracteres e uma sequência de palavras não vazia, retorne uma sequência feita de cada caractere imediatamente antes e logo após cada aparição da palavra na sequência. Ignore os casos em que não há caractere antes ou depois da palavra e um caractere pode ser incluído duas vezes se estiver entre duas palavras.

wordEnds("abcXY123XYijk", "XY") → "c13i"
wordEnds("XY123XY", "XY") → "13"
wordEnds("XY1XY", "XY") → "11"
wordEnds("XYXY", "XY") → "XY"

É o mais simples que posso fazer com meu conhecimento atual de regex:

public String wordEnds(String str, String word) {
  return str.replaceAll(
     ".*?(?=word)(?<=(.|^))word(?=(.|$))|.+"
       .replace("word", java.util.regex.Pattern.quote(word)),
     " de codingbat.com2"
  );
}

replace é usado para colocar no realword string no padrão para facilitar a leitura.Pattern.quote não é necessário passar nos testes, mas acho que é necessário para uma solução adequada baseada em regex.

O regex tem duas partes principais:

Se depois de corresponder o mínimo de caracteres possível ".*?",word ainda pode ser encontrado "(?=word)", em seguida, olhe para trás para capturar qualquer caractere imediatamente anterior a ele"(?<=(.|^))", Combine "word"e antecipadamente para capturar qualquer caractere a seguir"(?=(.|$))"O teste inicial "if" garante que a aparência atômica captura apenas se houver umwordO uso de lookahead para capturar o seguinte caractere não o consome, portanto pode ser usado como parte de outras correspondênciasCaso contrário, corresponda ao que resta "|.+"Os grupos 1 e 2 capturariam cadeias vazias

Eu acho que isso funciona em todos os casos, mas é obviamente bastante complexo. Só estou me perguntando se outros podem sugerir um regex mais simples para fazer isso.

Nota: não estou procurando uma solução usandoindexOf e um loop. Eu quero um baseado em regexreplaceAll solução. Também preciso de um regex de trabalho que passe em todos os testes de codingbat.

Eu consegui reduzir a ocorrência deword dentro do padrão para apenas um.

".+?(?<=(^|.)word)(?=(.?))|.+"

Ainda estou procurando se é possível simplificar ainda mais isso, mas também tenho outra pergunta:

Com esse último padrão, simplifiquei.|$ para somente.? com sucesso, mas se eu também tentasse simplificar^|. para.? isso não funciona. Por que é que?

questionAnswers(3)

yourAnswerToTheQuestion