Динамический кодировщик 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


Это действительно может быть я, и я прошу прощения за этот вопрос, если это так, но как именно вы должны кодировать свое сообщение с недорогими символами? Добавление кодов ASCII для 5 недорогих символов? На самом деле, этот вопрос имеет основание, только если ваш декодер должен декодировать для всех генерируемых возможностей кодирования.
Коул

Чтобы быть ясным: Возможности кодировщика являются лишь примерами, и мы можем кодировать каждый символ, как мы хотим, да?
Деннис

@ Денис Да, это только примеры.
января

@Cole Не раскрывая фактического алгоритма , так как это главная проблема, я считаю, что это возможно. Есть только 62 возможных дорогих букв для кодирования, и с этими 4 символами ascii можно кодировать до 92, согласно A239914 . (огромное спасибо за комментарий песочницы PhiNotPi к этому - я не подсчитал точно, сколько можно закодировать)
jrich

@ Неопределенная функция Теперь я понимаю, что вы намеревались: вопрос Денниса ответил на то, что меня смутило.
Коул

Ответы:


5

Pyth, 46 байтов

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

@smfql{Td^<Szd4S4-Cw48

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

C+48xsmfql{Td^<sS{zd4S4z

Вау, это идеально подходит. 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

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


как это проверить? Пожалуйста, поделитесь некоторыми примерами.
Шраван Ядав

+1 за отличное объяснение! Кажется, есть много разных способов решения этой проблемы :)
jrich

1
Это было очень похоже на мой мыслительный процесс, за исключением того, что я не понимал, что грубое форсирование уникальных слабых комбинаций (где вы описали наибольшую цифру, не превышающую количество цифр) было жизнеспособным подходом. Престижность для следования до конца.
Патрик Робертс,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.