레일 펜스 암호


10

두 개의 프로그램을 작성하십시오
.-하나는 문자열과 키를 읽고 해당 키를 사용하여 문자열을 레일 울타리 암호로 인코딩합니다. -마찬가지로 역 기능을위한 프로그램을 작성하십시오 : 키를 사용하여 레일 펜스를 해독하십시오.

레일 펜스 암호가 무엇인지 모르는 사람들은 기본적으로 나선형으로 선형 패턴을 만드는 방식으로 일반 텍스트를 작성하는 방법입니다. 예-키 3을 사용하여 "FOOBARBAZQUX"가 레일 피어싱 된 경우

F . . . A . . . Z . . . .
  O . B . R . A . Q . X
    O . . . B . . . U

위의 나선형을 한 줄씩 읽으면 암호 텍스트가 "FAZOBRAQXOBU"가됩니다.

자세한 내용은 Rail fence cipher-Wikipedia를 참조하십시오 .

모든 언어의 코드를 환영합니다.

바이트 단위의 최단 답변이 이깁니다.


2
이기는 기준은 무엇입니까?
Paul R

답변:


9

파이썬 133 바이트

def cipher(t,r):
 m=r*2-2;o='';j=o.join
 for i in range(r):s=t[i::m];o+=i%~-r and j(map(j,zip(s,list(t[m-i::m])+[''])))or s
 return o

샘플 사용법 :

>>> print cipher('FOOBARBAZQUX', 3)
FAZOBRAQXOBU

>>> print cipher('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 4)
AGMSYBFHLNRTXZCEIKOQUWDJPV

>>> print cipher('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 5)
AIQYBHJPRXZCGKOSWDFLNTVEMU

>>> print cipher('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 6)
AKUBJLTVCIMSWDHNRXEGOQYFPZ

참고 : 짝수 레일 수의 결과는 제공 한 코드와 다르지만 올바른 것 같습니다. 예를 들어, 6 개의 레일 :

A         K         U
 B       J L       T V
  C     I   M     S   W
   D   H     N   R     X
    E G       O Q       Y
     F         P         Z

코드가 생성하는 AKUBJLTVCIMSWDHNRXEGOQYFPZ것이 AKUTBLVJICMSWXRDNHQYEOGZFP아니라에 해당 합니다.

기본적인 아이디어는 각 레일 문자열 조각을 복용하여 직접 볼 수 있다는 것입니다 [i::m], 어디 i(레일 번호 0-indexed)하고 m있다 (num_rails - 1)*2. 내부 레일은 추가로 [m-i::m]두 세트의 문자를 압축하고 결합하여 달성 해야합니다 . 이 중 두 번째 문자 _ 한 문자보다 짧을 수 있으므로 아무 곳에 나 나타나지 않는 것으로 채워진 문자로 채워 지고 ( ) 필요한 경우 해당 문자가 제거되어 목록으로 변환되고 빈 문자열로 채워집니다.


좀 더 사람이 읽을 수있는 형태 :

def cipher(text, rails):
  m = (rails - 1) * 2
  out = ''
  for i in range(rails):
    if i % (rails - 1) == 0:
      # outer rail
      out += text[i::m]
    else:
      # inner rail
      char_pairs = zip(text[i::m], list(text[m-i::m]) + [''])
      out += ''.join(map(''.join, char_pairs))
  return out

해독 기능도 필요합니다.
ShuklaSannidhya

@ShuklaSannidhya 그러면 왜 불완전한 대답을 받아들였습니까?
Jo King

3
명확성을 위해 @JoKing, 솔루션을 게시 한 후 1 년 후에 "두 프로그램"요구 사항이 추가되었습니다 .
primo

2

APL 52 41

i←⍞⋄n←⍎⍞⋄(,((⍴i)⍴(⌽⍳n),1↓¯1↓⍳n)⊖(n,⍴i)⍴(n×⍴i)↑i)~' '

입력 텍스트 문자열 i와 키 번호 n이 사전 초기화 된 경우 솔루션을 9 자로 줄일 수 있습니다. primo가 제공 한 예제에 대해 솔루션을 실행하면 동일한 대답을 얻을 수 있습니다.

FOOBARBAZQUX
3
FAZOBRAQXOBU

ABCDEFGHIJKLMNOPQRSTUVWXYZ
4
AGMSYBFHLNRTXZCEIKOQUWDJPV

ABCDEFGHIJKLMNOPQRSTUVWXYZ
5
AIQYBHJPRXZCGKOSWDFLNTVEMU

ABCDEFGHIJKLMNOPQRSTUVWXYZ
6
AKUBJLTVCIMSWDHNRXEGOQYFPZ

더 자세히 살펴보면 더 짧은 색인 기반 솔루션이있는 것으로 보입니다.

i[⍋+\1,(y-1)⍴((n←⍎⍞)-1)/1 ¯1×1 ¯1+y←⍴i←⍞]

해독 기능도 필요합니다.
ShuklaSannidhya

1

파이썬 2 , 124 + 179 = 303 바이트

인코딩 :

lambda t,k:''.join(t[i+j]for r in R(k)for i in R(k-1,len(t)+k,2*k-2)for j in[r-k+1,k+~r][:1+(k-1>r>0)]if i+j<len(t))
R=range

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

풀다:

lambda t,k:''.join(t[dict((b,a)for a,b in enumerate(i+j for r in R(k)for i in R(k-1,len(t)+k,2*k-2)for j in[r-k+1,k+~r][:1+(k-1>r>0)]if i+j<len(t)))[m]]for m in R(len(t)))
R=range

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


또한 해독 기능이 필요합니다
Jo King

@ 조 킹 : 나는 뒤늦게 해독기를 추가했습니다.
Chas Brown

0

MATL, 70 바이트 (총)

f'(.{'iV'})(.{1,'2GqqV'})'5$h'$1'0'$2'0K$hYX2Get2LZ)P2LZ(!tg)i?&S]1Gw)

