Steganografik Kareler


14

Steganografik Kareler

İşiniz bir dize alıp NxNbu dizeyi temsil eden bir görüntü oluşturmaktır . Ayrıca görüntüyü alan ve bir dizgeye dönüştüren algoritmayı da yazmalısınız. Puanlama, her iki algoritmanın bayt sayısını içerecektir:

"Şifreleme" Algoritması + "Şifre Çözme" Algoritması .

Her birini ayrı ayrı, hem şifreleme hem de şifre çözme algoritmaları için ayrı ayrı görüntülenen bayt sayılarıyla göndermelisiniz.


Örnek Algoritma

Örneğin, Mavi kanalda basit bir ASCII tabanlı steganografik algoritma kullanan "Programlama Bulmacaları ve Kod Golfü":

#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

Gerçek Görüntü ( Algoritma tarafından oluşturulan görüntü.)

Görüntü patladı.

Mavi kanalın bu görüntü için ascii değerlerini tuttuğunu görebilirsiniz:

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( )

Kanalların geri kalanı görüntüdeki renk çeşitliliğini "arttırmak" için rastgele oluşturulmuş değerleri tutarken. Mesajı görüntüden geri çekerken, diğer kanal değerlerini görmezden gelebilir ve dizeyi yeniden yapılandırarak mavi kanaldaki altıgen biti çekebiliriz:

"Programming Puzzles and Code Golf"

Kare içinde dizeyi doldurmak için kullanılan boşlukların son şifresi çözülmüş çıktıya dahil olmadığına dikkat edin. Dizeyi görüntüde doldurmanız gerekir, ancak giriş dizesinin boşluklarla bitmeyeceğini varsayabilirsiniz.


