Стеганографічні квадрати


14

Стеганографічні квадрати

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

Алгоритм "Шифрування" + Алгоритм "Розшифрування" .

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


Приклад алгоритму

Наприклад, ось "Головоломки програмування та кодовий гольф", використовуючи простий стеганографічний алгоритм на основі ASCII на каналі "Синій":

#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 символ на піксель.
Чарівний восьминога Урна

Я, мабуть, не збираюся цим користуватися, але: чи гаразд "перекривати" зображення з більшою кількістю пробілів, ніж потрібно? І чи гарно припускати, що зображення матиме таку ж кількість перевищення, як і кодер?

@ ais523 Я не можу побачити, як цей тип підходу зробив би щось, але потрібно більше байтів для реалізації. Я все одно не збираюся, оскільки виклик занадто старий, щоб зробити такі великі зміни.
Чарівна урва восьминога

1
Правильно, я не був впевнений, чи це було дозволено в оригінальному запитанні, а не рекомендувати зміни. (Я думав про упаковку введення в прямокутник, який має простіший і, можливо, коротший байт обчислень координат, ніж упаковка його в квадрат, а потім прокладка прямокутника на більший квадрат.)

Відповіді:


2

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

Використовує червоний канал.
05AB1E використовує кодування CP-1252 .

Кодування:

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

Спробуйте в Інтернеті!

Розшифруйте:

˜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 масиви були в порядку. Чи я це неправильно зрозумів?
Емінья

"Ви можете відокремити вкладки, коми або що-небудь інше, що було б чутним по горизонталі, але воно повинно підтримувати квадратний малюнок; іншими словами, ви повинні використовувати відповідне розділення нового рядка." настійно означає, що він повинен бути рядком, оскільки 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.png, на CWD з текстового виводу за допомогою наступної команди:

./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для цілого вводу. Виводить для ВИЗНАЧЕННЯ одно / багаторядкового рядка, що представляє декодоване повідомлення.

Я спробую пограти в гольф більше з часом, коли і де можу.


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

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

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


Нарешті, якщо ви хочете, ви можете отримати повністю підготовлену, готову до використання версію тут , хоча вона не є гольф, але також не видає жодних попереджень чи помилок при компіляції.


3

Пітон 2, 164 160 + 94 93 = 253 байти

Збережено 1 + 1 байт завдяки майстру пшениці.

-5 байт завдяки Kade

Зображення кодераЕнкодер: рядок повинен бути укладений у лапки, наприклад "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

Приклад:

Програмування Головоломки та Код ГольфПрограмування Головоломки та Код Гольф

Лорем ІпсумLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.


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

@ETHproductions: sqrt (25-1) = sqrt (24) <5 і> 4. intз цього виходить 4, який потім видається +1, тому 5
Karl Napf

О, моє погано, я не бачив цього -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

Математика, 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()і зробили обидва для петлі одностатевими.

Видалено марно 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(" +$",""));
}

Ця функція має ім'я файлу як параметр (як рядок). Тоді зображення у файлі зберігається у змінній, яка буде використана пізніше. Після того, як ми закінчимо з цим, ми встановимо рядок ""замість того, щоб створити новий рядок просто для того, щоб утримувати прихований рядок. Потім ми повторюємо зображення через дві вкладені цикли і додаємо до рядка значення символу червоного значення пікселя. Нарешті, ми друкуємо отриманий рядок після видалення з нього провідних пробілів (використовуючи регулярний вираз). Причина, коли ми друкуємо прихований текст, а не повертати його, тому що таким чином він коротший і ми економимо байти.


Зашифрований вихідний вихідний текст:

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


1

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

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

”#;;Ø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

У цих більших викликах терміновість Джеллі починає трохи знижуватися, для вирішення неоднозначностей потрібно кілька "структурних" персонажів, але, тим не менш, вона все ще є дуже короткою. Ось як працює кодер:

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.