Стеганографические площади


14

Стеганографические площади

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

Алгоритм «Шифрование» + Алгоритм «Расшифровка» .

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


Пример алгоритма

Например, вот «Программирование головоломок и Code Golf» с использованием простого стеганографического алгоритма на основе ASCII в канале Blue:

#2e7250,#6ea972,#04eb6f,#0fc767,#74ab72,#ee6161
#b73b6d,#1aae6d,#f37169,#bda56e,#1fe367,#e99620
#706450,#0d3575,#146b7a,#4ea47a,#2a856c,#95d065
#3f2d73,#cef720,#bab661,#d1b86e,#f22564,#12b820
#0f3d43,#c86e6f,#1ee864,#a66565,#247c20,#c3bb47
#0e296f,#89d46c,#585b66,#c08f20,#455c20,#136f20

Фактическое изображение ( Изображение сгенерировано алгоритмом.)

Изображение взорвано.

Вы можете видеть, что синий канал просто содержит значения ascii для этого изображения:

50 =  80(P) 72 = 114(r) 6f = 111(o) 67 = 103(g) 72 = 114(r) 61 =  97(a) 
6d = 109(m) 6d = 109(m) 69 = 105(i) 6e = 110(n) 67 = 103(g) 20 =  32( ) 
50 =  80(P) 75 = 117(u) 7a = 122(z) 7a = 122(z) 6c = 108(l) 65 = 101(e) 
73 = 115(s) 20 =  32( ) 61 =  97(a) 6e = 110(n) 64 = 100(d) 20 =  32( ) 
43 =  67(C) 6f = 111(o) 64 = 100(d) 65 = 101(e) 20 =  32( ) 47 =  71(G) 
6f = 111(o) 6c = 108(l) 66 = 102(f) 20 =  32( ) 20 =  32( ) 20 =  32( )

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

"Programming Puzzles and Code Golf"

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


правила

  • Вы должны кодировать 1 символ на пиксель, канал, выбранный для кодирования символа, является произвольным.
  • Каналы других цветов RGB должны быть случайными, кроме того, который вы выбираете для кодирования строки; это означает, что ваши окончательные некодированные каналы должны быть между0x0000-0xFFFF (случайно выбранными).
  • Выражение конечного результата в виде двумерного массива значений цвета RGB - это хорошо 0x000000-0xFFFFFF, нет необходимости использовать создание изображения, если вы не хотите с ним повеселиться или если оно меньше байтов. Если вы решите выводить как шестнадцатеричные строки, добавьте к шестнадцатеричной строке префикс #EG #FFFFFFили #05AB1E. Вы можете разделить вкладками, запятыми или чем-то еще, что будет иметь смысл по горизонтали, но оно должно поддерживать квадратный узор; другими словами, вы должны использовать соответствующее разделение новой строки.
  • Выходные данные должны быть в квадрате, и строка должна быть дополнена пробелами в конце, чтобы вместить это. Это значит что N≈SQRT(Input#Length()). Если длина ввода не является идеальным квадратом, вы должны округлитьN и дополнить пробелами.
  • Как указывалось ранее, если вы добавляете пробелы на изображении, вы не должны включать символы дополнения в окончательный «расшифрованный» вывод.
  • Вы можете предположить, что:
    • Входная строка не будет заканчиваться пробелами.
    • Во входной строке будут использоваться только печатные символы ASCII.
  • Это , выигрывает меньшее количество байт.

Просто чтобы уточнить, решения должны кодировать / декодировать ровно один символ на пиксель?
ETHproductions

@ETHproductions, которая звучит как хорошая последующая задача, но для целей этого конкурса вы выбираете канал кодирования и кодируете 1 символ на пиксель.
Волшебная Урна Осьминога

Я, вероятно, не собираюсь использовать это, но: это нормально, чтобы "overpad" изображение с большим количеством пробелов, чем необходимо? И можно ли предположить, что изображение будет иметь такое же количество оверпадов, которое генерирует кодер?

@ ais523 Я не могу понять, как такой подход мог бы что-то сделать, но потребовал бы больше байтов для реализации. Я собираюсь пойти без, хотя, так как задача слишком старая, чтобы делать большие изменения, как это.
Волшебная Урна Осьминога

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

Ответы:


2

05AB1E , 34 + 12 = 46 байт

Использует красный канал.
05AB1E использует CP-1252 кодировку .

Encode:

DgDtî©n-Äð×JvyÇh`4F15Ý.Rh«}})'#ì®ä

D                                   # duplicate input
 gDtî©n-Ä                           # abs(len(input)-round_up(sqrt(len(input)))^2)
         ð×J                        # join that many spaces to end of input
            v                       # for each char in string
             yÇ                     # get ascii value
               h`                   # convert to base-16 number
                 4F                 # 4 times do:
                   15Ý.Rh           # push random base-16 number
                         «          # concatenate
                          }}        # end inner and outer loop
                            )       # wrap in list
                             '#ì    # prepend a "#" to each element in list
                                ®ä  # split in pieces round_up(sqrt(len(input))) long

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

