¡Codificador ASCII dinámico!

16

Introducción

Algunos caracteres ASCII son tan caros en estos días ...

Para ahorrar dinero, ha decidido escribir un programa que codifique caracteres costosos utilizando caracteres económicos.

Sin embargo, los precios de los personajes cambian con frecuencia y no desea modificar su programa cada vez que necesita codificar o decodificar un personaje diferente. Necesitará una solución más dinámica.

Desafío

Su tarea es escribir dos programas: un codificador y un decodificador .

El codificador debe aceptar una lista de cinco caracteres económicos y un solo carácter costoso.

Debería generar una única cadena compuesta por los caracteres económicos, que codifica el carácter costoso.

Esta cadena no puede tener más de 4 caracteres para permanecer económica. Sin embargo, no tiene que usar todos los caracteres económicos en la codificación y las codificaciones pueden tener diferentes longitudes.


El decodificador debe aceptar la cadena producida por el codificador y generar el carácter costoso.

El decodificador no aceptará ninguna entrada que no sea la cadena codificada. Debe funcionar, sin modificar, desde la salida del codificador para cualquier combinación (válida) de entradas. En otras palabras, su programa de decodificador no sabe qué caracteres son caros o baratos.

Puntuación

¡El código combinado más corto gana!

Notas

  • Todos los caracteres serán letras mayúsculas [A-Z], minúsculas [a-z]o números [0-9].

  • La lista de caracteres económicos no contendrá duplicados. Ningún personaje será económico y costoso.

  • El codificador y el decodificador no tienen que estar escritos en el mismo idioma, pero pueden estarlo. Puedes escribir un programa o una función.

  • La entrada y salida pueden estar en cualquier formato razonable para su idioma.

  • Los dos programas pueden no compartir ninguna variable o información.

Resumen

  • La entrada de algunos caracteres económicos y un carácter costoso se da al codificador.

  • El codificador genera una cadena de caracteres económicos que codifica el carácter costoso.

  • El decodificador recibe la salida del codificador y genera el carácter costoso.

Ejemplos

Entrada:     a, b, c, d, e     f

Posibilidades de codificador:     a     eeee     caec

Descifrador:     f


Entrada:     a, b, c, d, e     h

Posibilidades de codificador:     bc     cea     eeaa

Descifrador:     h


Entrada:     q, P, G, 7, C     f

Posibilidades de codificador:     777     P7     PPCG

Descifrador:     f

