Carrés stéganographiques


14

Carrés stéganographiques

Votre travail consiste à prendre une chaîne et à générer une NxNimage qui représente cette chaîne. Vous devez également écrire l'algorithme qui prend l'image et la transforme également en chaîne. Le score sera comprendra le nombre d'octets des deux algorithmes:

Algorithme de "chiffrement" + algorithme de "déchiffrement" .

Vous devez publier chacun séparément, avec des nombres d'octets pour les algorithmes de chiffrement et de déchiffrement affichés individuellement.


Exemple d'algorithme

Par exemple, voici les "Puzzles de programmation et Golf de code" utilisant un algorithme stéganographique simple basé sur ASCII dans le canal bleu:

#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

Image réelle ( L'image générée par l'algorithme.)

Image agrandie.

Vous pouvez voir que le canal bleu contient simplement les valeurs ascii pour cette image:

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

Alors que le reste des canaux contiennent des valeurs générées aléatoirement pour "pimenter" la variété de couleurs dans l'image. Lorsque vous retirez le message de l'image, nous pouvons simplement ignorer les autres valeurs de canal et tirer le bit hexadécimal dans le canal bleu, reconstruisant la chaîne:

"Programming Puzzles and Code Golf"

Notez que les espaces qui ont été utilisés pour remplir la chaîne dans le carré ne sont pas inclus dans la sortie décryptée finale. Bien que vous deviez remplir la chaîne dans l'image, vous pouvez supposer que la chaîne d'entrée ne se terminera pas par des espaces.


Règles

  • Vous devez encoder 1 caractère par pixel, le canal choisi pour encoder le caractère est arbitraire.
  • Les canaux des autres couleurs RVB doivent être randomisés, autre que celui dans lequel vous choisissez d'encoder la chaîne; cela signifie que vos canaux finaux non codés devraient être compris entre 0x0000-0xFFFF(choisis au hasard).
  • L'expression du résultat final sous la forme d'un tableau 2D de valeurs de couleur RVB est très bien 0x000000-0xFFFFFF, pas besoin d'utiliser la création d'image sauf si vous voulez vous amuser avec elle ou si c'est moins d'octets. Si vous choisissez de sortir sous forme de chaînes hexadécimales, préfixez la chaîne hexadécimale avec #EG #FFFFFFou #05AB1E. Vous pouvez vous séparer avec des tabulations, des virgules ou toute autre chose qui serait sensée horizontalement, mais elle doit conserver le motif carré; en d'autres termes, vous devez utiliser une séparation de nouvelle ligne appropriée.
  • La sortie doit être dans un carré et la chaîne doit être complétée par des espaces à la fin pour s'adapter à cela. Cela veut dire que N≈SQRT(Input#Length()). Si la longueur d'entrée n'est pas un carré parfait, vous devez arrondir Net remplir avec des espaces.
  • Comme indiqué précédemment, si vous remplissez avec des espaces dans l'image, vous ne devez pas inclure les caractères remplis dans la sortie finale "décryptée".
  • Vous pouvez supposer que:
    • La chaîne d'entrée ne se terminera pas par des espaces.
    • La chaîne d'entrée n'utilisera que des caractères ASCII imprimables.
  • Il s'agit du , le nombre d'octets le plus bas gagne.

Juste pour clarifier, les solutions doivent encoder / décoder exactement un caractère par pixel?
ETHproductions du

@ETHproductions qui ressemble à un bon défi de suivi, mais dans le cadre de ce concours, vous choisissez un canal d'encodage et encodez 1 caractère par pixel.
Urne de poulpe magique

Je ne vais probablement pas utiliser cela, mais: est-ce correct de "surcharger" l'image avec plus d'espace que nécessaire? Et est-il OK de supposer que l'image aura la même quantité de sur-rembourrage que le codeur générerait?