Decode:

˜vy3£¦HçJ}ðÜ

˜               # deep flatten input to a list
 v              # for each color in the list
  y3£           # take the first 3 chars
     ¦          # remove the hash sign
      H         # convert from base-16 to base-10
       ç        # get the ascii char with that value
        J       # join to string
         }      # end loop
          ðÜ    # remove trailing spaces

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

Альтернативный метод заполнения с равным количеством байтов

Dgð×J¹gtî©n£

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

@ ais523: Правила гласят, что с 2D-массивами все в порядке. Я что-то не так понял?
Эминья

«Вы можете разделить табуляцией, запятыми или чем-то еще, что будет иметь смысл по горизонтали, но оно должно поддерживать квадратный узор; другими словами, вы должны использовать соответствующее разделение новой строки». строго подразумевает, что это должна быть строка, поскольку двумерные массивы по своей природе не содержат символов новой строки. Другими словами, я интерпретировал «массив» как описание формы вывода, а не типа данных вывода.

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

@ ais523 в любом случае приемлемо.
Волшебная Урна Осьминога

4

C, 201 (кодирование) + 175 (декодирование) = 376 байтов

Кодировать:

E(char*J){size_t L=ceil(sqrt(strlen(J)));int U;srand(time(NULL));for(int i=0;i<L;i++){for(int f=0;f<L;f++){printf("#%02X%02X%02X ",rand()%256,(U<strlen(J))?(int)J[U]:32,rand()%256);U+=1;}printf("\n");}}

Кодирует каждый символ входной строки в зеленом канале спектра RGB, устанавливая два других канала в качестве случайных шестнадцатеричных значений. Принимает ввод через STDIN в виде строки и выводит в STDOUT многострочную строку шестнадцатеричного цветового кода в форме квадрата. Предполагая, что у вас установлены Python 3 и ImageMagick, и указанный выше файл скомпилирован в файл с именем a.outв текущем рабочем каталоге (CWD), вы можете напрямую получить результирующий образ с именем Output.pngCWD из текстового вывода с помощью следующей команды:

./a.out "<Multiline Input>"|python3 -c "import sys,subprocess;Input=sys.stdin.read();print('# ImageMagick pixel enumeration: {0},{0},255,rgb\n'.format(len(Input.split('\n')[1].split()))+'\n'.join(['%d,%d:(%d,%d,%d)'%(g,i,int(j[1:][:2],16),int(j[1:][2:4],16),int(j[1:][4:6],16))for g,h in enumerate(Input.split('\n'))for i,j in enumerate(h.split())]))"|convert - -scale 1000% Output.png

Вот пример выходного изображения, созданного вышеуказанной запятой с использованием Programming Puzzles and Code Golfв качестве входной строки:

Пример вывода

Расшифровать:

D(int c,char**U){char T[c];for(int Y=1;Y<c;Y++){char G[2]={U[Y][3],U[Y][4]};T[Y-1]=(char)strtol(G,NULL,16);}int C=c-1;T[C]='\0';while(T[C]==' '){T[C]='\0';C-=1;}printf("%s\n",T);}

