Mappatura tra parola intera e pronunciabile


10

Scopo

L'idea è di fornire il codice necessario per mappare un numero intero a 32 bit a / da una parola pronunciabile di massimo 9 caratteri. Ciò potrebbe essere utile, ad esempio, per semplificare la memorizzazione di un numero seriale o digitare un modulo.

Sono richiesti sia il metodo per tradurre un numero intero nella parola corrispondente sia per tradurre una parola nel numero intero corrispondente.

Regole

Deve esserci un mapping uno a uno tra numeri interi e parole e l'intero set di numeri interi a 32 bit (o, in altre parole, qualsiasi numero intero compreso tra 0 e 4294967295) deve essere mappabile. Sebbene, ovviamente, non tutte le parole siano significative e l'immissione di parole che non corrispondono a un numero intero può avere un comportamento non specificato.

Sei libero di decidere esattamente quale insieme di parole "pronunciabili" è significativo e come viene eseguita la mappatura, ma le parole devono almeno seguire queste regole:

  • Solo le 26 lettere di base (A ... Z) dovrebbero essere usate come caratteri. Accenti, involucri, ecc ... non devono essere utilizzati per estendere le possibili combinazioni.
  • Massimo 9 caratteri per parola.
  • due consonanti (BCDFGHJKLMNPQRSTVWXZ - 20 possibilità) non devono essere posizionate una accanto all'altra (devono essere circondate da vocali).
  • due vocali (AEIOUY - 6 possibilità) non devono essere posizionate l'una accanto all'altra (devono essere circondate da consonanti).

Nota: lo schema più semplice in cui tutte le parole sono costruite come CVCVCVCVC( Cessendo una consonante e Vuna vocale) fornisce 4147200000 combinazioni e un numero intero a 32 bit ha 4294967296 valori possibili, quindi non è sufficiente. È necessario espandere il numero di combinazioni, sia consentendo parole più brevi, sia consentendo anche le VCVCVCVCVcombinazioni.

Si applicano altre regole standard e sono vietate le scappatoie standard.

Entrate uscite

Per ogni invio, devono essere fornite due parti di codice:

  • Uno che accetta un numero intero come argomento / input e restituisce / stampa la parola corrispondente
  • Uno che accetta una parola come argomento / input e restituisce / stampa il numero intero corrispondente

In alternativa, puoi scegliere di inviare un singolo pezzo di codice che gestisce entrambe le operazioni:

  • Quando viene fornito un numero intero come input, genera la parola corrispondente
  • Quando viene fornita una stringa come input, genera l'intero corrispondente

Condizioni vincenti

Questo è un , la risposta che ha il minor numero di byte (quando si sommano entrambi i pezzi di codice, per soluzioni che optano per i pezzi di codice separati) vince.


Ci sono vincoli di spazio o di tempo? Dobbiamo adattarci a 32 GB di memoria?
John Dvorak,

@JanDvorak Bene, dovremmo essere in grado di testare il tuo programma su un computer "standard". Ma l'algoritmo dovrebbe essere semplice, cosa hai in mente che richiede una quantità così grande di memoria?
fioco

Potrei semplicemente generare tutte le possibili parole di nove lettere che corrispondono alla tua formula e quindi indicizzarle nel set o fare una ricerca binaria.
John Dvorak,

@JanDvorak Devo ammettere che non ci avevo pensato. Stavo pensando di più a soluzioni che stavano fondamentalmente facendo conversioni in base 26, con alcuni aggiustamenti per soddisfare il vincolo vocale / consonante. Ma in qualche modo dubito che il modo "brutale" che avevi in ​​mente possa essere efficiente nel code-golf. Ad ogni modo, se devo davvero chiarire questo, supponiamo che non ti sia consentito allocare più di 4 GB di memoria.
dim

Potresti richiedere ai risponditori di eseguire il loro codice per alcuni valori predeterminati (0,1,10,2 ** 32-1 e simili) e quindi tornare indietro e includere i risultati nella risposta.
John Dvorak,

Risposte:


1

JavaScript (ES6), 205 byte

p=>(a='bcdfghjklmnpqrstvwxzaeiouy',1/p)?[...Array(9)].map(_=>r=a[p%(n=26-n)+(p=p/n|0,n<7)*20]+r,n=p>(p%=4e9)?20:6,r='')&&r:[...p].map(c=>r=r*(n=26-n)+a.search(c)%20,n=a.search(p[r=0])<20?6:20)&&r+(n<7)*4e9

Il punto di taglio tra CVCVCVCVC e VCVCVCVCV è 4e9, quindi inizia a non funzionare a 5244160000 (input numerico) o zesuwurib(input stringa).


Sei mesi dopo ... ti conferisco i punti di accettazione, poiché sei il più breve (e non posso accettare la risposta di rturnbull, che non soddisfa il chiarimento che ho fatto nei commenti).
dim

2

PHP, 353 byte