kurallar

  • Piksel başına 1 karakter kodlamanız gerekir, karakteri kodlamak için seçilen kanal isteğe bağlıdır.
  • Dizeyi kodlamak için seçtiğiniz kanal dışında, diğer RGB renklerinin kanalları rastgele olmalıdır; Bu, kodlanmamış son kanallarınızın arasında 0x0000-0xFFFF(rastgele seçilmiş) olması gerektiği anlamına gelir .
  • Nihai sonucu 2B RGB renk değerleri dizisi olarak ifade etmek iyidir 0x000000-0xFFFFFF, onunla eğlenmek istemiyorsanız veya daha az bayt değilse görüntü oluşturmaya gerek yoktur. Onaltılık dizeler olarak çıktı almayı seçerseniz, altıgen dizenin önüne #EG #FFFFFFveya ekleyin #05AB1E. Sekmeler, virgüller veya yatay olarak algılanabilecek başka bir şeyle ayrılabilirsiniz, ancak kare desenini korumalıdır; diğer bir deyişle, uygun satırsonu ayırmayı kullanmalısınız.
  • Çıktı kare şeklinde olmalı ve dizeyi buna uygun olacak şekilde sonunda boşluk bırakılmalıdır. Bu demektir N≈SQRT(Input#Length()). Giriş uzunluğu mükemmel bir kare değilse, yuvarlanmalı Nve boşluk bırakılmalıdır .
  • Daha önce belirtildiği gibi, görüntüdeki boşluklarla dolduruyorsanız, doldurulmuş karakterleri son "şifresi çözülmüş" çıktıya dahil etmemelisiniz.
  • Şunu kabul edebilirsiniz:
    • Giriş dizesi boşluklarla bitmez.
    • Giriş dizesi yalnızca yazdırılabilir ASCII karakterlerini kullanır.
  • Bu , en düşük bayt sayısı kazanır.

Açıklığa kavuşturmak için, çözümlerin piksel başına tam olarak bir karakteri kodlaması / kodunu çözmesi gerekir mi?
ETHproductions

İyi bir takip zorluğuna benzeyen yapımlar, ancak bu yarışmanın amacı için bir kodlama kanalı seçiyor ve piksel başına 1 karakteri kodluyorsunuz.
Sihirli Ahtapot Urn

Muhtemelen bunu kullanmayacağım, ama: görüntüyü gereğinden fazla boşlukla "aşmak" uygun mudur? Ve görüntünün kodlayıcının üreteceği miktarla aynı miktarda fazla dolguya sahip olacağını varsaymak doğru mu?

@ ais523 Bu tür bir yaklaşımın nasıl uygulanacağından başka bir şey yapamayacağını göremiyorum. Ben zorlanmayacağım, çünkü meydan okuma böyle büyük değişiklikler yapmak için çok eski.
Sihirli Ahtapot Urn

1
Doğru, bir değişiklik önermek yerine orijinal soruya izin verilip verilmediğinden emin değildim. (Girdiyi bir kareye paketlemekten daha kolay ve muhtemelen bayt-daha kısa koordinat hesaplamalarına sahip bir dikdörtgene paketlemeyi, sonra dikdörtgeni daha büyük bir kareye doldurmayı düşünüyordum.)

Yanıtlar:


2

05AB1E , 34 + 12 = 46 bayt

Kırmızı kanal kullanır.
05AB1E, CP-1252 kodlaması kullanır .

kodlama:

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

Çevrimiçi deneyin!

Kod Çözme:

˜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

Çevrimiçi deneyin!

Eşit bayt sayısı ile alternatif dolgu yöntemi

Dgð×J¹gtî©n£

Soruya göre özellikle yeni satırlara katılmanız gerektiğini düşünüyorum? (Yanıtınız, bunu yapmak için uyarlanmış olsa bile muhtemelen benimkini

@ ais523: Kurallar, 2D dizilerin iyi olduğunu belirtir. Bunu bir şekilde yanlış anladım mı?
Emigna

"Sekmelerle, virgüllerle veya yatay olarak algılanabilecek başka bir şeyle ayrılabilirsiniz, ancak kare desenini korumalıdır; başka bir deyişle, uygun satırsonu ayırmasını kullanmalısınız." 2B diziler doğal olarak yeni satır içermediğinden, bir dize olması gerektiği anlamına gelir. Başka bir deyişle, "dizi" yi, çıktının veri türünü değil, çıktı şeklini açıklayan olarak yorumladım.

@ ais523: OP'den açıklama istedim. Dediğiniz gibi, uygulanması büyük bir değişiklik değil, ancak biçimlendirme gerekli değilse belki de bayt kaydedebilirsiniz.
Emigna

@ ais523 her iki şekilde de kabul edilebilir.
Sihirli Ahtapot Urn

4

C, 201 (Kodlama) + 175 (Kod Çözme) = 376 bayt

Kodlamak için:

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");}}

Diğer iki kanalı rastgele onaltılı değerler olarak ayarlarken, giriş dizesinin her karakterini RGB spektrumunun yeşil kanalında kodlar. STDIN üzerinden bir dize olarak girdi alır ve bir kare şeklinde onaltılık renk kodlu çok satırlı bir dize STDOUT'a çıktılar. Python 3 ve ImageMagick'in yüklü olduğunu ve yukarıdaki dosyanın a.outgeçerli çalışma dizininde (CWD) adlandırılmış bir dosyada derlendiğini varsayarsak , elde edilen görüntüyü Output.pngaşağıdaki komutu kullanarak metin çıktısından doğrudan CWD'ye alabilirsiniz :

./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 GolfGirdi dizesi olarak yukarıdaki commamd tarafından oluşturulan örnek çıktı görüntüsü :

Örnek Çıktı

Kod Çözmek için:

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);}

