Cuadrados esteganográficos

14

Cuadrados esteganográficos

Su trabajo es tomar una cadena y generar una NxNimagen que represente esta cadena. También debe escribir el algoritmo que toma la imagen y la convierte nuevamente en una cadena. La puntuación incluirá el recuento de bytes de ambos algoritmos:

Algoritmo "Cifrado" + Algoritmo "Descifrado" .

Debe publicar cada uno por separado, con recuentos de bytes para los algoritmos de cifrado y descifrado que se muestran individualmente.


Algoritmo de ejemplo

Por ejemplo, aquí está el "Programa de acertijos y código de golf" usando un algoritmo esteganográfico simple basado en ASCII en el canal Azul:

#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

Imagen real ( La imagen generada por el algoritmo.)

Imagen ampliada.

Puede ver que el canal azul simplemente contiene los valores ascii para esta imagen:

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

Mientras que el resto de los canales contienen valores generados aleatoriamente para "condimentar" la variedad de colores en la imagen. Al extraer el mensaje de la imagen, simplemente podemos ignorar los otros valores del canal y extraer el bit hexadecimal en el canal azul, reconstruyendo la cadena:

"Programming Puzzles and Code Golf"

Observe que los espacios que se usaron para rellenar la cadena en el cuadrado no se incluyen en la salida descifrada final. Si bien debe rellenar la cadena en la imagen, puede suponer que la cadena de entrada no terminará con espacios.


