Chiffre de clôture ferroviaire


10

Écrivez deux programmes:
- Un qui lit une chaîne et une clé et code la chaîne en un chiffrement de barrière ferroviaire à l'aide de cette clé. - De même, écrivez un programme pour la fonction inverse: déchiffrer une clôture ferroviaire à l'aide d'une clé.

Pour ceux qui ne savent pas ce qu'est le chiffrement de clôture ferroviaire, il s'agit essentiellement d'une méthode d'écriture de texte brut d'une manière qui crée un motif linéaire en spirale. Exemple - lorsque "FOOBARBAZQUX" est clôturé sur rail à l'aide de la clé de 3.

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

En lisant la ligne spirale ci-dessus, le texte chiffré devient "FAZOBRAQXOBU".

En savoir plus sur - Chiffre de clôture ferroviaire - Wikipedia .

Le code dans n'importe quelle langue est le bienvenu.

La réponse la plus courte en octets l'emporte.


2
Quel est le critère gagnant?
Paul R

Réponses:


9

Python 133 octets

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

Exemple d'utilisation:

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

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

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

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

Remarque: les résultats des comptages de rails pairs sont différents de ceux du code que vous avez fourni, mais ils semblent être corrects. Par exemple, 6 rails:

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

correspond à AKUBJLTVCIMSWDHNRXEGOQYFPZ, et non AKUTBLVJICMSWXRDNHQYEOGZFPcomme le produit votre code.

L'idée de base est que chaque rail peut être trouvé directement en prenant des tranches de chaîne [i::m], où iest le numéro de rail ( 0-indexé), et se mtrouve (num_rails - 1)*2. Les rails intérieurs doivent en outre être entrelacés avec [m-i::m], réalisé en zippant et en joignant les deux ensembles de caractères. Étant donné que le second peut potentiellement être un caractère plus court, il est complété avec un caractère supposé ne pas apparaître n'importe où ( _), puis ce caractère est supprimé si nécessaire, il est converti en liste et complété avec une chaîne vide.


Une forme légèrement plus lisible par l'homme:

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

Une fonction de déchiffrement est également nécessaire.
ShuklaSannidhya

@ShuklaSannidhya Alors pourquoi avez-vous accepté une réponse incomplète?
Jo King

3
@JoKing pour plus de clarté, l'exigence de "deux programmes" a été ajoutée un an après la publication de ma solution.
primo

2

APL 52 41

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

Si la chaîne de texte d'entrée i et le numéro de clé n sont préinitialisés, la solution peut être raccourcie de 9 caractères. L'exécution de la solution contre les exemples donnés par primo donne des réponses identiques:

FOOBARBAZQUX
3
FAZOBRAQXOBU

ABCDEFGHIJKLMNOPQRSTUVWXYZ
4
AGMSYBFHLNRTXZCEIKOQUWDJPV

ABCDEFGHIJKLMNOPQRSTUVWXYZ
5
AIQYBHJPRXZCGKOSWDFLNTVEMU

ABCDEFGHIJKLMNOPQRSTUVWXYZ
6
AKUBJLTVCIMSWDHNRXEGOQYFPZ

Après réflexion, il semble y avoir une solution basée sur un indice plus court:

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

Une fonction de déchiffrement est également nécessaire.
ShuklaSannidhya

1

Python 2 , 124 + 179 = 303 octets

Encoder:

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

Essayez-le en ligne!

Décoder:

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

Essayez-le en ligne!


Vous avez également besoin d'une fonction de déchiffrement
Jo King

@Jo King: J'ai tardivement ajouté un déchiffreur.
Chas Brown

0

MATL, 70 octets (total)

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

Essayez-le sur MATL en ligne
Essayez plusieurs cas de test

Prend un drapeau comme troisième entrée, Fpour chiffrer la chaîne, Tpour la déchiffrer (merci à Kevin Cruijssen pour cette idée).

Cela a commencé comme une réponse de Julia jusqu'à ce que je réalise que la frappe stricte gênait trop, surtout pour le déchiffrement. Voici le code Julia que j'avais pour le chiffrement (rétroporté vers la v0.6 pour TIO):

Julia 0,6 , 191 octets

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

Essayez-le en ligne!

Explication:

L'opération de clôture ferroviaire

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

peut être vu comme lisant r = 3 caractères d'entrée, puis lisant r-2 caractères et préfixant et suffixant cela avec des valeurs fictives (null), puis relisant r caractères, etc., créant une nouvelle colonne à chaque fois:

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

puis inverser toutes les deux colonnes (puisque la partie zag du zigzag monte au lieu de descendre, ce qui fait une différence lorsque r> 3), puis lit cette matrice le long des lignes et supprime les caractères fictifs.

Le déchiffrement ne semblait pas avoir de modèles évidents comme celui-ci, mais en cherchant à ce sujet, je suis tombé sur ce post , qui m'a dit que (a) c'était un algorithme bien connu et (peut-être?) Publié pour les chiffrements ferroviaires, et ( b) le déchiffrement était une simple réutilisation de la même méthode, lui donnant les indices de la chaîne et obtenant les indices de ces indices après chiffrement, et lisant le texte chiffré à ces endroits.

Étant donné que le déchiffrement doit faire des choses en travaillant sur les indices, ce code effectue également le chiffrement en triant les indices de la chaîne, puis dans ce cas simplement en indexant ces index réarrangés.

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

Je veux être expliqué dans ce code.


Puisqu'il s'agit de code-golf , vous devriez essayer de raccourcir votre code. En outre, vous devez ajouter la langue et le nombre d'octets à cette soumission
Jo King

En plus de ce que Jo King a dit, vous pourriez envisager d'utiliser un service en ligne comme TIO afin que d'autres personnes puissent facilement tester votre code.
6urous

0

Java 10, 459 451 445 439 327 octets

(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 octets grâce à @ceilingcat .
-112 octets combinant les deux fonctions avec un indicateur de mode supplémentaire en entrée.

La fonction prend une troisième entrée M. Si c'est le cas, trueil chiffrera et s'il l'est, falseil déchiffrera.

Essayez-le en ligne.

Explication:

(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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.