MATL Online에서
사용해보십시오. 여러 테스트 사례를 사용해보십시오.

F문자열을 암호화하고 T해독하기 위해 플래그를 세 번째 입력으로 사용 합니다 ( 케빈 크루이 센 에게 감사의 말을 전합니다 ).

이것은 특히 타이핑이 엄격하게 타이핑되는 것을 깨달을 때까지 Julia의 대답으로 시작되었습니다. 다음은 암호화를 위해 가지고 있던 Julia 코드입니다 (TIO의 경우 v0.6으로 백 포트 됨).

Julia 0.6 , 191 바이트

!M=(M[2:2:end,:]=flipdim(M[2:2:end,:],2);M)
s|n=replace(String((!permutedims(reshape([rpad(replace(s,Regex("(.{$n})(.{1,$(n-2)})"),s"\1ø\2ø"),length(s)*n,'ø')...],n,:),(2,1)))[:]),"ø","")

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

설명:

레일 펜스 작업

F . . . A . . . Z . . . .
  O . B . R . A . Q . X
    O . . . B . . . U

r = 3 문자의 입력을 읽은 다음 r-2 문자를 읽고 접두어를 붙이고 더미 값 (널)로 접미사를 붙인 다음 r 문자를 다시 읽는 등으로 매번 새 열을 만듭니다.

F.A.Z.
OBRAQX
O.B.U.

그런 다음 지그재그zag 부분이 아래로 이동하지 않고 r> 3에서 차이가 있기 때문에 두 번째 열마다 반전 한 다음 행을 따라이 행렬을 읽고 더미 문자를 제거하십시오.

해독은 이와 같은 명백한 패턴이없는 것처럼 보이지만 이것에 대해 검색 할 때이 게시물을 보았습니다. (a) 이것은 레일 암호에 대해 잘 알려져 있고 (아마도?) 게시 된 알고리즘이며 b) 해독은 동일한 방법을 간단히 재사용하여 문자열의 인덱스를 제공하고 암호화 후 인덱스의 인덱스를 가져 와서 그 위치에서 암호문을 읽었습니다.

해독은 인덱스 작업을 통해 일을 수행해야하기 때문에이 코드는 문자열의 인덱스를 정렬하여 암호화를 수행 한 다음이 경우에는 재 배열 된 인덱스에서 인덱싱합니다.

              % implicit first input, say 'FOOBARBAZQUX'
f             % indices of input string (i.e. range 1 to length(input)
'(.{'iV'})(.{1,'2GqqV'})'5$h
              % Take implicit second input, say r = 3
              % Create regular expression '(.{$r})(.{1,$(r-2)})'
              % matches r characters, then 1 to r-2 characters
              %  (to allow for < r-2 characters at end of string)
'$1'0'$2'0K$h % Create replacement expression, '$1\0$2\0'
YX            % Do the regex replacement
2Ge           % reshape the result to have r rows (padding 0s if necessary)
t2LZ)         % extract out the even columns of that
P             % flip them upside down
2LZ(          % assign them back into the matrix
!             % transpose
tg)           % index into the non-zero places (i.e. remove dummy 0s)
i?            % read third input, check if it's true or false
&S]           % if it's true, decipherment needed, so get the indices of the 
              %  rearranged indices
