Un mnemonico per ricordare 23940


19

Il sistema principale è un dispositivo mnemonico per convertire i numeri in parole in modo che possano essere memorizzati più facilmente.

Si basa sul modo in cui le parole suonano foneticamente, ma per rendere le cose semplici per la sfida, ci occuperemo solo di come vengono scritte le parole. Ciò significa che ci saranno alcune conversioni errate, ma va bene.

Per convertire un numero in una parola usando il nostro sistema principale semplificato:

  • Sostituisci ciascuno 0con so z. (Alcuni potrebbero essere se alcuni potrebbero essere z. Lo stesso vale sotto.)
  • Sostituisci ciascuno 1con to do th.
  • Sostituisci ciascuno 2con n.
  • Sostituisci ciascuno 3con m.
  • Sostituisci ciascuno 4con r.
  • Sostituisci ciascuno 5con l.
  • Sostituisci ciascuno 6con jo sho ch.
  • Sostituisci ciascuno 7con ko co go q.
  • Sostituisci ciascuno 8con fo v.
  • Sostituisci ciascuno 9con po b.
  • Aggiungi le lettere aehiouwxyovunque in qualsiasi importo per creare una vera parola inglese, se possibile .
    L'unica eccezione è che hnon può essere inserito dopo un so c.

Il numero può effettivamente essere qualsiasi stringa delle cifre 0-9 (senza decimali o virgole o segni).
La parola può contenere solo le lettere minuscole az.

Esempi

Il numero 32deve essere convertito come ?m?n?, dove ?rappresenta qualsiasi stringa finita creata dalle lettere aehiouwxy(una stringa dal monoide libero se preferisci). Ci sono molti modi in cui questo potrebbe essere trasformato in una vera e propria parola inglese: mane, moon, yeoman, etc.

Il numero 05può essere convertito come ?s?l?o ?z?l?. Alcune possibilità sono easily, hasslee hazel. La parola shawlnon è consentita perché hnon può essere inserita dopo s; sarebbe erroneamente letto come 65.

Sfida

Scrivi un programma o una funzione che accetta una stringa di cifre 0-9 e trova tutte le parole in cui potrebbe essere convertito usando il sistema principale semplificato mnemonico.

Il tuo programma ha accesso a un file di testo dell'elenco di parole che definisce quali sono tutte le "vere" parole inglesi. Esiste una parola az minuscola su ciascuna riga di questo file e puoi facoltativamente supporre che abbia una nuova riga finale. Ecco un elenco di parole reali che puoi utilizzare per i test. Puoi presumere che questo file dell'elenco di parole sia chiamato f(o qualcosa di più) e si trovi in ​​qualsiasi directory conveniente.

Per una penalità di 35 byte (aggiungi 35 al tuo punteggio) puoi presumere che l'elenco di parole sia già caricato in una variabile come un elenco di stringhe. Questo è principalmente per le lingue che non possono leggere i file, ma qualsiasi invio può trarne vantaggio.

Il programma deve generare tutte le parole nell'elenco di parole in cui è possibile convertire il numero di input. Dovrebbero essere stampati su stdout (o simili), uno per riga (con una nuova riga finale facoltativa), oppure possono essere restituiti come un elenco di stringhe se si sceglie di scrivere una funzione. L'elenco di parole non è necessariamente in ordine alfabetico e neanche l'output deve essere.

Se non ci sono parole possibili, l'output (o l'elenco) sarà vuoto. L'output è anche vuoto se viene immessa la stringa vuota.

Accetta input tramite stdin, riga di comando o come argomento stringa in una funzione. L'elenco di parole o il nome del suo file non devono far parte dell'input, ma solo la stringa di cifre.

Stai abbinando solo singole parole nell'elenco delle parole, non sequenze di parole. La parola noonsarebbe probabilmente uno dei risultati per 22, ma la sequenza di parole no oneno.

Casi test

Supponiamo che questo sia l'elenco delle parole:

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

L'input 0123456789dovrebbe dare tutte le parole lunghe tranne zdnmrlshchvbe shthnmrlchgvb:

stnmrljkfp
zthnmrlshqfb
asatanamaralajakafapa
aizxydwwwnhimouooraleshhhcavabe
zdnmrlshcvb
sthnmrlchgvb

L'input 99dovrebbe dare:

bob
pop
bop
bopy

(Le parole in uscita possono essere in qualsiasi ordine.)

punteggio

Vince l' invio più breve in byte . Tiebreaker va alla presentazione pubblicata per prima.

Nifty sito correlato: numzi.com .


1
Ti è capitato di prendere l'idea di questa sfida da questo video ? Perché in realtà l'ho appena visto ieri. : P
Maniglia della porta

1
@Doorknob Non quel video, ma quel ragazzo. Anni fa mi è stata impartita una delle sue lezioni sui Grandi Corsi . È un po 'eccentrico ma fa cose davvero ordinate. :)
Calvin's Hobbies,

1
Nota per chi è interessato all'utilizzo del sistema principale mnemonico nella vita reale: è solo il suono che conta, non l'ortografia. Quindi "c", sebbene elencato qui come significato 7, potrebbe effettivamente significare 0 se nella parola è pronunciato con un suono "s" (come in "ace" = 0). Tuttavia, sono sicuro che l'OP ha semplificato la sfida, poiché un dizionario con fonetica completa è molto più difficile da trovare rispetto a un semplice elenco di parole. Oh, e un rendering di 23940 è "numeri".
ErikE,

@ErikE Dichiaro che stiamo usando una versione basata sull'ortografia nella seconda frase del post ...
Calvin's Hobbies

Lo vedo ora, anche se all'inizio mi mancava - ma mi sembra ancora che la tua spiegazione potrebbe essere ulteriormente arricchita e ne forniamo un esempio o due.
ErikE,

