柵フェンス暗号


10

2つのプログラムを作成
します。-文字列とキーを読み取り、そのキーを使用して文字列を柵フェンス暗号にエンコードするプログラム。-同様に、リバース機能のプログラムを作成します。キーを使用して柵のフェンスを解読します。

レールフェンス暗号が何であるかを知らない人にとって、それは基本的に、らせん状に線形パターンを作成する方法でプレーンテキストを書き込む方法です。例-「FOOBARBAZQUX」が3のキーを使用して柵で囲まれた場合

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

上記のスパイラルを1行ずつ読み取ると、暗号文は「FAZOBRAQXOBU」になります。

詳細については、- 柵フェンス暗号-ウィキペディアをご覧ください

任意の言語のコードを歓迎します。

バイト単位の最短回答が優先されます。


2
勝つ基準は何ですか?
Paul 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

はに対応しAKUBJLTVCIMSWDHNRXEGOQYFPZAKUTBLVJICMSWXRDNHQYEOGZFPコードが生成するとおりではありません。

基本的な考え方は、各レールは、文字列スライスを取ることによって直接求めることができることである[i::m]。ここで、i(レール番号0-indexed)、およびmです(num_rails - 1)*2。さらに、内側のレールをと織り合わせる必要があります[m-i::m]。これは、2つの文字セットを圧縮して結合することによって実現されます。これらの2番目の文字は1文字短くなる可能性があるため、どこにも表示されないと見なされる文字(_)が埋め込まれ、必要に応じその文字が削除されてリストに変換され、空の文字列が埋め込まれます。


もう少し人間が読める形式:

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 2014年

@ShuklaSannidhyaでは、なぜ不完全な回答を受け入れたのですか?
ジョーキング

3
わかりやすくするために、@ JoKingでは、「2つのプログラム」の要件は、ソリューションを投稿してから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 2014年

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

オンラインでお試しください!

デコード:

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で
試す複数のテストケースを試す

3番目の入力としてフラグを取り、F文字列を暗号化し、T解読します(そのアイデアを提供してくれたKevin Cruijssenに感謝し ます)。

これは、特に解読のために、厳密なタイピングが邪魔になりすぎていることに気づくまで、ジュリアの答えとして始まりました。これが暗号化のために持っていたJuliaコードです(TIOのv0.6にバックポートされました)。

ジュリア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文字を読み取って、ダミー値(null)で接頭辞と接尾辞を付けてから、r文字を再度読み取るなど、毎回新しい列を作成すると見なすことができます。

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

次に、2番目の列ごとに反転し(ジグザグのザグ部分が下ではなく上に移動するため、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などのオンラインサービスを使用して、他の人が簡単にコードをテストできるようにすることを検討してください。
Ο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++]);}

@ceilingcatのおかげで-12バイト。
入力として追加のモードフラグを使用して2つの関数を組み合わせた-112バイト。

関数は3番目の入力を受け取ります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.