Una mnemotécnica para recordar 23940

19

El sistema principal es un dispositivo mnemotécnico para convertir números en palabras para que puedan memorizarse más fácilmente.

Se basa en cómo suenan las palabras fonéticamente, pero para simplificar las cosas para el desafío, solo nos preocuparemos de cómo se deletrean las palabras. Esto significa que habrá algunas conversiones incorrectas, pero está bien.

Para convertir un número en una palabra utilizando nuestro sistema principal simplificado:

  • Reemplace cada uno 0con so z. (Algunos podrían ser sy otros podrían ser z. Lo mismo va abajo).
  • Reemplace cada uno 1con to do th.
  • Reemplace cada uno 2con n.
  • Reemplace cada uno 3con m.
  • Reemplace cada uno 4con r.
  • Reemplace cada uno 5con l.
  • Reemplace cada uno 6con jo sho ch.
  • Reemplace cada uno 7con ko co go q.
  • Reemplace cada uno 8con fo v.
  • Reemplace cada uno 9con po b.
  • Agregue las letras aehiouwxyen cualquier lugar en cualquier cantidad para hacer una palabra real en inglés, si es posible .
    La única excepción es que hno se puede insertar después de un so c.

El número en realidad puede ser cualquier cadena de los dígitos 0-9 (sin decimales, comas o signos).
La palabra solo puede contener las letras minúsculas az.

Ejemplos

El número 32debe convertirse como ?m?n?, donde ?representa cualquier cadena finita hecha de las letras aehiouwxy(una cadena del monoide libre si lo prefiere). Hay muchas maneras en que esto podría convertirse en una verdadera palabra Inglés: mane, moon, yeoman, etc.

El número 05se puede convertir como ?s?l?o ?z?l?. Algunas posibilidades son easily, hassley hazel. La palabra shawlno está permitida porque hno se puede colocar después s; se leería incorrectamente como 65.

Desafío

Escriba un programa o función que tome una cadena de los dígitos 0-9 y encuentre todas las palabras en las que podría convertirse utilizando el sistema principal simplificado mnemónico.

Su programa tiene acceso a un archivo de texto de lista de palabras que define cuáles son todas las palabras "reales" en inglés. Hay una palabra az minúscula en cada línea de este archivo, y opcionalmente puede suponer que tiene una nueva línea final. Aquí hay una lista de palabras reales que puede usar para probar. Puede suponer que este archivo de lista de palabras se llama f(o algo más largo) y se encuentra en cualquier directorio conveniente.

Para una penalización de 35 bytes (agregue 35 a su puntaje), puede suponer que la lista de palabras ya está cargada en una variable como una lista de cadenas. Esto es principalmente para idiomas que no pueden leer archivos, pero cualquier envío puede aprovecharlo.

Su programa debe generar todas las palabras en la lista de palabras a las que se puede convertir el número de entrada. Deben imprimirse en stdout (o similar), uno por línea (con una nueva línea final opcional), o pueden devolverse como una lista de cadenas si elige escribir una función. La lista de palabras no está necesariamente alfabetizada y la salida tampoco necesita serlo.

Si no hay palabras posibles, la salida (o la lista) estará vacía. La salida también está vacía si se ingresa la cadena vacía.

Tome la entrada a través de stdin, línea de comando o como argumento de cadena a una función. La lista de palabras, o su nombre de archivo, no debe ser parte de la entrada, solo la cadena de dígitos.

Solo está haciendo coincidir palabras individuales en la lista de palabras, no secuencias de palabras. La palabra noonprobablemente sería uno de los resultados 22, pero la secuencia de palabras no oneno lo sería.

Casos de prueba

Supongamos que esta es la lista de palabras:

stnmrljkfp
zthnmrlshqfb
asatanamaralajakafapa
aizxydwwwnhimouooraleshhhcavabe
zdnmrlshcvb
zdnmrlshchvb
sthnmrlchgvb
shthnmrlchgvb
bob
pop
bop
bopy
boppy

La entrada 0123456789debe dar todas las palabras largas excepto zdnmrlshchvby shthnmrlchgvb:

stnmrljkfp
zthnmrlshqfb
asatanamaralajakafapa
aizxydwwwnhimouooraleshhhcavabe
zdnmrlshcvb
sthnmrlchgvb

La entrada 99debe dar:

bob
pop
bop
bopy

(Las palabras de salida pueden estar en cualquier orden).

Puntuación

La presentación más corta en bytes gana. Tiebreaker va a la presentación publicada primero.

Sitio relacionado ingenioso : numzi.com .

