Aplicar reglas de puntuación en inglés

11

Lo contrataron para escribir un código para una aplicación de toma de dictado, que toma la entrada de voz de una fuente hablada, la analiza como palabras y la escribe en una pantalla.

La administración realmente no confía en ti con tanta potencia en el proyecto, desafortunadamente, te sientas y juegas al código de golf todo el día en lugar de hacer tu trabajo, por lo que simplemente te dan una tarea realmente simple: realizar un Oración con puntuación intercalada en una oración formateada correctamente, donde 'formateado correctamente' se define a continuación.

  1. La oración es la cadena de entrada. Una palabra es un grupo de caracteres no espaciales distinguidos. Una puntuación es una palabra cuyo primer carácter es ^.

  2. Una palabra está en mayúscula si la primera letra de la palabra no es una letra minúscula (las palabras en mayúscula coinciden con la expresión regular /[^a-z].*/).

  3. La primera palabra de la oración debe estar en mayúscula.

  4. A ^COMMAes el carácter de coma ,y tiene un espacio que sigue pero no precede. aaa ^COMMA bbbse convierte aaa, bbb.

  5. A ^COLONes una coma que se parece :.

  6. A ^SEMICOLONes una coma que se parece ;.

  7. A ^PERIODes una coma que se parece .. La palabra que sigue a ^PERIODdebe estar en mayúscula.

  8. A ^BANGes un período que se parece !.

  9. A ^DASHes el carácter de guión -y tiene un espacio que precede y sigue.

  10. A ^HYPHENtambién es el carácter de guión, -pero no tiene espacio siguiente o anterior.

  11. Un ^EMDASHes un guión (¡no un guión!) Que se deletrea --.

  12. Un ^OPENQUOTEes un carácter de comillas "que tiene un espacio que precede pero no sigue. La palabra que sigue a ^OPENQUOTEdebe estar en mayúscula. Si un ^OPENQUOTEestá precedido por una palabra que no es puntuación, agregue un ^COMMAentre esa palabra y el ^OPENQUOTE. Si un ^OPENQUOTEestá precedido por una puntuación que hace que la siguiente palabra esté en mayúscula, se salta ^OPENQUOTEa la siguiente palabra.

  13. A ^CLOSEQUOTEes el dígrafo ,"que tiene un espacio que sigue pero no precede. Si una ^CLOSEQUOTEestá precedida por una ^COMMA, ^PERIODo ^BANGque desaparece y la Puntuacion ^CLOSEQUOTEse escribe ,", ."o !"respectivamente. Si la puntuación que desaparece especifica una mayúscula, esa capitalización aún debe ocurrir en la siguiente palabra disponible.

  14. Los espacios iniciales o finales en el resultado final completo deben eliminarse, y cualquier cadena de dos o más espacios en una fila debe contraerse en un solo carácter de espacio.

  15. Cualquier caso no cubierto anteriormente (por ejemplo, ^COMMA ^COMMAor ^SEMICOLON ^CLOSEQUOTEo ^UNDEFINEDPUNCTUATION) no ocurrirá en una entrada bien formada y, por lo tanto, es un comportamiento indefinido.

