Mật mã hàng rào đường sắt


10

Viết hai chương trình:
- Một chương trình đọc một chuỗi và một khóa và mã hóa chuỗi thành một mật mã hàng rào đường sắt bằng cách sử dụng khóa đó. - Tương tự, viết chương trình cho chức năng đảo ngược: giải mã hàng rào đường sắt bằng phím.

Đối với những người không biết mật mã hàng rào đường sắt là gì, về cơ bản, đây là một phương pháp viết văn bản đơn giản theo cách nó tạo ra mô hình tuyến tính theo cách xoắn ốc. Ví dụ - khi đường ray "FOOebarBAZQUX" được rào bằng phím 3.

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

Đọc từng dòng xoắn ốc ở trên, văn bản mật mã trở thành "FAZOBRAQXOBU".

Đọc thêm tại - Mật mã hàng rào đường sắt - Wikipedia .

Mã trong bất kỳ ngôn ngữ đều được chào đón.

Câu trả lời ngắn nhất trong byte thắng.


2
Tiêu chí chiến thắng là gì?
Paul R

Câu trả lời:


9

Python 133 byte

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

Sử dụng mẫu:

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

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

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

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

Lưu ý: kết quả từ số lượng đường ray chẵn khác với mã bạn cung cấp, nhưng chúng có vẻ đúng. Ví dụ: 6 đường ray:

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

tương ứng với AKUBJLTVCIMSWDHNRXEGOQYFPZ, và không phải AKUTBLVJICMSWXRDNHQYEOGZFPnhư mã của bạn tạo ra.

Ý tưởng cơ bản là mỗi đường ray có thể được tìm thấy trực tiếp bằng cách lấy các lát chuỗi [i::m], trong đó isố đường ray ( 0-exexed), và m(num_rails - 1)*2. Các đường ray bên trong cũng cần phải được đan xen với nhau [m-i::m], đạt được bằng cách nén và nối hai bộ ký tự. Bởi vì cái thứ hai trong số này có khả năng ngắn hơn một ký tự, nó được đệm với một ký tự được cho là không xuất hiện ở bất cứ đâu ( _), và sau đó ký tự đó bị loại bỏ nếu cần, nó được chuyển đổi thành một danh sách và được đệm bằng một chuỗi trống.


Một dạng người dễ đọc hơn một chút:

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

Một chức năng giải mã cũng là cần thiết.
ShuklaSannidhya

@ShuklaSannidhya Vậy thì tại sao bạn lại chấp nhận một câu trả lời không đầy đủ?
Jo King

3
@JoKing cho rõ ràng, yêu cầu "hai chương trình" đã được thêm một năm sau khi tôi đăng giải pháp của mình.
primo

2

APL 52 41

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

Nếu chuỗi văn bản đầu vào i và số khóa n được xác định trước, giải pháp có thể được rút ngắn 9 ký tự. Chạy giải pháp chống lại các ví dụ được đưa ra bởi primo cho câu trả lời giống hệt nhau:

FOOBARBAZQUX
3
FAZOBRAQXOBU

ABCDEFGHIJKLMNOPQRSTUVWXYZ
4
AGMSYBFHLNRTXZCEIKOQUWDJPV

ABCDEFGHIJKLMNOPQRSTUVWXYZ
5
AIQYBHJPRXZCGKOSWDFLNTVEMU

ABCDEFGHIJKLMNOPQRSTUVWXYZ
6
AKUBJLTVCIMSWDHNRXEGOQYFPZ

Trên sự phản ánh hơn nữa dường như có một giải pháp dựa trên chỉ số ngắn hơn:

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

Một chức năng giải mã cũng là cần thiết.
ShuklaSannidhya

1

Python 2 , 124 + 179 = 303 byte

Mã hóa:

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

Hãy thử trực tuyến!

Giải mã:

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

Hãy thử trực tuyến!


Bạn cũng cần một chức năng giải mã
Jo King

@Jo King: Tôi đã thêm một bộ giải mã muộn màng.
Chas Brown

0

MATL, 70 byte (tổng cộng)

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

Dùng thử trên MATL Online
Hãy thử nhiều trường hợp thử nghiệm

Lấy một cờ làm đầu vào thứ ba, Fđể mã hóa chuỗi, Tđể giải mã nó (nhờ Kevin Cruijssen cho ý tưởng đó).

Điều này bắt đầu như một câu trả lời của Julia cho đến khi tôi nhận ra việc đánh máy nghiêm ngặt cản trở quá nhiều, đặc biệt là để giải mã. Đây là mã Julia tôi đã có để mã hóa (được nhập vào v0.6 cho TIO):

Julia 0,6 , 191 byte

!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)))[:]),"ø","")

Hãy thử trực tuyến!

Giải trình:

Hoạt động hàng rào đường sắt

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

có thể được xem là đọc r = 3 ký tự đầu vào, sau đó đọc r-2 ký tự và tiền tố và thêm vào đó bằng các giá trị giả (null), sau đó đọc lại ký tự r, v.v., tạo cột mới mỗi lần:

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

sau đó đảo ngược mỗi cột thứ hai (vì phần zag của zigzag tăng lên thay vì xuống, điều này tạo ra sự khác biệt khi r> 3), sau đó đọc ma trận này dọc theo các hàng và loại bỏ các ký tự giả.

Giải mã dường như không có bất kỳ mô hình rõ ràng nào như thế này, nhưng khi tìm kiếm xung quanh vấn đề này tôi đã tìm thấy bài đăng này , nó nói với tôi rằng (a) đây là một thuật toán được công bố nổi tiếng và (có thể?) Cho mật mã đường sắt, và ( b) giải mã là một cách sử dụng lại đơn giản của cùng một phương thức, cung cấp cho nó các chỉ số của chuỗi và nhận các chỉ số của các chỉ số đó sau khi mã hóa và đọc bản mã tại các vị trí đó.

Vì việc giải mã cần thực hiện mọi thứ bằng cách làm việc trên các chỉ mục, mã này cũng mã hóa bằng cách sắp xếp các chỉ mục của chuỗi, và trong trường hợp này chỉ cần lập chỉ mục tại các chỉ mục được sắp xếp lại đó.

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

Tôi muốn được giải thích trong mã này.


Vì đây là môn đánh gôn , bạn nên cố gắng rút ngắn mã của mình. Ngoài ra, bạn nên thêm ngôn ngữ và số byte vào bài nộp này
Jo King

Ngoài những gì Jo King nói, bạn có thể cân nhắc sử dụng một dịch vụ trực tuyến như TIO để người khác có thể dễ dàng kiểm tra mã của bạn.
Οurous

0

Java 10, 459 451 445 439 327 byte

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

-12 byte nhờ @ceilingcat .
-112 byte kết hợp hai chức năng với một cờ chế độ bổ sung làm đầu vào.

Hàm này có đầu vào thứ ba M. Nếu đây là truenó sẽ mã hóa, và nếu falsenó sẽ giải mã.

Hãy thử trực tuyến.

Giải trình:

(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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.