Кодировать - Перемешать - Декодировать


23

Вызов

Ваша задача - закодировать целое число в виде строки символов ASCII , а затем успешно декодировать его после случайного перемешивания указанной строки.

Вы напишите две программы / функции , которые будут называться Encoder и Decoder .

кодировщик

  • Ввод: целое число в диапазоне .N[0,231-1]
  • Вывод: строка из ASCII символов (не обязательно для печати).s

дешифратор

  • Входные данные: случайная перестановка строки .s's
  • Выходные данные: целое число .N

счет

Пусть быть максимальной длиной по во всех возможных значениях . Если кодировщик действует недетерминированно (что разрешено, см. Ниже), тогда будет максимальной длиной которая может возникнуть (возможно, ).AsNAs

Пусть - длина кодера в байтах, а - длина декодера в байтах.LЕLD

Тогда ваш счет .A(LЕ+LD)

Победа присуждается при подаче наименьшего балла .

Лимит времени

Существует несколько произвольных временных ограничений в 1 минуту на время выполнения как кодера, так и декодера для одного тестового случая (то есть одного значения ).N

Цель состоит в том, чтобы избежать решения, которое находит, что грубая сила кодирует, перечисляя все последовательности с определенными свойствами. Если ваше решение делает что-то более умное, оно, скорее всего, будет соответствовать временным ограничениям и будет считаться действительным. Аналогично, если он работает на TIO для некоторых случайно выбранных значений он будет считаться действительным. В противном случае я протестирую его на своей машине, но учтите, что если ваше решение чисто грубое, оно почти наверняка потерпит неудачу.N

правила

  • Кодер и декодер должны быть написаны на одном языке .
  • Декодер необходимо выводить правильно целое число для каждого из возможных перестановок из строки , возвращенного кодировщик .Ns's
  • Кодер и декодер являются не разрешается обмениваться информацией любым способом (например , с помощью глобальных переменных или файлов).
  • Выходные данные кодера не обязательно должны быть детерминированными (то есть один и тот же вход N может выдавать разные выходные строки, если кодировщик запускается несколько раз), но декодер всегда должен угадывать правильное целое число N .
  • Кодер и декодер могут принимать и возвращать целое число N в любом удобном способе (например , если Nзнак равно14 это нормально для ввода , чтобы быть 14, "14"или [1,4]).
  • Кодер может выводить строку s либо путем печати его на stdout или путем возвращения строки, список / массив символов или список / массив целых чисел в диапазоне [0,127] ; Обратите внимание , что декодер будет принимать в качестве входных данных перестановки s возвращаемой в кодировщике , поэтому он должен принять строку s' в том же формате , как s .
  • Стандартные лазейки запрещены.
  • Если возможно, объясните, как работает ваш код и почему правильная оценка.

пример

Предположим, что Nзнак равно14 .

  • Кодер принимает в 14качестве входных данных. Это может вывести "qwerty".
  • Декодер принимает перестановку в "qwerty"качестве входных данных, например "tweyqr". Он должен выводиться 14(в любом удобном формате).

Кодировщик мог бы вернуться , [113,119,101,114,116,121]а также, в этом случае декодер получил бы (например) [116,119,101,121,113,114].

Обратите внимание, что строка, возвращаемая кодировщиком, также может содержать непечатаемые символы ASCII (но всегда в диапазоне [0x00, ..., 0x7F]).


Конечно, длина вывода не может быть бесконечностью, вы не можете перетасовать бесконечную строку
H.PWiz

@ H.PWiz Нет, не может, но длина может быть неограниченной, если кодировщик недетерминирован
Delfad0r

«Кодеру и декодеру не разрешается каким-либо образом обмениваться информацией» Включает ли это вспомогательные функции? т.е. пользовательская функция, которая вычисляет N факториал плюс три (случайный пример)
pizzapants184

Может ли наш кодировщик вернуть пустую строку / список?
pizzapants184

2
@Kroppeb Да, в настоящее время правила говорят, что вы должны считать байты дважды. Мне очень интересно посмотреть на представление с двумя одинаковыми программами.
Delfad0r

Ответы:


12

Желе (17 байт + 18 байт) × длина 6 = 210 баллов

b36μỤỤ + x + S 3μŒ¿b3U
СУБЪЕКТ: 3_J
Š% 3Uḅ3œ? Çḅ36

Попробуйте онлайн! (или с дополнительной отладочной информацией)

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

объяснение

кодирование

Первый шаг в кодировании состоит в том, чтобы представить входные данные как base 36 ( b36). 36 6 = 2176782336> 2147483647, поэтому в результате будет не более 6 цифр, каждая из которых находится в диапазоне 0–35.

