Um mnemônico para lembrar 23940

19

O sistema principal é um dispositivo mnemônico para converter números em palavras, para que possam ser memorizados mais facilmente.

É baseado em como as palavras soam foneticamente, mas para simplificar as coisas para o desafio, apenas nos preocuparemos com a forma como as palavras são escritas. Isso significa que haverá algumas conversões incorretas, mas tudo bem.

Para converter um número em uma palavra usando nosso sistema principal simplificado:

  • Substitua cada um 0por sou z. (Alguns poderiam ser se outros poderiam ser z. O mesmo se aplica a seguir.)
  • Substitua cada um 1por tou dou th.
  • Substitua cada um 2por n.
  • Substitua cada um 3por m.
  • Substitua cada um 4por r.
  • Substitua cada um 5por l.
  • Substitua cada um 6por jou shou ch.
  • Substitua cada um 7por kou cou gou q.
  • Substitua cada um 8por fou v.
  • Substitua cada um 9por pou b.
  • Adicione as letras aehiouwxyem qualquer lugar, em qualquer quantidade, para formar uma palavra em inglês real, se possível .
    A única exceção é que hnão pode ser inserido após um sou c.

Na verdade, o número pode ser qualquer sequência de dígitos de 0 a 9 (sem decimais, vírgulas ou sinais).
A palavra pode conter apenas as letras minúsculas az.

Exemplos

O número 32deve ser convertido como ?m?n?, onde ?representa qualquer sequência finita feita a partir das letras aehiouwxy(uma sequência do monóide livre, se você preferir). Há muitas maneiras isso pode ser feito em uma palavra Inglês real: mane, moon, yeoman, etc.

O número 05pode ser convertido como ?s?l?ou ?z?l?. Algumas possibilidades são easily, hasslee hazel. A palavra shawlnão é permitida porque hnão pode ser colocada depois s; seria incorretamente lido como 65.

Desafio

Escreva um programa ou função que utilize uma sequência de dígitos de 0 a 9 e encontre todas as palavras nas quais ele pode ser convertido usando o mnemônico simplificado do sistema principal.

Seu programa tem acesso a um arquivo de texto da lista de palavras que define quais são todas as palavras "reais" em inglês. Há uma palavra az em minúscula em cada linha deste arquivo e, opcionalmente, você pode assumir que ela possui uma nova linha à direita. Aqui está uma lista de palavras reais que você pode usar para testar. Você pode assumir que esse arquivo de lista de palavras é chamado f(ou algo mais) e fica em qualquer diretório conveniente.

Para uma penalidade de 35 bytes (adicione 35 à sua pontuação), você pode assumir que a lista de palavras já está carregada em uma variável como uma lista de cadeias. Isso é principalmente para idiomas que não conseguem ler arquivos, mas qualquer envio pode tirar proveito dele.

Seu programa deve exibir todas as palavras da lista de palavras nas quais o número de entrada pode ser convertido. Eles devem ser impressos em stdout (ou similar), um por linha (com uma nova linha à direita opcional) ou podem ser retornados como uma lista de cadeias, se você optar por escrever uma função. A lista de palavras não é necessariamente alfabetizada e a saída também não precisa ser.

Se não houver palavras possíveis, a saída (ou a lista) estará vazia. A saída também está vazia se a sequência vazia for inserida.

Aceite a entrada via stdin, linha de comando ou como um argumento de string para uma função. A lista de palavras ou o nome do arquivo não deve fazer parte da entrada, apenas a sequência de dígitos.

Você está correspondendo apenas palavras únicas na lista de palavras, não seqüências de palavras. A palavra noonprovavelmente seria um dos resultados para 22, mas a sequência de palavras no onenão.

Casos de teste

Suponha que esta seja a lista de palavras:

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

A entrada 0123456789deve conter todas as palavras longas, exceto zdnmrlshchvbe shthnmrlchgvb:

stnmrljkfp
zthnmrlshqfb
asatanamaralajakafapa
aizxydwwwnhimouooraleshhhcavabe
zdnmrlshcvb
sthnmrlchgvb

A entrada 99deve fornecer:

bob
pop
bop
bopy

(As palavras de saída podem estar em qualquer ordem.)

Pontuação

O menor envio em bytes vence. O desempatador vai para a submissão postada primeiro.

Site bacana : numzi.com .

Passatempos de Calvin
fonte
11
Você teve a idéia deste desafio neste vídeo ? Porque eu realmente apenas observava que ontem. : P
Maçaneta da porta
11
@ Doorknob Não é esse vídeo, mas esse cara. Anos atrás, recebi uma de suas palestras sobre Grandes Cursos . Ele é meio doido, mas faz coisas realmente legais. :)
Hobbies de Calvin
11
Nota para os interessados ​​em usar o sistema principal mnemônico na vida real: é apenas o som que importa, não a ortografia. Portanto, "c", embora listado aqui como significando 7, pode realmente significar 0 se na palavra for pronunciado com um som "s" (como em "ace" = 0). No entanto, tenho certeza de que o OP simplificou o desafio, pois um dicionário com fonética completa é muito mais difícil de encontrar do que uma simples lista de palavras. Ah, e uma renderização de 23940 é "números".
ErikE 23/02
@ErikE I estado que estamos usando uma versão baseada ortografia na segunda frase do post ...
Calvin Passatempos
Vejo isso agora, embora tenha sentido falta dela a princípio - mas ainda me parece que sua explicação poderia ser aprofundada um pouco mais e um ou dois exemplos.
ErikE 24/02