El equipo de desarrollo le informa lo siguiente:

  • El proyecto se está escribiendo en el idioma [su idioma aquí] , y debe ser lo más breve posible para que ocupe el menor espacio posible cuando se trata de una aplicación para Android / iPhone. Intentas explicar que no es así como funciona el desarrollo de aplicaciones, pero no escuchan. Pero oye, ¡qué coincidencia! ¡Eres un golfista increíble en [tu idioma aquí] !

  • La aplicación no tendrá ningún permiso de acceso web y no habrá ninguna biblioteca instalada que realice este formateo por usted. Sin embargo, probablemente pueda convencer al líder del equipo para que le permita una biblioteca de expresiones regulares si existe una para su idioma, si cree que necesita una.

  • El soporte para citas anidadas que usan comillas dobles / simples correctamente está planeado para una versión posterior de la aplicación, pero no para la versión en la que está trabajando ahora, así que no se preocupe.

  • La administración es un gran admirador del desarrollo basado en pruebas, por lo que el equipo de desarrollo ya ha hecho que un mono de teclado desafortunado escriba algunas pruebas para su parte del programa: (se agregaron nuevas líneas para facilitar la lectura, trátelas como espacios)

    Entrada:

    hello ^COMMA   world ^BANG
    

    Salida:

    Hello, world!
    

    Entrada:

    once upon a time ^COMMA there was a horse ^PERIOD that horse cost me $50
    ^PERIOD ^OPENQUOTE eat your stupid oats ^COMMA already ^BANG ^CLOSEQUOTE
    I told the horse ^PERIOD the horse neighed back ^OPENQUOTE no ^CLOSEQUOTE
    and died ^PERIOD THE END
    

    Salida:

    Once upon a time, there was a horse. That horse cost me $50. "Eat your
    stupid oats, already!" I told the horse. The horse neighed back, "No,"
    and died. THE END
    

    Entrada:

    begin a ^PERIOD b ^COMMA c ^COLON d ^SEMICOLON e ^BANG f ^HYPHEN g ^DASH h
    ^EMDASH i ^OPENQUOTE j ^PERIOD ^OPENQUOTE k ^SEMICOLON ^OPENQUOTE l
    ^CLOSEQUOTE m ^BANG ^CLOSEQUOTE n ^PERIOD 0x6C6F6C end
    

    Salida:

    Begin a. B, c: d; e! F-g - h--i, "j. "K; "l," m!" N. 0x6C6F6C end
    

Este es un código de golf: gana el puntaje más bajo. Puede escribir una función de un argumento de cadena o un programa que lea desde STDIN y escriba en STDOUT.

Algoritmo de tiburón
fuente
¿Qué pasa si quiero usar JavaScript? No hay entrada estándar en él. Puedo usar prompt()?
nicael
@nicael OP menciona el uso de un argumento de cadena, por lo que para mi ejemplo de JS, acabo de hacer una función que toma un argumento y asumí que ese argumento era la cadena de palabras similares a STDIN
Eric Lagergren
1
Me pregunto si hay esolang llamado "[su idioma aquí]"
Akangka

Respuestas:

4

JavaScript: 653 611 547 514 487 bytes

Oh Dios mío. Brendan Eich Lo siento mucho por esto.

PD: He agregado un espacio en blanco para facilitar la lectura, pero al eliminar todos los espacios en blanco permitidos se obtiene el recuento de bytes enumerado.

Teóricamente, podría acortar algunas partes como el -e-a algo como -eo -e, pero eso podría causar un problema si la palabra anterior termina con, o la siguiente palabra comienza con la letra 'e' (o cualquier palabra que decida usar). Supongo que podría usar un carácter ASCII. Lo investigaré.

487 FF22 + solamente