Затем мы преобразуем это в представление, которое содержит 6 различных цифр. Для этого существует несколько возможных алгоритмов, но один из них используется для добавления 1 к наименьшей цифре, 2 к второй наименьшей, 3 к третьей наименьшей и т. Д. Это означает, что если бы две цифры были одинаковыми, одна из них будет произвольно считаться меньшей, и, таким образом, они станут другими; и очевидно, что этот алгоритм не может привести к тому, что две разные цифры станут одинаковыми. Чтобы представить это в Jelly, мы используем («сортировать индексы по значениям»), чтобы получить список индексов в отсортированном порядке; снова, чтобы инвертировать это, эффективно отображая каждый элемент оригинала в его положение в отсортированном порядке; а такжеµ…+добавить оригинал в новый список. Результатом является представление входного числа в виде шести различных цифр в диапазоне 1–41 (минимум 0 + 1, максимум 35 + 6).

Затем мы разделить это на еще одну форму: в отсортированный список цифр в диапазоне 1-41, наряду с числом от 1 до 720 , который представляет , какие из 720 возможных перестановок цифр были в (The. Œ¿И извлечь количество перестановок и сортируются список соответственно.)

Наконец, мы конвертируем число от 1 до 720 в base 3 ( b3), инвертируем его ( U) и кодируем шесть базовых 3 цифр и шесть 1–41 цифр, упаковывая их каждый в один символ ASCII, используя обратный divmod (значение символьный мод 3 - это базовая цифра 3, значение, деленное на 3, - это цифра 1–41). Возможный диапазон результатов составляет (1 × 3) + 0 = 3 минимум и (41 × 3) + 2 = 125 максимум, что соответствует нашему диапазону ASCII. Упаковка выполняется через ×3и +вместе с дополнительным, µчтобы убедиться, что каждая команда работает с нужным битом данных. (Здесь есть небольшая хитрость в том, что мы умножаем на 3 перед извлечением перестановки; это избавляет от необходимости тратить байт на группирующего персонажа.)

Кстати, причина, по которой следует изменить номер 3 базы, состоит в том, что он может содержать меньше цифр, чем номер 1–41. (У него не может быть больше; наименьшее число, для которого n !> 3 n немного выше 6.) Желе эффективно вставляет конечные нули при сложении двух чисел разной длины, чтобы они совпали; замыкающие нули будут влиять на интерпретацию числа, но ведущие нули не будет, поэтому обратный используется для того, чтобы лишние нули в конечном итоге где - то , что не испортит наш ответ.

Декодирование

Первый шаг в декодировании состоит в извлечении двух чисел (номер основания 3 и номер 1–41). Мы можем легко получить их цифры с помощью Division ( :3) и Modulo ( %3) соответственно, но как узнать, в каком порядке они были? Ну, числа 1–41 имели свои цифры в отсортированном порядке, а цифры в соответствующих позициях двух чисел были сохранены в одних и тех же символах; таким образом, мы можем определить, в каком порядке были перемешаны цифры номера 1–41 (глядя на их относительные значения), и знаем, что цифры номера основания-3 должны были быть перетасованы таким же образом. На самом деле, поскольку символы нашей кодировки ASCII сортируются так же, как цифры числа 1–41 (все они отличались друг от друга и более значимы, чем цифры базовых 3),, Таким образом, оба извлечения начинаются с , затем %3или по :3мере необходимости.

В то время как цифры номера 1–41 все еще в отсортированном порядке, у нас есть очень удобный / краткий способ вернуться к 0–35 цифрам базы 36; просто вычтите 1 из первого, 2 из второго, 3 из третьего и так далее. В Jelly это можно сделать с помощью _J(«индекса вычитания»).

В то же время, в другой ветви декодирования, мы возвращаем цифры числа 3 базы обратно в order ( U) и преобразуем их из базы 3 обратно в индекс перестановки с помощью ḅ3.

Затем мы можем объединить две ветви с œ?Ç; œ?означает «перестановка с учетом этого индекса перестановки» и Çозначает «результат применения строки выше», т. е. это то, что говорит Jelly для запуска обеих строк отдельно на одном входе.

Теперь у нас есть цифры исходного числа, в базе 36 (из-за _J) и в исходном порядке (из-за œ?), поэтому мы можем просто сделать ḅ36преобразование обратно из базы 36 в одно целое число.

Комментарий

ТИО! ссылка выше использует 312699167 в качестве числа для кодирования. Это число в базе 36 равно [5, 6, 6, 8, 7, 35]и, таким образом, демонстрирует все аспекты кодирования: 35 тестирует предел диапазона 0–127, который мы имеем; дубликаты 6s проверяют разрешение идентичных цифр в исходной базе 36; и тот факт, что цифры почти (но не совсем) отсортированы, означает, что число перестановок очень мало, что дает ему намного меньше цифр, чем число в базовом 36, и, таким образом, показывает необходимость обратить его перед добавлением к оригиналу.