Принимает через STDIN последовательность строк шестнадцатеричного кода цвета, разделенных пробелами, каждая из которых заключена в двойные кавычки ( ") ( char** argvin main), а также, когда вызывается main,int argc для целочисленного ввода. Выводит в STDOUT одну / многострочную строку, представляющую декодированное сообщение.

Я буду стараться играть в гольф с течением времени, когда и где только смогу.


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

int main(int argc,char**argv){if(strcmp(argv[1],"E")==0){Encode(argv[2]);}else{Decode(argc,argv);}}

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


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


3

Python 2, 164 160 + 94 93 = 253 байта

Сохранено 1 + 1 байт благодаря Wheat Wizard.

-5 байт благодаря Kade

Encoder PictureКодировщик: строка должна быть заключена в кавычки, например "CodeGolf", вывод представляет собой цветное изображение ascii PPM.

from random import*
s=input()
n=int((len(s)-1)**0.5)+1
s=s.ljust(n*n)
r=randint
print"P3 %d %d 255 "%(n,n)+''.join("%d "*3%(r(0,255),r(0,255),ord(c))for c in s)

Декодер ИзображениеДекодер: принимает входное имя файла в качестве аргумента командной строки

from sys import*
print''.join(chr(int(c))for c in open(argv[1]).read().split()[6::3]).strip()

Использование:

 python golf_stegansquare_enc.py > stega.ppm

 python golf_stegansquare_dec.py stega.ppm

Пример:

Пазлы для программирования и Code GolfПазлы для программирования и Code Golf

Лорем ИпсумLorem Ipsum Dolor Sit Amet, Contetur Sadipscing Elitr, Sed Diam Nonumy Eirmod Tempor Invidunt UT Labore et Dolore Magna Aliquyam Erat, Sed Diam Volptua. В vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, нет моря Такимата святилище Есть Lorem Ipsum Долор Сит Амет. Lorem Ipsum Dolor Sit Amet, Contetur Sadipscing Elitr, Sed Diam Nonumy Eirmod Tempor Invidunt UT Labore et Dolore Magna Aliquyam Erat, Sed Diam Volptua. В vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, нет моря Такимата святилище Есть Lorem Ipsum Долор Сит Амет.


Вы можете удалить пространство между близким парнем, а затемfor
Post Rock Garf Hunter

@ETHproductions: sqrt (25-1) = sqrt (24) <5 и> 4. intиз этого получается 4, которое затем +1
редактируется

О, мой плохой, я не видел -1.
ETHproductions

1
Вы можете удалить пространство между printи 'в декодере. Я также уверен, что вы могли int((len(s)+1)**.5)бы сэкономить несколько байтов.
Каде

1
Я редактирую последнее предложение моего предыдущего комментария, однако вы можете сократить печать, изменив ' '.join("%d %d %d"на, ''.join(3*"%d "так как я почти уверен, что завершающий пробел в порядке.
Каде

2

Scala, 97 + 68 = 165 байт

Шифрование (97 байт):

s=>s.map(_+((math.random*65535).toInt<<8)).iterator.grouped(math.sqrt(s.size)toInt)withPadding 32

Принимает строку и повторно запускает итератор последовательностей целых чисел.

Расшифровка (68 байт):

a=>" +$".r.replaceAllIn(a.flatten.map(h=>(h&0xFF)toChar)mkString,"")

Принимает итератор последовательностей целых чисел и возвращает строку.

Объяснение:

s=>                         //define an anonymous function
  s.map(                      //map each char of the string
    _+(                         //to the ascii value plus
      (math.random*65535).toInt)  //a random integer between 0 and 65535
      <<8                         //shifted 8 bits to the left
    )
  )
  .iterator                     //create an iterator
  .grouped(                     //group them in groups of size...
    math.sqrt(s.size)toInt        //sqrt of the size of the input, rounded up
  )withPadding 32               //pad with spaces to make a square

,

a=>
  " +$"              //take this string
  .r                 //parse it as a regex
  .replaceAllIn(     //replace every occurence of the regex in...
    a.flatten          //a flattened
    .map(h=>           //each element mapped
      (h&0xFF)toChar)    //to the character of the lower 8 bits
    mkString,          //joined to a string
    ""               //with an empty string
  )

2

Perl, (103 + 1) + (36 + 2) = 142 байта

Кодер текста в изображение (выполняется с -p1-байтовым штрафом; -p0(для дополнительного байта штрафов) необходим, если вы хотите обрабатывать переводы строки во входной строке):

$_.=$"while($a=(length)**.5)=~/\./;$_=unpack"H*";s/../sprintf"#%04x$&,",rand+4**8/eg;s/(.*?\K,){$a}/
/g

Декодер изображения в текст (работает с -p02-байтовым штрафом):

$\.=chr hex for/..\W/g;$\=~s/ *$//}{

При этом используется #abcdefтекстовый формат изображения и кодируется синим каналом. Вот пример возможного вывода, заданного Programming Puzzles and Code Golfв качестве ввода:

# B4d250, # bccb72, # 43f06f, # 4d6767, # 74ba72, # 269461
# E4f26d, # f63d6d, # 701c69, # bbf56e, # 6ef967, # d78d20
# 4e0d50, # 9b2775, # afd37a, # 12a47a, # 63e46c, # 0e9565
# 4cad73, # e43420, # 6da761, # 5a306e, # 8fba64, # 58f720
# D52443, # b4446f, # fbaf64, # 4a4365, # 1a5020, # f3ea47
# 354c6f, # 52cb6c, # 11a766, # 4c380a, # 553820, # b31120

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

$_.=$"             # append a space ($") to the input ($_)
  while            # as long as the following condition holds:
(($a=length)**.5)  # the square root of the input length (save this in $a)
=~/\./;            # has no decimal points in its string represenation
$_=unpack"H*";     # convert the input from base-256 to hexadecimal
s/../              # replace two characters of the input
  sprintf          # with a string formed from the template
  "#%04x$&,",      # four hex digits, the two matched characters, and a comma
  rand+4**8        # those hex digits are a random number from 0 to 4**8 (= 65536)
/eg;               # and do this for every non-overlapping match
s/(.*?             # find the minimum number of characters needed to match
   \K,)            # replacing the part of the match after the last matched comma
  {$a}/            # a string containing $a commas
/gx                # with a newline, for every non-overlapping match

Я был действительно счастлив, что это использование \Kсработало; он указывает, где заменить, и помещая его в цикл, кажется, что вхождение в последнюю итерацию цикла имеет значение. Таким образом, s/(.*?\K,){$a}/\n/gбудет соответствовать строка минимальной длины в виде любой запятой, любой запятой ... любой запятой, которая имеет $aзапятые, но фактически замененная часть совпадения будет просто последней запятой. Это имеет эффект замены каждого$a запятой на новую строку, давая нам квадратную форму для изображения.

Большим преимуществом Perl для этой задачи (кроме встроенного символьно-шестнадцатеричного преобразователя строки, что было невероятно удобно) является то, что он имеет очень короткий декодер (настолько короткий, что, хотя в Perl есть встроенная функция для преобразование шестнадцатеричного в строку, это было короче, чтобы не использовать его). Вот как это работает:

$\.=chr      # append to $\ the character code
  hex        # of the hexadecimal-string-to-number-translation
for/..\W/g;  # of each two characters that appear before a
             # non-alphanumeric character (not counting overlapping matches)
$\=~s/ *$//  # delete all spaces at the end of $\
}{           # in this context, this means "implicitly print $\,
             # prevent any other implicit printing"

Единственными экземплярами двух символов непосредственно перед не алфавитно-цифровым символом являются синие каналы (которые мы хотим распаковать), которые появляются непосредственно перед запятыми и символами новой строки; и два символа, которые появляются друг перед #другом, чем первый. Мы не хотим последней категории совпадений, но они неизбежно перекрывают первую категорию и, таким образом, будут исключены проверкой перекрывающихся совпадений.


1

MySQL, 438 + 237 = 675 байт

В конце выходных данных есть завершающая новая строка, но она не отображается после расшифровки. Шестнадцатеричная функция (целочисленная перегрузка) отсекает начальные 0, поэтому мне пришлось заполнить ее строкой 0. Я мог бы сохранить несколько байтов, если бы мог объявить обе функции между разделителями.

шифровать

delimiter //create function a(i text)returns text begin declare r int;declare q,p text;while mod(length(i),sqrt(length(i)))<>0 do set i:=concat(i,' ');end while;set r:=1;set q:="";while r<=length(i) do set p:=",";if mod(r,sqrt(length(i)))=0 then set p:="\r\n";end if;set q:=concat(q,'#',right(concat(0,hex(floor(rand()*256))),2),right(concat(0,hex(floor(rand()*256))),2),hex(mid(i,r,1)),p);set r:=r+1;end while;return q;end//
delimiter ;

Расшифровать

delimiter //create function b(i text)returns text begin declare x int;declare y text;set x:=0;set y:="";while instr(i,'#')>0 do set i:=substr(i,instr(i,'#')+5);set y:=concat(y,unhex(left(i,2)));end while;return trim(y);end//
delimiter ;

Использование:

select a('test')
select b('#7D1874,#FFB465')
select b(a('test'))

1

C #, 312 + 142 = 454 байта

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

using System;I=>{var r=new Random();int i=I.Length;int N=(int)Math.Floor(Math.Sqrt(i))+1,S=N*N;while(i++<S){I+=' ';}var R="";for(i=0;i<S;){R+=i%N<1&i>0?"\n":i<1?"":" ";R+="#"+r.Next(256).ToString("X").PadLeft(2,'0')+r.Next(256).ToString("X").PadLeft(2,'0')+((int)I[i++]).ToString("X").PadLeft(2,'0');}return R;};

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

using System;I=>{var s=I.Replace('\n',' ').Split(' ');var R="";foreach(var t in s)R+=(char)System.Convert.ToInt32(t[5]+""+t[6],16);return R.TrimEnd(' ');};

Полная программа:

using System;
class Steganographic
{
    static void Main()
    {
        Func<string, string> E = null;
        Func<string, string> D = null;

        E=I=>
        {
            var r=new Random();
            int i=I.Length;
            int N=(int)Math.Floor(Math.Sqrt(i))+1,S=N*N;
            while(i++<S){I+=' ';}
            var R="";
            for(i=0;i<S;)
            {
                R+=i%N<1&i>0?"\n":i<1?"":" ";
                R+="#"+r.Next(256).ToString("X").PadLeft(2,'0')+r.Next(256).ToString("X").PadLeft(2,'0')+((int)I[i++]).ToString("X").PadLeft(2,'0');
            }
            return R;
        };

        D=I=>
        {
            var s=I.Replace('\n',' ').Split(' ');
            var R="";
            foreach(var t in s)
                R+=(char)Convert.ToInt32(t[5]+""+t[6],16);
            return R.TrimEnd(' ');
        };

        string encoded = E("Programming Puzzles and Code Golf");
        Console.WriteLine(encoded);
        Console.WriteLine(D(encoded));

        encoded = E("Hello, World!");
        Console.WriteLine(encoded);
        Console.WriteLine(D(encoded));

        Console.Read(); // For Visual Studio
    }
}

1

Mathematica, 111 + 65 = 176 байт

кодировщик

Join[255~RandomInteger~{n=⌈Sqrt@Length@#⌉,n,2},ArrayReshape[#,{n,n,1},32],3]~Image~"Byte"&@*ToCharacterCode

дешифратор

StringTrim[""<>FromCharacterCode@ImageData[#,"Byte"][[;;,;;,3]]]&

1

Обработка, 220 209 194 + 171 167 151 = 391 380 376 361 345 байт

Обновить:

Удалены бесполезны noStroke()и сделаны оба цикла for-statementers.

Удалено бесполезно image(p,0,0);, расшифровщик дал имя файла в качестве параметра

Алгоритм шифрования

void g(String h){int s=ceil(sqrt(h.length()));for(int y=0,x;y<s;y++)for(x=0;x<s;rect(x,y,1,1),x++)stroke(h.length()>y*s+x?h.charAt(y*s+x):32,random(255),random(255));get(0,0,s,s).save("t.png");}

Вызов функции: g("Programming Puzzles and Code Golf");

Это функция, которая принимает строку и создает вывод, прежде чем сохранить его как t.png. Он использует redзначение для хранения скрытого текста.

Алгоритм дешифрования

void u(String f){PImage p=loadImage(f);f="";for(int j=0,i;j<p.height;j++)for(i=0;i<p.width;i++)f+=(char)red(p.get(i,j));print(f.replaceAll(" +$",""));}

Вызов функции по: u(file_name);

Это также функция, которая ищет изображение, указанное в параметре, а затем выводит скрытую строку (поскольку она короче, чем возвращение строки).

Расширенный код

(Алгоритм шифрования)

void g(String h) {
  int s=ceil(sqrt(h.length()));
  for(int y=0,x;y<s;y++)
    for(x=0;x<s;rect(x,y,1,1),x++)
      stroke(h.length()>y*s+x?h.charAt(y*s+x):32,random(255),random(255));
  get(0,0,s,s).save("t.png");
}

Строка передается при вызове функции. Первая строка функции вычисляет длину стороны квадрата, беря ceilего квадратный корень. Затем мы вводим цикл for, в котором мы устанавливаем stroke(цвет края), чтобы значение ASCII символа было красным, а случайные значения - синим и зеленым. После этого мы создаем rect(прямоугольник) с шириной = 1и высотой = 1, то есть пикселем (по какой-то странной причине я не могу использовать pointправильно). В последней строке полученное изображение затем сохраняется какt.png .

(Алгоритм расшифровки)

void u(String f) {
  PImage p=loadImage(f);
  f="";
  for(int j=0,i;j<p.height;j++)
    for(i=0;i<p.width;i++)
      f+=(char)red(p.get(i,j));
  print(f.replaceAll(" +$",""));
}

Эта функция имеет имя файла в качестве параметра (в виде строки). Затем изображение в файле сохраняется в переменной для последующего использования. После того, как мы закончили с этим, мы устанавливаем строку ""вместо того, чтобы создавать новую строку просто для хранения скрытой строки. Затем мы перебираем изображение через два вложенных цикла for и добавляем в строку символьное значение красного значения пикселя. Наконец, мы печатаем полученную строку после удаления начальных пробелов из нее (используя регулярное выражение). Причина, по которой мы печатаем скрытый текст, а не возвращаем его, заключается в том, что таким образом он короче и мы сохраняем байты.


Зашифрованный текст запроса:

введите описание изображения здесь


1

Желе, 40 + 20 = 60 байт в кодовой странице желе

Кодировщик (текст → изображение):

”#;;ØHX¤¥4¡
»⁶x⁹²¤¤Ob⁴‘ịØHÇ€sj€”,Y
L½Ċç@

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

Декодер (изображение → текст):

ḣ2ØHiЀ’ḅ⁴Ọ
ṣ”#Ç€œr⁶

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

Пример вывода, который может выдать программа (она хранит информацию в красном канале):

#504219,#720200,#6F38F1,#67055F,#7228C7,#61AC95
#6DD797,#6D20CB,#6962FA,#6E69B1,#67C41C,#209436
#50CB19,#75C9FC,#7A1B06,#7A695B,#6C5D5B,#6539A6
#735925,#20C80F,#612C38,#6EBF9E,#64C79E,#200915
#4337C5,#6F4704,#64FB5F,#65B2D1,#20E075,#47BC7C
#6F0C16,#6CD8EF,#66060B,#203C6C,#20D6E9,#20C0D7

В этих более сложных задачах краткость Jelly начинает немного уменьшаться, требуя нескольких «структурных» символов для разрешения разборов, но, тем не менее, все еще очень краткая. Вот как работает кодировщик:

Subroutine 1: convert digits to randomly padded hex string
”#;;ØHX¤¥4¡
”#;                     prepend #
    ØHX                 random hexadecimal digit
       ¤                parse ØH and X as a unit
   ;                    append
        ¥               parse ; and ØHX¤ as a unit
         4¡             repeat four times

Subroutine 2: convert string λ to square with size ρ
»⁶x⁹²¤¤Ob⁴‘ịØHÇ€sj€”,Y
 ⁶                      space
   ⁹²                   ρ squared
     ¤                  parse ⁹² as a unit
  x                     repeat string (i.e. ρ² spaces)
      ¤                 parse ⁶x⁹²¤ as a unit
»                       take maximum
Because space has the lowest value of any printable ASCII character,
this has the effect of padding λ to length ρ² with spaces.
       O                take codepoints of string
        b⁴              convert to base 16
           ịØH          use as indexes into a list of hexadecimal digits
          ‘             0-indexed (Jelly uses 1-indexing by default)
              ǀ        run subroutine 1 on each element
                s       split into groups of size ρ
                  €     inside each group
                 j ”,   join on commas
                     Y  join on newlines

Main program: basically just calculates ρ and lets subroutine 2 do the work
L½Ċç@
L                       length of input
 ½                      square rooted
  Ċ                     rounded up to the next highest integer
   ç@                   call subroutine 2 with the original input and the above

А вот как работает декодер:

Subroutine: convert hexadecimal color string (without #) to character
ḣ2ØHiЀ’ḅ⁴Ọ
ḣ2                      take first two characters
  ØHi                   find indexes in a string of hexadecimal digits
     Ѐ                 for each of those characters
       ’                0-indexed (Jelly uses 1-indexing by default)
        ḅ⁴              convert from base 16
          Ọ             convert integer to character

Main program:
ṣ”#Ç€œr⁶
ṣ”#                     split on # signs
   ǀ                   run the subroutine for each element
     œr⁶                remove spaces from the right
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.