1Gw)          % index the input string at those positions

0
int r=depth,len=plainText.length();
int c=len/depth;
char mat[][]=new char[r][c];
int k=0;
String cipherText="";
for(int i=0;i< c;i++)
{
 for(int j=0;j< r;j++)
 {
  if(k!=len)
   mat[j][i]=plainText.charAt(k++);
  else
   mat[j][i]='X';
 }
}
for(int i=0;i< r;i++)
{
 for(int j=0;j< c;j++)
 {
  cipherText+=mat[i][j];
 }
}
return cipherText;
}

이 코드에서 설명하고 싶습니다.


이것은 code-golf 이므로 코드 단축을 시도해야합니다. 또한이 제출물에 언어와 바이트 수를 추가해야합니다
Jo King

Jo King이 말한 것 외에도 TIO 와 같은 온라인 서비스를 사용하여 다른 사람들이 쉽게 코드를 테스트 할 수 있습니다.
OUurous

0

자바 10, 459 451 445 439 327 바이트

(s,k,M)->{int l=s.length,i=-1,f=0,r=0,c=0;var a=new char[k][l];for(;++i<l;a[r][c++]=M?s[i]:1,r+=f>0?1:-1)f=r<1?M?f^1:1:r>k-2?M?f^1:0:f;for(c=i=0;i<k*l;i++)if(a[i/l][i%l]>0)if(M)System.out.print(a[i/l][i%l]);else a[i/l][i%l]=s[c++];if(!M)for(r=c=i=0;i++<l;f=r<1?1:r>k-2?0:f,r+=f>0?1:-1)if(a[r][c]>1)System.out.print(a[r][c++]);}

@ceilingcat 덕분에 -12 바이트 .
두 개의 기능을 추가 모드 플래그와 입력으로 결합한 -112 바이트

이 함수는 세 번째 입력을 M받습니다. 이것이 true암호화 일 경우, false해독 될 것입니다.

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

설명:

(s,k,M)->{              // Method with character-array, integer, and boolean parameters
                        // and no return-type
  int l=s.length,       //  Length of the input char-array
      i=-1,             //  Index-integer, starting at -1
      f=0,              //  Flag-integer, starting at 0
      r=0,c=0;          //  Row and column integers, starting both at 0
  var a=new char[k][l]; //  Create a character-matrix of size `k` by `l`
  for(;++i<l            //  Loop `i` in the range (-1, `l`):
      ;                 //    After every iteration:
       a[r][c++]=       //     Set the matrix-cell at `r,c` to:
         M?s[i++]       //      If we're enciphering: set it to the current character
         :1,            //      If we're deciphering: set it to 1 instead
       r+=f>0?          //     If the flag is 1:
           1            //      Go one row down
          :             //     Else (flag is 0):
           -1)          //      Go one row up
    f=r<1?              //   If we're at the first row:
       M?f^1            //    If we're enciphering: toggle the flag (0→1; 1→0)
       :1               //    If we're deciphering: set the flag to 1
      :r>k-2?           //   Else-if we're at the last row:
       M?f^1            //    If we're enciphering: toggle the flag (0→1; 1→0)
       :0               //    If we're deciphering: set the flag to 0
      :                 //   Else (neither first nor last row):
       f;               //    Leave the flag unchanged regardless of the mode
  for(c=i=0;            //  Reset `c` to 0
            i<k*l;i++)  //  Loop `i` in the range [0, `k*l`):
    if(a[i/l][i%l]>0)   //   If the current matrix-cell is filled with a character:
      if(M)             //    If we're enciphering:
        System.out.print(a[i/l][i%l]);}
                        //     Print this character
      else              //    Else (we're deciphering):
        a[r][i]=s[c++]; //     Fill this cell with the current character
  if(!M)                //  If we're deciphering:
    for(r=c=i=0;        //   Reset `r` and `c` both to 0
        i++<l           //   Loop `i` in the range [0, `l`)
        ;               //     After every iteration:
         f=r<1?         //      If we are at the first row:
            1           //       Set the flag to 1
           :r>k-2?      //      Else-if we are at the last row:
            0           //       Set the flag to 0
           :            //      Else:
            f,          //       Leave the flag the same
         r+=f>0?        //      If the flag is now 1:
             1          //       Go one row up
            :           //      Else (flag is 0):
             -1)        //       Go one row down
      if(a[r][c]>1)     //    If the current matrix-cell is filled with a character:
        System.out.print(a[r][c++]);}
                        //     Print this character
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.