Her bir (çift tırnak içinde bir ile STDIN'den yoluyla boşlukla ayrılmış heks renk kodu şeritlerinin bir dizi girişi alır "() char** argviçinde mainolarak adlandırılır de), ve main, int argctam sayı girişi için. Kod çözülen mesajı temsil eden tek / çok satırlı bir dize STDOUT'a çıktılar.

Bunları zaman ve nerede yapabileceğim konusunda daha fazla golf oynamaya çalışacağım.


Ayrıca, her iki yöntemi de aynı dosyaya mainbağlarsanız, her yöntemi doğru girişleri alan her bir işlevle bir araya getirmek için aşağıdaki yöntemi kullanabilirsiniz :

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

ve bunu kullanarak, kodlama Eiçin kodlama yöntemini çağırmak için ilk argüman ve ardından tek dize argümanını sağlamanız gerekirken, kod çözme için sağlamanız gereken tek şey, her biri içine alınmış boşlukla ayrılmış onaltılık renk kodu dizilerinin dizisidir. çift ​​tırnak ( ").


Son olarak, isterseniz, tam hazırlanmış, kullanıma hazır sürümü burada bulabilirsiniz , ancak golf olmasa da, derleme üzerine herhangi bir uyarı veya hata vermez .


3

Python 2, 164160 + 94 93 = 253 bayt

Buğday Sihirbazı sayesinde 1 + 1 bayt tasarruf edildi.

Kade sayesinde -5 bayt

Kodlayıcı ResmiKodlayıcı: dize tırnak içine alınmalıdır, örneğin "CodeGolf"çıktı bir renk ascii PPM görüntüsüdür.

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)

Kod Çözücü ResmiKod çözücü: Girdi dosya adını komut satırı bağımsız değişkeni olarak alır

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

Kullanımı:

 python golf_stegansquare_enc.py > stega.ppm

 python golf_stegansquare_dec.py stega.ppm

Misal:

Programlama Bulmacaları ve Code GolfProgramlama Bulmacaları ve Code Golf

Lorem IpsumLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. Vero eos et accusam ve justo duo dolores ve ea rebum'da. Stet clita kasd gubergren, deniz 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. Vero eos et accusam ve justo duo dolores ve ea rebum'da. Stet clita kasd gubergren, deniz takimata sanctus est Lorem ipsum dolor sit amet.


Yakın paren arasındaki boşluğu kaldırabilir ve sonrafor
Post Rock Garf Hunter

@ETHproductions: sqrt (25-1) = sqrt (24) <5 ve> 4. intbundan sonra 4 olan +1ed, bu yüzden 5
Karl Napf

Oh, benim hatam, görmedim -1.
ETHproductions

1
Kod çözücü arasındaki printve 'kod çözücü arasındaki boşluğu kaldırabilirsiniz . Ayrıca int((len(s)+1)**.5)bazı baytları kaydetmek için yapabileceğinizden de eminim .
Kade

1
Önceki yorumumun son cümlesini düzeltiyorum, ancak sondaki boşluğun iyi olduğundan emin olduğum ' '.join("%d %d %d"için değiştirerek baskıyı kısaltabilirsiniz ''.join(3*"%d ".
Kade

2

Scala, 97 + 68 = 165 bayt

Şifreleme (97 bayt):

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

Bir String alır ve bir Tamsayı Dizileri Yineleyicisini yeniden dener.

Şifre çözme (68 bayt):

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

Tamsayılar Dizisi Yineleyicisini alır ve bir dize döndürür.

Açıklama:

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 bayt

Metin-görüntü kodlayıcı ( -p1 baytlık bir ceza için çalıştır ; -p0(ek bir baytlık ceza için) giriş dizesindeki yeni satırları işlemek istiyorsanız gereklidir):

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

Resimden metne dekoderi ( -p02 baytlık bir ceza için çalıştırın ):

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

Bu, #abcdefmetin tabanlı görüntü biçimini kullanır ve mavi kanalda kodlar. Programming Puzzles and Code GolfGiriş olarak verilen olası bir çıktıya bir örnek :

# 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

Kodlayıcının açıklaması:

$_.=$"             # 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

Çalışmanın bu kullanımından gerçekten memnun kaldım \K; nerede değiştirileceğini belirler ve bir döngünün içine yerleştirirse, son döngü yinelemesinde gerçekleşmenin önemli olduğu görülmektedir. Yani s/(.*?\K,){$a}/\n/gformu minimum uzunlukta dize maç olacak şey virgül şey virgül ... şey vardır virgül, $avirgül, ama maçın gerçek yerini kısmı sadece son virgül olacak. Bu, her $avirgülün yerini bir satırsonu ile değiştirerek bize görüntü için kare şekli verir.

Bu meydan okuma için Perl'in en büyük avantajı (inanılmaz derecede kullanışlı olan dahili karakter dizgiden onaltılık dönüştürücüye dışında) çok kısa bir kod çözücüye sahip olması (aslında, Perl için bir yerleşik olmasına rağmen onaltılık bir dizgeye dönüştürülürse, onu kullanmamak daha kısaydı). Şöyle çalışır:

$\.=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"

Alfasayısal olmayan bir karakterden hemen önce iki karakterin tek örneği, virgül ve satırsonlarından hemen önce görünen mavi kanallardır (paketini açmak istediğimiz); ve birbirinden önce birinciden önce görünen iki karakter #. İkinci eşleşme kategorisini istemiyoruz, ancak kaçınılmaz olarak eski kategoriyle çakışıyor ve bu nedenle örtüşen eşleşme kontrolü tarafından hariç tutulacak.


1

MySQL, 438 + 237 = 675 bayt

Çıktının sonunda yeni bir satır var, ancak şifresi çözüldükten sonra görünmüyor. Onaltılık işlevi (tamsayı aşırı) 0 önde keser, bu yüzden bir dize 0 ile doldurmak zorunda kaldım. Sınırlayıcılar arasında her iki işlevi de beyan edebilseydim bazı baytlar kaydedebilirim.

şifrele

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 ;

azalmak

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 ;

Kullanımı:

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

1

C #, 312 + 142 = 454 bayt

Kodlama:

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;};

deşifre etmek:

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(' ');};

Tam program:

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 bayt

Encoder

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

şifre çözücü

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

1

İşlem, 220 209 194 + 171 167 151 = 391 380 376 361 345 bayt

Güncelleme:

İşe yaramaz hale geldi noStroke()ve her iki for döngüsü için de tek açıklama yaptı.

Yararsız kaldırıldı image(p,0,0);, şifre çözücüye parametre olarak dosya adı verdi

Şifreleme algoritması

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");}

İşlevi çağırmak: g("Programming Puzzles and Code Golf");

Bu, bir Dize alan ve çıktıyı olarak kaydetmeden önce oluşturan bir işlevdir t.png. redGizli metni saklamak için değeri kullanır .

Şifre Çözme Algoritması

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(" +$",""));}

