Quadrati Steganografici


14

Quadrati Steganografici

Il tuo compito è prendere una stringa e generare NxNun'immagine che rappresenti questa stringa. Devi anche scrivere l'algoritmo che riprende l'immagine e la trasforma anche in una stringa. Il punteggio includerà il conteggio dei byte di entrambi gli algoritmi:

Algoritmo "Crittografia" + Algoritmo "Decrittazione" .

È necessario pubblicarli separatamente, con conteggi dei byte per gli algoritmi di crittografia e decrittografia visualizzati singolarmente.


Algoritmo di esempio

Ad esempio, ecco il "Puzzle di programmazione e Code Golf" che utilizza un semplice algoritmo steganografico basato su ASCII nel canale Blue:

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

Immagine reale ( L'immagine generata dall'algoritmo.)

Immagine esplosa.

Puoi vedere che il canale blu contiene semplicemente i valori ASCII per questa immagine:

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

Mentre il resto dei canali contiene valori generati casualmente per "ravvivare" la varietà di colori nell'immagine. Quando si estrae il messaggio dall'immagine, possiamo semplicemente ignorare gli altri valori del canale e tirare il bit esadecimale nel canale blu, ricostruendo la stringa:

"Programming Puzzles and Code Golf"

Notare che gli spazi utilizzati per riempire la stringa nel quadrato non sono inclusi nell'output decrittografato finale. Mentre devi riempire la stringa nell'immagine, puoi supporre che la stringa di input non finisca con spazi.


Regole

  • Devi codificare 1 carattere per pixel, il canale scelto per codificare il carattere è arbitrario.
  • I canali degli altri colori RGB devono essere randomizzati, diversi da quello in cui si sceglie di codificare la stringa; questo significa che i tuoi canali finali non codificati dovrebbero essere tra 0x0000-0xFFFF(scelti casualmente).
  • Esprimere il risultato finale come una matrice 2D di valori di colore RGB va bene 0x000000-0xFFFFFF, non è necessario utilizzare la creazione di immagini a meno che non si desideri divertirsi con esso o se è meno byte. Se si sceglie di generare come stringhe esadecimali, aggiungere il prefisso alla stringa esadecimale con #EG #FFFFFFo #05AB1E. È possibile separare con schede, virgole o qualsiasi altra cosa che sia sensibile in senso orizzontale, ma deve mantenere il modello quadrato; in altre parole, è necessario utilizzare la separazione newline appropriata.
  • L'output deve essere in un quadrato e la stringa deve essere riempita con spazi alla fine per adattarlo. Questo significa che N≈SQRT(Input#Length()). Se la lunghezza dell'input non è un quadrato perfetto, è necessario arrotondare Ne riempire con gli spazi.
  • Come affermato in precedenza, se si esegue il riempimento con spazi nell'immagine, non è necessario includere i caratteri imbottiti nell'output finale "decrittografato".
  • Puoi presumere che:
    • La stringa di input non terminerà con spazi.
    • La stringa di input utilizzerà solo caratteri ASCII stampabili.
  • Questo è , vince il conteggio di byte più basso.

Giusto per chiarire, le soluzioni devono codificare / decodificare esattamente un carattere per pixel?
ETHproductions

@ETHproduzioni che sembrano una buona sfida di follow-up, ma ai fini di questa competizione, scegli un canale di codifica e codifica 1 carattere per pixel.
Magic Octopus Urn

Probabilmente non lo userò, ma: va bene "overpad" l'immagine con più spazi del necessario? Ed è corretto supporre che l'immagine avrà la stessa quantità di sovrimpressione che genererebbe l'encoder?

@ ais523 Non riesco a vedere come questo tipo di approccio farebbe qualsiasi cosa ma richiederebbe più byte da implementare. Non ci andrò comunque, dato che la sfida è troppo vecchia per apportare grandi cambiamenti in questo modo.
Magic Octopus Urn

