Steganographische Quadrate


14

Steganographische Quadrate

Ihre Aufgabe ist es, eine Zeichenfolge aufzunehmen und ein NxNBild zu generieren , das diese Zeichenfolge darstellt. Sie müssen auch den Algorithmus schreiben, der das Bild aufnimmt und es wieder in eine Zeichenfolge umwandelt. Die Bewertung wird die Anzahl der Bytes beider Algorithmen beinhalten:

Algorithmus "Verschlüsselung" + Algorithmus "Entschlüsselung" .

Sie sollten jedes einzeln veröffentlichen, wobei die Byteanzahl sowohl für die Verschlüsselungs- als auch für die Entschlüsselungsalgorithmen einzeln angezeigt wird.


Beispielalgorithmus

Hier ist zum Beispiel das "Programmieren von Rätseln und Code Golf" mit einem einfachen ASCII-basierten steganografischen Algorithmus im blauen Kanal:

#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

Tatsächliches Bild ( Das vom Algorithmus erzeugte Bild.)

Bild vergrößert.

Sie können sehen, dass der blaue Kanal einfach die ASCII-Werte für dieses Bild enthält:

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

Während der Rest der Kanäle zufällig generierte Werte enthält, wird die Vielfalt der Farben im Bild "aufgepeppt". Wenn Sie die Nachricht wieder aus dem Bild ziehen, können Sie einfach die anderen Kanalwerte ignorieren und das Hex-Bit im blauen Kanal ziehen, um die Zeichenfolge zu rekonstruieren:

"Programming Puzzles and Code Golf"

Beachten Sie, dass die Leerzeichen, die zum Auffüllen der Zeichenfolge im Quadrat verwendet wurden, in der endgültigen entschlüsselten Ausgabe nicht enthalten sind. Während Sie die Zeichenfolge im Bild auffüllen müssen, können Sie davon ausgehen, dass die Eingabezeichenfolge nicht mit Leerzeichen endet.