Risposte:


6

Perl, 87 84

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

Accetta input come parametro della riga di comando:

$perl m.pl 23940

Può essere un po 'più breve se l'elenco di parole fosse consentito sull'input standard:

$perl -lnE'INIT{$;=pop}$;eq s/[cs]h/j/gr=~y/stnmrljkfpzdcgqvba-z/0-90177789/dr&&say' 99 <f

Cosa Asignifica in open A,f?
feersum

@feersum Un handle di file utilizzato in seguito per leggere il file ( <A>).
Nutki,

4

Python 2, 215 208 byte

Questa soluzione Python crea una regex dalle parti indicizzate dall'argomento della riga di comando, quindi verifica ogni parola con quella (piuttosto grande) regex.

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 originale prima del minificatore:

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

Ad esempio, la regex per il test 99è:

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

Il (?<![sc])hbit è un componente "cerca dietro un'asserzione negativa" che assicura hche a non segua una so cnelle parti di riempimento generali.

Grazie Calvin. Questa sfida mi ha motivato a rispolverare le mie abilità di regex arrugginite.


b=c='((?<![sc])h|[aeiouwxy])*'salverà due byte.
matsjoyce,

t|th -> th?salva un byte
Sp3000,

Puoi evitare la mappa prendendo direttamente int (i).
xnor

Grazie matsjoyce, Sp3000 e xnor per utili suggerimenti sul golf. Ora modificato con suggerimenti implementati.
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='')

Versione leggibile:

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

Il codice utilizza il fatto che thè ridondante (poiché si associa allo stesso numero di ted hè un carattere di riempimento).

La maketransfunzione statica crea una tabella che associa i caratteri del primo argomento a quelli del secondo argomento e i caratteri del terzo argomento su None(il che comporterà l'eliminazione di tali caratteri).

Il codice finale potrebbe essere ridotto di alcuni byte creando la tabella come argomento diretto di translate.


Puoi salvare un paio di byte usando input () invece di sys.argv [1] e '[sc] h' per la tua espressione regolare.
swstephe

@swstephe. Grazie per il feedback, ma non credo che input()possa essere utilizzato, perché viene chiamato all'interno di un ciclo. Inoltre, il regex suggerito ha la stessa lunghezza di quello che sto già utilizzando (5 byte).
ekhumoro,

Stavo pensando a qualcosa come "z, t = input (), str.maketrans ...", quindi usa solo z invece di sys.argv. Ok, pensavo che il mio regex fosse di 4 byte.
swstephe

2

sed, paste, grep, cut - 109

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

Prende un file "w", converte ogni parola nel suo numero, ritorna all'originale, grep per il numero e restituisce la parola corrispondente. Si noti che lo spazio dopo la citazione dopo grep è una scheda, delimitatore predefinito incolla.

So che Perl è molto avanti, volevo solo una versione migliore della shell come esempio.

Oh sì, la parte $ 1 significa che questo dovrebbe essere eseguito da uno script di shell (la maggior parte delle shell dovrebbe funzionare), quindi prende un argomento da riga di comando.


Stavo pensando di convertire la mia risposta in puro sedper evitare l'apertura e il @ARGVsovraccarico di Perl , ma la mancanza di intervalli e le funzioni di eliminazione y///lo spezzano. Sorprendentemente, anche se non ci sono variabili, puoi esprimere direttamente la logica stessa sed. Ecco la mia soluzione 92:sed -e'h;s/[sc]h/6/g;y/sztdnmrljkcqgfvpb/00112345677778899/;s/[^0-9]*//g;T;s/^$1$//;x;t;d' f
nutki,

Sembra funzionare, perché non renderlo una risposta?
venerdì

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
  • L'elenco di parole in un file chiamato w
  • Il più interno sedsostituisce le cifre con le loro possibili sostituzioni
  • Gli eval printfusi shell espansioni gancio per espandere tutte le possibili sostituzioni
  • Il secondo sedsulla prima riga rimuove aeiouwxye h(quando non è preceduto da [sc]) dall'elenco delle parole
  • Il grep stampa tutte le partite, con i numeri di riga
  • Dato che abbiamo eliminato aeiouwxye hdall'elenco di parole, l'ultimo sedtrasforma i risultati di grep (numeri di riga di ogni corrispondenza) in un'altra sedespressione, che viene elaborata seddall'esterno per rivelare tutte le possibili parole dall'elenco di parole.

Produzione:

Il file dell'elenco di parole viene specificato come arg della riga di comando, seguito dal numero da mnemonicizzare:

ubuntu@ubuntu:~$ ./numzi.sh 99
bob
pop
bop
bopy
boppy
$ ./numzi.sh 0123456789
stnmrljkfp
zthnmrlshqfb
asatanamaralajakafapa
aizxydwwwnhimouooraleshhhcavabe
zdnmrlshcvb
sthnmrlchgvb
$ 

@ Calvin'sHobbies Done.
Trauma digitale

Sembra che ti sei dimenticato di aggiornare il tuo esempio.
Calvin's Hobbies,

-1

tr, sed, grep, xargs, sh, 77

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

Si aspetta il numero in stdin e l'elenco di parole dovrebbe essere memorizzato nel file f.

Non usa tutti i rimpiazzi (1 sarà sempre z, 7 sarà sempre k), quindi può essere chiamato una soluzione pigra, ma trova almeno un mnemonico per 95 numeri in [1-100].


3
La domanda ti chiede di trovare tutte le parole corrispondenti nell'elenco delle parole. Non puoi 1essere sempre zo 7sempre k. Questo non è valido.
Calvin's Hobbies,

Abbastanza giusto, rimuoverò la mia risposta.
Pgy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.