Quadrados esteganográficos


14

Quadrados esteganográficos

Seu trabalho é coletar uma sequência e gerar uma NxNimagem que represente essa sequência. Você também deve escrever o algoritmo que captura a imagem e a transforma novamente em uma string. A pontuação será incluirá a contagem de bytes de ambos os algoritmos:

Algoritmo "Criptografia" + Algoritmo "Descriptografia" .

Você deve postar cada um separadamente, com contagens de bytes para os algoritmos de criptografia e descriptografia exibidos individualmente.


Exemplo de algoritmo

Por exemplo, aqui está o "Programming Puzzles and Code Golf" usando um algoritmo esteganográfico simples baseado em ASCII no canal 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

Imagem real ( A imagem gerada pelo algoritmo.)

Imagem ampliada.

Você pode ver que o canal azul simplesmente contém os valores ascii para esta imagem:

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

Enquanto o restante dos canais mantém valores gerados aleatoriamente para "apimentar" a variedade de cores na imagem. Ao retirar a mensagem da imagem, podemos simplesmente ignorar os outros valores do canal e puxar o bit hexadecimal no canal azul, reconstruindo a string:

"Programming Puzzles and Code Golf"

Observe que os espaços que foram usados ​​para preencher a cadeia no quadrado não estão incluídos na saída descriptografada final. Enquanto você deve preencher a sequência na imagem, você pode assumir que a sequência de entrada não terminará com espaços.