1
Giusto, non ero sicuro che fosse consentito nella domanda originale, piuttosto che raccomandare una modifica. (Stavo pensando di impacchettare l'input in un rettangolo, che ha calcoli di coordinate più facili e quindi più corti di byte che impacchettarlo in un quadrato, quindi riempire il rettangolo in un quadrato più grande.)

Risposte:


2

05AB1E , 34 + 12 = 46 byte

Utilizza il canale rosso.
05AB1E utilizza la codifica CP-1252 .

Codificare:

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

Provalo online!

Decodificare:

˜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

Provalo online!

Metodo di riempimento alternativo con uguale numero di byte

Dgð×J¹gtî©n£

Penso che devi aderire in modo specifico alle newline, secondo la domanda? (La tua risposta probabilmente batterà la mia anche se è adattata per farlo, però, perché ho speso solo cinque byte occupandomi di quella parte della domanda, e tu sei avanti di più.)

@ ais523: le regole affermano che gli array 2D erano a posto. L'ho frainteso in qualche modo?
Emigna,

"È possibile separare con schede, virgole o qualsiasi altra cosa che sia sensibilmente orizzontale, ma deve mantenere il modello quadrato; in altre parole, è necessario utilizzare un'adeguata separazione da riga a capo." implica fortemente che deve essere una stringa, poiché gli array 2D non contengono intrinsecamente nuove righe. In altre parole, ho interpretato "array" come descrivendo la forma dell'output, non il tipo di dati dell'output.

@ ais523: ho chiesto chiarimenti all'OP. Come dici tu, non è un grande cambiamento da implementare, ma forse puoi salvare anche alcuni byte se non è necessaria la formattazione.
Emigna,

@ ais523 in entrambi i casi è accettabile.
Magic Octopus Urn

4

C, 201 (codifica) + 175 (decodifica) = 376 byte

Per codificare:

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

Codifica ogni carattere della stringa di input nel canale verde dello spettro RGB mentre imposta gli altri due canali come valori esadecimali casuali. Prende input tramite STDIN come stringa e genera in STDOUT una stringa multilinea di codice esadecimale a forma di quadrato. Supponendo che tu abbia installato Python 3 e ImageMagick e che il file sopra sia compilato in un file denominato a.outnella directory di lavoro corrente (CWD), puoi ottenere direttamente l'immagine risultante, denominata Output.png, nel CWD dall'output testuale usando il seguente comando:

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

Ecco un'immagine di output di esempio creata dal commamd sopra usando Programming Puzzles and Code Golfcome stringa di input:

Uscita campione

Per decodificare:

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

Prende l'input tramite STDIN una sequenza di stringhe di codice di colore esadecimale separate da spazi con ognuna racchiusa tra virgolette doppie ( ") ( char** argvin main) e anche, quando viene chiamata inmain , int argcper l'input intero. Emette su STDOUT una stringa singola / multi-riga che rappresenta il messaggio decodificato.

Proverò a giocare a golf più nel tempo, quando e dove posso.


Inoltre, se si maininseriscono entrambi i metodi nello stesso file, è possibile utilizzare il metodo seguente per mettere tutto insieme a ciascuna funzione che ottiene gli input corretti:

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

e usando questo, per la codifica è necessario fornire Ecome primo argomento per chiamare il metodo di codifica seguito dall'argomento stringa singola, mentre per la decodifica, tutto ciò che è necessario fornire è la sequenza di stringhe di codice di colore esadecimale separate da spazio con ciascuna racchiusa in virgolette (" ).


Infine, se si desidera, è possibile ottenere il ben preparati, la versione pronta per l'uso qui , anche se non è giocato a golf, ma non lo fa anche in uscita eventuali avvisi o errori su di compilazione.


3

Python 2, 164 160 + 94 93 = 253 byte

Salvato 1 + 1 byte grazie a Wheat Wizard.

-5 byte grazie a Kade

Immagine dell'encoderEncoder: la stringa deve essere racchiusa tra virgolette, ad esempio "CodeGolf", l'output è un'immagine PPM ascii a colori.

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)

Immagine del decodificatoreDecoder: accetta il nome file di input come argomento della riga di comando

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

Uso:

 python golf_stegansquare_enc.py > stega.ppm

 python golf_stegansquare_dec.py stega.ppm

Esempio:

Puzzle di programmazione e Code GolfPuzzle di programmazione e Code Golf

Lorem IpsumLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod time invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. In 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 time invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. In 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.


È possibile rimuovere lo spazio tra il paren vicino e quindifor
Post Rock Garf Hunter

@ETHproductions: sqrt (25-1) = sqrt (24) <5 e> 4. intda questo è 4 che viene quindi +1ed, quindi 5
Karl Napf

Oh, mio ​​male, non ho visto il -1.
ETHproductions

1
È possibile rimuovere lo spazio tra printe 'nel decodificatore. Sono anche abbastanza sicuro che potresti fare int((len(s)+1)**.5)per salvare alcuni byte.
Kade,

1
Sto redattendo l'ultima frase del mio commento precedente, tuttavia puoi accorciare la stampa cambiando ' '.join("%d %d %d"in ''.join(3*"%d "poiché sono abbastanza sicuro che uno spazio finale sia OK.
Kade,

2

Scala, 97 + 68 = 165 byte

Crittografia (97 byte):

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

Prende una stringa e riavvia un Iteratore di sequenze di numeri interi.

Decrittazione (68 byte):

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

Prende un iteratore di sequenze di numeri interi e restituisce una stringa.

Spiegazione:

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 byte

Codificatore da testo a immagine (eseguito con -pper una penalità di 1 byte; -p0(per un byte di penalità aggiuntivo) è necessario se si desidera gestire le nuove righe nella stringa di input):

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

Decodificatore da immagine a testo (eseguito con -p0per una penalità di 2 byte):

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

Questo utilizza il #abcdefformato immagine basato su testo e codifica nel canale blu. Ecco un esempio di un possibile output dato Programming Puzzles and Code Golfcome input:

