รหัสรั้วรถไฟ


10

เขียนโปรแกรมสองโปรแกรม:
- โปรแกรมหนึ่งที่อ่านสตริงและคีย์และเข้ารหัสสตริงลงในรหัสเข้ารหัสรางรั้วโดยใช้คีย์ - ในทำนองเดียวกันเขียนโปรแกรมสำหรับฟังก์ชั่นย้อนกลับ: ถอดรหัสรั้วรถไฟโดยใช้ปุ่ม

สำหรับผู้ที่ไม่ทราบว่ารหัสรถไฟรั้วคืออะไรมันเป็นวิธีการเขียนข้อความธรรมดาในแบบที่มันสร้างรูปแบบเชิงเส้นในลักษณะเกลียว ตัวอย่าง - เมื่อรางรถไฟ "FOOBARBAZQUX" ใช้คีย์ 3

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

เมื่ออ่านเกลียวข้างต้นทีละบรรทัดข้อความตัวเลขจะกลายเป็น "FAZOBRAQXOBU"

อ่านเพิ่มเติมได้ที่ - รถไฟรั้วตัวเลข - วิกิพีเดีย

รหัสในภาษาใดก็ได้ยินดีต้อนรับ

คำตอบที่สั้นที่สุดในการชนะไบต์


2
เกณฑ์การชนะคืออะไร?
พอล R

คำตอบ:


9

Python 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
@ โจ้กกิ้งเพื่อความชัดเจนข้อกำหนด "สองโปรแกรม" ถูกเพิ่มหนึ่งปีหลังจากที่ฉันโพสต์โซลูชันของฉัน
โม่

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

Python 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

ลองออนไลน์!

Decode:

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

@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เพื่อถอดรหัส (ขอบคุณ Kevin Cruijssenสำหรับแนวคิดนั้น)

สิ่งนี้เริ่มต้นจากคำตอบของ Julia จนกระทั่งฉันรู้ว่าการพิมพ์ที่เข้มงวดได้มากเกินไปโดยเฉพาะการถอดรหัส นี่คือรหัส Julia ที่ฉันมีสำหรับการเข้ารหัส (backported ถึง v0.6 สำหรับ TIO):

Julia 0.6 , 191 bytes

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

จากนั้นกลับทุกคอลัมน์ที่สอง (เนื่องจากส่วนที่เป็นซิกแซกของซิกแซกขึ้นไปแทนที่จะลงซึ่งทำให้เกิดความแตกต่างเมื่อ r> 3) จากนั้นอ่านเมทริกซ์นี้ตามแนวแถวและลบอักขระจำลองออก

ดูเหมือนว่าการถอดรหัสไม่ได้มีรูปแบบที่ชัดเจนใด ๆ เช่นนี้ แต่เมื่อค้นหารอบ ๆ นี้ฉันเจอโพสต์นี้ซึ่งบอกฉันว่า (a) นี่เป็นอัลกอริทึมที่รู้จักกันดี b) decipherment เป็นการใช้ซ้ำอย่างง่ายของวิธีการเดียวกันทำให้มันเป็นดัชนีของสตริงและรับดัชนีของดัชนีเหล่านั้นหลังจากการเข้ารหัสและการอ่าน ciphertext ที่สถานที่เหล่านั้น

เนื่องจากการถอดรหัสต้องทำสิ่งต่าง ๆ โดยการทำงานกับดัชนีรหัสนี้ทำการเข้ารหัสด้วยการเรียงลำดับดัชนีของสตริงและจากนั้นในกรณีนี้เพียงแค่ทำดัชนีดัชนีที่จัดเรียงใหม่เหล่านั้น

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

ฉันต้องการอธิบายในรหัสนี้


เนื่องจากนี่เป็นโค้ดกอล์ฟคุณควรพยายามทำให้รหัสของคุณสั้นลง นอกจากนี้คุณควรเพิ่มภาษาและจำนวนไบต์ในการส่งนี้
Jo King

นอกจากสิ่งที่โจคิงกล่าวไว้คุณอาจลองใช้บริการออนไลน์เช่นTIOเพื่อให้ผู้อื่นสามารถทดสอบโค้ดของคุณได้อย่างง่ายดาย
Οurous

0

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

-12 ไบต์ขอบคุณที่@ceilingcat
-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.