R = "replace", C = "charAt", U = "toUpperCase";
alert(a[R](/\^((COMMA)|(SEMICOLON)|(COLON)|(PERIOD)|(BANG)|(DASH)|(HYPHEN)|(EMDASH)|(OPENQUOTE)|(CLOSEQUOTE))/g, ((m, _, a, b, c, d, e, f, g, h, i, j) => a ? "," : b ? ";" : c ? ":" : d ? "." : e ? "!" : f ? "-" : g ? "-h-" : h ? "-e-" : i ? ' "' : '" '))[R](/\s((\.)|(\!)|(\,)|(\;)|(\:)|(\-\h\-\s)|(\-\e\-\s))/g, ((k, l, v, n, o, p, q, r, s) => v ? "." : n ? "!" : o ? "," : p ? ";" : q ? ":" : r ? "-" : "--"))[R](/[^!,"'.]\"\s/g, '"')[R](/.+?[\.\?\!](\s|$)/g, (t => t[C](0)[U]() + t.substr(1)))[R](/\"[a-z]/g, (u => u[C](0) + u[C](1)[U]())))

514 FF22 + solamente

alert(function(z) {
    R = "replace", C = "charAt", U = "toUpperCase";
    return z[R](/\^((COMMA)|(SEMICOLON)|(COLON)|(PERIOD)|(BANG)|(DASH)|(HYPHEN)|(EMDASH)|(OPENQUOTE)|(CLOSEQUOTE))/g, ((m, _, a, b, c, d, e, f, g, h, i, j) => a ? "," : b ? ";" : c ? ":" : d ? "." : e ? "!" : f ? "-" : g ? "-h-" : h ? "-e-" : i ? ' "' : '" '))[R](/\s+((\.)|(\!)|(\,)|(\;)|(\:)|(\-\h\-\s+)|(\-\e\-\s+))/g, ((k, l, v, n, o, p, q, r, s) => v ? "." : n ? "!" : o ? "," : p ? ";" : q ? ":" : r ? "-" : "--"))[R](/[^!,"'.]\"\s/g, '"')[R](/.+?[\.\?\!](\s+|$)/g, (t => t[C](0)[U]() + t.substr(1)))[R](/\"[a-z]/g, (u => u[C](0) + u[C](1)[U]()))
}(a))

547 FF22 + solamente

alert(function(z) {
    R = "replace", C = "charAt", U = "toUpperCase";
    return z[R](/\^((COMMA)|(SEMICOLON)|(COLON)|(PERIOD)|(BANG)|(DASH)|(HYPHEN)|(EMDASH)|(OPENQUOTE)|(CLOSEQUOTE))/g, ((m, _, a, b, c, d, e, f, g, h, i, j) => a ? "," : b ? ";" : c ? ":" : d ? "." : e ? "!" : f ? "-" : g ? "-h-" : h ? "-e-" : i ? ' "' : '" '))[R](/\s+((\.)|(\!)|(\,)|(\;)|(\:)|(\-\h\-\s+)|(\-\e\-\s+))/g, ((xx, __, k, l, m, n, o, p, q) => k ? "." : l ? "!" : m ? "," : n ? ";" : o ? ":" : p ? "-" : "--"))[R](/[^!,"'.]\"\s/g, '"')[R](/.+?[\.\?\!](\s+|$)/g, function(r) {
        return r[C](0)[U]() + r.substr(1)
    })[R](/\"[a-z]/g, function(s) {
        return s[C](0) + s[C](1)[U]()
    })
}(a))

611 FF 22+ solamente

alert(function(c) {
    return c.replace(/\^((COMMA)|(SEMICOLON)|(COLON)|(PERIOD)|(BANG)|(DASH)|(HYPHEN)|(EMDASH)|(OPENQUOTE)|(CLOSEQUOTE))/g, ((x, _, a, b, c, d, e, f, g, h, i) = > a ? "," : b ? ";" : c ? ":" : d ? "." : e ? "!" : f ? "-" : g ? "-h-" : h ? "-e-" : i ? ' "' : '" ')).replace(/\s+\./g, ".").replace(/\s+\!/g, "!").replace(/\s+\,/g, ",").replace(/\s+\;/g, ";").replace(/\s+\:/g, ":").replace(/\s\-\h\-\s/g, "-").replace(/[^!,"'.]\"\s/g, '"').replace(/\s+\-\e-\s+/g, "--").replace(/.+?[\.\?\!](\s+|$)/g, function(b) {
        return b.charAt(0).toUpperCase() + b.substr(1)
    }).replace(/\"[a-z]/g, function(b) {
        return b.charAt(0) + b.charAt(1).toUpperCase()
    })
}(a))

653 cross-browser

alert(function(c) {
    return c.replace(/\^COMMA/g, ",").replace(/\^SEMICOLON/g, ";").replace(/\^COLON/g, ":").replace(/\^PERIOD/g, ".").replace(/\^BANG/g, "!").replace(/\^DASH/g, "-").replace(/\^HYPHEN/g, "h-h").replace(/\^EMDASH/g, "-e-").replace(/\^OPENQUOTE/g, ' "').replace(/\^CLOSEQUOTE/g, '" ').replace(/\s+\./g, ".").replace(/\s+\!/g, "!").replace(/\s+\,/g, ",").replace(/\s+\;/g, ";").replace(/\s+\:/g, ":").replace(/\s\h\-\h\s/g, "-").replace(/[^!,"'.]\"\s/g, '"').replace(/\s+\-\e-\s+/g, "--").replace(/.+?[\.\?\!](\s|$)/g, function(b) {
        return b.charAt(0).toUpperCase() + b.substr(1)
    }).replace(/\"[a-z]/g, function(b) {
        return b.charAt(0) + b.charAt(1).toUpperCase()
    })
}(a))

Cómo funciona:

https://gist.github.com/ericlagergren/1a61b5d772ae49ab3aea

JSFiddle (para la solución de navegador cruzado de 653 bytes)

JSFiddle (para la única solución 595 FF 22+ )

JSFiddle (para la única solución 547 FF 22+ )

JSFiddle (para la única solución 514 FF 22+ )

JSFiddle (para la única solución 487 FF 22+ )

Esta es la primera vez que tengo que escribir JS que usa más de una expresión regular, y generalmente mi expresión regular está predefinida.

Continuaré recortando bytes tanto como pueda.

Eric Lagergren
fuente
Puede acortar sus primeros reemplazos de esta manera: c.replace(/\^((COMMA)|(SEMICOLON)|(COLON)|(PERIOD)|(BANG))/g,(m,_,a,b,c,d,e)=>a?',':b?';':c?':':d?'.':'!'))... y así sucesivamente. Arrow sintax es corto, pero incluso la 'función' debería guardar los mismos caracteres
edc65
Tienes razón. Probé mi expresión regular con Chrome, y no admite flechas gruesas. Estoy trabajando para arreglarlo con FF en este momento, pero odio que las expresiones regulares realmente no tengan un operador "y" como lo hacen con "o". @ edc65
Eric Lagergren
@ edc65, así que creo que tendré que usar dos =>s para que funcione, ¡pero usar las flechas me ahorró 40 bytes!
Eric Lagergren
Reemplazar reemplazar con R = 'reemplazar' ... [R] ;-)
edc65
Acabo de hacer eso :) Lo bajé a 563 @ edc65
Eric Lagergren
1