jrich
fuente
Esto realmente podría ser yo, y me disculpo por esta pregunta si es así, pero ¿cómo exactamente se supone que codifiques tu mensaje con los caracteres económicos? ¿Adición de los códigos ASCII para los 5 caracteres económicos? En realidad, esta pregunta solo tiene una base si su decodificador debe decodificar para todas las posibilidades de codificación generadas.
cole
Para ser claros: las posibilidades del codificador son solo ejemplos y podemos codificar cada carácter como queramos, ¿sí?
Dennis
@ Dennis Sí, esos son solo ejemplos.
jrich
@Cole Sin regalar un algoritmo real , ya que ese es el principal desafío aquí, creo que es posible. Solo hay 62 posibles letras caras para codificar, y con estos 4 caracteres ascii se pueden codificar hasta 92, de acuerdo con A239914 . (Muchísimas gracias al comentario de sandbox de PhiNotPi para este, no
calculé
@UnfinedFunction Ahora me doy cuenta de lo que has querido: la pregunta de Dennis respondió sobre lo que estaba confundido.
cole

Respuestas:

5

Pyth, 46 bytes

Codificador, 22 bytes

@smfql{Td^<Szd4S4-Cw48

Decodificador, 24 bytes

C+48xsmfql{Td^<sS{zd4S4z
orlp
fuente
Wow, eso encaja perfectamente. 75 combinaciones diferentes de caracteres y un rango de caracteres de 75.
Jakube
Creo que se puede sustituir S4con Ty guardar cada uno de bytes en ambos programas.
Jakube
7

CJam, 55 50 48 47 bytes

Codificador, 24 22 21 bytes

l$:L4m*{$L|L=},rc'0-=

Pruébalo en línea.

Decodificador, 31 28 27 26 bytes

4_m*{$4,|4,=},l_$_|f#a#'0+

Pruébalo en línea.

Dennis
fuente
¿Hay una hoja de sintaxis de CJam que usa? El que está en sourceforge y esa otra hoja de trucos en pdf no contienen todos los caracteres que usas como'
Luminous
'No es un operador. Puede encontrarlo en la página de sintaxis .
Dennis
4

gawk, 163 + 165 = 328

Probado con gawk 4.1.1, pero también debería funcionar en versiones anteriores de gawk. Necesita ser ligeramente modificado (alargado) para trabajar con mawk.

codificador (163):

{for(gsub(", ",_);sprintf("%c",++r)!=$NF;asort(a))split($1,a,_);r-=r>64?53:46;for(k=4^5;r-=_~i;j=_)for(i=++k;gsub(++j,_,i);)split(k,b,_);for(j in b)printf a[b[j]]}

decodificador (165):

{split($1,a,_);for(i in a)d[a[i]]=a[i];asort(d);for(k=4^5;c!~$1;x+=_~i){i=++k;for(c=j=_;gsub(++j,_,i);split(k,b,_));for(g in b)c=c d[b[g]]}printf"%c",x+(x>10?54:47)}

Bueno, funciona, pero soy consciente de que este podría no ser el mejor enfoque para esto. No tengo idea de para qué sirve la quinta carta barata, porque uso solo cuatro.

Estos son de un solo uso. Si desea ingresar un segundo código, debe reiniciarlos. Los espacios después de las comas se requieren en la entrada para codificar.

Lo que pensé

Mi primera pregunta fue "¿Qué podría obtener un decodificador de estos 4 caracteres?" (Los llamaré a, b, cyd), y mi idea inicial era obtener 6 bits de información de las siguientes relaciones:

a>b
a>c
a>d
b>c
b>d
c>d

¡Guau, 6 bits, eso es perfecto! Pensé que era genial, pero las pruebas mostraron que esto no funcionaría. Solo hay 24 combinaciones posibles. Maldición.

El siguiente paso fue tratar de contar, basado en lo que ya sabía. Entonces, la primera letra que aparece en la cadena se convertiría en 0, luego la segunda letra introducida en la cadena se convertiría en 1 y así sucesivamente. Pero no me llevaría a las 62 combinaciones necesarias.

0000
0001
0010
0011
0012
0100
0101
0102
0110
0111
0112
0120
0121
0122
0123

Pero de todos modos me gusta la idea.

Bueno, entonces me di cuenta de que podía combinar estos dos, porque los caracteres en la entrada ya tienen relaciones, y no tendría que esperar hasta que se introdujeran para darles un valor.

Cómo funciona

Nota: Esto ya no es exactamente cómo funcionan las versiones de golf, pero el principio se mantuvo igual.

Para el decodificador:

Se construye una matriz, cuyo índice contiene todos los números de cuatro dígitos cuyo dígito más grande no es mayor que el número de dígitos distintos en ese número. Hay 75 números diferentes de cuatro dígitos que cumplen esa condición. Los forcé, porque hasta ahora no pude encontrar una manera de construirlos, y no estoy seguro de que esto sea más corto de todos modos. Mientras los encuentro, les asigno los caracteres caros en orden asciibético.

Luego reemplazo todos los caracteres de la cadena de entrada con un dígito. El más pequeño (por ejemplo, 'B' más pequeño que 'a') se convierte en 1, el segundo más pequeño se convierte en 2, y así sucesivamente hasta 4. Por supuesto, depende de cuántos caracteres diferentes hay en la entrada, cuál es el dígito más alto en la cadena resultante será.

Luego simplemente imprimo el elemento de matriz, que tiene esa cadena como índice.

El codificador funciona en consecuencia.

Cómo utilizar

Copie el código directamente en un comando de línea de bash awk o haga dos archivos "encode.awk" y "decode.awk" y pegue el código en consecuencia. O incluso mejor use el siguiente código, que sale automáticamente después de en / decodificación, o puede usarse varias veces eliminando el comando de salida al final.

encode.awk

{
    if(!x) # only do first time
        for(i=1e3;i++<5e3;delete a)
        {
            for(m=j=0;p=substr(i,++j,1);p>m?m=p:0)++a[p];
            length(a)>=m&&i!~0?c[(x>9?55:48)+x++]=i:_
        }
    r=u=_; # clear reused variables 
    for(gsub(",",FS);sprintf("%c",++r)!=$NF;); # more flexible concerning
    --NF;                                      # spaces in input
    split($0,b);
    asort(b);
    split(c[r],a,_);
    for(j in a)u=u b[a[j]]; # prettier printing than golfed version
    print u
    exit # <=== remove to encode input file
}

decode.awk

{
    if(!x) # only do first time 
        for(i=1e3;i++<5e3;delete a)
        {
            for(m=j=0;p=substr(i,++j,1);p>m?m=p:_)++a[p];
            length(a)>=m&&i!~0?c[i]=sprintf("%c",(x>9?55:48)+x++):_
        }
    delete t; delete d; o=_; # clear reused variables 
    split($1,a,_);
    for(i in a)t[a[i]]=1;
    for(i in t)d[++y]=i;
    asort(d);
    for(i in a)for(j in d)if(d[j]~a[i])o=o j;
    print c[o]
    exit # <=== remove to encode input file
}

Aquí hay un ejemplo de uso:

me@home:~/$ awk -f encode.awk
w, 0, R, 1, d X
10R1
me@home:~/$ awk -f decode.awk
10R1
X

Recuerde que se requiere el espacio después de cada coma, si utiliza las versiones de golf.

Si lo desea, puede usar este script corto y sucio para generar algunos datos de muestra

BEGIN{
    for(srand();i++<1000;)
    {
        erg="";
        for(j=0;j++<5;)
        {
            while(erg~(a[j]=substr(c="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",rand()*62+1,1)));
            erg=erg a[j]
        }
        print a[1]", "a[2]", "a[3]", "a[4]", "a[5](rand()>.5?" ":rand()>.5?"  ":"   ")substr(c,rand()*62+1,1)
    }
}

y hacer algo divertido como

me@home:~/$ awk -f gen.awk|awk -f encode.awk|awk -f decode.awk|sort -u|wc -l
62

Lo he visto más como un rompecabezas de programación. Creo que es un poco triste, que casi todo aquí está golfizado, porque puedes aprender mucho más de código legible y bien documentado, pero esa es solo mi opinión. Y lo jugué como lo solicité;)

Cabbie407
fuente
¿Cómo probarlo? por favor comparta algunos ejemplos.
Shravan Yadav
+1 por la gran explicación! Parece que hay muchas maneras diferentes de abordar este problema :)
jrich
1
Esto fue muy similar a mi proceso de pensamiento, excepto que no me di cuenta de que el forzamiento bruto de las combinaciones débiles únicas (donde describiste que el dígito más grande no es mayor que la cantidad de dígitos) era un enfoque viable. Felicitaciones por seguir adelante.
Patrick Roberts el