Eliminar palabras duplicadas de una oración

10

En este desafío, eliminará palabras duplicadas de cada oración .

Ejemplos

Hello Hello, World!
Hello, World!

Code Code! Golf Code
Code! Golf Code

Hello  hello   World
Hello   World

Programming Golf Programming!
Programming Golf!

Especificación

  • La entrada será una cadena de caracteres ASCII.
  • Una oración se define como cualquier cosa hasta el final de la cadena, un salto de línea ( \n) o una puntuación ( .!?).
  • Una palabra se define como una secuencia de A-Za-z.
  • Las palabras no distinguen entre mayúsculas y minúsculas ( Hello== heLlO).
  • Solo se mantiene la primera aparición de una palabra en una oración.
  • Si se elimina una palabra, se deben eliminar los espacios antes de la palabra eliminada. (por ejemplo, A A B-> A B).

Este es el código más corto en bytes gana!

Downgoat
fuente
1
a b a.va a que?
lirtosiast el
@ThomasKwa a b.porque se elimina la `a`.
Downgoat
Para a__b_b_a, ¿obtienes a_b_a(primero beliminado) o a__b_a(segundo beliminado)?
@CamilStaps que obtendría a__b__porque lo repetido bse elimina y lo repetido ase elimina
Downgoat
1
@ BradGilbertb2gills Todos los caracteres ASCII están permitidos en la entrada. Sin embargo
Downgoat

Respuestas:

3

Vim, 27 bytes

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

Tenga en cuenta que los 27 bytes incluyen un retorno de carro final al final.

Pruébalo en línea! Nota al margen: Este es un enlace a un idioma diferente que estoy escribiendo llamado "V". V es en su mayoría compatible con vim, por lo que, para todos los efectos, puede contar como un intérprete de vim. También agregué un byte %para que pueda verificar todos los casos de prueba a la vez.

Explicación:

: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
fuente
6

JavaScript (ES6), 98

Tenga en cuenta que aunque lo encontré yo mismo, es molestamente similar a @ Neil, solo que con la lógica adicional para dividir toda la cadena de entrada en oraciones.

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

Prueba

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
fuente
6

Retina , 66 46 bytes

El recuento de bytes asume la codificación ISO 8859-1.

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

Pruébalo en línea!

Explicación

Dado que solo las letras deben considerarse caracteres de palabras (pero regex trata los dígitos y los guiones bajos como caracteres de palabras también), necesitamos establecer nuestros propios límites de palabras. Como se garantiza que la entrada contiene solo caracteres ASCII, estoy insertando ·(fuera de ASCII, pero dentro de ISO 8859-1) alrededor de todas las palabras y las elimino nuevamente con los duplicados. Eso ahorra 20 bytes sobre el uso de lookarounds para implementar límites de palabras genéricas.

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

Esto coincide con cada palabra y lo rodea ·.

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

Estos son dos pasos comprimidos en uno. <sp>*(·[a-z]+·)(?<=\1[^.!?¶]+)coincide con una palabra completa (asegurada al incluirla ·en la coincidencia), junto con los espacios que la preceden, siempre que (tal como lo asegura el reverso) podamos encontrar la misma palabra en algún lugar anterior en la oración. (El coincide con un salto de línea).

La otra parte es simplemente el ·, que coincide con todos los límites de palabras artificiales que no coincidieron como parte de la primera mitad. En cualquier caso, la coincidencia simplemente se elimina de la cadena.

Martin Ender
fuente
4

C, 326 bytes

¿Quién necesita expresiones 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
fuente
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!

Explicación

{
  [~]                         # 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
fuente
1

Perl 5, 57 bytes

56 bytes código + 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!

Puede que tenga que ser +1, actualmente estoy asumiendo que solo habrá espacios en la entrada, sin pestañas.

Dom Hastings
fuente
De un comentario "Todos los caracteres ASCII están permitidos en la entrada. Sin embargo, solo las letras se consideran palabras" (creo que editaré esto en el desafío)
Martin Ender
@ MartinBüttner Maldición, vale, actualizaré para usar \sen su lugar ... ¡Sin embargo, aún no estoy cerca de tu respuesta de retina!
Dom Hastings
Oh, ya veo por qué preguntaste ahora. Si necesitamos eliminar espacios en blanco delante de las palabras, también necesito otro byte. Sin embargo, la pregunta dice específicamente "espacios". He pedido aclaraciones.
Martin Ender
@ MartinBüttner ¡Creo que mi comentario tampoco fue muy claro! ¡Gracias por sus comentarios!
Dom Hastings