Çağrı fonksiyonu: u(file_name);

Bu aynı zamanda parametre tarafından belirtilen görüntüyü arayan ve daha sonra gizli dize çıktısını veren bir işlevdir (bir dize döndürmekten daha kısa olduğu için).

Genişletilmiş kod

(Şifreleme algoritması)

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");
}

Dize, işlev çağrıldığında geçirilir. Fonksiyonun ilk satırı, ceilkarekökünü alarak karenin yan uzunluğunu hesaplar . Sonra bir for-loop giriyoruz, burada strokekarakterin ASCII değerini kırmızı ve mavi ve yeşil için rastgele değerler olacak şekilde (kenarın rengi) ayarlıyoruz . Bunu yaptıktan sonra, rectwidth = 1ve height = 1, yani bir pikselle (bazı tuhaf nedenlerden dolayı pointdüzgün kullanamıyorum ) bir (dikdörtgen) oluşturuyoruz . Son satırda, sonuçta elde edilen görüntü olarak kaydedilir t.png.

(Şifre Çözme Algoritması)

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(" +$",""));
}

Bu işlev dosyanın adını parametre olarak (dize olarak) alır. Daha sonra dosyadaki görüntü daha sonra kullanılmak üzere bir değişkende saklanır. Bunu yaptıktan sonra, ""dizeyi yalnızca gizli dizeyi tutmak için yeni bir dize oluşturmak yerine olarak ayarladık . Sonra görüntüyü iki iç içe döngü için yineliyoruz ve pikselin kırmızı değerinin karakter değerini dizeye ekliyoruz. Son olarak, sonuçtaki dizeyi ondan önde gelen boşlukları çıkardıktan sonra yazdırırız (normal ifade kullanarak). Gizli metni döndürmek yerine yazdırmamızın nedeni, bu şekilde daha kısa olması ve bayt tasarrufu yapmamızdır.


Şifreli sınama ham metni:

resim açıklamasını buraya girin


1

Jelly, 40 + 20 = Jelly kod sayfasında 60 bayt

Kodlayıcı (metin → resim):

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

Çevrimiçi deneyin!

Kod çözücü (resim → metin):

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

Çevrimiçi deneyin!

Programın üretebileceği bir örnek çıktı (kırmızı kanalda bilgi depolar):

#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

Bu daha büyük zorluklarda, Jelly'in tersliği biraz düşmeye başlar ve ayrıştırma belirsizliklerini çözmek için birkaç "yapısal" karaktere ihtiyaç duyar, ancak yine de çok gerçektir. Kodlayıcı şu şekilde çalışır:

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

Ve kod çözücü şu şekilde çalışır:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.