스테 가노 그래피 스퀘어


14

스테 가노 그래피 스퀘어

당신의 임무는 문자열을 받아이 문자열 NxN을 나타내는 이미지를 생성하는 것 입니다. 또한 이미지를 가져 와서 다시 문자열로 바꾸는 알고리즘을 작성해야합니다. 스코어링에는 두 알고리즘의 바이트 수가 포함됩니다.

"암호화"알고리즘 + "암호화"알고리즘 .

암호화 및 암호 해독 알고리즘 모두에 대해 바이트 수와 함께 각각 개별적으로 게시해야합니다.


알고리즘 예

예를 들어 다음은 Blue 채널에서 간단한 ASCII 기반 스테 가노 그래피 알고리즘을 사용하는 "프로그래밍 퍼즐 및 코드 골프"입니다.

#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

실제 이미지 ( 알고리즘에 의해 생성 된 이미지.)

이미지가 날아갔습니다.

파란색 채널이 단순히이 이미지의 ASCII 값을 보유하고 있음을 알 수 있습니다.

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

나머지 채널은 무작위로 생성 된 값을 유지하면서 이미지의 다양한 색상을 "스파이 업"합니다. 이미지에서 메시지를 다시 가져올 때 다른 채널 값을 무시하고 파란색 채널에서 16 진수 비트를 당겨 문자열을 재구성하면됩니다.

"Programming Puzzles and Code Golf"

정사각형에서 문자열을 채우는 데 사용 된 공백은 최종 해독 된 출력에 포함되지 않습니다. 이미지에서 문자열을 채워야하지만 입력 문자열이 공백으로 끝나지 않는다고 가정 할 수 있습니다.


