Descifrar ranas neuróticas

28

Descifrar ranas neuróticas

Ahora que Puzzling.SE finalmente ha descifrado mi cifrado obsesionado con los anfibios , ¡escribamos un programa o función para descifrarlo!

(Si desea ver el rompecabezas antes de que se lo estropee, haga clic en el enlace anterior ahora)


Cómo funciona el cifrado

En Neurotic ranas O ught Para Rel una x en M ud Baños ( "neurótica ranas" para abreviar), cada letra es encriptada como una o dos palabras:

  • La longitud de una palabra sin cursiva representa una letra.
    • neurotic => 8 letras => H
    • frogs => 5 letras => E
    • perpendicular => 13 letras = M
  • Una palabra que contiene cursiva modifica la siguiente palabra, agregando 10 si la palabra en cursiva tenía una longitud impar o 20 si la palabra en cursiva tenía una longitud par. Cualquiera o toda la palabra puede estar en cursiva. Una palabra en cursiva siempre va seguida de una palabra sin cursiva.
    • *o*ught to => impar, 2 => 12 => L
    • lo*u*nging calms => par, 5 => 25 => Y

Cada palabra de texto sin formato corresponde a una oración de texto cifrado, y cada oración de texto sin formato corresponde a un párrafo de texto cifrado.

Formato de entrada

Su programa o función ingresará un mensaje en Neurotic Frogs, formateado en Markdown. La entrada consistirá solo en ASCII imprimible y líneas nuevas.

  • Las palabras son series de caracteres que coinciden con la expresión regular [A-Za-z0-9'].
    • Los números y las letras cuentan para la longitud de una palabra. QB64representa D.
    • NOTA: Los apóstrofes no cuentan para la longitud de una palabra. Isn'trepresenta D, no E.
  • Las letras en cursiva se envuelven en un par de asteriscos ( *letters*).
    • Una o más letras consecutivas pueden estar en cursiva, hasta una palabra completa ( masseus*es*, *all*); múltiples letras no consecutivas en una palabra también pueden estar en cursiva ( g*e*n*e*rates).
    • Las cursivas nunca abarcan varias palabras, nunca incluyen signos de puntuación y nunca incluyen apóstrofes.
    • Los asteriscos no apareados y los asteriscos adyacentes múltiples nunca ocurrirán.
  • Puntuacion es cualquiera de los siguientes caracteres: .,?!:;-()".
    • Las palabras dentro de una oración están separadas por uno o más caracteres de puntuación y / o un solo espacio. Ejemplos: *all* welcomed, toad*s*, newts, Ever*y*one--frogs, cap... bliss,they're (I
    • Las oraciones terminan con uno o más caracteres de puntuación y están separadas por un doble espacio: Th*e* Montgomery A*m*phibian Salon! Come luxuriate today!
    • Los párrafos están separados por una sola línea nueva. (La última oración de un párrafo todavía tiene uno o más caracteres de puntuación al final).

Otros caracteres no aparecerán en la entrada y no necesitan ser manejados.

Su código puede, a su discreción, esperar que la entrada tenga una nueva línea final.

Formato de salida

El resultado de descifrar la entrada será una o más oraciones. Las letras de texto sin formato pueden ser cualquier combinación de mayúsculas y minúsculas. Las palabras dentro de una oración deben estar separadas por espacios individuales. Las oraciones deben terminar con un punto ( .) y estar separadas por un solo espacio. Puede generar un espacio final después de la última oración. Todos sus resultados estarán en una línea, pero puede generar una nueva línea final.

Detalles varios

Su código puede usar cualquiera de los métodos estándar de entrada y salida. Debe recibir la entrada como una cadena multilínea, no como una lista u otra estructura de datos, y debe generar una cadena.

¡El código más corto en bytes gana!

Casos de prueba

-->
Neurotic Frogs *O*ught To Rel*a*x In *M*ud Baths!
<--
HELLO.

-->
Business standards all*o*w only *adult* amphibians.
<--
HINT.

-->
Rejoice, *a*ll frogs an*d* toads also!  Montgomery Sal*o*n opens up!  Ha*pp*y throng fill*s* street ecstatically!
<--
GOOD JOB PPL.

-->
I like 3.1415926535897.
IM*O*, it's a *b*la*st*, yeah!
<--
ADAM. MAN.

-->
*I*, happily, *th*anks 2 u *e*ditin*g* specific wor*ding*--clarifying a *bit*--betterment :D!
<--
QUARTATA.

-->
Perpendicular l*ou*nging calms.  *A* frog, a m*u*d cap... bliss!  Wallowing g*e*n*e*rates happiness.  Amphibian sp*a* isn't expensive--seventy d*o*llars--cheap!  That'*s* not *a* large e*x*pens*e* from an*y* discerning fr*o*g's money, unlik*e* Super 8.
Ever*y*one--frogs, toad*s*, newts, *a*nd salamanders!  G*e*t a wonderful shiat*s*u, or recei*v*e an other kind.  Masseus*es* are her*e* today!  Invite a fianc*e*e, supervisor, roommate, niece: *all* welcomed!
Y*o*u simply ne*v*er believed these p*o*ssibilitie*s*; they're (I *swear*) absolute truth!  Th*e* Montgomery A*m*phibian Salon!  Come luxuriate today!
<--
MY NAME IS INIGO MONTOYA. YOU KILLED MY FATHER. PREPARE TO DIE.
DLosc
fuente
44
+1 para la entrada de la princesa princesa. Ah, y por tu habilidad, eso también.
Urna de pulpo mágico
¿Se garantiza que una palabra que contenga cursiva sea seguida por una que no contenga cursiva?
R. Kap
@ R.Kap Correcto. He editado la pregunta para aclarar eso.
DLosc

Respuestas:

5

Perl, 72 bytes

#!perl -n
$x=/\*/?2-y/'//c%2:!print/ /?$':chr$x.0+y/'//c+64for/[\w*']+|  /g,' . '