Это действительно удобно, как все константы здесь сочетаются друг с другом. 36 6 только лишь достаточно высоко , чтобы соответствовать 2 31 , 3 6 только лишь достаточно высоко , чтобы соответствовать 6 !, и (36 + 6) × 3 только лишь достаточно высоко , чтобы соответствовать в пределах 128 возможностей мы имеем. (Последнее ограничение здесь наименее жесткое, потому что мы могли бы использовать 0-индексирование, а не 1-индексирование, чтобы использовать символы в диапазоне 0-2. Тем не менее, это дало бы достаточно места для использования 37 в качестве основы, а не чем 36.)


9

Желе ( 4 3 байта + 6 5 байтов) × длина 8 = 80 64 балла

b⁴Ä
ṢŻIḅ⁴

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

Желе , ( 2 1 байт + 4 3 байт) × длина 10 = 60 40 баллов

Ä
Szi

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

объяснение

Решение 1

Это использует алгоритм, отличный от большинства других ответов. Мы начнем с кодирования значения в шестнадцатеричном ( b⁴), как и в других ответах, а затем возьмем кумулятивную сумму ( Ä). Каждый вход будет давать разные выходные данные (поскольку обе эти операции являются обратимыми), и, учитывая, что шестнадцатеричное кодирование будет содержать не более 8 цифр, максимальные значения которых равны 7 (для 8-й последней цифры) и 15 (для последней до 7-й- последние цифры), максимальное число в списке вывода будет 7+ (7 × 15) = 112, что меньше 127, требуемого в вопросе. Кроме того, вывод будет обязательно в отсортированном порядке, что позволяет нам обратить вспять перемешивание.

Для декодера мы сначала обращаем shuffle с помощью sort ( ); затем поменяйте местами суммарную сумму, добавив ноль ( Ż) и взяв разность последовательных пар ( I); затем преобразовать обратно из шестнадцатеричного ( ḅ⁴).

Решение 2

Вопрос на самом деле позволяет нам принимать входные данные в виде списка (предположительно десятичных) цифр, поэтому мы можем «обмануть», просто удалив базовое преобразование; максимальное число, используемое в выходных данных, будет тогда 2 + (9 × 9) = 83 (фактически 82, потому что 2999999999 находится вне диапазона, поэтому наихудший возможный ввод - 1999999999). Результирующее кодирование является довольно ужасным с точки зрения кодирования для этой проблемы, но его преимущество заключается в том, что оно очень лаконично для генерации, что перевешивает многословность кодирования.

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

Комментарий

Я имею в виду некоторые алгоритмы для получения длины менее 8, но кажется маловероятным, что вы могли бы реализовать алгоритм длины 7 в ≤9 байт (без мошенничества) или ≤5 байт (мошенничество), поэтому, набрав в этом вопросе, это вероятно, лучший способ сделать это. (В любом случае, я мог бы найти решение для альтернативной задачи «минимизировать длину кодирования», просто для удовольствия.)

В отличие от некоторых решений, использование 16 в качестве основы здесь не критично; Есть много других чисел, которые будут работать для решения длины 8 (например, 18). Я выбрал 16 для первого решения просто потому, что у Jelly есть 1-байтовый способ для представления этого, и другие жизнеспособные базы должны будут использовать несколько байтов из программы. Конечно, второе решение должно использовать 10 в качестве основы, чтобы использовать лазейку.

Спасибо @Dennis за указание на некоторые новые команды Jelly, которые сделали этот алгоритм еще более трудным для написания.


3
Äэто сокращение от +\, Żэто сокращение от 0;.
Деннис

7

Язык программирования Шекспира , 10 * (264 + 494) = 8650 7910 7580

Кодировщик: 264 байта

,.Ajax,.Ford,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:Open mind.Be you nicer zero?You be the sum ofyou the product ofthe sum ofI a big big pig the sum ofa big big big big cat a big big pig.If soSpeak thy.Ford:You are the sum ofyou a cat.If soLet usAct I.

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

Декодер: 494

,.Ajax,.Ford,.Page,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:Open mind.Is you nicer a pig?If soRemember you.If soLet usAct I.Scene V:.Ford:Remember I.Ajax:Recall.Is you worse the sum ofPage twice the sum ofa big big cat a cat?If soYou be the difference betweenyou Page.If soOpen heart.If notlet usScene V.Scene X:.Ford:Recall.Ajax:Be I nicer zero?If soRemember I.If soLet usScene X.[Exit Ajax][Enter Page]Ford:You be the sum ofyou twice twice the sum ofa big big cat a pig.Let usAct I.

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

Это была вещь.

Кодировщик кодирует каждую цифру в виде цифры плюс индекс цифры, умноженной на двенадцать. Декодер сохраняет все входные данные в памяти Ford, а затем зацикливает их на счетчике, выводя и удаляя каждую цифру ниже, чем счетчик * 12 + 10.

Объяснение:

кодировщик

,.Ajax,.Ford,.Act I:.Scene I:.      Boilerplate introducing the two characters
[Exeunt][Enter Ajax and Ford]       Enter the two characters Ajax and Ford
                                    Ford will be handling the input
                                    Ajax will be the counter
