Remover palavras duplicadas de uma frase

10

Neste desafio, você removerá palavras duplicadas de cada frase .

Exemplos

Hello Hello, World!
Hello, World!

Code Code! Golf Code
Code! Golf Code

Hello  hello   World
Hello   World

Programming Golf Programming!
Programming Golf!

Especificação

  • A entrada será uma sequência de caracteres ASCII.
  • Uma sentença é definida como qualquer coisa até o final da string, avanço de linha ( \n) ou pontuação ( .!?).
  • Uma palavra é definida como uma sequência de A-Za-z.
  • As palavras não diferenciam maiúsculas de minúsculas ( Hello== heLlO).
  • Somente a primeira ocorrência de uma palavra em uma frase é mantida.
  • Se uma palavra for removida, os espaços antes da palavra removida deverão ser removidos. (por exemplo A A B-> A B).

Este é o pelo que o código mais curto em bytes vence!

Downgoat
fonte
11
a b a.vai para o que?
precisa saber é o seguinte
@ThomasKwa a b.porque o `a` foi removido.
Downgoat
Para a__b_b_a, você recebe a_b_a(primeiro bremovido) ou a__b_a(segundo bremovido)?
@CamilStaps você iria ficar a__b__porque o repetido bé removido e as repetidas aé removido
Downgoat
11
@ BradGilbertb2gills Todos os caracteres ASCII são permitidos na entrada. Apenas letras são consideradas palavras
Downgoat

Respostas:

3

Vim, 27 bytes

:s/\v\c(<\a+>).{-}\zs\s+\1

Observe que os 27 bytes incluem um retorno de carro à direita no final.

Experimente online! Nota lateral: este é um link para um idioma diferente que estou escrevendo chamado "V". O V é principalmente compatível com o vim, portanto, para todos os efeitos, pode contar como um intérprete do vim. Também adicionei um byte %para que você possa verificar todos os casos de teste de uma só vez.

Explicação:

:s/\v                       "Substitute with the 'Magic flag' on. This magic flag allows us
                            "to shorten the regex by removing a lot of \ characters.
     \c(<\a+>)              "A case-insensitive word
              .{-}          "Any character (non-greedy)
                  \zs       "Start the selection. This means everything after this atom
                            "will be removed
                     \s+    "One or more whitespace characters,
                        \1  "Followed by the first word
James
fonte
6

JavaScript (ES6), 98

Note que enquanto eu o encontrei, é irritantemente semelhante ao do @ Neil, apenas com a lógica adicional para dividir toda a cadeia de entrada em frases.

s=>s.replace(/[^\n.!?]+/g,s=>s.replace(/ *([a-z]+)/ig,(r,w)=>k[w=w.toUpperCase()]?'':k[w]=r,k=[]))

Teste

f=s=>s.replace(/[^\n.!?]+/g,s=>s.replace(/ *([a-z]+)/ig,(r,w)=>k[w=w.toUpperCase()]?'':k[w]=r,k=[]))

console.log=x=>O.textContent+=x+'\n'

;[['Hello Hello, World!','Hello, World!']
,['Code Code! Golf Code','Code! Golf Code']
,['Hello  hello   World','Hello   World']
,['Programming Golf Programming!','Programming Golf!']]
.forEach(t=>{
  var i=t[0],k=t[1],r=f(i)
  console.log((r==k?'OK ':'KO ')+i+' -> '+r)
})  
<pre id=O></pre>

edc65
fonte
6

Retina , 66 46 bytes

A contagem de bytes assume a codificação ISO 8859-1.

i`[a-z]+
·$0·
i` *(·[a-z]+·)(?<=\1[^.!?¶]+)|·

Experimente online!

Explicação

Como apenas letras devem ser consideradas caracteres de palavras (mas o regex trata dígitos e sublinhados como caracteres de palavras também), precisamos criar nossos próprios limites de palavras. Como a entrada é garantida para conter apenas caracteres ASCII, estou inserindo ·(fora do ASCII, mas dentro da ISO 8859-1) todas as palavras e removendo-as novamente com as duplicatas. Isso economiza 20 bytes com o uso de lookarounds para implementar limites genéricos de palavras.

