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é;)