Ajax:Open mind.                     Set Ford to the next character of input
Be you nicer zero?                  Check if it is EOF
You be the sum of                   Set Ford to the sum of 
    you                             His original value (48 to 58)
    the product of                 
          the sum of               
              I                     Ajax's value
              a big big pig         Minus 4 (this handles the offset of 48)
          the sum of                Multiplied by
              a big big big big cat 2^4
              a big big pig.        + -2^2 = 12
                                    This essentially sets Ford to (F+12*(A-4))
If soSpeak thy.                      If not EOF, print Ford's value
Ford:You are the sum ofyou a cat.   Increment Ajax's value
If soLet usAct I.                   If not EOF, Repeat again.

дешифратор

,.Ajax,.Ford,.Page,.Act I:.Scene I:.  Boilerplate introducing three characters
                                      Ajax is the spare stack
                                      Ford is the storage stack
                                      Puck is the counter, increasing by 12
[Exeunt][Enter Ajax and Ford]            Enter Ajax and Ford onto the stage
Ajax:Open mind.                          Get the next character of input
Is you nicer a pig?                      If not EOF
If soRemember you.                         Store the value in Ford's memory
If soLet usAct I.                          And repeat the loop
Scene V:.                                Otherwise move to the next scene
Ford:Remember I.                         Store Ford's value (initially -1 from EOF) in Ajax's memory
Ajax:Recall.                             Get the next value from Ford's memory
Is you worse the sum of                  Is the value smaller than
        Puck                                  Puck's value
        twice the sum ofa big big cat a cat?  + 10 ?
                                              i.e. is it the next digit?
If soYou be the difference betweenyou Puck.   If so, subtract Puck's value from Ford
If soOpen heart.                              And print Ford's value
If notlet usScene V.                     If that was not the digit, repeat
Scene X:.
Ford:Recall.                             Get the next value from Ajax's memory
Ajax:Be I nicer zero?                    Until the -1
If soRemember I.                         Returning the values to Ford's memory
If soLet us Scene X.                     Repeat until Ajax's memory is exhausted
[Exit Ajax][Enter Page]                  Swap Ajax and Page
Ford:You be the sum of                   Set Puck's value to
              you                        Puck +   
              twice twice the sum of     2*2*(
                           a big big cat      4
                           a pig.             -1) = 12
Let usAct I.                             And start from the beginning again, having removed one number

5

Python 2.7, 31 * (52 + 37) = 2759

Кодировщик ( 69 52 байта):

lambda n:[chr(i)if n&(1<<i)else""for i in range(32)]

Декодер ( 41 37 байт):

lambda s:sum([1<<(ord(c))for c in s])

Сохраняет все ненулевые биты во входном номере в качестве значений ascii. Значение символа ascii хранит позицию установленного бита. Например, значение «а» будет означать, что установлен 97-й бит.

Несколько улучшений, благодаря @ Delfad0r

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


Добро пожаловать в PPGC! Вы можете отбросить e = и d = в начале - анонимные функции прекрасно работают. Также обратите внимание, что в заявлении о проблеме четко сказано, что кодировщик может возвращать список целых чисел вместо символов, поэтому вы можете избежать преобразования целое число -> символ-> целое число. Кроме того, вы можете использовать n&(1<<i)вместо n&(1<<i)>0и сохранить 2 байта. Наконец, верхняя граница для i(127) слишком велика, 32 достаточно и сохраняет 1 байт.
Delfad0r

1
Пожалуйста, укажите свой результат в соответствии с разделом « Оценка » в описании проблемы.
Delfad0r

@ Delfad0r Теперь правильная оценка? И спасибо за советы.
Хейн Вессельс,

Я думаю, что оценка является (52+37)*31=2759самой длинной, когда установлены все 31 бит.
Джонатан Аллан

Кодировщик можно lambda n:[chr(i)*(n&1<<i>0)for i in range(32)]сохранить 6 байтов.
Mypetlion

5

Stax , оценка 8 × (10 + 9) = 152

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

Ç·MÉJ'♀τ│½

Запустите и отладьте его