i`[a-z]+
·$0·

Isso corresponde a cada palavra e a envolve ·.

i` *(·[a-z]+·)(?<=\1[^.!?¶]+)|·

Este é dois passos compactados em um. <sp>*(·[a-z]+·)(?<=\1[^.!?¶]+)corresponde a uma palavra completa (garantida pela inclusão de ·na correspondência), juntamente com todos os espaços anteriores, desde que (conforme garantido pelo lookbehind), possamos encontrar a mesma palavra em algum lugar anteriormente na frase. ( Corresponde a um avanço de linha.)

A outra parte é simplesmente a ·, que corresponde a todos os limites de palavras artificiais que não foram correspondidos como parte da primeira metade. Em ambos os casos, a correspondência é simplesmente removida da sequência.

Martin Ender
fonte
4

C, 326 bytes

Quem precisa de expressões regulares?

#include <ctype.h>
#define a isalpha
#define c(x)*x&&!strchr(".?!\n",*x)
#define f(x)for(n=e;*x&&!a(*x);++x);
main(p,v,n,e,o,t)char**v,*p,*n,*e,*o,*t;{for(p=v[1];*p;p=e){f(p)for(e=p;c(e);){for(;a(*++e););f(n)if(c(n)){for(o=p,t=n;a(*o)&&(*o-65)%32==(*t-65)%32;o++,t++);if(a(*t))e=n;else memmove(e,t,strlen(t)+1);}}}puts(v[1]);}
Cole Cameron
fonte
3

Perl 6 , 104 bytes

{[~] .split(/<[.!?\n]>+/,:v).map(->$_,$s?{.comb(/.*?<:L>+/).unique(as=>{/<:L>+/;lc $/}).join~($s//'')})} # 104

Uso:

# give it a lexical name
my &code = {...}

say code "Hello Hello, World!
Code Code! Golf Code
Hello  hello   World
Programming Golf Programming!";
Hello, World!
Code! Golf Code
Hello   World
Programming Golf!

Explicação

{
  [~]                         # join everything that follows:

  .split(/<[.!?\n]>+/,:v)     # split on boundaries, keeping them
  .map(                       # loop over sentence and boundary together
    -> $_, $s? {              # boundary is optional (at the end of the string)
      .comb(/.*?<:L>+/)       # grab the words along with leading non letters
      .unique(                # keep the unique ones by looking at …
        as => {/<:L>+/;lc $/} # only the word chars in lowercase
      )
      .join                   # join the sentence parts
      ~                       # join that with …
      ($s//'')                # the boundary characters or empty string 
    }
  )
}
Brad Gilbert b2gills
fonte
1

Perl 5, 57 bytes

Código de 56 bytes + 1 para -p

s/[^.!?
]+/my%h;$&=~s~\s*([A-z]+)~!$h{lc$1}++&&$&~egr/eg

Uso:

perl -pe 's/[^.!?
]+/my%h;$&=~s~\s*([A-z]+)~!$h{lc$1}++&&$&~egr/eg' <<< 'Hello Hello, World!
Code Code! Golf Code
Hello  hello   World
Programming Golf Programming!
'
Hello, World!
Code! Golf Code
Hello   World
Programming Golf!

Talvez precise ser +1, atualmente estou assumindo que haverá apenas espaços na entrada, sem guias.

Dom Hastings
fonte
De um comentário "Todos os caracteres ASCII são permitidas na entrada Somente letras são consideradas palavras embora." (Eu vou editar este para o desafio, eu acho)
Martin Ender
@ MartinBüttner Porra, ok, vou atualizar para usar \s... Ainda não está nem perto da sua resposta da retina!
Dom Hastings
Oh, eu vejo porque você perguntou agora. Se precisamos remover o espaço em branco na frente das palavras, também preciso de outro byte. A pergunta diz especificamente "espaços". Eu pedi esclarecimentos.
Martin Ender
@ MartinBüttner Acho que meu comentário também não foi muito claro! Obrigado pelos seus comentários!
Dom Hastings