Pasatiempos de Calvin
fuente
1
¿Se te ocurrió la idea de este desafío en este video ? Porque en realidad acabo de ver eso ayer. : P
Pomo de la puerta
1
@Doorknob No ese video, sino ese tipo. Hace años recibí una de sus conferencias de Grandes Cursos . Es un poco estrafalario pero hace cosas muy buenas. :)
Las aficiones de Calvin el
1
Nota para aquellos interesados ​​en usar el sistema mnemotécnico principal en la vida real: lo único que importa es el sonido , no la ortografía. Entonces, "c", aunque aparece aquí como significado 7, en realidad podría significar 0 si en la palabra se pronuncia con un sonido "s" (como en "ace" = 0). Sin embargo, estoy seguro de que el OP simplificó el desafío, ya que es mucho más difícil encontrar un diccionario con fonética completa que una simple lista de palabras. Ah, y una representación de 23940 es "números".
ErikE
@ErikE Declaro que estamos usando una versión basada en la ortografía en la segunda oración de la publicación ...
Calvin's Hobbies
Ahora veo eso, aunque lo extrañé al principio, pero todavía me parece que su explicación podría desarrollarse un poco más y se proporcionarán un ejemplo o dos.
ErikE

Respuestas:

6

Perl, 87 84

open A,f;"@ARGV"eq s/[cs]h/j/gr=~y/stnmrljkfpzdcgqvb\0-z/0-90177789/dr&&print for<A>

Toma la entrada como el parámetro de línea de comando:

$perl m.pl 23940

Se puede acortar un poco si se permitiera la lista de palabras en la entrada estándar:

$perl -lnE'INIT{$;=pop}$;eq s/[cs]h/j/gr=~y/stnmrljkfpzdcgqvba-z/0-90177789/dr&&say' 99 <f
nutki
fuente
¿Qué Asignifica en open A,f?
feersum
@feersum Un identificador de archivo utilizado más tarde para leer el archivo ( <A>).
nutki
4

Python 2, 215 208 bytes

Esta solución de Python crea una expresión regular a partir de partes indexadas por el argumento de la línea de comando, luego prueba cada palabra con esa expresión regular (bastante grande).

import re,sys
a='[sz] (d|th?) n m r l (j|sh|ch) [kcgq] [fv] [pb]'.split()
b=z='((?<![sc])h|[aeiouwxy])*'
for i in sys.argv[1]:b+=a[int(i)]+z
for d in open('f'):
 d=d.strip()
 if re.match('^'+b+'$',d):print d

Fuente original antes del minificador:

import re,sys
regexbits = '[sz] (d|th?) n m r l (j|sh|ch) [kcgq] [fv] [pb]'.split()

regex = other = '((?<![sc])h|[aeiouwxy])*'
for i in sys.argv[1] :
    regex += regexbits[int(i)] + other
print regex     # DEBUG

for word in open('f'):
    word = word.strip()
    if re.match('^'+regex+'$', word) :
        print word

Por ejemplo, la expresión regular para la prueba 99es:

^((?<![sc])h|[aeiouwxy])*[pb]((?<![sc])h|[aeiouwxy])*[pb]((?<![sc])h|[aeiouwxy])*$

El (?<![sc])hbit es un componente de "mirar detrás de la afirmación negativa" que asegura que a hno siga a soc en las partes de relleno generales.

Gracias calvin Este desafío me motivó a repasar mis habilidades oxidadas de expresiones regulares.

Caballero Lógico
fuente
b=c='((?<![sc])h|[aeiouwxy])*'ahorrará dos bytes.
matsjoyce
t|th -> th?guarda un byte
Sp3000
Puede evitar el mapa tomando int (i) directamente.
xnor
Gracias matsjoyce, Sp3000 y xnor por útiles consejos de golf. Ahora editado con sugerencias implementadas.
Logic Knight
2

Pitón 3, 170

import sys,re
t=str.maketrans('sztdnmrljkcgqfvpb','00112345677778899','aehiouwxy\n')
for s in open('f'):re.sub('sh|ch','j',s).translate(t)!=sys.argv[1] or print(s,end='')

Versión legible:

import sys, re

table = str.maketrans('sztdnmrljkcgqfvpb', '00112345677778899', 'aehiouwxy\n')

for line in open('f'):
    line = re.sub('sh|ch', 'j', line)
    if line.translate(table) == sys.argv[1]:
        print(line, end='')

El código hace uso del hecho de que thes redundante (ya que se asigna al mismo número que t, y hes un carácter de relleno).

La maketransfunción estática crea una tabla que asigna los caracteres del primer argumento a los del segundo argumento y los caracteres del tercer argumento a None(lo que dará como resultado que esos caracteres se eliminen).