16|E{i16*+m Full program, implicit input
16|E        Get hexadecimal digits
    {     m Map:
     i16*+    Add 16 * loop index
            Implicit output as string

Кодировщик выводит строку в возрастающем порядке.

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

üL∟n╫k∞‼9

Запустите и отладьте его

o{16%m16|E Full program, implicit input
o          Sort string
 {16%m     Module each element by 16
      16|E Interpret as array of hex digits


5

Python 3 , 8 * (45 + 38) = 664

Кодер (45 байт):

lambda n:[16*i+(n>>4*i)%16 for i in range(8)]

Декодер (38 байт):

lambda l:sum(x%16<<x//16*4 for x in l)

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


1
Вы можете удалить пробелы перед "для", lambda l:sum(x%16<<x//16*4for x in l)работает просто отлично :)
FatalError

4
Это не работает. Выходные данные не отображаются в формате ASCII (в диапазоне 0,127)
GB

2
@ ГБ моя ошибка. Я сломал это с моим последним редактированием. Возвращаясь сейчас
Кертис Бектел

сохранить 3 байта в кодировщике: lambda n:[n>>4*i&15|i<<4for i in range(8)]и 1 в декодере: lambda l:sum(x%16<<x//16*4for x in l)для общего результата 632
Аарон

4

JavaScript (ES6), 8 * (40 + 32) = 576

08

Кодировщик (40 байт)

E=(n,k=0)=>n?[k|n&15,...E(n>>4,k+16)]:[]

Декодер (32 байта)

s=>s.map(c=>s|=c%16<<(c/4&~3))|s

демонстрация

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

Как?

Вход делится на 8 блоков по 4 бита, и каждый блок кодируется с 1 из 16 возможных символов. Самый старший бит последнего блока никогда не устанавливается.

       3222222222211111111110000000000
bit:   0987654321098765432109876543210
       \_/\__/\__/\__/\__/\__/\__/\__/
block:  7  6   5   4   3   2   1   0

block #0 is encoded with char. 00 to 0F (NUL to SI)
block #1 is encoded with char. 10 to 1F (DLE to ES)
block #2 is encoded with char. 20 to 2F (' ' to '/')
block #3 is encoded with char. 30 to 3F ('0' to '?')
block #4 is encoded with char. 40 to 4F ('@' to 'O')
block #5 is encoded with char. 50 to 5F ('P' to '_')
block #6 is encoded with char. 60 to 6F ('`' to 'o')
block #7 is encoded with char. 70 to 77 ('p' to 'w')

4

Желе , (8 + 9) байтов * 8 макс. Длина = 136

b⁴+J’Ɗ⁴¡

Кодировщик (нижний колонтитул форматирует список так, как это делает Python для ясности)

Ṣ_J‘Ɗ⁴¡ḅ⁴

дешифратор

Теоретически возможно иметь максимальную длину шесть, это может быть сделано в 22 байта или меньше?

Σязнак равно0язнак равно5(127+я127)знак равно321402081<231-1

Как?

231-17fffffff[7,15,15,15,15,15,15,15][7,15,15,15,15,15,15,15] + [0,16,32,48,64,80,96,112] = [7,31,47,63,79,95,111,127]

Кодировщик :

b⁴+J’Ɗ⁴¡ - Link: integer, n    e.g. 1234
 ⁴       - literal 16               16          
b        - convert to base          [4,13,2]
       ¡ - repeat...
      ⁴  - ...16 times:
     Ɗ   -   last 3 links as a monad:
   J     -     range of length        [1,2,3]     iter 2    iter 3    ...  iter 16
  +      -     add                    [5,15,5]   [5,16,7]   [5,17,9]  ...  [5,30,35]
    ’    -     decrement              [4,14,4]   [4,15,6]   [4,16,8]  ...  [4,29,34]
         -                                                                 [4,29,34]

Декодер :

Ṣ_J‘Ɗ⁴¡ḅ⁴ - Link: list of integers   e.g. [29,34,4]
Ṣ         - sort                          [4,29,34]
      ¡   - repeat...
     ⁴    - ...16 times:
    Ɗ     -   last 3 links as a monad:
  J       -     range of length           [1,2,3]
 _        -     subtract                  [3,27,31]   [3,26,29]   [3,25,27]  ...  [3,12,1]
   ‘      -     increment                 [4,28,32]   [4,27,30]   [4,26,28]  ...  [4,13,2] 
        ⁴ - literal 16                    16
       ḅ  - from base                     1234

"шестнадцатеричные цифры", конечно. («цифры с использованием простого шестнадцатеричного числа» длиннее, а «цифры»
означают

Я изменил это, хотя это должно было быть очевидно из контекста, поскольку я сразу же сослался на шестнадцатеричные цифры
Джонатан Аллан

Ваш расчет отклонен на единицу: существует 321402081 комбинаций с заменой с максимальной длиной 5 и 7177979809 с максимальной длиной 6.
Андерс Касорг

@AndersKaseorg Упс, так и есть - так что это возможно с максимальной длиной 6 ... давая 22 байта для игры!
Джонатан Аллан

4

Шекспир Программирование Язык , 31 * (472 + 383 379 344) = 26505 26381 25296

Предыдущий счет: 16909322 * (246 + 217) = 7829016086

Это все еще очень высоко, но это самый низкий уровень, о котором я могу думать прямо сейчас.

Кодер:

,.Ajax,.Ford,.Act I:.Scene I:.[Enter Ajax and Ford]Ajax:Remember a pig.Ford:Listen tothy.Scene V:.Ajax:Remember the remainder of the quotient betweenI a big cat.Ford:You be the quotient betweenyou a big cat.Be you nicer zero?If solet usScene V.Remember a pig.Scene X:.Ajax:Recall.Ford:Am I worse zero?If notremember I.If notlet usScene X.Ajax:You zero.Scene L:.Ford:Recall.Ajax:You be the sum ofyou a cat.Am I nicer zero?If sospeak thy.Am I worse zero?If notlet usScene L.

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

декодер:

,.Ajax,.Ford,.Page,.Act I:.Scene I:.[Exeunt][Enter Ajax and Ford]Ajax:You cat.Ford:Open mind.Remember the sum ofyou I.Scene V:.Ajax:Am I nicer a cat?If soyou be twice you.Ford:If soyou be the sum ofyou a pig.If solet usScene V.[Exit Ford][Enter Page]Page:Recall.Ajax:Am I worse a cat?If notyou be the sum ofyou Ford.If notlet usAct I.Open heart

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

В основном, если строка содержит символ с кодом ASCII (n + 1), устанавливается n-ая двоичная цифра.


344 байта для декодера
Джо Кинг,

3

Python 3, (208 байт + 200 байт) * 6 длина = 2448

Попробуйте онлайн! (содержит оба, дополнительный байт - новая строка между ними).

-4 байта (-24 балла), используя пустой список (который позволял большему количеству начинаться с 0)

Кодировщик (208 байт)

def E(n,h=128):
    T=lambda n,d:n*T(n+1,d-1)//d if d>1else d and n or 1
    d=l=0
    s=[]
    while n>=T(h,d):
        n-=T(h,d)
        d+=1
    for i in range(d):
        while n>=T(h-l,d+~i):
            n-=T(h-l,d+~i)
            l+=1
        s+=[l]
    return s

Декодер (200 байт)

def D(s):
    T=lambda n,d:n*T(n+1,d-1)//d if d>1else d and n or 1
    s.sort()
    l=0
    d=len(s)
    n=sum(T(128,D)for D in range(d))
    for i in s:
        for j in range(l,i):
            n+=T(128-j,d-1)
        l=i
        d-=1
    return n

Замечания:

  • Перестановка может быть полностью изменена без потерь для строго не увеличивающихся (т.е. отсортированных) списков.

  • Строго не увеличивающиеся числовые списки одинаковой длины могут быть полностью упорядочены (как в Python).

  • Мы можем определить, что списки сначала упорядочены по длине, чтобы сформировать общий порядок всех отсортированных списков.

  • Мы можем сформировать индексируемую последовательность этих списков , если мы определим , что только действительные значения в списке являются целыми числами от 0до 127включительно (т.е. существует конечное число действительных списков с длиной L).

Стратегия:

  • Кодировщик: По заданному номеру Nнайдите Nдействительный строго не возрастающий список.

  • Декодер. По заданному (перемешанному) допустимому списку отсортируйте его и верните индекс в последовательности действительных списков.

Общее объяснение кода:

  • T=lambda n,d:n*T(n+1,d-1)//d if d>1else d and n or 1

  • Вычислить число nth- dсимплекс

    • Ибо d=0всегда1

    • Для d=1, n(количество точек в линии точек с длиной n)

    • d=2Σязнак равно1Nяn

    • d=3ΣJзнак равно1NΣязнак равно1Jяn

Объяснение кодера:

  • def E(n,h=128): d=l=0, s=[]

  • nявляется входным числом, hявляется «высоким значением» (то есть наибольшим допустимым числом + 1), dявляется длиной, на которой будет выводиться, sявляется выводом, lявляется «низким значением» (начиная с 0, поясняется ниже)

  • while n>=T(h,d):, n-=T(h,d),d+=1

  • Существуют T(h,d)допустимые dсписки длин , и наши вычисления проще, если nэто индекс относительно списка [0]*d(по индексу 0) вместо фактического индекса, поэтому уменьшите nсоответствующим образом. Это также корректирует d(длину), чтобы быть правильным для данного n.

  • for i in range(d):

  • Эффективно: «за i+1номер в списке»

    • Вот где я объясню l, «низкое значение»

    • После того, как число было добавлено в список, не меньшее число, чем оно может быть помещено в список (чтобы сохранить его сортировку), lравно как и последнее число, которое было добавлено в список.

    • while n>=T(h-l,d+~i):, n-=T(h-l,d+~i),i+=1

    • Если nон слишком велик для кодирования с lэтой «цифрой», отрегулируйте nсоответственно и увеличьтеl

    • s+=[l]

    • Кодировать nс помощью lэтой «цифры».

    • Сначала у нас есть hопции для того, какую «цифру» вводить следующей, но как только мы введем «цифру» (которая назначена l), мы ограничимся h-lвариантами для следующей «цифры».

    • Сначала были T(h,d)действительные списки, но мы добавили «цифру» l, уменьшив количество оставшихся «цифр» d-1и количество действительных следующих «цифр» h-l, чтобы число действительных списков после этого былоT(h-l,d-1)

Объяснение декодера:

  • def D(s):, s.sort(), l=0,d=len(s)

  • sэто (перемешанный) список ввода, так что s.sort()это; lэто «низкое значение» ( h«высокое значение» - это просто литерал 128s в коде для сохранения байтов), nэто выходное число, dэто длина.

  • n=sum(T(128,D)for D in range(d))

  • Отрегулируйте nдо точки в последовательности[0]*length

  • for i in s:

  • Для каждой цифры:

    • for j in range(l,i):, n+=T(128-j,d-1)

    • Отрегулируйте nдо точки в последовательности[...prevdigits, thisdigit, 0...]

      • l=i: Установите «низкое значение» на самую последнюю цифру

      • d-=1: Уменьшить длину, так как мы использовали цифру

  • return n: После того, nкак были откорректированы все цифры, это правильный номер; верни это.

Извините, если это не ясно, но вот моя оригинальная версия без отладки. Попробуйте онлайн! , который не использует пустой список, поэтому 1 от всех чисел, используемых в этой версии


3

Рубин (36 + 29 байт) * 8, оценка 520

Encode:

->n{(0..7).map{|x|(n>>x*=4)%16+x*4}}

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

Decode:

->a{a.sum{|x|x%16<<(x/4&28)}}

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

Как это работает:

Число кодируется с использованием 4-битных фрагментов и 3-битного индекса.

Декодер берет входной массив и снова помещает каждый кусочек на свое место.


3

Древесный уголь , оценка 10 * (10 + 15) = 250.

Использует десятичную; предыдущее решение на основе базы 16 набрало 328 296 264.

Может выводить непечатные символы. В частности, символ 10 сложно ввести в древесный уголь.

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

⭆⮌S℅⁺Iι×χκ

Попробуйте онлайн! Ссылка на подробную версию кода.

Декодер, 15 байт:

IΣES×﹪℅ιχXχ÷℅ιχ

Попробуйте онлайн! Ссылка на подробную версию кода.

Версия с использованием списка целых чисел 360 296 (основание 16; десятичное число будет 310):

Кодер, 19 байт:

NθIE⁸⁺﹪÷θX¹⁶ι¹⁶×¹⁶ι

Попробуйте онлайн! Ссылка на подробную версию кода.

Декодер, 18 байт:

IΣEE⁸N×﹪ι¹⁶X¹⁶÷ι¹⁶

Попробуйте онлайн! Ссылка на подробную версию кода.

Версия с использованием печатаемых символов 360 баллов (было 416 384 368 в базе 16):

Кодер, 19 байт:

⭆⮌S℅⁺Iι×χ⁺κ×⁵⊕׳÷κ⁵

Попробуйте онлайн! Ссылка на подробную версию кода.

Декодер, 17 байт:

Fθ⊞υ⌈Φθ¬№υκ⭆υ﹪℅ιχ

Попробуйте онлайн! Ссылка на подробную версию кода.


2

Brachylog , 17 + 18 байтов * 8 длина = 280

Кодер:

ḃ₁₆I∧7⟧₁;Iz₁~ḃ₁₆ᵐ

декодер:

ḃ₁₆I∧7⟧₁;Iz₁~ḃ₁₆ᵐp

P может быть добавлен в конец энкодера без эффекта. Декодер запускается путем помещения (перемешанного) результата в качестве вывода и получения исходного числа на входе.

Если будет (правильно реализованный) предикат накопленной суммы, оценка может снизиться до 20

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


@ Delfad0r добавление p к кодировщику сделало бы его тем же кодом для кодирования и декодирования
Kroppeb

2

05AB1E , оценка: (2 + 2 байта ) * 11 максимальная длина = 44

Кодировщик (2 байта ):

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

Декодер (2 байта ):

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

Вход кодера и выход декодера представляют собой список цифр.

Порт @ ais523 второго ответчика Jelly .

Объяснение:

    # Undelta (automatically prepends a 0)
      #  i.e. [3,0,4,7,8,2,0,1,9] → [0,3,3,7,14,22,24,24,25,34]

{     # Sort
      #  i.e. [14,7,22,25,24,3,0,24,34,3] → [0,3,3,7,14,22,24,24,25,34]
 ¥    # Deltas
      #  i.e. [0,3,3,7,14,22,24,24,25,34] → [3,0,4,7,8,2,0,1,9]

Потому что 231-1


2

Гол> <> , 8 * (14 + 13) = 216

Кодер Попробуй онлайн! 14 байт:

I8FfPSD8*L+o|;

Декодер Попробуй онлайн! 13 байт:

iEh8SD4*2$X*+

Так как это может выводить непечатаемые символы ascii, что мешает работе декодера, теперь есть версия, использующая числа в выводе / вводе:

кодировщик Попробуй онлайн! 14 байт:

I8FfPSD8*L+N|;

дешифратор Попробуй онлайн! 13 байт:

IEh8SD4*2$X*+

Кодирование:

Кодирование работает путем разбиения заданного числа на 8 x 4-битных кусков. Эти чанки затем сдвигаются вправо на 3 бита, и исходное местоположение чанка добавляется в конце как число от 0 до 7. Таким образом, кодировка выглядит следующим образом:

0AAAABBB
 |__|    -> the original part of the number
     |_| -> the position of the chunk inside the original number 0 = LSB and 7 = MSB

2

Perl 6 , 10 * (10 + 12) = 340 220

Кодер:

{^@_ Z~@_}

декодер:

{.sort X%10}

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

Функция кодировщика упаковывает каждую цифру в 0-значный номер. Затем кодировщик сортирует список чисел и получает по модулю 10, другими словами, вторую цифру числа.

Всего 10, так как это максимальная длина 2 31 -1.


1

Haskell , 10 * (23 + 51) = 740

Вот программа, которая кодирует, перемешивает, декодирует и проверяет значения: попробуйте онлайн!

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

zipWith((+).(10*))[0..]

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

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

map snd.sortOn fst.map(`divMod`10)
import Data.List

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

объяснение

Так как нам разрешено использовать ввод в качестве десятичных цифр, мы будем использовать это .. Кодировщик отображает каждую встречающуюся цифру 10*index + digit, обратите внимание, что все digits будут в, [0..9]так что мы можем отменить вышеупомянутое, используяdivMod . После восстановления индексов и цифр нужно лишь отсортировать индексы и избавиться от них.

231-1знак равно214748364799знак равно81<128



1

LЕ+LDзнак равно36;Aзнак равно8288

d←{16n-16×⍳≢n←⍵[⍋⍵]}
e←(⊢+16×⍳∘≢)16⊥⍣¯1

Попробуйте онлайн! (содержит 5 дополнительных байтов для назначений и новой строки).

Пользы ⎕IO←0

Как:

(⊢+16×⍳∘≢)16⊥⍣¯1  Encoder; input 1234
          16⊥⍣¯1  Convert input to base 16  4 13 2
      ⍳∘≢           [0..length of the list-1]  0 1 2
   16×              times 16  0 16 32
 ⊢+                 plus the original list  4 29 34

{16n-16×⍳≢n←⍵[⍋⍵]}  Decoder; input   34 4 29
              [⍋⍵]   Grade  up  2 0 1
                    Index  with that list  4 29 34
           n        assign that to n
      16×⍳≢          16×[0..length(n)-1]  0 16 32
    n-               subtract that from n  4 13 2
 16                 Decode from base 16  1234

1

PHP, 8 * (44 + 53) = 776

кодер, 44 байта:

for(;$n=&$argn;$n>>=4)echo$n&15|16*$i++," ";

печатает разделенный пробелами список целых чисел. Беги как труба с -nR.

максимум 8 байтов с 4 битами данных (нижний полубайт) и 3 битами веса (верхний полубайт).

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

пример:

1457893891( 0x56e5b203) Превратится в
0x03, 0x10, 0x22, 0x3b,0x45 , 0x5e, 0x66, 0x75
3 16 34 59 69 94 102 117

декодер, 53 байта:

while($i++<8)$n+=(15&$x=$argv[$i])<<($x>>4)*4;echo$n;

или

while($i++<8)$n+=(15&$x=$argv[$i])<<($x/4&~3);echo$n;

или

for(;$i<9;$x=$argv[++$i])$n+=$x%16<<($x/4&~3);echo$n;

взять целые числа из аргументов командной строки. Бежать с-nr .


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


0

Python 2 , 10 * (68 + 54) = 1220

e=lambda n:"".join(chr(int(`i`+j))for i,j in enumerate(`n`)if j<'L')
d=lambda s:int("".join(`ord(c)%10`for c in sorted(s)))

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

РЕДАКТИРОВАТЬ: Спасибо Джо Кинг за указатели - не уверен, почему я оглянулся на 32, оглядываясь назад.

Кодирует позицию и значение каждого места как один символ, начиная с [пробел] (позиция 0, значение 0) байта NUL 0x0.

Расшифровывает:

  • сортировка строки (Python будет сортировать символы по их порядковому значению)
  • преобразует каждый символ в его порядковое значение
  • принимает последнюю цифру каждого порядкового числа
  • объединяет целые числа в строку
  • преобразует объединенную строку обратно в int

Вам нужно 32смещение? Кроме того, [-1]может быть %10вместо этого, в нужном месте
Джо Кинг,

0

C (gcc) , 10 * 112 = 1120

c,i;e(i,s)char*s;{for(c=1;i;c+=10,i/=10)*s++=c+i%10;*s=0;}
d(char*s){for(i=0;c=*s++;i+=--c%10*pow(10,c/10));s=i;}

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

У меня есть глобальные переменные, но они фактически не передают никакой информации между двумя функциями. Объявление переменной дляc используется в обеих функциях, экономя 2 байта в длине кода.

Версия, которая использует печатный ASCII только для штрафа за 3 5 байтов, здесь:

c,i;e(i,s)char*s;{for(c=32;i;c+=10,i/=10)*s++=c+i%10;*s=0;}
d(char*s){for(i=0;c=*s++;i+=(c-=32)%10*pow(10,c/10));s=i;}

Спасибо @ceilingcat за 70 улучшений.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.