Codifica + decodifica

is_numeric($argn)contiene il booleano. È vero se l'input è un numero intero.

$c=array_diff(range(A,Z),$v=[A,E,I,O,U,Y]);sort($c);if(is_numeric($a=$argn)){$r=($a)%26<6?$v[$a%26]:$c[$a%26-6];$a=$a/26^0;while($a){$z=count($t=in_array($r[0],$v)?$c:$v);$r=$t[$n=$a%$z].$r;$a=$a/$z^0;}echo$r;}else{for($p=1;$i++<strlen($a);){$u=($b=in_array($a[-$i],$c))?$c:$v;$s+=array_flip($u)[$a[-$i]]*$p+($b&$i<2?6:0);$p*=$i>1?count($u):26;}echo$s;}

PHP, 190 byte (codifica) + 195 byte (decodifica) = 385 byte

Codifica

$c=array_diff(range(A,Z),$v=[A,E,I,O,U,Y]);sort($c);$r=($a=$argn)%26<6?$v[$a%26]:$c[$a%26-6];$a=$a/26^0;while($a){$z=count($t=in_array($r[0],$v)?$c:$v);$r=$t[$n=$a%$z].$r;$a=$a/$z^0;}echo$r;

5391360000 = 26 * 120 ** Sono disponibili 4 combinazioni

Codifica versione online senza E_NOTICE

allargato

$c=array_diff(range(A,Z),$v=[A,E,I,O,U,Y]);
sort($c); # End of Prepare the two array
$r=($a=$argn)%26<6?$v[$a%26]:$c[$a%26-6]; #base 26 decision input mod 26 <6 end with vowel
$a=$a/26^0; #integer division input with 26
while($a){
    $z=count($t=in_array($r[0],$v)?$c:$v); # use vowel if last entry is consonant and viceversa
    $r=$t[$n=$a%$z].$r; # base 6 or base 20 decision
    $a=$a/$z^0; # divide through base
}echo$r; # Output result

Input => Output

4294967296 => TYPYQACOV 
333 => DAT 
1 => E 
7 => C 
4294967276 => UTOPOQAMI

Se hai bisogno sempre del risultato di 9 byte, sostituiscilo while($a)con while(strlen($r)<9)+ 10 byte

decodifica

$c=array_diff(range(A,Z),$v=[A,E,I,O,U,Y]);sort($c);for($p=1;$i++<strlen($a=$argn);){$u=($b=in_array($a[-$i],$c))?$c:$v;$s+=array_flip($u)[$a[-$i]]*$p+($b&$i<2?6:0);$p*=$i>1?count($u):26;}echo$s;

allargato

$c=array_diff(range("A","Z"),$v=["A","E","I","O","U","Y"]);
sort($c); # End of Prepare the two array
for($p=1;$i++<strlen($a=$argn);){ 
    $u=($b=in_array($a[-$i],$c))?$c:$v; # find use array for $a[-$i]
    $s+=array_flip($u)[$a[-$i]]*$p+($b&$i<2?6:0); # sum value
    $p*=$i>1?count($u):26; # raise multiple for next item
}echo$s;

Input => Output

ABABABABE => 1
E => 1
UTOPOQAMI => 4294967276
BABABADAT => 333
DAT => 333
TYPYQACOV => 4294967296

Decodifica della versione online senza E_NOTICE

Controllo aggiuntivo

Se abbiamo bisogno di un controllo se una stringa è valida.

Aggiungi $x.=$b?:0;alla fine del ciclo di decodifica + 10 byte

Sostituire echo$s;con echo!preg_match('#([01])\1$#',$x)?$s:_;+ 32 byte


1

R, 165 byte

Codifica e decodifica in un'unica funzione.

Questa funzione utilizza il metodo della forza bruta per creare tutti i possibili valori e quindi semplicemente restituire l'indice quando viene fornito l'input della stringa e restituire la stringa quando viene fornito l'input intero. Di conseguenza, è molto lento e utilizza 16 GB + di memoria!

function(x){i=c(1,5,9,15,21,25)
d=apply(expand.grid(c<-letters[-i],v<-letters[i],c,v,c,v,c,v,c(c,"")),1,paste,collapse="")
`if`(mode(x)=="numeric",d[x],which(d==x))}

4.354.560.000 valori sono possibili. Questo copre tutte le stringhe del modulo CVCVCVCV (C), con l'ultima C facoltativa.


@ mbomb007 Gigabytes, scusa per l'errore di battitura. La funzione esegue sia la codifica che la decodifica a seconda che l'argomento sia una stringa o un numero intero. Ho aggiornato il post per chiarirlo.
rturnbull,

Il downvoter può lasciare un commento per suggerire un miglioramento? Grazie.
rturnbull,

1
Nei commenti della domanda, dim chiarisce che non è possibile utilizzare più di 4 GB di memoria ....
Socratic Phoenix
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.