Regras

  • Você deve codificar 1 caractere por pixel, o canal escolhido para codificar o caracter é arbitrário.
  • Os canais das outras cores RGB devem ser randomizados, diferente daquele em que você deseja codificar a sequência; isso significa que seus canais finais não codificados precisariam estar entre 0x0000-0xFFFF(escolhidos aleatoriamente).
  • Expressar o resultado final como uma matriz 2D de valores de cores RGB é bom 0x000000-0xFFFFFF, não há necessidade de usar a criação de imagens, a menos que você queira se divertir com ele ou menos bytes. Se você escolher a saída como cadeias hexadecimais, prefixe a cadeia hexadecimal com #EG #FFFFFFou #05AB1E. Você pode separar com guias, vírgulas ou qualquer outra coisa que seja horizontalmente sensível, mas deve manter o padrão quadrado; em outras palavras, você deve usar a separação de nova linha apropriada.
  • A saída deve estar em um quadrado e a cadeia deve ser preenchida com espaços no final para acomodar isso. Isso significa isso N≈SQRT(Input#Length()). Se o comprimento da entrada não for um quadrado perfeito, você deve arredondar para cima Ne preencher com espaços.
  • Como mencionado anteriormente, se você estiver preenchendo espaços na imagem, não deverá incluir os caracteres preenchidos na saída final "descriptografada".
  • Você pode assumir que:
    • A sequência de entrada não termina com espaços.
    • A sequência de entrada usará apenas caracteres ASCII imprimíveis.
  • Isso é , menor número de bytes ganhos.

Apenas para esclarecer, as soluções devem codificar / decodificar exatamente um caractere por pixel?
ETHproductions

O @ETHproductions parece um bom desafio de acompanhamento, mas para os fins desta competição, você escolhe um canal de codificação e codifica 1 caractere por pixel.
Magic Octopus Urn

Provavelmente não vou usar isso, mas: está tudo bem em "exagerar" a imagem com mais espaços do que o necessário? E não há problema em supor que a imagem terá a mesma quantidade de overpadding que o codificador geraria?

@ ais523 Não consigo ver como esse tipo de abordagem faria qualquer coisa, além de exigir mais bytes para implementar. Não vou embora, pois o desafio é velho demais para fazer grandes mudanças como essa.
Magic Octopus Urn

1
Certo, eu não tinha certeza se isso era permitido na pergunta original, em vez de recomendar uma alteração. (Eu estava pensando sobre a embalagem a entrada em um retângulo, que tem mais fáceis e, portanto, possivelmente byte mais curto coordenar cálculos que embalá-lo em um quadrado, então preenchimento do retângulo para um quadrado maior.)

Respostas:


2

05AB1E , 34 + 12 = 46 bytes

Usa canal vermelho.
05AB1E usa a codificação 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

Experimente online!

Decodificar:

˜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

Experimente online!

Método alternativo de preenchimento com contagem de bytes igual

Dgð×J¹gtî©n£

Eu acho que você tem que participar especificamente de novas linhas, de acordo com a pergunta? (Sua resposta provavelmente vai bater o meu mesmo que seja adaptado para fazer isso, porém, porque eu só passou cinco bytes lidar com essa parte da pergunta, e você está à frente por mais do que isso.)

@ ais523: As regras afirmam que as matrizes 2D estavam corretas. Eu entendi isso de alguma maneira?
Emigna

"Você pode separar com guias, vírgulas ou qualquer outra coisa que seja sensata horizontalmente, mas deve manter o padrão quadrado; em outras palavras, você deve usar a separação de nova linha apropriada". implica fortemente que ele precisa ser uma sequência, pois as matrizes 2D não contêm inerentemente novas linhas. Em outras palavras, interpretei "array" como descrevendo a forma da saída, não o tipo de dados da saída.

@ ais523: pedi esclarecimentos ao OP. Como você diz, não é uma grande mudança para implementar, mas talvez você possa salvar alguns bytes também, se a formatação não for necessária.
Emigna

@ ais523 de qualquer maneira é aceitável.
Magic Octopus Urn

4

C, 201 (codificação) + 175 (decodificação) = 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 caractere da sequência de entrada no canal verde do espectro RGB enquanto define os outros dois canais como valores hexadecimais aleatórios. Leva a entrada através de STDIN como uma sequência e gera para STDOUT uma sequência multilinha de código de cores hexadecimal na forma de um quadrado. Supondo que você tenha o Python 3 e o ImageMagick instalados e o arquivo acima seja compilado em um arquivo nomeado a.outno diretório de trabalho atual (CWD), é possível obter diretamente a imagem resultante, denominada Output.png, no CWD a partir da saída textual, usando o seguinte 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

Aqui está uma imagem de saída de amostra criada pela vírgula acima, usando Programming Puzzles and Code Golfcomo string de entrada:

Saída de amostra

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

Recebe da entrada STDIN uma sequência de cadeias de código hexadecimal de espaço separadas por espaço, cada uma entre aspas duplas ( ") ( char** argvin main) e também, quando chamada main, int argcpara a entrada inteira. Emite para STDOUT uma sequência de linhas únicas / múltiplas, representando a mensagem decodificada.

Vou tentar jogar estes mais ao longo do tempo, quando e onde puder.


Além disso, se você mesclar os dois métodos no mesmo arquivo, poderá usar o mainmétodo a seguir para reunir tudo, com cada função obtendo as entradas corretas:

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

e usando isso, para a codificação, você deve fornecer Ecomo o primeiro argumento a chamar o método de codificação seguido pelo argumento de cadeia única, enquanto que para a decodificação, tudo o que você precisa fornecer é a sequência de cadeias de código de cores hexadecimais separadas por espaço, com cada uma delas aspas duplas ( ").


Por fim, se desejar, você pode obter a versão totalmente preparada e pronta para uso aqui , embora não seja um jogo de golfe, mas também não gera nenhum aviso ou erro na compilação.


3

Python 2, 164 160 + 94 93 = 253 bytes

Economizou 1 + 1 byte graças ao Wheat Wizard.

-5 bytes graças ao Kade

Imagem do codificadorCodificador: a string deve estar entre aspas; por exemplo "CodeGolf", a saída é uma imagem PPM ascii colorida.

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)

Imagem do decodificadorDecodificador: recebe o nome do arquivo de entrada como argumento da linha 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

Exemplo:

Programação de quebra-cabeças e código de golfeProgramação de quebra-cabeças e código de golfe

Lorem IpsumLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod temporariamente associado a labore et dolore magna aliquyam erat, sed diam voluptua. No vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no mar takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod temporariamente associado a labore et dolore magna aliquyam erat, sed diam voluptua. No vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no mar takimata sanctus est Lorem ipsum dolor sit amet.


Você pode remover o espaço entre os paren fechar efor
post rock Garf Hunter

@ETHproductions: sqrt (25-1) = sqrt (24) <5 e> 4. inta partir deste é 4, que é, em seguida, +1ed, assim 5
Karl Napf

Oh, meu mal, eu não vi o -1.
ETHproductions

1
Você pode remover o espaço entre printe 'no decodificador. Também tenho certeza de que você poderia fazer int((len(s)+1)**.5)para salvar alguns bytes.
Kade 6/12

1
Estou redigindo a última frase do meu comentário anterior, no entanto, você pode reduzir a impressão alterando ' '.join("%d %d %d"para, ''.join(3*"%d "pois tenho certeza de que um espaço à direita está OK.
Kade

2

Scala, 97 + 68 = 165 bytes

Criptografia (97 bytes):

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

Pega uma String e executa um Iterador de Sequências de Inteiros.

Descriptografia (68 bytes):

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

Toma um iterador de sequências de números inteiros e retorna uma string.

Explicação:

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

O codificador de texto em imagem (executado com -puma penalidade de 1 byte; -p0(para um byte adicional de penalidades) é necessário se você deseja manipular novas linhas na sequência de entrada):

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

Decodificador de imagem em texto (executado com -p0uma penalidade de 2 bytes):

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

Isso usa o #abcdefformato de imagem baseado em texto e codifica no canal azul. Aqui está um exemplo de uma saída possível fornecida Programming Puzzles and Code Golfcomo 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

Explicação do 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

Fiquei muito feliz com esse uso do \Ktrabalho; especifica onde substituir e, colocando-o dentro de um loop, parece que a ocorrência na última iteração do loop é o que conta. Então, s/(.*?\K,){$a}/\n/gvai encontrar uma string de tamanho mínimo da forma nada vírgula qualquer coisa vírgula ... nada vírgula, que tem $avírgulas, mas a parte real substituído do jogo será simplesmente a última vírgula. Isso tem o efeito de substituir todas as $avírgulas por uma nova linha, fornecendo a forma quadrada da imagem.

A grande vantagem do Perl para esse desafio (além do conversor de cadeia de caracteres para hexadecimal de caracteres embutido, que era incrivelmente conveniente) é que ele possui um decodificador muito curto (tão curto, de fato, que, embora o Perl tenha um built-in para convertendo hexadecimal em uma string, era mais curto não usá-lo). Veja 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"

As únicas instâncias de dois caracteres imediatamente antes de um caractere não alfanumérico são os canais azuis (que queremos descompactar), que aparecem logo antes de vírgulas e novas linhas; e os dois caracteres que aparecem um antes do #outro que o primeiro. Não queremos a última categoria de correspondências, mas elas inevitavelmente se sobrepõem à categoria anterior e, portanto, serão excluídas pela verificação de correspondências sobrepostas.


1

MySQL, 438 + 237 = 675 bytes

Há uma nova linha à direita no final da saída, mas ela não aparece após ser descriptografada. A função hexadecimal (sobrecarga de número inteiro) cortaria os zeros à esquerda, então tive que preenchê-la com uma string 0. Eu poderia economizar alguns bytes se pudesse declarar as duas funções entre os delimitadores.

Criptografar

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 ;

Descriptografar

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 bytes

Codificação:

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ção:

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

1

Mathematica, 111 + 65 = 176 bytes

Codificador

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

Decodificador

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

1

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

Atualizar:

Removido inútil noStroke() e feito os dois for-loops one-statementers.

Removido inútil image(p,0,0); , deu ao decodificador o nome do arquivo como parâmetro

Algoritmo de criptografia

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

Chamando a função: g("Programming Puzzles and Code Golf");

Esta é uma função que recebe uma String e cria a saída antes de salvá-la como t.png. Ele usa ored valor para armazenar o texto oculto.

Algoritmo de descriptografia

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

Chamar a função por: u(file_name);

Essa também é uma função que procura a imagem especificada pelo parâmetro e, em seguida, gera a string oculta (já que é mais curta do que retornar uma string).

Código expandido

(Algoritmo de criptografia)

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

A cadeia é passada quando a função é chamada. A primeira linha da função calcula o comprimento lateral do quadrado tirando a ceilraiz quadrada. Em seguida, inserimos um loop for, onde definimos a stroke(a cor da borda) para que o valor ASCII do caractere seja vermelho e os valores aleatórios para azul e verde. Depois disso, criamos um rect(retângulo) com largura = 1e altura = 1, ou seja, um pixel (por algum motivo estranho, não posso usar pointcorretamente). Na última linha, a imagem resultante é salva comot.png .

(Algoritmo de descriptografia)

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 função tem o nome do arquivo como parâmetro (como uma string). Em seguida, a imagem no arquivo é armazenada em uma variável para ser usada posteriormente. Depois que terminamos, definimos a string para, em ""vez de criar uma nova string apenas para manter a string oculta. Em seguida, iteramos na imagem por meio de dois loops for-aninhados e adicionamos à string o valor do caractere do valor vermelho do pixel. Por fim, imprimimos a sequência resultante após remover os espaços iniciais (usando uma regex). A razão pela qual imprimimos o texto oculto em vez de retorná-lo é porque dessa maneira é mais curto e economizamos bytes.


Texto bruto do desafio criptografado:

insira a descrição da imagem aqui


1

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

Codificador (texto → imagem):

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

Experimente online!

Decodificador (imagem → texto):

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

Experimente online!

Um exemplo de saída que o programa pode produzir (armazena informações no canal vermelho):

#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

Nesses desafios maiores, a discrepância de Jelly começa a diminuir um pouco, precisando de vários caracteres "estruturais" para resolver as ambiguidades da análise, mas ainda assim é muito concisa. Veja como o codificador funciona:

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

E aqui está como o decodificador funciona:

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.