Regeln

  • Sie müssen 1 Zeichen pro Pixel codieren, der Kanal, der zum Codieren des Zeichens ausgewählt wurde, ist willkürlich.
  • Die Kanäle der anderen RGB-Farben müssen nach dem Zufallsprinzip ausgewählt werden. Dies bedeutet, dass Ihre letzten nicht codierten Kanäle zwischen 0x0000-0xFFFF(zufällig ausgewählt) liegen müssen.
  • Das Endergebnis als 2D-Array von RGB-Farbwerten auszudrücken, ist in Ordnung 0x000000-0xFFFFFF. Sie müssen die Bilderstellung nicht verwenden, es sei denn, Sie möchten Spaß damit haben oder es sind weniger Bytes. Wenn Sie sich für die Ausgabe als Hex-Zeichenfolge entscheiden, stellen Sie der Hex-Zeichenfolge #EG #FFFFFFoder voran #05AB1E. Sie können mit Tabulatoren, Kommas oder allem anderen trennen, was horizontal sinnvoll wäre, aber das quadratische Muster muss beibehalten werden. Mit anderen Worten, Sie müssen einen geeigneten Zeilenumbruch verwenden.
  • Die Ausgabe muss in einem Quadrat erfolgen, und die Zeichenfolge muss am Ende mit Leerzeichen aufgefüllt werden, um dies zu berücksichtigen. Das bedeutet das N≈SQRT(Input#Length()). Wenn die eingegebene Länge kein perfektes Quadrat ist, sollten Sie aufrunden Nund mit Leerzeichen auffüllen.
  • Wie bereits erwähnt, dürfen Sie beim Auffüllen mit Leerzeichen im Bild die aufgefüllten Zeichen nicht in die endgültige "entschlüsselte" Ausgabe einbeziehen.
  • Sie können davon ausgehen, dass:
    • Die Eingabezeichenfolge endet nicht mit Leerzeichen.
    • Die Eingabezeichenfolge verwendet nur druckbare ASCII-Zeichen.
  • Dies ist , die niedrigste Anzahl an Bytes gewinnt.

Um dies zu verdeutlichen, müssen Lösungen genau ein Zeichen pro Pixel codieren / decodieren .
ETHproductions

@ETHproductions, das klingt wie eine gute Folgeherausforderung, aber für diesen Wettbewerb wählen Sie einen Kodierungskanal und kodieren 1 Zeichen pro Pixel.
Magic Octopus Urn

Ich werde das wahrscheinlich nicht verwenden, aber: Ist es in Ordnung, das Bild mit mehr Leerzeichen als nötig zu "überfüllen"? Und ist es in Ordnung anzunehmen, dass das Bild die gleiche Überfüllung aufweist, die der Encoder erzeugen würde?

@ AIS523 Ich kann nicht sehen, wie diese Art von Ansatz alles tun würde, außer mehr Bytes zu implementieren. Ich werde mit Nein weitermachen, da die Herausforderung zu alt ist, um so große Änderungen vorzunehmen.
Magic Octopus Urn

1
Richtig, ich war mir nicht sicher, ob es in der ursprünglichen Frage erlaubt war, anstatt eine Änderung zu empfehlen. (Ich habe darüber nachgedacht, die Eingabe in ein Rechteck zu packen.

Antworten:


2

05AB1E , 34 + 12 = 46 Bytes

Verwendet roten Kanal.
05AB1E verwendet die CP-1252- Codierung.

Kodieren:

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

Probieren Sie es online!

Dekodieren:

˜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

Probieren Sie es online!

Alternative Auffüllmethode mit gleicher Bytezahl

Dgð×J¹gtî©n£

Ich denke du musst gezielt an Newlines teilnehmen, je nach Fragestellung? (Ihre Antwort wird wahrscheinlich meine übertreffen, selbst wenn sie dafür geeignet ist, da ich nur fünf Bytes für diesen Teil der Frage aufgewendet habe und Sie mehr als das voraus sind.)

@ ais523: Die Regeln besagen, dass 2D-Arrays in Ordnung waren. Habe ich das irgendwie falsch verstanden?
Emigna

"Sie können mit Tabulatoren, Kommas oder allem anderen trennen, was horizontal sinnvoll wäre, aber es muss das quadratische Muster beibehalten; mit anderen Worten, Sie müssen einen geeigneten Zeilenumbruch verwenden." impliziert nachdrücklich, dass es sich um eine Zeichenfolge handeln muss, da 2D-Arrays keine Zeilenumbrüche enthalten. Mit anderen Worten, ich habe "Array" so interpretiert, dass es die Form der Ausgabe beschreibt, nicht den Datentyp der Ausgabe.

@ ais523: Ich habe das OP um Klarstellung gebeten. Wie Sie sagen, ist die Implementierung keine große Änderung, aber vielleicht können Sie auch einige Bytes einsparen, wenn keine Formatierung erforderlich ist.
Emigna

@ ais523 so oder so ist akzeptabel.
Magic Octopus Urn

4

C 201 (Codierung) + 175 (Decodierung) = 376 Bytes

Um zu kodieren:

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

Codiert jedes Zeichen der Eingabezeichenfolge im grünen Kanal des RGB-Spektrums, während die beiden anderen Kanäle als zufällige hexadezimale Werte festgelegt werden. Nimmt Eingaben über STDIN als Zeichenfolge und gibt eine mehrzeilige Zeichenfolge mit hexadezimalem Farbcode in Form eines Quadrats an STDOUT aus. Angenommen, Sie haben Python 3 und ImageMagick installiert und die obige Datei wurde in eine Datei kompiliert, die a.outim aktuellen Arbeitsverzeichnis (CWD) benannt Output.pngist. Mit dem folgenden Befehl können Sie das resultierende benannte Bild direkt aus der Textausgabe auf das CWD übertragen:

./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

Hier ist ein Beispiel für ein Ausgabebild, das mit dem obigen Kommando Programming Puzzles and Code Golfals Eingabezeichenfolge erstellt wurde:

Beispielausgabe

Dekodieren:

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

Nimmt die Eingabe über STDIN in eine Folge von durch Leerzeichen getrennten hexadezimalen Farbcode-Zeichenfolgen auf, wobei jede in doppelte Anführungszeichen ( ") ( char** argvin main) eingeschlossen mainist.int argc für die Ganzzahleingabe. Gibt eine ein- / mehrzeilige Zeichenfolge an STDOUT aus, die die decodierte Nachricht darstellt.

Ich werde versuchen, diese im Laufe der Zeit zu spielen, wann und wo immer ich kann.


Wenn Sie beide Methoden in derselben Datei verwenden, können Sie auch die folgende mainMethode verwenden, um alle Methoden zusammenzufassen, wobei jede Funktion die richtigen Eingaben erhält:

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

Wenn Sie dies verwenden, müssen Sie für die Codierung Eals erstes Argument die Codierungsmethode gefolgt von dem Argument für eine einzelne Zeichenfolge angeben, während Sie für die Decodierung nur die Folge von durch Leerzeichen getrennten hexadezimalen Farbcode-Zeichenfolgen angeben müssen, wobei jede Zeichenfolge in eingeschlossen ist doppelte Anführungszeichen ( ").


Schließlich, wenn Sie möchten, können Sie die voll und ganz bereit, ready-to-use - Version bekommen hier , obwohl es nicht golfed, aber auch nicht ausgibt keine Warnungen oder Fehler bei der Kompilierung.


3

Python 2, 164 160+ 94 93 = 253 Bytes

1 + 1 Byte dank Weizen-Assistent gespeichert.

-5 Bytes dank Kade

Encoder-BildEncoder: Der String muss in Anführungszeichen gesetzt werden, z. B. "CodeGolf"ist die Ausgabe ein farbiges ASCII-PPM-Bild.

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)

Decoder-BildDecoder: Übernimmt den eingegebenen Dateinamen als Befehlszeilenargument

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

Verwendung:

 python golf_stegansquare_enc.py > stega.ppm

 python golf_stegansquare_dec.py stega.ppm

Beispiel:

Programmieren von Rätseln und Code GolfProgrammieren von Rätseln und Code Golf

Lorem IpsumLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy temporär invidunt ut labore und dolore magna aliquyam erat, sed diam voluptua. Bei vero eos et accusam et justo duo dolores et ea rebum. Es gibt keinen Grund zur Besinnung, keinen Grund zur Besinnung. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy temporär invidunt ut labore und dolore magna aliquyam erat, sed diam voluptua. Bei vero eos et accusam et justo duo dolores et ea rebum. Es gibt keinen Grund zur Besinnung, keinen Grund zur Besinnung.


Sie können das Leerzeichen zwischen der nahen Paren entfernen und dannfor
Post Rock Garf Hunter

@ETHproductions: sqrt (25-1) = sqrt (24) <5 und> 4. intDaraus ergibt sich 4, die dann +1bearbeitet wird, also 5
Karl Napf

Oh, mein Schlimmes, ich habe das nicht gesehen -1.
ETHproduktionen

1
Sie können das Leerzeichen zwischen printund 'im Decoder entfernen . Ich bin mir auch ziemlich sicher, dass Sie ein int((len(s)+1)**.5)paar Bytes sparen können.
Kade

1
Ich redigiere den letzten Satz meines vorherigen Kommentars. Sie können den Ausdruck jedoch verkürzen, indem Sie auf ändern ' '.join("%d %d %d", ''.join(3*"%d "da ich mir ziemlich sicher bin, dass ein Leerzeichen in Ordnung ist.
Kade

2

Scala, 97 + 68 = 165 Bytes

Verschlüsselung (97 Bytes):

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

Nimmt einen String und wiederholt einen Iterator von Sequenzen von ganzen Zahlen.

Entschlüsselung (68 Bytes):

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

Nimmt einen Iterator von Sequenzen von ganzen Zahlen und gibt eine Zeichenfolge zurück.

Erläuterung:

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 Bytes

Text-zu-Bild-Encoder (wird mit -peiner 1-Byte-Strafe ausgeführt; -p0(für ein zusätzliches Byte Strafe) ist erforderlich, wenn Sie Zeilenumbrüche in der Eingabezeichenfolge verarbeiten möchten):

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

Bild-zu-Text-Decoder (wird mit -p0einer 2-Byte-Strafe ausgeführt):

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

Dies verwendet das #abcdeftextbasierte Bildformat und codiert im blauen Kanal. Hier ist ein Beispiel für eine mögliche AusgabeProgramming Puzzles and Code Golf als Eingabe:

# 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

Erklärung des Gebers:

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

Ich war wirklich froh, dass dieser Einsatz \Kfunktioniert hat; es gibt an, wo ersetzt werden soll, und es scheint, dass das Auftreten bei der letzten Schleifeniteration zählt, wenn es in einer Schleife platziert wird. Entspricht also s/(.*?\K,){$a}/\n/geiner Zeichenfolge mit minimaler Länge der Form " alles Komma alles Komma" ... alles Komma, das $aKommas enthält, aber der tatsächlich ersetzte Teil der Übereinstimmung ist einfach das letzte Komma. Dies hat den Effekt, dass jedes $aKomma durch eine neue Linie ersetzt wird, wodurch wir die quadratische Form für das Bild erhalten.

Der große Vorteil von Perl für diese Herausforderung (abgesehen vom eingebauten Konverter für die Zeichenfolge in Hexadezimalzahlen, der unglaublich praktisch war) ist, dass es einen sehr kurzen Decoder hat (in der Tat so kurz, dass Perl zwar einen eingebauten Decoder für hat) Um hexadezimal in einen String umzuwandeln, war es kürzer, ihn nicht zu verwenden. So funktioniert das:

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

Die einzigen Vorkommen von zwei Zeichen unmittelbar vor einem nicht-alphanumerischen Zeichen sind die blauen Kanäle (die entpackt werden sollen), die direkt vor Kommas und Zeilenumbrüchen stehen. und die beiden Zeichen, die vor #dem ersten vorkommen. Wir möchten nicht, dass die letztgenannte Kategorie von Übereinstimmungen, aber sie überlappen zwangsläufig die erstgenannte Kategorie und werden daher von der Überprüfung überlappender Übereinstimmungen ausgeschlossen.


1

MySQL, 438 + 237 = 675 Bytes

Am Ende der Ausgabe befindet sich eine nachgestellte neue Zeile, die jedoch nach dem Entschlüsseln nicht angezeigt wird. Die Hex-Funktion (Integer-Überladung) würde führende Nullen abhacken, daher musste ich sie mit einem String 0 auffüllen. Ich könnte einige Bytes sparen, wenn ich beide Funktionen zwischen den Begrenzern deklarieren könnte.

Verschlüsseln

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 ;

Entschlüsseln

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 ;

Verwendung:

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

1

C #, 312 + 142 = 454 Bytes

Codierung:

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

Dekodierung:

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

Volles Programm:

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 Bytes

Encoder

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

Decoder

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

1

Verarbeitung, 220 209 194 + 171 167 151 = 391 380 376 361 345 Bytes

Aktualisieren:

Nutzlos entfernt noStroke()und beide for-Loops zu Einsätzen gemacht.

image(p,0,0);Nutzlos entfernt , gab dem Entschlüsseler den Dateinamen als Parameter

Verschlüsselungsalgorithmus

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

Aufruf der Funktion: g("Programming Puzzles and Code Golf");

Dies ist eine Funktion, die einen String aufnimmt und die Ausgabe erstellt, bevor sie gespeichert wird t.png. Es verwendet den redWert, um den verborgenen Text zu speichern.

Entschlüsselungsalgorithmus

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

Funktion aufrufen durch: u(file_name);

Dies ist auch eine Funktion, die nach dem durch den Parameter angegebenen Bild sucht und dann die verborgene Zeichenfolge ausgibt (da sie kürzer ist als die Rückgabe einer Zeichenfolge).

Erweiterter Code

(Verschlüsselungsalgorithmus)

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

Die Zeichenfolge wird beim Aufruf der Funktion übergeben. Die erste Zeile der Funktion berechnet die Seitenlänge des Quadrats aus der ceilQuadratwurzel. Dann geben wir eine for-Schleife ein, in der wir die stroke(die Farbe der Kante) so einstellen , dass der ASCII-Wert des Zeichens rot und die Zufallswerte für blau und grün sind. Danach erstellen wir ein rect(Rechteck) mit width = 1und height = 1, dh ein Pixel (aus irgendeinem seltsamen Grund kann ich es nicht pointrichtig verwenden). In der letzten Zeile wird das resultierende Bild dann als gespeichert t.png.

(Entschlüsselungsalgorithmus)

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

Diese Funktion hat den Namen der Datei als Parameter (als String). Dann wird das Bild in der Datei in einer Variablen gespeichert, die später verwendet werden soll. Nachdem wir damit fertig sind, setzen wir die Zeichenfolge auf, ""anstatt eine neue Zeichenfolge zu erstellen, die nur die verborgene Zeichenfolge enthält. Dann iterieren wir über zwei verschachtelte for-Schleifen durch das Bild und addieren den Zeichenwert des roten Wertes des Pixels zum String. Zum Schluss drucken wir den resultierenden String, nachdem wir führende Leerzeichen entfernt haben (unter Verwendung eines regulären Ausdrucks). Der Grund, warum wir den verborgenen Text drucken, anstatt ihn zurückzugeben, ist, dass er auf diese Weise kürzer ist und wir Bytes sparen.


Verschlüsselter Challenge-Rohtext:

Bildbeschreibung hier eingeben


1

Jelly, 40 + 20 = 60 Bytes in Jellys Codepage

Encoder (Text → Bild):

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

Probieren Sie es online!

Decoder (Bild → Text):

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

Probieren Sie es online!

Eine Beispielausgabe, die das Programm erzeugen könnte (es speichert Informationen im roten Kanal):

#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

Bei diesen größeren Herausforderungen lässt die Knappheit von Jelly allmählich nach und es werden mehrere "strukturelle" Zeichen benötigt, um Parsing-Ambiguitäten aufzulösen, aber es ist dennoch sehr knapp. So funktioniert der Encoder:

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

Und so funktioniert der Decoder:

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.