@ ais523 Je ne vois pas comment ce type d'approche ferait autre chose que nécessiterait plus d'octets pour être implémenté. Je vais aller avec non, car le défi est trop ancien pour faire de grands changements comme ça.
Urne de poulpe magique du

1
Bon, je ne savais pas si c'était autorisé dans la question d'origine, plutôt que de recommander un changement. (Je pensais à empaqueter l'entrée dans un rectangle, ce qui a des calculs de coordonnées plus faciles et donc peut-être plus courts que de les empaqueter dans un carré, puis de rembourrer le rectangle sur un carré plus grand.)

Réponses:


2

05AB1E , 34 + 12 = 46 octets

Utilise le canal rouge.
05AB1E utilise le codage CP-1252 .

Encoder:

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

Essayez-le en ligne!

Décoder:

˜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

Essayez-le en ligne!

Méthode de remplissage alternative avec nombre d'octets égal

Dgð×J¹gtî©n£

Je pense que vous devez vous inscrire spécifiquement sur les nouvelles lignes, selon la question? (Votre réponse battra probablement la mienne même si elle est adaptée pour le faire, car je n'ai dépensé que cinq octets pour traiter cette partie de la question, et vous êtes en avance de plus.)

@ ais523: Les règles stipulent que les tableaux 2D étaient corrects. Ai-je mal compris cela d'une manière ou d'une autre?
Emigna

"Vous pouvez séparer avec des tabulations, des virgules ou tout autre élément qui serait sensé horizontalement, mais il doit conserver le motif carré; en d'autres termes, vous devez utiliser une séparation de nouvelle ligne appropriée." implique fortement qu'il doit s'agir d'une chaîne, car les tableaux 2D ne contiennent pas intrinsèquement de nouvelles lignes. En d'autres termes, j'ai interprété "tableau" comme décrivant la forme de la sortie, pas le type de données de la sortie.

@ ais523: J'ai demandé des éclaircissements au PO. Comme vous le dites, ce n'est pas un gros changement à implémenter, mais vous pouvez peut-être également enregistrer quelques octets si le formatage n'est pas nécessaire.
Emigna

@ ais523 dans les deux cas est acceptable.
Urne de poulpe magique du

4

C, 201 (codage) + 175 (décodage) = 376 octets

Pour encoder:

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

Encode chaque caractère de la chaîne d'entrée dans le canal vert du spectre RVB tout en définissant les deux autres canaux comme des valeurs hexadécimales aléatoires. Prend l'entrée via STDIN sous forme de chaîne et envoie à STDOUT une chaîne multiligne de code de couleur hexadécimal sous la forme d'un carré. En supposant que vous avez installé Python 3 et ImageMagick et que le fichier ci-dessus est compilé dans un fichier nommé a.outdans le répertoire de travail actuel (CWD), vous pouvez directement obtenir l'image résultante, nommée Output.png, dans le CWD à partir de la sortie textuelle à l'aide de la commande suivante:

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

Voici un exemple d'image de sortie créée par la commande ci-dessus en utilisant Programming Puzzles and Code Golfcomme chaîne d'entrée:

Exemple de sortie

Pour décoder:

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

Prend en entrée via STDIN une séquence de chaînes de code de couleur hexadécimales séparées par des espaces, chacune étant placée entre guillemets ( ") ( char** argvin main) et également, lorsqu'elle est appelée main,int argc pour l'entrée entière. Fournit à STDOUT une chaîne simple / multiligne représentant le message décodé.

Je vais essayer de jouer au golf au fil du temps quand et où je peux.


En outre, si vous utilisez les deux méthodes dans le même fichier, vous pouvez utiliser la mainméthode suivante pour tout regrouper avec chaque fonction obtenant les entrées correctes:

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

et en utilisant cela, pour l'encodage, vous devez fournir Ecomme premier argument pour appeler la méthode d'encodage suivie par l'argument de chaîne unique, tandis que pour le décodage, tout ce que vous devez fournir est la séquence de chaînes de code de couleur hexadécimales séparées par des espaces, chacune étant incluse dans guillemets doubles ( ").


Enfin, si vous voulez, vous pouvez obtenir le bien préparé, la version prête à utiliser ici le fait, bien qu'il ne soit pas golfed, mais aussi pas émis des avertissements ou des erreurs lors de la compilation.


3

Python 2, 164 160 + 94 93 = 253 octets

1 + 1 octet enregistré grâce à l'assistant de blé.

-5 octets grâce à Kade

Image de l'encodeurEncodeur: la chaîne doit être placée entre guillemets, par exemple "CodeGolf", la sortie est une image PPM ascii couleur.

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)

Image du décodeurDécodeur: prend le nom du fichier d'entrée comme argument de ligne de commande

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

Usage:

 python golf_stegansquare_enc.py > stega.ppm

 python golf_stegansquare_dec.py stega.ppm

Exemple:

Programmation de puzzles et de code golfProgrammation de puzzles et de 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. Chez 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. Chez 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.


Vous pouvez supprimer l'espace entre la paren proche, puisfor
Post Rock Garf Hunter

@ETHproductions: sqrt (25-1) = sqrt (24) <5 et> 4. à intpartir de cela est 4 qui est ensuite +1édité, donc 5
Karl Napf

Oh, mon mauvais, je n'ai pas vu le -1.
ETHproductions

1
Vous pouvez supprimer l'espace entre printet 'dans le décodeur. Je suis également sûr que vous pourriez faire int((len(s)+1)**.5)pour économiser quelques octets.
Kade

1
J'efface la dernière phrase de mon commentaire précédent, mais vous pouvez raccourcir l'impression en changeant ' '.join("%d %d %d"en ''.join(3*"%d "car je suis sûr qu'un espace de fin est OK.
Kade

2

Scala, 97 + 68 = 165 octets

Cryptage (97 octets):

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

Prend une chaîne et répète un itérateur de séquences de nombres entiers.

Décryptage (68 octets):

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

Prend un itérateur de séquences de nombres entiers et renvoie une chaîne.

Explication:

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 octets

L'encodeur de texte en image (exécuté avec -ppour une pénalité de 1 octet; -p0(pour un octet supplémentaire de pénalités) est nécessaire si vous souhaitez gérer les retours à la ligne dans la chaîne d'entrée):

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

Décodeur image vers texte (exécuté avec -p0une pénalité de 2 octets):

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

Celui-ci utilise le #abcdefformat d'image textuelle et encode dans le canal bleu. Voici un exemple d'une sortie possible donnée Programming Puzzles and Code Golfen entrée:

# 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

Explication de l'encodeur:

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

J'étais vraiment content de cette utilisation de \Ktravaillé; il spécifie où remplacer, et en le plaçant dans une boucle, il semble que l'occurrence sur la dernière itération de la boucle soit ce qui compte. Donc s/(.*?\K,){$a}/\n/g, correspondra à une chaîne de longueur minimale de la forme quoi que ce soit virgule quoi que ce soit virgule ... tout virgule, qui a des $avirgules, mais la partie remplacée réelle de la correspondance sera simplement la dernière virgule. Cela a pour effet de remplacer chaque$a e virgule par une nouvelle ligne, ce qui nous donne la forme carrée de l'image.

Le grand avantage de Perl pour ce défi (autre que le convertisseur chaîne de caractères-hexadécimal intégré, qui était incroyablement pratique) est qu'il a un décodeur très court (si court, en fait, que même si Perl a une fonction intégrée pour conversion hexadécimale en chaîne, il était plus court de ne pas l'utiliser). Voici comment ça fonctionne:

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

Les seules instances de deux caractères juste avant un caractère non alphanumérique sont les canaux bleus (que nous voulons décompresser), qui apparaissent juste avant les virgules et les retours à la ligne; et les deux caractères qui apparaissent l'un devant l' #autre que le premier. Nous ne voulons pas de cette dernière catégorie de matchs, mais ils chevauchent inévitablement l'ancienne catégorie, et seront donc exclus par la vérification des matches qui se chevauchent.


1

MySQL, 438 + 237 = 675 octets

Il y a une nouvelle ligne à la fin de la sortie, mais elle n'apparaît pas après avoir été déchiffrée. La fonction hexadécimale (surcharge d'entier) couperait les 0 en tête, donc je devais la remplir avec une chaîne 0. Je pourrais économiser quelques octets si je pouvais déclarer les deux fonctions entre les délimiteurs.

Crypter

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 ;

Déchiffrer

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 ;

Usage:

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

1

C #, 312 + 142 = 454 octets

Codage:

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

Décodage:

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

Programme complet:

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 octets

Encodeur

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

Décodeur

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

1

Transformation, 220 209 194 + 171 167 151 = 391 380 376 361 345 octets

Mise à jour:

Supprimé inutile noStroke() et rendu les deux boucles pour un-déclaration.

Supprimé inutile image(p,0,0); , a donné au décrypteur le nom de fichier comme paramètre

Algorithme de cryptage

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

Appel de la fonction: g("Programming Puzzles and Code Golf");

Il s'agit d'une fonction qui prend une chaîne et crée la sortie avant de l'enregistrer sous t.png. Il utilise lered valeur pour stocker le texte masqué.

Algorithme de déchiffrement

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

Fonction d'appel par: u(file_name);

Il s'agit également d'une fonction qui recherche l'image spécifiée par le paramètre, puis génère la chaîne masquée (car elle est plus courte que le renvoi d'une chaîne).