El código final podría acortarse unos pocos bytes creando la tabla como argumento directo de translate.

ekhumoro
fuente
Puede guardar un par de bytes usando input () en lugar de sys.argv [1] y '[sc] h' para su expresión regular.
swstephe
@swstephe. Gracias por los comentarios, pero no creo que input()se pueda usar, porque se llama dentro de un bucle. Además, su expresión regular sugerida tiene la misma longitud que la que ya estoy usando (5 bytes).
ekhumoro
Estaba pensando en algo como "z, t = input (), str.maketrans ...", luego solo uso z en lugar de sys.argv. Bien, pensé que mi expresión regular era de 4 bytes.
swstephe
2

sed, pegar, grep, cortar - 109

sed -e 's/[sc]h/6/g;s/[aehiouwxy]//g;y/sztdnmrljkcqgfvpb/00112345677778899/' w|paste w -|grep " $1$"|cut -f1

Toma un archivo "w", convierte cada palabra en su número, vuelve a pegarla al original, grep para el número y devuelve la palabra coincidente. Tenga en cuenta que el espacio en blanco después de la cita después de grep es una pestaña, delimitador predeterminado de pegar.

Sé que Perl está muy por delante, solo quería una mejor versión de shell como ejemplo.

Ah, sí, la parte de $ 1 significa que se supone que se debe ejecutar desde un script de shell (la mayoría de los shells deberían funcionar), por lo que requiere un argumento de línea de comandos.

swstephe
fuente
Estaba pensando en convertir mi respuesta a pura sedpara evitar la apertura y la @ARGVsobrecarga de Perl , pero la falta de rangos y funciones de eliminación la y///rompe. Sorprendentemente, aunque no hay variables en las que pueda expresar la lógica directamente sed. Aquí está mi solución 92:sed -e'h;s/[sc]h/6/g;y/sztdnmrljkcqgfvpb/00112345677778899/;s/[^0-9]*//g;T;s/^$1$//;x;t;d' f
nutki
Parece funcionar, ¿por qué no hacerlo una respuesta?
swstephe
1

Bash + coreutils, 216

sed -n "$(sed 's/[aeiouwxy]//g
:l
s/\([^sc]\)h/\1/g
tl'<w|grep -nf <(eval printf '%s\\n' `sed 's/0/{s,z}/g
s/1/{t,th,d}/g
y/2345/nmrl/
s/6/{j,sh,ch}/g
s/7/{k,c,g,q}/g
s/8/{f,v}/g
s/9/{p,b}/g'<<<$1`)|sed s/:.\*/p/)" w
  • La lista de palabras en un archivo llamado w
  • El más interno sedreemplaza los dígitos con sus posibles reemplazos.
  • los eval printf usos shell expansiones abrazadera para ampliar a cabo todas las posibles sustituciones
  • El segundo seden la primera línea elimina aeiouwxyy h(cuando no está precedido por [sc]) de la lista de palabras
  • El grep imprime todas las coincidencias, con números de línea.
  • Como nos hemos despojado aeiouwxyy hde la lista de palabras, el último sedconvierte los resultados de grep (números de línea de cada coincidencia) en otra sedexpresión, que es procesada por el exterior sedpara revelar todas las palabras posibles de la lista de palabras.

Salida:

El archivo de lista de palabras se especifica como un argumento de línea de comando, seguido del número para mnemonizar:

ubuntu@ubuntu:~$ ./numzi.sh 99
bob
pop
bop
bopy
boppy
$ ./numzi.sh 0123456789
stnmrljkfp
zthnmrlshqfb
asatanamaralajakafapa
aizxydwwwnhimouooraleshhhcavabe
zdnmrlshcvb
sthnmrlchgvb
$ 
Trauma digital
fuente
@ Calvin'sHobbies Hecho.
Trauma digital
Parece que olvidó actualizar su ejemplo.
Aficiones de Calvin
-1

tr, sed, grep, xargs, sh, 77

tr 0123456789 ztnmrljkfp|sed 's/ */[aehiouwxy]*/g'|xargs sh -c 'grep -x $0 f'

Espera el número en stdin y la lista de palabras debe almacenarse en el archivo f .

No utiliza todos los reemplazos (1 siempre será z, 7 siempre será k), por lo que puede llamarse una solución perezosa, pero encuentra al menos un mnemónico para 95 números en [1-100].

pgy
fuente
3
La pregunta le pide que encuentre todas las palabras coincidentes en la lista de palabras. No puedes hacer que 1siempre sea zo 7siempre k. Esto no es válido
Aficiones de Calvin
Muy bien, eliminaré mi respuesta.
pgy