Contando el shebang como uno, la entrada se toma de stdin.

Uso de muestra

$ more in.dat
Neurotic Frogs *O*ught To Rel*a*x In *M*ud Baths!
Perpendicular l*ou*nging calms.  *A* frog, a m*u*d cap... bliss!  Wallowing g*e*n*e*rates happiness.  Amphibian sp*a* isn't expensive--seventy d*o*llars--cheap!  That'*s* not *a* large e*x*pens*e* from an*y* discerning fr*o*g's money, unlik*e* Super 8.
Ever*y*one--frogs, toad*s*, newts, *a*nd salamanders!  G*e*t a wonderful shiat*s*u, or recei*v*e an other kind.  Masseus*es* are her*e* today!  Invite a fianc*e*e, supervisor, roommate, niece: *all* welcomed!
Y*o*u simply ne*v*er believed these p*o*ssibilitie*s*; they're (I *swear*) absolute truth!  Th*e* Montgomery A*m*phibian Salon!  Come luxuriate today!

$ perl neurotic-frogs.pl < in.dat
HELLO. MY NAME IS INIGO MONTOYA. YOU KILLED MY FATHER. PREPARE TO DIE.
primo
fuente
1
Estoy otorgando la recompensa por esta respuesta, ya que es la más corta al final del período de recompensa además de la mía (de hecho, la única que se acercó).
DLosc
4

JavaScript (ES6), 172 169 157 150 bytes

Guardado 10 bytes gracias a @Neil