PHP, 412 bytes

(Ungolfed aquí para mayor claridad; ver ideone para la versión de golf ).

La función preg_replace () de PHP aceptará argumentos de matriz, lo cual es bastante útil aquí. Creo que el siguiente código hace todo lo necesario. Pasa todos los casos de prueba al menos.

function x($s) {
    $r='preg_replace';
    $s=$r('/ +/',' ',$s);
    $s=$r(array('/ \^COMMA/','/ \^COLON/','/ \^SEMICOLON/','/ \^PERIOD/','/ \^BANG/',
                '/\^DASH/','/ \^HYPHEN /','/ \^EMDASH /','/\^OPENQUOTE /','/ \^CLOSEQUOTE/'),
          array(',',':',';','.','!','-','-','--','"',',"'),
          $s);
    $s=$r('/(^\W*\w|([\.!]| ")\W+\w)/e','strtoupper("$0")',$s);
    $s=$r('/([,\.!]),/','\1',$s);
    $s=$r('/(\w)( "\w)/e','"$1,".strtoupper("$2")',$s);
    echo $s;
}
r3mainer
fuente
¡Funciona perfectamente! ideone.com/AYtTiI Aunque lo que me confunde es ¿se supone que debemos tener comas antes de las comillas abiertas? Porque, hablando gramaticalmente, las comillas son para algo más que discurso, pero solo el discurso tiene la coma antes de las comillas. Supuse que, dado que había un ^ COMMA, estaríamos permitiendo que el usuario ingrese la coma
Eric Lagergren