Reglas

  • Debe codificar 1 carácter por píxel, el canal elegido para codificar el carácter es arbitrario.
  • Los canales de los otros colores RGB deben ser aleatorios, distintos del que está eligiendo codificar la cadena; Esto significa que sus canales finales no codificados tendrían que estar entre 0x0000-0xFFFF(elegidos al azar).
  • Expresar el resultado final como una matriz 2D de valores de color RGB está bien 0x000000-0xFFFFFF, no es necesario usar la creación de imágenes a menos que quiera divertirse con él o si tiene menos bytes. Si elige generar como cadenas hexadecimales, prefije la cadena hexadecimal con #EG #FFFFFFo #05AB1E. Puede separarse con pestañas, comas o cualquier otra cosa que sea horizontalmente sensible, pero debe mantener el patrón cuadrado; en otras palabras, debe usar la separación de línea nueva apropiada.
  • La salida debe estar en un cuadrado, y la cadena debe estar rellenada con espacios al final para acomodar esto. Esto significa que N≈SQRT(Input#Length()). Si la longitud de entrada no es un cuadrado perfecto, debe redondear Ny rellenar con espacios.
  • Como se indicó anteriormente, si está rellenando con espacios en la imagen, no debe incluir los caracteres rellenados en la salida final "descifrada".
  • Puedes asumir que:
    • La cadena de entrada no terminará con espacios.
    • La cadena de entrada solo usará caracteres ASCII imprimibles.
  • Este es el , el conteo de bytes más bajo gana.
Urna de pulpo mágico
fuente
Solo para aclarar, ¿las soluciones deben codificar / decodificar exactamente un carácter por píxel?
ETHproductions
@ETHproductions que suena como un buen desafío de seguimiento, pero para el propósito de esta competencia, usted elige un canal de codificación y codifica 1 carácter por píxel.
Urna mágica del pulpo
Probablemente no voy a usar esto, pero: ¿está bien "sobrecargar" la imagen con más espacios de los necesarios? ¿Y está bien suponer que la imagen tendrá la misma cantidad de relleno que generaría el codificador?
@ ais523 No puedo ver cómo este tipo de enfoque haría algo más que requerir más bytes para implementar. Sin embargo, voy a ir con un no, ya que el desafío es demasiado viejo para hacer grandes cambios como ese.
Magic Octopus Urn
1
Correcto, no estaba seguro de si estaba permitido en la pregunta original, en lugar de recomendar un cambio. (Estaba pensando en empacar la entrada en un rectángulo, que tiene más fácil y por lo tanto posiblemente byte más corto que los cálculos de coordenadas de embalaje en un cuadrado, entonces el relleno del rectángulo a un cuadrado más grande.)

Respuestas:

2

05AB1E , 34 + 12 = 46 bytes

Utiliza canal rojo.
05AB1E utiliza la codificación CP-1252 .

Codificar:

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

Pruébalo en línea!

Descodificar:

˜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

Pruébalo en línea!

Método de relleno alternativo con recuento de bytes igual

Dgð×J¹gtî©n£
Emigna
fuente
Creo que tiene que unirse específicamente a las nuevas líneas, de acuerdo con la pregunta. (Su respuesta es probable que pegue al mío incluso si está adaptado para hacer eso, sin embargo, porque yo sólo pasamos cinco bytes hacer frente a esa parte de la pregunta, y ya está por delante por más que eso.)
@ ais523: Las reglas establecen que las matrices 2D estaban bien. ¿Entendí mal eso de alguna manera?
Emigna
"Se puede separar con pestañas, comas o cualquier otra cosa que sea horizontalmente sensible, pero debe mantener el patrón cuadrado; en otras palabras, debe usar la separación de línea nueva apropiada". implica fuertemente que debe ser una cadena, ya que las matrices 2D no contienen inherentemente nuevas líneas. En otras palabras, interpreté "matriz" como una descripción de la forma de la salida, no el tipo de datos de la salida.
@ ais523: le he pedido aclaraciones al OP. Como usted dice, no es un gran cambio implementar, pero quizás también pueda guardar algunos bytes si no se necesita formatear.
Emigna
@ ais523 de cualquier manera es aceptable.
Magic Octopus Urn
4

C, 201 (codificación) + 175 (decodificación) = 376 bytes

Para codificar:

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 cada carácter de la cadena de entrada en el canal verde del espectro RGB mientras configura los otros dos canales como valores hexadecimales aleatorios. Toma la entrada a través de STDIN como una cadena y emite a STDOUT una cadena multilínea de código de color hexadecimal en forma de cuadrado. Suponiendo que tiene instalado Python 3 e ImageMagick, y el archivo anterior se compila en un archivo nombrado a.outen el directorio de trabajo actual (CWD), puede obtener directamente la imagen resultante, denominada Output.png, en el CWD desde la salida de texto usando el siguiente 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

Aquí hay una imagen de salida de muestra creada por el comando anterior utilizando Programming Puzzles and Code Golfcomo cadena de entrada:

Salida de muestra

Para decodificar:

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

Toma entrada a través de STDIN una secuencia de cadenas de código de color hexadecimales separadas por espacios con cada una encerrada entre comillas dobles ( ") ( char** argvin main) y también, cuando se llama main, int argcpara la entrada entera. Emite a STDOUT una cadena simple / multilínea que representa el mensaje decodificado.

Intentaré jugar al golf más a lo largo del tiempo cuando y donde pueda.


Además, si usa ambos métodos en el mismo archivo, puede usar el siguiente mainmétodo para unirlo todo con cada función obteniendo las entradas correctas:

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

y usando esto, para la codificación debe proporcionar Ecomo primer argumento para llamar al método de codificación seguido del argumento de cadena única, mientras que para la decodificación, todo lo que necesita proporcionar es la secuencia de cadenas de código de color hexadecimal separadas por espacios con cada una encerrada en doble comillas (" ).


Por último, si se quiere, se puede obtener la versión de usar listos totalmente preparado aquí , aunque no se jugó golf, pero tampoco lo hace la salida cualquier advertencias o errores en la compilación.

R. Kap
fuente
3

Python 2, 164160 + 94 93 = 253 bytes

Guardado 1 + 1 byte gracias a Wheat Wizard.

-5 bytes gracias a Kade

Imagen del codificadorCodificador: la cadena debe estar entre comillas, por ejemplo "CodeGolf", la salida es una imagen PPM de color ascii.

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)

Imagen del decodificadorDecodificador: toma el nombre de archivo de entrada como argumento de línea de 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

Ejemplo:

Programación de puzzles y código de golfProgramación de puzzles y código de 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. En 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. En 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.

Karl Napf
fuente
Puede eliminar el espacio entre los paren cercanos y luegofor
Post Rock Garf Hunter
@ETHproductions: sqrt (25-1) = sqrt (24) <5 y> 4. intde esto es 4, que luego se +1edita, entonces 5
Karl Napf
Oh, mi mal, no vi el -1.
ETHproductions
1
Puede eliminar el espacio entre printy 'en el decodificador. También estoy bastante seguro de que podría hacer int((len(s)+1)**.5)para guardar algunos bytes.
Kade
1
Estoy redactando la última oración de mi comentario anterior, sin embargo, puede acortar la impresión cambiando ' '.join("%d %d %d"a ''.join(3*"%d "ya que estoy bastante seguro de que un espacio final está bien.
Kade
2

Scala, 97 + 68 = 165 bytes

Cifrado (97 bytes):

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

Toma una cuerda y vuelve a ejecutar un iterador de secuencias de enteros.

Descifrado (68 bytes):

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

Toma un iterador de secuencias de enteros y devuelve una cadena.

Explicación:

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
  )
corvus_192
fuente
2

Perl, (103 + 1) + (36 + 2) = 142 bytes

El codificador de texto a imagen (se ejecuta con -puna penalización de 1 byte; -p0(para un byte adicional de penalizaciones) es necesario si desea manejar nuevas líneas en la cadena de entrada)

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

Imagen para decodificador de texto (correr con -p0una pena de 2 bytes):

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

Utiliza el #abcdefformato de imagen basado en texto y codifica en el canal azul. Aquí hay un ejemplo de un posible resultado dadoProgramming Puzzles and Code Golf como entrada:

# 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

Explicación del codificador:

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

Estaba realmente feliz de este uso de \Ktrabajado; especifica dónde reemplazar, y colocándolo dentro de un bucle, parece que la ocurrencia en la última iteración del bucle es lo que cuenta. Por s/(.*?\K,){$a}/\n/glo tanto , coincidirá con una cadena de longitud mínima de la forma algo coma cualquier cosa coma ... cualquier coma, que tenga $acomas, pero la parte real reemplazada del partido simplemente será la última coma. Esto tiene el efecto de reemplazar cada $acoma con una nueva línea, dándonos la forma cuadrada de la imagen.

La gran ventaja de Perl para este desafío (aparte del convertidor de cadena a hexadecimal de caracteres incorporado, que era increíblemente conveniente) es que tiene un decodificador muy corto (tan corto, de hecho, que aunque Perl tiene un generador incorporado para convirtiendo hexadecimal a una cadena, era más corto no usarlo). Así es como funciona:

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

Las únicas instancias de dos caracteres inmediatamente antes de un carácter no alfanumérico son los canales azules (que queremos desempaquetar), que aparecen justo antes de las comas y las nuevas líneas; y los dos personajes que aparecen uno frente al #otro que el primero. No queremos la última categoría de coincidencias, pero inevitablemente se superponen a la categoría anterior y, por lo tanto, serán excluidas por la comprobación de coincidencias superpuestas.


fuente
1

MySQL, 438 + 237 = 675 bytes

Hay una nueva línea al final de la salida, pero no aparece después de ser descifrada. La función hexadecimal (sobrecarga de enteros) cortaría los ceros iniciales, por lo que tuve que rellenarlo con una cadena 0. Podría guardar algunos bytes si pudiera declarar ambas funciones entre los delimitadores.

Encriptar

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 ;

Descifrar

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'))
Wahooka
fuente
1

C #, 312 + 142 = 454 bytes

Codificación:

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

Descodificación:

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

Programa 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
    }
}
Yodle
fuente
1

Mathematica, 111 + 65 = 176 bytes

Codificador

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

Descifrador

StringTrim[""<>FromCharacterCode@ImageData[#,"Byte"][[;;,;;,3]]]&
JungHwan Min
fuente
1

Procesamiento, 220 209 194 + 171 167 151 = 391 380 376 361 345 bytes

Actualizar:

Eliminado inútil noStroke() e hizo que ambos bucles for-one-statementers.

Eliminado inútil image(p,0,0); , le dio al descifrador el nombre de archivo como parámetro

Algoritmo de cifrado

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

Llamando a la función: g("Programming Puzzles and Code Golf");

Esta es una función que toma una Cadena y crea la salida, antes de guardarla como t.png. Utiliza elred valor para almacenar el texto oculto.

Algoritmo de descifrado

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

Función de llamada por: u(file_name);

Esta también es una función que busca la imagen especificada por el parámetro y luego genera la cadena oculta (ya que es más corta que devolver una cadena).

Código expandido

(Algoritmo de cifrado)

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 cadena se pasa cuando se llama a la función. La primera línea de la función calcula la longitud del lado del cuadrado tomando el ceilde su raíz cuadrada. Luego ingresamos un bucle for, donde configuramos el stroke(el color del borde) para que tenga el valor ASCII del personaje en rojo, y valores aleatorios para azul y verde. Después de hacer esto, creamos un rect(rectángulo) con ancho = 1y alto = 1, es decir, un píxel (por alguna extraña razón, no puedo usarpoint correctamente). En la última línea, la imagen resultante se guarda como t.png.

(Algoritmo de descifrado)

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

Esta función tiene el nombre del archivo como parámetro (como una cadena). Luego, la imagen en el archivo se almacena en una variable para ser utilizada más tarde. Una vez que hayamos terminado con eso, configuramos la cadena"" lugar de crear una nueva cadena solo para contener la cadena oculta. Luego iteramos a través de la imagen a través de dos bucles for anidados, y agregamos a la cadena el valor del carácter del valor rojo del píxel. Finalmente, imprimimos la cadena resultante después de eliminar los espacios iniciales (usando una expresión regular). La razón por la que imprimimos el texto oculto en lugar de devolverlo es porque de esta manera es más corto y guardamos bytes.


Texto sin formato de desafío cifrado:

ingrese la descripción de la imagen aquí

Kritixi Lithos
fuente
1

Jelly, 40 + 20 = 60 bytes en la página de códigos de Jelly

Codificador (texto → imagen):

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

Pruébalo en línea!

Decodificador (imagen → texto):

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

Pruébalo en línea!

Un ejemplo de salida que el programa podría producir (almacena información en el canal rojo):

#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

En estos desafíos más grandes, la brevedad de Jelly comienza a disminuir un poco, necesitando varios caracteres "estructurales" para resolver las ambigüedades de análisis, pero aún así es muy breve. Así es como funciona el codificador:

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

Y así es como funciona el decodificador:

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

fuente