# B4d250, # bccb72, # 43f06f, # 4d6767, # 74ba72, # 269.461
# 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, # 553.820, # b31120

Spiegazione dell'encoder:

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

Sono stato davvero contento di questo uso di \Klavorato; specifica dove sostituire e posizionandolo all'interno di un ciclo, sembra che l'occorrenza nell'ultima iterazione del ciclo sia ciò che conta. Quindi s/(.*?\K,){$a}/\n/gcorrisponderà a una stringa di lunghezza minima del modulo qualunque cosa virgola qualsiasi virgola ... qualsiasi virgola, che abbia $avirgole, ma la parte effettiva della corrispondenza sostituita sarà semplicemente l'ultima virgola. Questo ha l'effetto di sostituire ogni$a nuova virgola con una nuova riga, dandoci la forma quadrata per l'immagine.

Il grande vantaggio di Perl per questa sfida (oltre al convertitore string-to-hexadecimal di carattere incorporato, che era incredibilmente conveniente) è che ha un decodificatore molto corto (così corto, in effetti, che sebbene Perl abbia un incorporato per convertendo esadecimale in una stringa, era più breve non usarlo). Ecco come funziona:

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

Le uniche istanze di due caratteri immediatamente prima di un carattere non alfanumerico sono i canali blu (che vogliamo decomprimere), che appaiono appena prima delle virgole e delle nuove righe; e i due personaggi che appaiono uno di fronte #all'altro rispetto al primo. Non vogliamo quest'ultima categoria di partite, ma inevitabilmente si sovrappongono alla precedente categoria e quindi saranno esclusi dal controllo delle partite sovrapposte.


1

MySQL, 438 + 237 = 675 byte

C'è una nuova riga finale alla fine dell'output, ma non viene visualizzata dopo essere stata decodificata. La funzione esadecimale (sovraccarico intero) taglierebbe gli 0 iniziali, quindi ho dovuto riempirlo con una stringa 0. Potrei salvare alcuni byte se potessi dichiarare entrambe le funzioni tra i delimitatori.

Encrypt

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 ;

Decrypt

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 ;

Uso:

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

1

C #, 312 + 142 = 454 byte

Codifica:

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

decodifica:

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

Programma completo:

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 byte

Codificatore

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

decoder

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

1

Elaborazione, 220 209 194 + 171 167 151 = 391 380 376 361 345 byte

Aggiornare:

Rimosso inutile noStroke() e reso entrambi gli one-statementer for-loop.

Rimosso inutile image(p,0,0); , ha dato al decryptor il nome file come parametro

Algoritmo di crittografia

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

Chiamare la funzione: g("Programming Puzzles and Code Golf");

Questa è una funzione che accetta una stringa e crea l'output, prima di salvarlo come t.png. Usa ilred valore per memorizzare il testo nascosto.

Algoritmo di decrittazione

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

Funzione di chiamata da: u(file_name);

Questa è anche una funzione che cerca l'immagine specificata dal parametro e quindi genera la stringa nascosta (poiché è più breve della restituzione di una stringa).

Codice espanso

(Algoritmo di crittografia)

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 stringa viene passata quando viene chiamata la funzione. La prima riga della funzione calcola la lunghezza laterale del quadrato prendendo la ceilradice quadrata. Quindi inseriamo un ciclo for, in cui impostiamo il stroke(colore del bordo) in modo che il valore ASCII del carattere sia rosso e valori casuali per blu e verde. Dopo averlo fatto, creiamo un rect(rettangolo) con width = 1e height = 1, ovvero un pixel (per qualche strana ragione, non riesco a usarlo pointcorrettamente). Nell'ultima riga, l'immagine risultante viene quindi salvata come t.png.

(Algoritmo di decrittazione)

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

Questa funzione ha il nome del file come parametro (come stringa). Quindi l'immagine nel file viene archiviata in una variabile da utilizzare in seguito. Dopo aver finito, impostiamo la stringa su ""invece di creare una nuova stringa solo per contenere la stringa nascosta. Quindi ripetiamo l'immagine tramite due cicli for nidificati e aggiungiamo alla stringa il valore del carattere del valore rosso del pixel. Infine, stampiamo la stringa risultante dopo aver rimosso gli spazi iniziali da essa (usando una regex). Il motivo per cui stampiamo il testo nascosto invece di restituirlo è perché in questo modo è più breve e salviamo i byte.


Testo non crittografato della sfida:

inserisci qui la descrizione dell'immagine


1

Jelly, 40 + 20 = 60 byte nella tabella codici di Jelly

Encoder (testo → immagine):

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

Provalo online!

Decodificatore (immagine → testo):

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

Provalo online!

Un esempio di output che il programma potrebbe produrre (memorizza le informazioni nel canale rosso):

#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

In queste sfide più grandi, la perplessità di Jelly inizia a calare un po ', necessitando di diversi personaggi "strutturali" per risolvere le ambiguità di analisi, ma è comunque molto concisa. Ecco come funziona l'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

Ed ecco come funziona il decodificatore:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.