Динамический кодировщик ASCII!

16

Вступление

Некоторые персонажи ASCII просто так дороги в наши дни ...

Чтобы сэкономить, вы решили написать программу, которая кодирует дорогие символы, используя недорогие.

Однако цены на символы часто меняются, и вы не хотите изменять свою программу каждый раз, когда вам нужно кодировать или декодировать другой символ! Вам понадобится более динамичное решение.

Вызов

Ваша задача - написать две программы: кодировщик и декодер .

Кодер должен принимать список из пяти недорогих персонажей, и один дорогостоящий характер.

Он должен вывести единственную строку, составленную из недорогих символов, которая кодирует дорогой символ.

Эта строка не может быть длиннее 4 символов , чтобы остаться недорогой. Однако не обязательно использовать все недорогие символы в кодировании, и кодировки могут иметь разную длину.


Декодер должен принимать строку , выдаваемого кодером, и вывод дорогой символов.

Декодер не должен принимать никаких входных данных, кроме кодированной строки. Он должен работать без изменений с выхода энкодера для любой (действительной) комбинации входов. Другими словами, ваша программа декодера не знает, какие символы дорогие или недорогие.

счет

Самый короткий комбинированный код выигрывает!

Примечания

  • Все символы будут состоять из заглавных букв [A-Z], строчных букв [a-z]или цифр [0-9].

  • Список недорогих символов не будет содержать дубликатов. Ни один персонаж не будет и недорогим, и дорогим.

  • Кодер и декодер не обязательно должны быть написаны на одном языке, но они могут быть. Вы можете написать программу или функцию.

  • Ввод и вывод могут быть в любом разумном формате для вашего языка.

  • Эти две программы не могут совместно использовать какие-либо переменные или данные.

Резюме

  • Ввод некоторых недорогих символов и дорогостоящего символа передается кодировщику.

  • Кодировщик выводит строку недорогих символов, кодирующих дорогой символ.

  • Декодер получает выходные данные кодера и выводит дорогой символ.

Примеры

Входные данные:     a, b, c, d, e     f

Возможности кодировщика:     a     eeee     caec

декодер:     f


Входные данные:     a, b, c, d, e     h

Возможности кодировщика:     bc     cea     eeaa

декодер:     h


Входные данные:     q, P, G, 7, C     f

Возможности кодировщика:     777     P7     PPCG

декодер:     f

jrich
источник
Это действительно может быть я, и я прошу прощения за этот вопрос, если это так, но как именно вы должны кодировать свое сообщение с недорогими символами? Добавление кодов ASCII для 5 недорогих символов? На самом деле, этот вопрос имеет основание, только если ваш декодер должен декодировать для всех генерируемых возможностей кодирования.
Коул
Чтобы быть ясным: Возможности кодировщика являются лишь примерами, и мы можем кодировать каждый символ, как мы хотим, да?
Деннис
@ Денис Да, это только примеры.
января
@Cole Не раскрывая фактического алгоритма , так как это главная проблема, я считаю, что это возможно. Есть только 62 возможных дорогих букв для кодирования, и с этими 4 символами ascii можно кодировать до 92, согласно A239914 . (огромное спасибо за комментарий песочницы PhiNotPi к этому - я не подсчитал точно, сколько можно закодировать)
jrich
@ Неопределенная функция Теперь я понимаю, что вы намеревались: вопрос Денниса ответил на то, что меня смутило.
Коул

Ответы:

5

Pyth, 46 байтов

Кодировщик, 22 байта

@smfql{Td^<Szd4S4-Cw48

Декодер, 24 байта

C+48xsmfql{Td^<sS{zd4S4z
orlp
источник
Вау, это идеально подходит. 75 различных комбинаций символов и диапазон 75
символов.
Я думаю , вы можете заменить S4с Tи сохранить каждый один байт в обеих программах.
Якуб
7

CJam, 55 50 48 47 байт

Кодировщик, 24 22 21 байт

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

Попробуйте онлайн.

Декодер, 31 28 27 26 байт

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

Попробуйте онлайн.

Деннис
источник
Есть ли там лист синтаксиса CJam, который вы используете? Один на SourceForge и другие PDF шпаргалка не содержат все символы , которые вы используете , как'
Luminous
'не оператор. Вы можете найти его на странице синтаксиса .
Деннис
4

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

Я видел это больше как программирование. Я думаю, это немного грустно, что почти все здесь - игра в гольф, потому что вы можете узнать намного больше из хорошо документированного, читаемого кода, но это только мое мнение. И я играл в гольф, как просили;)

Cabbie407
источник
как это проверить? Пожалуйста, поделитесь некоторыми примерами.
Шраван Ядав
+1 за отличное объяснение! Кажется, есть много разных способов решения этой проблемы :)
jrich
1
Это было очень похоже на мой мыслительный процесс, за исключением того, что я не понимал, что грубое форсирование уникальных слабых комбинаций (где вы описали наибольшую цифру, не превышающую количество цифр) было жизнеспособным подходом. Престижность для следования до конца.
Патрик Робертс,