규칙

  • 픽셀 당 1 개의 문자를 인코딩해야하며 문자를 인코딩하기 위해 선택한 채널은 임의적입니다.
  • 다른 RGB 색상의 채널은 문자열을 인코딩하도록 선택한 채널 이외의 무작위로 지정해야합니다. 즉, 인코딩되지 않은 최종 채널 사이 0x0000-0xFFFF(임의로 선택) 가 필요합니다 .
  • 최종 결과를 RGB 색상 값의 2D 배열로 표현하는 0x000000-0xFFFFFF것이 좋습니다. 재미 있기를 원하거나 바이트가 적지 않으면 이미지를 만들 필요가 없습니다. 당신이 16 진수 문자열로 출력을 선택하는 경우와 16 진수 문자열 앞에 #EG #FFFFFF또는 #05AB1E. 탭, 쉼표 또는 가로로 구분되는 다른 것으로 분리 할 수 ​​있지만 정사각형 패턴을 유지해야합니다. 즉, 적절한 줄 바꿈 구분을 사용해야합니다.
  • 출력은 정사각형이어야하며,이를 위해 문자열 끝에 공백이 채워 져야합니다. 이것은 의미합니다 N≈SQRT(Input#Length()). 입력 길이가 완벽한 정사각형이 아닌 경우 반올림 N하여 공백으로 채워야합니다.
  • 앞에서 언급했듯이 이미지에 공백으로 채워지는 경우 최종 "암호화 된"출력에 채워진 문자를 포함해서는 안됩니다.
  • 다음과 같이 가정 할 수 있습니다.
    • 입력 문자열은 공백으로 끝나지 않습니다.
    • 입력 문자열은 인쇄 가능한 ASCII 문자 만 사용합니다.
  • 이것은 이며 가장 낮은 바이트 수입니다.

명확히하기 위해 솔루션은 픽셀 당 정확히 하나의 문자를 인코딩 / 디코딩해야 합니까?
ETHproductions

@ETH 프로덕션은 훌륭한 후속 과제처럼 들리지만이 경쟁의 목적을 위해 인코딩 채널을 선택하고 픽셀 당 1 문자를 인코딩합니다.
Magic Octopus Urn

아마 이것을 사용하지는 않겠지 만, 필요한 것보다 더 많은 공간으로 이미지를 "오버 패드"해도 괜찮습니까? 그리고 이미지가 인코더가 생성하는 것과 동일한 양의 오버 패딩을 가질 것이라고 가정해도 괜찮습니까?

@ ais523이 유형의 접근 방식이 어떻게 작동하는지 알 수 없지만 구현하려면 더 많은 바이트가 필요합니다. 도전이 너무 오래되어서 큰 변화를 일으키지 않기 때문에 나는 계속 갈 것입니다.
Magic Octopus Urn

1
맞습니다. 변경을 권장하기보다는 원래 질문에서 허용되는지 확실하지 않았습니다. (입력을 사각형으로 묶는 것에 대해 생각하고 있었는데, 사각형으로 포장하는 것보다 쉽고 계산 가능한 바이트-짧은 좌표 계산을 한 다음 사각형을 더 큰 사각형으로 채 웁니다.)

답변:


2

05AB1E , 34 + 12 = 46 바이트

빨간색 채널을 사용합니다.
05AB1E는 CP-1252 인코딩을 사용합니다.

인코딩 :

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

온라인으로 사용해보십시오!

풀다:

˜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

온라인으로 사용해보십시오!

바이트 수가 동일한 대체 패딩 방법

Dgð×J¹gtî©n£

질문에 따르면 개행에 구체적으로 참여해야한다고 생각합니까? (하지만 질문에 해당하는 부분을 처리하는 데 5 바이트 만 소비했으며 그보다 더 앞서 있기 때문에 귀하의 답변은 그렇게 할지라도 내 대답을 능가 할 것입니다.)

@ ais523 : 규칙에 따르면 2D 배열이 정상입니다. 어떻게 든 오해 했습니까?
Emigna

"탭, 쉼표 또는 가로로 구분되는 다른 것으로 분리 할 수 ​​있지만 정사각형 패턴을 유지해야합니다. 즉, 적절한 줄 바꿈 구분을 사용해야합니다." 2D 배열에는 본질적으로 줄 바꿈이 포함되어 있지 않으므로 문자열이어야 함을 강력하게 암시합니다. 다시 말해, 출력의 데이터 유형이 아니라 출력의 모양을 설명하는 것으로 "배열"을 해석했습니다.

@ ais523 : OP에 설명을 요청했습니다. 당신이 말했듯이, 그것은 구현하기위한 큰 변화는 아니지만 포맷이 필요하지 않은 경우 바이트를 절약 할 수 있습니다.
Emigna

@ ais523 어느 쪽이든 허용됩니다.
Magic Octopus Urn

4

C, 201 (인코딩) + 175 (디코딩) = 376 바이트

인코딩하려면 :

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

입력 문자열의 각 문자를 RGB 스펙트럼의 녹색 채널로 인코딩하고 다른 두 채널을 임의의 16 진수 값으로 설정합니다. STDIN을 통해 입력을 문자열로 가져와 사각형 모양의 16 진 색상 코드의 여러 줄 문자열을 STDOUT에 출력합니다. Python 3과 ImageMagick이 설치되어 있고 위의 파일이 a.out현재 작업 디렉토리 (CWD)에 이름이 지정된 파일로 컴파일되었다고 가정하면 Output.png다음 명령을 사용하여 텍스트 출력에서 이라는 이름의 결과 이미지를 CWD로 직접 가져올 수 있습니다 .

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

다음은 Programming Puzzles and Code Golf입력 문자열로 사용하여 위의 commamd에 의해 생성 된 샘플 출력 이미지입니다 .

샘플 출력

디코딩하려면 :

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

STDIN을 통해 공백으로 구분 된 16 진 색상 코드 문자열 시퀀스를 각각 큰 따옴표 ( ") ( char** argvin main)로 묶고로 호출 할 때 main,int argc 정수 입력. 디코딩 된 메시지를 나타내는 단일 / 멀티 라인 문자열을 STDOUT에 출력합니다.

나는 언제 어디서나 시간이 지남에 따라 더 많은 골프를하려고합니다.


또한 두 메소드를 모두 동일한 파일에 동일하게 사용하면 다음 main메소드를 사용 하여 올바른 입력을 얻는 각 함수와 함께 사용할 수 있습니다 .

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

이것을 사용하면 인코딩을 위해 E인코딩 방법과 단일 문자열 인수를 호출하는 첫 번째 인수로 제공해야 하지만 디코딩을 위해서는 공백으로 구분 된 16 진수 색상 코드 문자열 시퀀스가 ​​있어야합니다. 큰 따옴표 ( ").


마지막으로 원하는 경우 완전히 준비된 즉시 사용 가능한 버전을 얻을 수 있습니다. 여기 가 golfed되지는 않지만,뿐만 아니라 출력되지 않는 어떤 컴파일시 경고 또는 오류.


3

파이썬 2, 164160 + 94 93 = 253 바이트

Wheat Wizard 덕분에 1 + 1 바이트가 절약되었습니다.

Kade 덕분에 -5 바이트

인코더 사진인코더 : 문자열은 따옴표로 묶어야합니다. 예 : "CodeGolf"출력은 색상 아스키 PPM 이미지입니다.

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)

디코더 사진디코더 : 입력 파일 이름을 명령 줄 인수로 사용합니다.

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

용법:

 python golf_stegansquare_enc.py > stega.ppm

 python golf_stegansquare_dec.py stega.ppm

예:

프로그래밍 퍼즐 및 코드 골프프로그래밍 퍼즐 및 코드 골프

로렘 입숨Lorem ipsum dolor는 amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut worke et dolore magna aliquyam erat, sed diam voluptua에 앉아 있습니다. vero eos et accusam et justo duo dolores et eea rebum. 스텔라 kasd gubergren, 바다 takimata sanctus est Lorem ipsum dolor 앉아있는 amet 없습니다. Lorem ipsum dolor는 amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut worke et dolore magna aliquyam erat, sed diam voluptua에 앉아 있습니다. vero eos et accusam et justo duo dolores et eea rebum. 스텔라 kasd gubergren, 바다 takimata sanctus est Lorem ipsum dolor 앉아있는 amet 없습니다.


그런 다음 닫기 괄호 사이의 공간을 제거 할 수 있습니다for
포스트 록 Garf 헌터

@ETHproductions : sqrt (25-1) = sqrt (24) <5 and> 4. int이 중 4는 +1ed이므로 5
Karl Napf

오, 내 나쁜, 나는 보지 못했다 -1.
ETHproductions

1
디코더 사이 print'디코더 사이의 공간을 제거 할 수 있습니다 . 또한 int((len(s)+1)**.5)바이트를 절약하기 위해 할 수 있다고 확신합니다 .
Kade

1
이전 주석의 마지막 문장을 수정하고 있지만 후행 공백이 양호 ' '.join("%d %d %d"하기 ''.join(3*"%d "때문에 로 변경하여 인쇄를 줄일 수 있습니다 .
Kade

2

스칼라, 97 + 68 = 165 바이트

암호화 (97 바이트) :

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

문자열을 가져와 정수 시퀀스 반복자를 재조정합니다.

암호 해독 (68 바이트) :

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

정수 시퀀스의 반복자를 가져 와서 문자열을 반환합니다.

설명:

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

펄, (103 + 1) + (36 + 2) = 142 바이트

텍스트 입력 이미지 인코더 ( -p1 바이트 페널티로 실행; -p0입력 문자열에서 줄 바꿈을 처리하려면 추가 페널티 페널티)이 필요합니다.

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

이미지 대 텍스트 디코더 ( -p02 바이트 페널티로 실행) :

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

이것은 사용하는 #abcdef텍스트 기반의 이미지 포맷을, 청색 채널 인코딩합니다. 다음 Programming Puzzles and Code Golf은 입력으로 제공되는 가능한 출력의 예입니다 .

# 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

엔코더 설명 :

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

나는이 \K일의 사용이 정말로 기뻤다 . 대체 할 위치를 지정하고 루프 안에 배치하면 마지막 루프 반복에서 발생하는 횟수가 중요합니다. 그래서 s/(.*?\K,){$a}/\n/g양식의 최소 길이 문자열과 일치합니다 아무것도 쉼표 아무것도 쉼표 ... 아무것도 가지고 쉼표, $a쉼표, 그러나 경기의 실제 교체 된 부품은 단순히 마지막 쉼표 될 것입니다. 이것은 모든 것을 교체하는 효과가 있습니다$a 쉼표를 줄 바꿈 이미지의 사각형 모양을 얻을 수 있습니다.

이 문제에 대한 Perl의 가장 큰 장점은 (매우 편리한 내장 문자 스트링 -16 진수 변환기를 제외하고) 매우 짧은 디코더를 가지고 있다는 것입니다. 16 진수를 문자열로 변환하면 사용하지 않는 것이 더 짧습니다). 작동 방식은 다음과 같습니다.

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

영숫자가 아닌 문자 바로 앞에있는 두 문자의 유일한 인스턴스는 압축을 풀고 자하는 파란색 채널이며 쉼표와 줄 바꿈 직전에 나타납니다. #첫 번째 문자가 아닌 두 문자가 앞에 나타납니다 . 우리는 후자의 범주의 일치를 원하지 않지만 필연적으로 전자의 범주와 겹치므로 겹치는 일치 검사로 제외됩니다.


1

MySQL, 438 + 237 = 675 바이트

출력 끝에 새 줄이 있지만 해독 후에는 표시되지 않습니다. 16 진수 함수 (정수 과부하)는 선행 0을 잘라 버릴 수 있으므로 문자열 0으로 채워야했습니다. 구분 기호 사이에 두 함수를 선언 할 수 있으면 일부 바이트를 절약 할 수 있습니다.

암호화

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 ;

해독

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 ;

용법:

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

1

C #, 312 + 142 = 454 바이트

부호화:

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

디코딩:

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

전체 프로그램 :

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

수학, 111 + 65 = 176 바이트

엔코더

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

디코더

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

1

처리 220 209 194 + 171 167 151 = 391 380 376 361 345 바이트

최신 정보:

쓸모없는 제거 noStroke() 하고 두 개의 for-loops 문 하나를 만들었습니다.

쓸모없는 제거 image(p,0,0); 하고 암호 해독기에 파일 이름을 매개 변수로 지정했습니다.

암호화 알고리즘

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

함수 호출 g("Programming Puzzles and Code Golf");

이것은 String을 받아서로 저장하기 전에 출력을 생성하는 함수입니다 t.png. 그것은red 값을 사용하여 숨겨진 텍스트를 저장합니다.

암호 해독 알고리즘

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

다음에 의해 함수 호출 : u(file_name);

매개 변수로 지정된 이미지를 검색 한 다음 숨겨진 문자열을 출력하는 함수이기도합니다 (문자열을 반환하는 것보다 짧기 때문에).

확장 코드

(암호화 알고리즘)

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

함수가 호출되면 문자열이 전달됩니다. 함수의 첫 번째 행은 제곱근을 취하여 사각형의 측면 길이를 계산합니다 ceil. 그런 다음 for-loop를 입력합니다. 여기서 stroke(가장자리 색상)은 문자의 ASCII 값을 빨간색으로, 파란색 및 녹색의 임의 값을 갖도록 설정합니다. 이 작업을 수행 한 후 rectwidth = 1및 height = 1, 즉 픽셀 (이상한 이유로 point올바르게 사용할 수 없음 )을 가진 (사각형)을 만듭니다 . 마지막 줄에서 결과 이미지는로 저장됩니다 t.png.

(암호 해독 알고리즘)

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

이 함수는 파일 이름을 매개 변수 (문자열)로 갖습니다. 그런 다음 파일의 이미지는 나중에 사용할 수 있도록 변수에 저장됩니다. 이 작업을 마치면 ""숨겨진 문자열을 유지하기 위해 새 문자열을 만드는 대신 문자열을 설정 합니다. 그런 다음 두 개의 중첩 된 for- 루프를 통해 이미지를 반복하고 픽셀의 빨간색 값에 대한 문자 값을 문자열에 추가합니다. 마지막으로 정규식을 사용하여 선행 공백을 제거한 후 결과 문자열을 인쇄합니다. 숨겨진 텍스트를 반환하는 대신 인쇄하는 이유는 길이가 짧고 바이트를 절약하기 때문입니다.


암호화 된 챌린지 원시 텍스트 :

여기에 이미지 설명을 입력하십시오


1

젤리 코드 페이지에서 40 + 20 = 60 바이트

인코더 (텍스트 → 이미지) :

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

온라인으로 사용해보십시오!

디코더 (이미지 → 텍스트) :

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

온라인으로 사용해보십시오!

프로그램이 생성 할 수있는 출력 예 (빨간색 채널에 정보를 저장) :

#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

이러한 더 큰 도전에서 젤리의 간결함은 약간 떨어지기 시작하고, 파싱 모호성을 해결하기 위해 몇 가지 "구조적"문자가 필요하지만 그럼에도 불구하고 여전히 간결합니다. 인코더 작동 방식은 다음과 같습니다.

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

다음은 디코더 작동 방식입니다.

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.