Arregla mis palabras tartamudeadas

12

La tartamudez es un problema que muchos de nosotros podríamos haber experimentado o al menos haber visto. Aunque la mayoría de los software de reconocimiento de voz famosos tienen serios problemas con el habla tartamudeada, imaginemos un software que entienda la tartamudez, pero que no pueda solucionarlos y solo los escriba como están.

Un texto escrito de ejemplo de dicho software puede ser así: "tenga cuidado" . En este ejemplo, "cuidadoso" es la palabra original y "ca ca" son las palabras tartamudeadas.

Desafío

Escriba un programa o función que repare las palabras tartamudeadas eliminándolas de la entrada mientras mantiene las palabras originales. Por ejemplo, la versión fija de "por favor tenga cuidado" sería "por favor tenga cuidado" .

Este es el , ¡la respuesta más corta en todos los idiomas gana!

¿Qué son las palabras tartamudeadas?

La tartamudez tiene muchas variaciones diferentes. Pero para simplificar este desafío, vamos a limitarlo a las siguientes reglas:

  • Las palabras tartamudeadas pueden ser una parte incompleta o la totalidad de la palabra original. Por "parte incompleta" quiero decir que la palabra original debe comenzar exactamente con la palabra tartamudeada. Por ejemplo, "ope" y "open" pueden ser una palabra tartamudeada para "abrir" , pero "pen" no puede serlo ya que "abrir" no comienza con "pen" .
  • Las palabras tartamudeadas deben contener al menos una de las vocales "aeiou" . Por ejemplo, "estrella" puede ser una palabra tartamudeada para "inicio" ya que contiene "a" , pero "st" no puede ser una palabra tartamudeada ya que no contiene ninguna de las vocales mencionadas.
  • Las palabras tartamudeadas solo pueden aparecer antes de la palabra original y deben repetirse al menos dos veces para ser válidas (la palabra original no cuenta en las repeticiones). Por ejemplo, "oo open" tiene palabras tartamudeadas pero "o open o" no lo hace, porque la "o" después de la palabra original no cuenta y "o" antes de la palabra original no se repite al menos dos veces. "go go go go go go" tiene cinco repeticiones de palabras tartamudeadas antes de la palabra original y es válido.
  • Un conjunto único de palabras tartamudeadas repetidas no puede contener formas mixtas y las palabras deben ser exactamente iguales entre sí. Por ejemplo, "op o op open" no cuenta como palabras tartamudeadas. Por otro lado, "o op op open" tiene palabras tartamudeadas porque la primera "o" se ve aquí como una palabra completamente diferente y las dos "op" s se cuentan como palabras tartamudeadas de "open" .
  • En el caso de varios conjuntos válidos de palabras tartamudeadas repetidas una tras otra, solo queda la última palabra original. Por ejemplo, en "ooo op op op open" , la parte "oo o" se ve como palabras tartamudeadas de la primera "op" , por lo que deben eliminarse y luego "op op op" se ve como palabras tartamudeadas de "open " y también deberían eliminarse, por lo que solo quedará el " abierto " después de eliminar las palabras tartamudeadas. Puede suponer que múltiples conjuntos válidos de palabras tartamudeadas repetidas solo suceden de izquierda a derecha, por lo que corregir "op op ooo open" resultaría en "op op open" (también conocido como

Entrada

  • La entrada es una cadena de línea única que contiene solo letras ASCII en inglés (az), dígitos (0-9) y caracteres de espacio. El uso de mayúsculas y minúsculas no es importante y puede decidir aceptar minúsculas o mayúsculas, o ambas, pero la carcasa debe permanecer igual y no puede cambiarla en la salida.
  • Puede usar una lista de letras (como ["l","i","s","t"," ","o","f"," ","l","e","t","t","e","r","s"]) en lugar de la cadena, pero no puede usar una lista de palabras. Si su idioma tiene una estructura de entrada diferente, úsela. El punto es que la entrada no debe estar separada por palabras, por lo que el costo de separar las palabras en algunos idiomas podría desencadenar otras soluciones creativas.
  • La entrada puede contener ninguna, una o varias palabras tartamudeadas.
  • Las palabras y / o números están separados por un solo espacio y la entrada no contendrá espacios dobles uno al lado del otro.

Salida

  • Una cadena o una lista de letras o la estructura apropiada en su idioma con todas las palabras tartamudeadas eliminadas de la entrada.
  • Las palabras de salida deben estar separadas exactamente por un espacio (igual que la entrada).
  • Se permiten líneas o espacios iniciales y finales únicos.

Las lagunas estándar están prohibidas.

Casos de prueba

No hay palabras tartamudeadas:

"hello world" => "hello world"

Una sola instancia de palabras tartamudeadas repetidas:

"ope ope ope ope open the window" => "open the window"

Múltiples instancias de palabras tartamudeadas repetidas:

"there is is is is something un un under the the the table" => "there is something under the table"

No hay palabras tartamudeadas, no se repiten lo suficiente:

"give me the the book" => "give me the the book"

Sin palabras tartamudeadas, no tenga ninguna de las vocales mencionadas:

"h h help m m m me" => "h h help m m m me"

Los números no son palabras tartamudeadas, no tienen ninguna de las vocales mencionadas:

"my nu nu number is 9 9 9 9876" => "my number is 9 9 9 9876"

Pero una palabra con vocales y números puede tener palabras tartamudeadas:

"my wi wi windows10 is slow" => "my windows10 is slow"

No se cuentan diferentes formas de palabras tartamudeadas en el mismo grupo de repetición:

"this is an ant antarctica does not have" => "this is an ant antarctica does not have"

Para múltiples conjuntos continuos de palabras tartamudeadas una tras otra, solo mantenga la última palabra original:

"what a be be be beauti beauti beautiful flower" => "what a beautiful flower"

Este no es un caso de múltiples conjuntos continuos de palabras tartamudeadas una tras otra:

"drink wat wat wa wa water" => "drink wat wat water"

Entrada vacía:

"" => ""

Más casos de comentarios:

"a ab abc" => "a ab abc"
"a ab ab abc" => "a abc"
"ab ab abc abcd" => "abc abcd"
"a a ab a able" => "ab a able"
"i have ave ave average" => "i have average"
"my wi wi windows 10 is cra cra crap" => "my windows 10 is crap"

Una lista fácil de copiar de los casos de prueba anteriores:

"hello world",
"ope ope ope ope open the window",
"there is is is is something un un under the the the table",
"give me the the book",
"h h help m m m me",
"my nu nu number is 9 9 9 9876",
"my wi wi windows10 is slow",
"this is an ant antarctica does not have",
"what a be be be beauti beauti beautiful flower",
"drink wat wat wa wa water",
"",
"a ab abc",
"a ab ab abc",
"ab ab abc abcd",
"a a ab a able",
"i have ave ave average",
"my wi wi windows 10 is cra cra crap"
Noche2
fuente
2
"drink wat wat wa wa water" => "drink wat wat water"realmente parece que la regla debería aplicarse de manera recursiva para que esto se convierta en "beber agua"
Jonás
2
@ Jonás si lees el último elemento en ¿Qué son las palabras tartamudeadas? He explicado este asunto. "wat wat" no son palabras tartamudeadas para "wa" y solo lo arreglamos una vez, así que una vez que obtenemos "beba agua wat wat", no lo arreglamos nuevamente para eliminar palabras tartamudeadas recién formadas. Pero en un caso inverso como "wa wa wat wat water" el resultado será "agua" porque "wa wa" son palabras tartamudeadas para el primer "wat" y "wat wat" también son palabras tartamudeadas de "agua".
Noche2
De acuerdo, es justo decir que tendría sentido seguir arreglando hasta que ya no puedas más, pero también puedo ver el argumento para centrarme en una sola iteración.
Jonás

Respuestas:

6

C (gcc), 183 180 178 bytes

f(s,t,u,T,e,r)char*s,*t,*u,*r;{for(;s=index(u=s,32);T>1&strpbrk(u,"aeiou")-1<s&&memmove(s=u,t-e,r-t-~e))for(e=++s-u,r=u+strlen(t=u),T=0;(t+=e)<r&!memcmp(u,t,e-1)&t[-1]==32;++T);}

Pruébalo en línea!

Bueno, C ciertamente no puede competir con la brevedad de la expresión regular ...

Este es particularmente difícil de leer porque terminé colapsando toda la función en un solo par de forbucles anidados (¡sin cuerpo!). Eso hace que el orden de evaluación sea inestable: el código cerca del principio realmente se ejecuta en último lugar.

Mi truco favorito aquí es strpbrk(u,"aeiou")-1<s. Esto se usa para verificar si la palabra repetida contiene vocales. useñala el comienzo de la palabra repetida y sseñala la segunda repetición de la palabra; por ejemplo:

"my nu nu number is 9 9 9 9876"
    ^  ^
    u  s

strpbrkluego encuentra el primer personaje "aeiou"que aparece después u. (En este caso, es 'u'inmediatamente después). Luego podemos verificar que esto viene antes spara verificar que la palabra contenga una vocal. Pero hay un pequeño problema: los strpbrkretornos NULL(es decir, 0si no hay vocal en toda la cadena). Para solucionar esto, simplemente resta 1, que se convierte 0en 0xffffffffffffffff(en mi máquina) debido al desbordamiento. Al ser el valor máximo de un puntero, este es decididamente mayor que s, lo que hace que la verificación falle.

Aquí hay una versión un poco más antigua (antes de la transformación que confunde el flujo de control) con comentarios:

f(s,t,u,c,n,e)char*s,*t,*u,*e;{
    // set s to the position of the *next* check; u is the old position
    for(;s=index(u=s,32);) {
        // count the length of this word (incl. space); also fix s
        n=++s-u;
        // find the end of the string; assign temp pointer to start
        e=u+strlen(t=u);
        // count repetitions of the word
        for(c=0;                // number of repetitions
            (t+=n)              // advance temp pointer by length of word
            <e&&                // check that we haven't hit the end...
            !strncmp(u,t,n-1)&& // ...and the word matches...
            t[-1]==32;          // ...and the previous character was space
            ++c);               // if so, increment count
        // decide whether to remove stuttering
        c>1&&                    // count must be at least 2
        strpbrk(u,"aeiou")-1<s&& // word must contain a vowel
        // if so, move everything after the last occurrence back to the
        // beginning, and also reset s to u to start scanning from here again
        memmove(s=u,t-n,e-t+n+1);
    }
}

Gracias a @ user1475369 por 3 bytes y @ceilingcat por 2 bytes.

Pomo de la puerta
fuente
-3 bytes reemplazando T>1&&strpbrkcon T>1&strpbrk, r&&!strncmpcon r&!strncmpy &&t[-1]con &t[-1].
girobuz
@ceilingcat Su enlace falla en algunos de los casos de prueba, pero 2 de esas 3 optimizaciones funcionan; ¡Gracias!
Pomo de la puerta
Sugerir en bcmp()lugar dememcmp()
ceilingcat
4

Perl 5 (-p), 34 bytes

Basado en la respuesta eliminada de Arnauld.

s/(\b(\w*[aeiou]\w*) )\1+(?=\2)//g

Pruébalo en línea!

Mugriento
fuente
Esto produce "zab" para "za a ab". No creo que deba detectarse un tartamudeo en esa entrada.
recursivo el
@recursivas gracias, arreglado.
Grimmy
2
Miré los casos de prueba e ideé una expresión regular, solo para encontrarla aquí. Naturalmente, esto significa que el puerto de Retina trivial es de 30 bytes.
Neil
3

05AB1E , 30 29 28 bytes

-1 byte gracias a Kevin Cruijssen

#Rγε®y¬©žMÃĀiнkĀDygαΘ+∍]R˜ðý

Pruébalo en línea!

05AB1E, al no tener expresiones regulares, definitivamente no parece ser la mejor herramienta para esta tarea. Aún así, de alguna manera logra apenas vencer a Retina.

#                     # split on spaces
 R                    # reverse the list of words
  γ                   # group consecutive identical words together

ε                   ] # for each group of words y:
 ®                    #  push the previous word on the stack (initially -1)
  y                   #  push another copy of y
   ¬                  #  push the first element without popping
    ©                 #  save the current word for the next loop
     žM               #  built-in constant aeiou
       ÃĀi          ] #  if the length of the intersection is non-zero:
           н          #   take the first element of y
            kĀ        #   0 if the previous word starts with this word, 1 otherwise
              D       #   duplicate
               yg     #   length of y (the number of consecutive identical words)
                 α    #   subtract the result of the startsWith check
                  Θ   #   05AB1E truthify (1 -> 1, anything else -> 0)
                   +  #   add the result of the startsWith check
                    ∍ #   set the length of y to that value
                      #  otherwise leave y unchanged