Code développé

(Algorithme de cryptage)

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

La chaîne est passée lorsque la fonction est appelée. La première ligne de la fonction calcule la longueur du côté du carré en prenant la ceilracine carrée. Ensuite, nous entrons dans une boucle for, où nous définissons la stroke(la couleur du bord) pour que la valeur ASCII du caractère soit rouge et des valeurs aléatoires pour le bleu et le vert. Après cela, nous créons un rect(rectangle) avec width = 1et height = 1, c'est-à-dire un pixel (pour une raison étrange, je ne peux pas l'utiliser pointcorrectement). Dans la dernière ligne, l'image résultante est ensuite enregistrée sous t.png.

(Algorithme de décryptage)

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

Cette fonction a le nom du fichier comme paramètre (sous forme de chaîne). Ensuite, l'image dans le fichier est stockée dans une variable pour être utilisée ultérieurement. Après avoir terminé avec cela, nous définissons la chaîne au ""lieu de créer une nouvelle chaîne juste pour contenir la chaîne masquée. Ensuite, nous parcourons l'image via deux boucles for imbriquées, et nous ajoutons à la chaîne la valeur de caractère de la valeur rouge du pixel. Enfin, nous imprimons la chaîne résultante après en avoir supprimé les espaces de tête (à l'aide d'une expression régulière). La raison pour laquelle nous imprimons le texte masqué au lieu de le renvoyer est que, de cette façon, il est plus court et nous économisons des octets.


Texte brut de défi chiffré:

entrez la description de l'image ici


1

Jelly, 40 + 20 = 60 octets dans la page de codes de Jelly

Encodeur (texte → image):

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

Essayez-le en ligne!

Décodeur (image → texte):

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

Essayez-le en ligne!

Un exemple de sortie que le programme pourrait produire (il stocke des informations dans le canal rouge):

#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

Dans ces défis plus importants, la lacune de Jelly commence à diminuer un peu, nécessitant plusieurs caractères "structurels" pour résoudre les ambiguïtés d'analyse, mais elle est néanmoins toujours très laconique. Voici comment fonctionne l'encodeur:

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

Et voici comment fonctionne le décodeur:

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.