x=>x.match(/[\w'*]+|\s+/g).map(y=>y[0]==" "?y[1]:y==`
`?". ":/\*/.test(y,l+=y.match(/\w/g).length)?(l=l%2*10+19,""):l.toString(36,l=9),l=9).join``+"."

Probablemente se puede mejorar aún más. Salidas en minúsculas.

ETHproducciones
fuente
Ahorre 2 bytes moviendo el i=0a toString.
Neil
Por interés, tuve la oportunidad de arreglar esos errores y se me ocurrió esto:x=>x.replace(/([\w*']+)[^\w\n*' ]* ?( ?)/g,(_,y,z)=>/\*/.test(y,l=y.replace(/'/g ,"").length)?(i=l%2||2,""):l+i*10+9).toString(36,i=0)+z,i=0).replace(/\n|$/g,". ")
Neil
Parece funcionar en su forma actual.
primo
@Neil Gracias. Eso ahorra 12 bytes, pero no funciona en el último caso de prueba. Corrección que agrega 9 para un acortamiento neto de 3 bytes.
ETHproductions
@Neil Deshacerse .replacey simplemente usar .matchotros 12 bytes guardados.
ETHproductions
3

Python 2, 238 221 218 214 207 205 bytes

from re import*
def f(x):
 d='';m=0
 for w in split(r"[^\w\d*'~\n]+",sub('  ','~',x))[:-1]:l=len(sub("[*'~\n]",'',w));q='*'in w;d+='. '[w[0]>'}':]*(w[0]in'~\n')+chr(64+l+m)[q:];m=(2-l%2)*10*q
 print d+'.'

Utiliza muchas expresiones regulares para hacer el procesamiento. Transformamos el doble espacio en ~y lo usamos para procesarlo. ~y \nse manejan especialmente.

La mayor ganancia de caracteres proviene del preprocesamiento de la entrada en la forlínea; Esto definitivamente se puede jugar más golf.

Ideone it! (todos los casos de prueba)

¡Guardado 7 bytes gracias a DLosc!

Cobre
fuente
3

Pip , 65 64 bytes

La puntuación es de 62 bytes de código + 2 para las -rsbanderas.

Flg{O{{(zy*t+#a-1)X!Y'*Na&2-#a%2}MJa@`[\w*]+`}MlRM''^sX2O". "}

Pruébalo en línea!

Explicación

La -rbandera lee todas las líneas de stdin y almacena una lista de ellas g. El -sindicador establece el formato de salida de las listas en espacios separados.

La forma más fácil de leer este código es desde afuera en:

Flg{...}                   For each line l in g, do:

O{...}MlRM''^sX2O". "      Translate a paragraph into a sentence of plaintext:
       lRM''               Remove apostrophe characters
            ^sX2           Split on "  " into sentences
 {...}M                    Map the below function to each sentence
O                          Output the result list, space-separated, without newline
                O". "      Output that string, without newline

{...}MJa@`[\w*]+`          Translate a sentence into a word of plaintext:
       a@`[\w*]+`          Find all matches of regex (runs of alphanumeric and *)
{...}MJ                    Map the below function to each word and join into string

(zy*t+#a-1)X!Y'*Na&2-#a%2  Translate a word into a letter of plaintext:
      #a-1                 Length of word minus 1
  y*t+                     Add 10 or 20 if y is set (see below)
(z        )                Use that number to index into lowercase alphabet
              '*Na&        Count * characters in word, logical AND with...
                   2-#a%2  2 if word is even length, 1 if odd
             Y             Yank that value into y, to modify the following word
           X!              String multiply the character by not(y)
                           If y is truthy, the word had italics, and we get ""
                           If y is falsy, the word had no italics, and we get a letter
DLosc
fuente
Parece inmejorable.
primo
1

Python 2.7, 390 342 341 339 335 bytes:

from re import*
def F(i):
 W=X="";S,s=split,sub;D='[^\w\s*]';Q=lambda c,t:len(s(D,X,c.group()).split()[t])
 for m in S('\W\n',s(D+"*\w*\*\w+\*.*?(?=\s) \w+",lambda v:"a"*([20,10][Q(v,0)%2]+Q(v,1)),s("'",X,s("--"," ",i)))):
  for g in S('\W  ',m):
   for q in S('\W',g):
    W+=chr(64+len(q))
   W+=" "
  W=W[:-1]+". "
 print s("@",X,W)

Toma entrada en el formato:

F('''Multi or Single-lined String''')

Se puede jugar mucho más al golf, lo que haré siempre que tenga la oportunidad.

Repl.it con todos los casos de prueba!

Explicación:

Utiliza el inmenso poder de las expresiones integradas de Python incorporadas para descifrar la entrada. Este es el proceso fundamental por el que pasa la función para cada entrada:

  1. En primer lugar, todos --se reemplazan con un solo espacio y se elimina cada apóstrofe. Luego, todas las palabras que contienen componentes en cursiva y la palabra que lo sigue se combinan en una cadena y se reemplazan con un 10 + len(second word)número de as consecutivos si la longitud de la primera palabra es odd, y de lo contrario, s 20 + len(second word)consecutivos a. Esto utiliza la siguiente expresión regular:

    [^\w\s*]*\w*\*\w+\*.*?(?=\s) \w+

    Por ejemplo, si tenemos la oración Perpendicular l*ou*nging calms., l*ou*nging calmsse reemplazará con aaaaaaaaaaaaaaaaaaaaaaaaa, o 25 as, ya que l*ou*ngingtiene un número par de caracteres y calmstiene 5 20+5=25..

  2. Ahora, la entrada recién modificada se divide en cada signo de puntuación seguido de una nueva línea ( \n) para obtener los párrafos, luego cada párrafo se divide en cada puntuación seguido de 2 espacios para obtener las oraciones, y finalmente, cada oración se divide en palabras a lo largo cualquier puntuación, incluido un espacio. Luego, para cada palabra (incluidas las corridas de as consecutivas ), agregamos a una cadena Wla letra correspondiente al punto de código Unicode 64(el punto de código Unicode del carácter anterior A, que es @) más len(word). Luego agregamos un solo espacio a Wuna vez que todas las palabras de una oración se han agotado, y cuando todas las oraciones en un párrafo están agotadas, agregamos un .seguido de un solo espacio.

  3. Finalmente, una vez que se ha procesado toda la entrada, Wse envía stdoutcomo mensaje descifrado.

R. Kap
fuente
Nitpick menor: la especificación dice que las oraciones de salida están separadas por un espacio simple, no doble (este cambio también guarda un byte). Sugerencia inicial de golf: ya que está importando todo re, use en sublugar de str.replace. Sugerencia de golf más general: probablemente sea más eficiente tratar todo lo que no es una palabra o una *puntuación. Ahorra en grandes clases de personajes enormes.
DLosc
@DLosc Oh, mi mal. Pensé que la especificación era separar las oraciones en la salida por 2 espacios. Lo arreglaré Además, gracias por las sugerencias de golf! Veré qué puedo hacer con ellos.
R. Kap
1

PHP, 196 bytes

<?preg_match_all("#[\w*']+|  |$#m",$_GET[s],$m);foreach($m[0]as$s){if(!$s||$s=="  ")echo!$s?". ":" ";else{$l=$p+64+strlen(str_replace("'","",$s));if(!$p=strstr($s,"*")?20-$l%2*10:0)echo chr($l);}}

Si pudiera suponer que solo hay un apóstrofe en medio de una palabra, 194 bytes

<?preg_match_all("#[\w*]+(<?=')[\w*]+|[\w*]+|  |$#m",$_GET[s],$m);foreach($m[0]as$s){if(!$s||$s=="  ")echo!$s?". ":" ";else{$l=$p+64+strlen($s);if(!$p=strstr($s,"*")?20-$l%2*10:0)echo chr($l);}}
Jörg Hülsermann
fuente
@DLosc Fue urlencoded %0A como una función rawurlencode("\n"). Prefiero en este caso un formulario con un área de texto para la entrada, por lo que mi sitio html hace que codifique automáticamente la cadena
Jörg Hülsermann
@DLosc Sospecho que error_reporting en php.ini está activado. intente 'error_reporting (0);' despues del <?. Un error le pertenece $_GET[s], pero funciona correctamente $_GET["s"]y es mejor declarar e inicializar la variable $p=0;antes del ciclo. Ahora mi pregunta es: ¿Puedo suponer que en una Palabra hay un solo Apóstrofe en el medio de la Palabra?
Jörg Hülsermann
@DLosc para múltiples Apostrophes Debo usar mi primera respuesta. El segundo - 2 bytes funciona solo con un apótrofo en el medio si la palabra.
Jörg Hülsermann
Descubrí cuál era mi problema: mi servidor no tiene habilitadas etiquetas de apertura cortas. Cambiando a <?phptrabajado.
DLosc
@Dlosc que nunca he usado <?en la realidad. Utilizo la etiqueta corta solo en mi publicación aquí. Ahora sé que puede quedar en una página en blanco.
Jörg Hülsermann
1

PHP, 231 226 228 bytes

para comenzar

<?preg_match_all("#([\w\*']+)([^\w\*']*)#",$argv[1],$m,2);foreach($m as list(,$a,$b)){$e=strlen(strtr($a,["'"=>""]))+$d;if(!$d=strstr($a,'*')?$e%2*10:0)echo chr($e+64),strpos(".$b","
")?". ":(strpos(".$b","  ")?" ":"");}echo".";

Guardar en archivo, rund php <scriptpath> <text>. Escapar de nuevas líneas en el texto para que funcione en shell.

Titus
fuente
1
¿Puedes dar algunas instrucciones sobre cómo ejecutar esto? Parece que lee la entrada de $argv[1], pero no sé cómo funcionará ese enfoque cuando la entrada contenga nuevas líneas. Lo intenté "Neurotic Frogs *O*ught To Re*a*x In *M*ud Baths!"como argumento de línea de comandos y obtuve la IFHCHCFF.salida (así como una Undefined variable: dadvertencia).
DLosc
@DLosc: Ese aviso (no una advertencia) no debería estar allí con la configuración predeterminada. La forma más fácil es anteponer <?, guardarlo en un archivo y llamar a eso con php <filename> <string>. Puede que tenga que agregar 2 al recuento de bytes.
Tito
@Titus Si comienza <?, también puede terminar con ?>.una ganancia neta de 1. FWIW, obtengo IFHCMFF.el primer caso de prueba (usando PHP 5.5.21 de 64 bits, VC14). Usar $argncon -Ftambién puede ser una opción.
primo
Lo que quiero decir es que no veo cómo php <filename> <string>es posible cuando <string>puede contener nuevas líneas.
DLosc
@DLosc: reparó el error. Para las nuevas líneas: escapar de ellas.
Tito