gawk, 163 + 165 = 328
Протестировано с gawk 4.1.1, но должно работать и в старых версиях gawk. Нужно немного изменить (удлинить) для работы с mawk.
кодировщик (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]]}
декодер (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)}
Ну, это работает, но я знаю, что это может быть не лучшим подходом для этого. Я понятия не имею, для чего пятое недорогое письмо, потому что я использую только четыре.
Они предназначены только для одноразового использования. Если вы хотите ввести второй код, вы должны перезапустить его. Пробелы после запятых необходимы во входных данных для кодирования.
О чем я думал
Мой первый вопрос был "Что мог получить декодер от этих 4 символов?" (Я назову их a, b, c и d), и моей первоначальной идеей было получить 6 битов информации из следующих отношений:
a>b
a>c
a>d
b>c
b>d
c>d
Вау, 6 бит, это прекрасно! Я думал, что это гений, но тестирование показало, что это не сработает. Есть только 24 возможных комбинации. Черт.
Следующим шагом была попытка сосчитать, исходя из того, что я уже знал. Таким образом, первая буква в строке станет 0, затем вторая буква в строке станет 1 и так далее. Но это не привело бы меня к 62 нужным комбинациям.
0000
0001
0010
0011
0012
0100
0101
0102
0110
0111
0112
0120
0121
0122
0123
Но мне все равно идея нравится.
Ну, тогда меня поразило, что я могу объединить эти два, потому что символы во входных данных уже имеют отношения, и мне не нужно было ждать, пока они будут введены, чтобы дать им значение.
Как это устроено
Примечание: это уже не совсем то, как работают версии для гольфа, но принцип остался прежним.
Для декодера:
Создается массив, индекс которого содержит все четыре цифры, чья наибольшая цифра не превышает число различных цифр в этом числе. Существует 75 различных четырехзначных номеров, соответствующих этому условию. Я грубо насилую их, потому что до сих пор я не мог придумать, как их построить, и я не уверен, что это все равно будет короче в awk. В то время как я нахожу их, я назначаю им дорогих персонажей в азиатском порядке.
Затем я заменяю каждый символ из входной строки цифрой. Наименьшее (например, «B» меньше, чем «a») становится 1, второе наименьшее становится 2 и т. Д. До 4. Конечно, это зависит от того, сколько разных символов на входе, какая наибольшая цифра в результирующая строка будет.
Затем я просто печатаю элемент массива, который имеет эту строку в качестве индекса.
Кодер работает соответственно.
Как пользоваться
Либо скопируйте код непосредственно в команду awk bash line, либо создайте два файла «encode.awk» и «decode.awk» и вставьте код соответствующим образом. Или даже лучше использовать следующий код, который автоматически завершается после en / decoding или может использоваться несколько раз, удаляя команду выхода в конце.
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
}
Вот пример использования:
me@home:~/$ awk -f encode.awk
w, 0, R, 1, d X
10R1
me@home:~/$ awk -f decode.awk
10R1
X
Помните, что пробел после каждой запятой требуется, если вы используете версии для гольфа.
Если вы хотите, вы можете использовать этот короткий и грязный скрипт для генерации примеров данных
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)
}
}
и сделать что-нибудь смешное, как
me@home:~/$ awk -f gen.awk|awk -f encode.awk|awk -f decode.awk|sort -u|wc -l
62
Я видел это больше как программирование. Я думаю, это немного грустно, что почти все здесь - игра в гольф, потому что вы можете узнать намного больше из хорошо документированного, читаемого кода, но это только мое мнение. И я играл в гольф, как просили;)