˜                     # flatten the modified list of groups of words
 R                    # reverse the list of words
  ðý                  # join with spaces
Mugriento
fuente
1
Puede eliminar el gantes de Ā. La verdad al estilo Python ya dará como resultado 0cadenas vacías y cadenas 1no vacías.
Kevin Cruijssen
@KevinCruijssen buen hallazgo!
Grimmy
1

Perl 6 , 45 bytes

{S:g/<|w>(\S*<[aeiou]>\S*)\s$0+%%\s{}<?$0>//}

Pruébalo en línea!

Una respuesta simple regex que sustituye todas las coincidencias de tartamudeos con la cadena vacía.

Jo King
fuente
1

Stax , 26 bytes

å╬↓<▀.₧▀"╦n▐∞↨vß%ù:Qa3@=↔_

Ejecutar y depurarlo

Puerto directo de la respuesta perl de @ Grimy. Stax puede reducir el patrón de expresión regular literal, y tiene una constante de vocales que puede reducir [aeiou].

recursivo
fuente
1

Limpio , 184 bytes

import StdEnv,Data.List,Text
$s=join[' '](f(group(split[' ']s)))
f[[a]:t]=[a:f t]
f[h=:[a:_]:t=:[[b:_]:_]]|intersect['aeiou']a==[]=h++f t|isPrefixOf a b=f t=if(h>[a,a])[a]h++f t
f[]=[]

Pruébalo en línea!

Define $ :: [Char] -> [Char], que divide la cadena de entrada en espacios y agrupa elementos idénticos que luego son colapsados ​​por el ayudante f :: [[[Char]]] -> [[Char]], uniéndose antes de regresar.

Οurous
fuente