Respostas:

6

Perl, 87 84

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

Recebe entrada como o parâmetro da linha de comandos:

$perl m.pl 23940

Pode ser um pouco menor se a lista de palavras for permitida na entrada padrão:

$perl -lnE'INIT{$;=pop}$;eq s/[cs]h/j/gr=~y/stnmrljkfpzdcgqvba-z/0-90177789/dr&&say' 99 <f
nutki
fonte
O que Asignifica open A,f?
23615 feersum
@feersum Um identificador de arquivo usado posteriormente para ler o arquivo ( <A>).
nutki
4

Python 2, 215 208 bytes

Essa solução Python cria um regex a partir de partes indexadas pelo argumento da linha de comando e testa cada palavra com esse regex (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

Fonte original antes do 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 exemplo, a regex para o teste 99é:

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

O (?<![sc])hbit é um componente "veja por trás da afirmação negativa" que garante que a hnão siga uma sou cnas partes gerais de preenchimento.

Obrigado Calvin. Esse desafio me motivou a aprimorar minhas habilidades de regex enferrujadas.

Cavaleiro Lógico
fonte
b=c='((?<![sc])h|[aeiouwxy])*'irá salvar dois bytes.
matsjoyce
t|th -> th?salva um byte
Sp3000 23/02
Você pode evitar o mapa usando int (i) diretamente.
Xnor
Agradecemos a matsjoyce, Sp3000 e xnor pelas dicas úteis sobre golfe. Agora editado com sugestões implementadas.
Logic Knight
2

Python 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='')

Versão legível:

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='')

O código utiliza o fato de thser redundante (já que mapeia para o mesmo número que te hé um caractere de preenchimento).

A maketransfunção estática cria uma tabela mapeando os caracteres do primeiro argumento para os do segundo argumento e os caracteres do terceiro argumento para None(o que resultará na exclusão desses caracteres).

O código final pode ser reduzido em alguns bytes criando a tabela como argumento direto de translate.

ekhumoro
fonte
Você pode salvar alguns bytes usando input () em vez de sys.argv [1] e '[sc] h' para sua expressão regular.
swstephe
@swstephe. Obrigado pelo feedback, mas acho que não input()pode ser usado, porque é chamado dentro de um loop. Além disso, seu regex sugerido tem o mesmo tamanho que eu já estou usando (5 bytes).
ekhumoro
Eu estava pensando em algo como "z, t = input (), str.maketrans ...", em seguida, basta usar z em vez de sys.argv. Ok, eu pensei que meu regex era de 4 bytes.
28515 swswphe
2

sed, colar, grep, cortar - 109

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

Pega um arquivo "w", converte cada palavra em seu número, cola novamente no original, grep pelo número e retorna a palavra correspondente. Observe que o espaço em branco após a citação após grep é uma guia, o delimitador padrão da pasta.

Eu sei que Perl está muito à frente, só queria uma versão melhor do shell como exemplo.

Ah, sim, a parte $ 1 significa que isso deve ser executado a partir de um script de shell (a maioria dos shells deve funcionar), portanto é necessário um argumento na linha de comando.

swstephe
fonte
Eu estava pensando em converter minha resposta em pura sedpara evitar a @ARGVsobrecarga e a sobrecarga de Perl , mas a falta de intervalos e as funções de exclusão a y///quebram. Surpreendentemente, embora não haja variáveis ​​em que você possa expressar a própria lógica diretamente sed. Aqui está a minha solução 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 que não fazer disso uma resposta?
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
  • A lista de palavras em um arquivo chamado w
  • O mais interno sedsubstitui dígitos por suas possíveis substituições
  • Os eval printfusos desembolsar expansões cinta para expandir todas as substituições possíveis
  • O segundo sedna 1ª linha remove aeiouwxye h(quando não é precedido por [sc]) da lista de palavras
  • O grep imprime todas as correspondências, com números de linha
  • Como removemos aeiouwxye hremovemos da lista de palavras, o último sedtransforma os resultados de grep (números de linha de cada correspondência) em outra sedexpressão, que é processada pela parte externa sedpara revelar todas as palavras possíveis da lista de palavras.

Resultado:

O arquivo da lista de palavras é especificado como um argumento da linha de comandos, seguido pelo número para mnemonicizar:

ubuntu@ubuntu:~$ ./numzi.sh 99
bob
pop
bop
bopy
boppy
$ ./numzi.sh 0123456789
stnmrljkfp
zthnmrlshqfb
asatanamaralajakafapa
aizxydwwwnhimouooraleshhhcavabe
zdnmrlshcvb
sthnmrlchgvb
$ 
Trauma Digital
fonte
@ Calvin'sHobbies Feito.
Digital Trauma
Parece que você esqueceu de atualizar seu exemplo.
Hobbies de Calvin
-1

tr, sed, grep, xargs, sh, 77

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

Espera o número em stdin e a lista de palavras deve ser armazenada no arquivo f.

Não usa todas as substituições (1 sempre será z, 7 sempre será k); portanto, pode ser chamada de solução lenta, mas encontra pelo menos um mnemônico para 95 números em [1-100].

pgy
fonte
3
A pergunta pede que você encontre todas as palavras correspondentes na lista de palavras. Você não pode fazer 1sempre ser zou 7sempre k. Isso é inválido.
Hobbies de Calvin
É justo, vou remover minha resposta.
26615 pgy