Escribe un programa de encriptación de Playfair

20

Escriba un programa que tome dos líneas de entrada y use la primera como una frase clave para encriptar la segunda de acuerdo con la técnica de encriptación de Playfair.

Wikipedia describe el cifrado de Playfair con cierto detalle , pero para evitar cualquier ambigüedad, aquí hay un breve resumen:

1. Genere una tabla clave:

Reemplace todas las apariciones de Jla frase clave con I, luego elimine todos los caracteres que no sean del alfabeto y los caracteres repetidos. Inserte en una tabla de cifrado de 5 × 5, llenando las celdas restantes con el resto del alfabeto (excepto J; no nos gusta J).

Ejemplo:

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

2. Prepare el mensaje para ser encriptado

Reemplace cada Jcon un I, elimine todos los caracteres que no sean del alfabeto y divídalos en pares, usando un Xpara separar cualquier par que contenga la misma letra dos veces. Si termina con un número impar de letras, agregue Xal final. (Nota: los números se deben detallar por completo - ONE,TWO ,THREE , etc - pero se puede suponer que esto ya se ha hecho por ti.)

Ejemplo:

In:
The cat crept into the crypt, crapped, and crept out again.

Out:
TH EC AT CR EP TI NT OT HE CR YP TC RA PX PE DA ND CR EP TO UT AG AI NX

3. Cifrado

Cifre cada par de letras a su vez. Si están en diferentes filas y columnas de la tabla de claves, reemplace cada una con la letra de la misma fila en la columna donde se encuentra la otra letra (por ejemplo, VMEI, LZGQ). Si están en la misma fila (o columna), elija los dos caracteres inmediatamente a la derecha (o debajo), envolviéndolos si es necesario (por ejemplo, OEVR, ZGKP ).

Ejemplo:

In:
TH EC AT CR EP TI NT OT HE CR YP TC RA PX PE DA ND CR EP TO UT AG AI NX

Out:
SI RA CA RD FM VU IC VS MO RD ZN AK EC MZ MF BC YN RD FM SV TV KB TM MY

La cadena producida por este proceso es el mensaje cifrado, que su programa debería generar.

Reglas:

  • El texto de entrada y la clave se pueden obtener de stdin argumentos de línea de comandos u otras fuentes similares. La entrada codificada no está permitida.
  • Su programa debe aceptar texto en mayúsculas y minúsculas para la frase de paso y el mensaje.
  • La salida cifrada puede ser mayúscula o minúscula.
  • Su programa debe aceptar frases clave de al menos 64 caracteres de longitud y mensajes de texto de al menos 16 KB.
  • No es necesario que maneje entradas que no sean ASCII.
  • Puede ignorar la posibilidad de que el par de letras XXocurra durante el cifrado.
  • No es necesario agregar espacios en blanco a la salida del programa.
  • Su respuesta debe incluir un ejemplo de mensaje, frase clave y salida cifrada producida por su programa.
  • Este es un desafío de código de golf, por lo que la respuesta con el código más corto (en bytes) ganará.

NOTA: Recuerde que solo necesita romper letras consecutivas si aparecen en el mismo par . Entonces, por ejemplo, MASSACHUSETTSdebe cifrarse como MA SX SA CH US ET TS: el doble Sdebe dividirse, pero el doble Tno.

ossifrage aprensivo
fuente
8
"No nos gusta J" ¿Albergan sentimientos similares sobre APL?
algorithmshark
Gobbledygook! (Aunque la falta de una J en su nombre es solvente, supongo)
Aprensivo ossifrage
Con respecto al requisito de entrada, ¿están permitidos los argumentos de función? (no estoy seguro si esto constituye una "codificación rígida") Si no es así, ¿podemos suponer que la clave no contiene nuevas líneas (preferiblemente, el texto sin formato también)? Si no, los argumentos de la línea de comando podrían ser más viables en comparación con stdin.
AlliedEnvy

Respuestas:

13

JI *, 536 431 417 380 263 218 203 197 186 167

p=:4 :0
a=.u:65+9-.~i.26
,_2(5|,:~@|.@(=/)+$$,A.~5*1-0{=/)&.(5 5#:(~.n x,a)&i.)\(,'X'#~2|#)(({.,'X',}.)~1+2*1{&I._2{.\2=/\]) ::]^:_(n=:a(e.~#])'JI'charsub toupper)y
)

(con amplias sugerencias de @algorithmshark)

ejemplo de uso:

   'Stack Overflow' p 'The cat crept into the crypt, crapped, and crept out again.'
SIRACARDFMVUICVSMORDZNAKECMZMFBCYNRDFMSVTVKBTMMY

divide la entrada correctamente:

   d=:(({.,'X',}.)~1+2*1{&I._2{.\2=/\]) ::]
   d^:_ 'MASSACHUSETTS'
MASXSACHUSETTS

* reemplazar cada Jcon un I, ¿verdad?

AlliedEnvy
fuente
2
¡No nos gusta J, pero soy hermosa!
Vereos
Wow, esto es extraordinario.
aprensivo ossifrage
Mientras que la primera versión se parecía un poco a la brujería para mí, esta última es puro vudú. Muy impresionante reducción.
Geobits
Pop pop pop, viendo caer las pulsaciones de teclas! Si alguien quiere una explicación de cómo funciona esta magia vudú, aquí hay un enlace ; es demasiado largo para caber en la respuesta sin calambres severos.
algorithmshark
Me gusta J ahora :-)
aprensivo ossifrage
7

Ruby, 461 411 366 359 352 346 330 caracteres

k,m=$<.map{|x|x.tr(?j,?i).upcase.tr('^A-Z','').chars}
t=[*((k&k)|[*?A..?Z]-[?J]).each_slice(5)]
m=(m*'').gsub(/(.)\1/,'\1X\1').chars
c=->n{[t.index{|r|k=r.index n},k]}
$><<(m.size%2<1?m:m+[?X]).each_slice(2).map{|p,q|a,b,d,e=*c[p],*c[q]
a==d ?[t[a][(b+1)%5],t[d][(e+1)%5]]:b==e ?[t[(a+1)%5][b],t[(d+1)%5][e]]:[t[a][e],t[d][b]]}*''

Gracias a @daniero por guardar ... err, muchos bytes. \ o /

Aquí está el código sin golf:

key = gets.chomp
msg = gets.chomp
transform = ->str{
    str.gsub! 'j', 'i'
    str.upcase!
    str.gsub! /[^A-Z]/, ''
    str.split('')
}

# 1. Generate a key table
key = transform[key]
chars = key.uniq + ([*?A..?Z] - key - ['J'])
tbl = Array.new(5) {
    Array.new(5) {
        chars.shift
    }
}

# 2. Prepare the message
msg = transform[msg]
msg = msg.join('').gsub(/(.)\1/){ "#{$1}X#{$1}" }.split('')
msg = (msg.length % 2 == 0 ? msg : msg + ['X']).each_slice(2).to_a

# 3. Encryption
coords = ->chr{
    i = -1
    [tbl.index{|row| i = row.index chr}, i]
}
msg.map! do |c1, c2|
    c1, c2 = coords[c1], coords[c2]
    if c1[0] == c2[0]
        # same row
        [tbl[c1[0]][(c1[1] + 1) % 5], tbl[c2[0]][(c2[1] + 1) % 5]]
    elsif c1[1] == c2[1]
        # same column
        [tbl[(c1[0] + 1) % 5][c1[1]], tbl[(c2[0] + 1) % 5][c2[1]]]
    else
        # neither
        [tbl[c1[0]][c2[1]], tbl[c2[0]][c1[1]]]
    end
end

# Output!
puts msg.join

Aquí hay algunos resultados de muestra:

llama@llama:...code/ruby/ppcg23276playfair$ printf 'Stack Overflow\nThe cat crept into the crypt, crapped, and crept out again.\n' | ./playfair.rb; printf 'This is a password!\nProgramming Puzzles and Code Golf is a Stack Exchange site.\n' | ./playfair.rb
SIRAVXRDFMVUUYVSBLRDZNYVECMZMFBCYNRDFMSVTVKBVBMY
WDDEDSXIXOQFBTUYVQFISQWGRPFBWMESATAHHGMBVEITQFFISHMI
Pomo de la puerta
fuente
Se ve bien, pero hay margen de mejora: en la primera línea no hay necesidad de "convertir" charsen una matriz, suponiendo que esté usando Ruby 2. También puede usarlo &como operador de conjunto en lugar de tr: t=->s{s.gsub(?j,?i).upcase.chars&[*?A..?Z]}(7 bytes guardados). Las dos líneas siguientes se pueden unir con algo como k,m=[1,2].map{t[gets.chop]}(nota en choplugar de chomp).
daniero
El uso &también elimina la necesidad de uniqmás tarde. Y lo charsde matriz también se aplica a la línea 6.
daniero
@daniero Correcto, esto se hizo hace mucho tiempo, por lo que probablemente haya muchas más mejoras que podría hacer. Gracias por los consejos; ¡Es hora de volver a visitar esto!
Pomo de la puerta
Sí, veo eso :) Me topé con el desafío e inmediatamente quise apuñalarlo en Ruby, hasta que vi tu respuesta. La complejidad del código me asustó un poco, pero tuve que tomarlo. un vistazo :)
daniero
@daniero Por desgracia, tra &la línea 1 no funciona porque mno se puede uniqified. Sin embargo, k.uniqse puede acortar a (k&k)(1 byte apagado).
Pomo de la puerta
4

C: 495 401 355 341 caracteres

Es solo un esbozo a partir de ahora. Debería poder depilar al menos cien caracteres.

Objetivo cumplido: más de cien caracteres (154 a partir de ahora) han desaparecido misteriosamente del código.

p[25],l[96],a=1,b,c;o(x,y){putchar(p[x%5^y%5?x/5*5+(x/5^y/5?y:x+1)%5:(x+5)%25]);}main(){for(;a&&((a=(b=getchar())>31)||(b=65))||b++<90;c=0)for(b&=-33;b/65-b/91&&p[c]^b-(b==74);p[c++]||(p[--c]=b-(b==74),l[b]=c));for(;b=getchar(),b=b>31?b&-33:(c=88),b=b/65-b/91?a?a^b?(c*=c==88,b):(c=b,88):(a=b,0):0,a&b&&(o(a=l[a],b=l[b]),o(b,a),a=c),c^88;);}

Con un espacio en blanco agradable:

p[25],l[96],a=1,b,c;
o(x,y){
    putchar(p[
        x%5^y%5
            ?x/5*5+(x/5^y/5?y:x+1)%5
            :(x+5)%25
    ]);
}
main(){
    for(;
        a&&(
            (a=(b=getchar())>31)||
            (b=65)
        )||b++<90;
        c=0
    )for(
        b&=-33;
        b/65-b/91&&
        p[c]^b-(b==74);
        p[c++]||(
            p[--c]=b-(b==74),
            l[b]=c
        )
    );
    for(;
        b=getchar(),
        b=b>31
            ?b&-33
            :(c=88),
        b=b/65-b/91
            ?a
                ?a^b
                    ?(c*=c==88,b)
                    :(c=b,88)
                :(a=b,0)
            :0,
        a&b&&(
            o(a=l[a],b=l[b]),
            o(b,a),
            a=c
        ),
        c^88;
    );
}

Escribí la primera iteración del programa a punto de quedarse dormido, por lo que tenía muchas declaraciones sin sentido superfluas y cosas así. La mayor parte de eso se rectifica, pero hay bastantes áreas donde la mejora es definitivamente posible.

Fors
fuente
1
¡Bueno, esto está haciendo que mi esfuerzo se vea muy mal! Mirando hacia adelante para ver qué tan lejos puede ir con este :-)
quebrantahuesos aprensivos
2

Matlab - 458 caracteres

function p=pf(k,p)
k=[upper(k),65:90];k(k==74)=73;k(k<65|k>90)='';[~,i]=unique(k,'first');k=reshape(k(sort(i)),5,5);e=[k,k(:,1);k(1,:)];p=upper(p);p(p==74)=73;p(p<65|p>90)='';n=length(p);for i=1:2:n
if i<n&&p(i)==p(i+1)p=[p(1:i),88,p(i+1:end)];end
n=length(p);end
if mod(n,2)p=[p,88];n=n+1;end
for i=1:2:n [x,y]=find(k==p(i));[w,z]=find(k==p(i+1));p(i:i+1)=[k(w,y),k(x,z)];if x==w p(i:i+1)=[e(w,y+1),e(x,z+1)];end
if y==z p(i:i+1)=[e(x+1,z),e(w+1,y)];end
end

Algunos ejemplos:

octave:180> pf('Stack Overflow', 'The cat crept into the crypt, crapped, and crept out again.')
ans = SIRACARDFMVUICVSMORDZNAKECMZMFBCYNRDFMSVTVKBTMMY

octave:181> pf('This is a password!','Programming Puzzles and Code Golf is a Stack Exchange site.')
ans = WDDEDSXIXOQFBTUYVQFISQWGRPFBWMESATAHHGMBVEITQFFISHMI

octave:182> pf('Matlab needs lambdas', 'Who thought elseif is good syntax?')
ans = XGQMFQPKQDSACDKGRIFPQNILDMTW
intx13
fuente
2

Haskell - 711

Manifestación:

[timwolla@/data/workspace/haskell/PCG]ghc pcg-23276.hs
[1 of 1] Compiling Main             ( pcg-23276.hs, pcg-23276.o )
Linking pcg-23276 ...
[timwolla@/data/workspace/haskell/PCG]./pcg-23276 "Stack Overflow" "The cat crept into the crypt, crapped, and crept out again."
SIRACARDFMVUICVSMORDZNAKECMZMFBCYNRDFMSVTVKBTMMY

Código:

import Data.List
import Data.Char
import Data.Maybe
import System.Environment
main=do a<-getArgs
    putStrLn$concat$map(x (a!!0))$map(\x->if (length x)==1 then x++"X"else x)$s 2$concat$map(\x->if (length x)==1then x else intersperse 'X' x)$group$p (a!!1)
p=map(\x->if x=='J' then 'I' else x).filter(isUpper).map toUpper
k x=y++(delete 'J'$['A'..'Z']\\y)where y=nub$p x
u l m=(div i 5,mod i 5)where i=fromJust$elemIndex l$k m
x y z
    |a/=c&&b/=d=(e!!(a*5+d)):(e!!(c*5+b)):[]
    |a==c=(e!!(a*5+(mod(b+1)5))):(e!!(c*5+(mod(d+1)5))):[]
    |True=(e!!((5*(mod(a+1)5))+b)):(e!!((5*(mod(c+1)5))+d)):[]
    where
        o=u(z!!0)y
        t=u(z!!1)y
        a=fst o
        b=snd o
        c=fst t
        d=snd t
        e=k y
s _ []=[]
s n l=(take n l):(s n(drop n l))

Versión grande:

import Data.List
import Data.Char
import Data.Maybe

encryptAll key text = map (encrypt key) (transformValue text)

clean x = map (\x -> if x == 'J' then 'I' else x) $ filter (isUpper) $ map (toUpper) x
transformKey x = y ++ (delete 'J' $ ['A'..'Z'] \\ y)
    where y = nub (clean x)

transformValue x = map (\x -> if (length x) == 1 then x ++ "X" else x) $ split 2 $ concat $ map (\x -> if (length x) == 1 then x else intersperse 'X' x) $ group $ clean x

search letter key = (div index 5, mod index 5)
    where index = fromJust $ elemIndex letter $ transformKey key

encrypt key chars
    | rowA /= rowB && colA /= colB = (key' !! (rowA * 5 + colB)) : (key' !! (rowB * 5 + colA)) : []
    | rowA == rowB = (key' !! (rowA * 5 + ((colA + 1) `mod` 5))) : (key' !! (rowB * 5 + ((colB + 1) `mod` 5))) : []
    | otherwise = (key' !! ((5 * ((rowA + 1) `mod` 5)) + colA)) : (key' !! ((5 * ((rowB + 1) `mod` 5)) + colB)) : []
    where
        rowA = fst $ search (head chars) key
        colA = snd $ search (head chars) key
        rowB = fst $ search (last chars) key
        colB = snd $ search (last chars) key
        key' = transformKey key

-- http://stackoverflow.com/a/12876438/782822
split :: Int -> [a] -> [[a]]
split _ [] = []
split n l
  | n > 0 = (take n l) : (split n (drop n l))
  | otherwise = error "Negative n"
TimWolla
fuente
2

Pyth - 111

Demasiado tarde para competir, solo quería compartir. Aquí está el codificador y decodificador.

L@G:rb0\j\iJ{y+wGKywWhZ=Zh*2xlR{RcK2 1IhZ=KXZK\x;M@J+G?!eH5?!hH?q4%G5_4 1eHVcK2A,xJhNxJeN=Z-V.DH5.DG5pgGZpgH_RZ

Explicación:

L    b                              L defines common method y(b); 2 calls helps us saving two bytes
    r 0                             lowercase r(b,0)
   :   \j\i                         : replaces all occurrences of "j" with "i"
 @G                                 strips all non-alphabetic characters; G = pyth built-in alphabet

    w                               first input argument
   + G                              appends the alphabet (G)
  y                                 calls y(b)
 {                                  { makes set (removes duplicated characters)
J                                   assigns result to 'J' (KEY VARIABLE)

Kyw                                 assigns output from y(second input argument) to 'K' (TEXT VARIABLE)

WhZ                         ;       While (Z+1 != 0) <-> While (Z != -1) <-> While mismatched items found
             cK2                    list of K pairs.                    e.g. 'ABCCDDE' -> [AB, CC, DD, E]
         lR{R                       l length of { unique characters.    e.g. [2, 1, 1, 1]
        x       1                   1-length first index.               e.g. 1
     h*2                            *2+1 (Index in K)                   e.g. 3 'ABC CDDE'
   =Z                               Assigns to 'Z'
                  IhZ               if (Z != -1) <-> if (mismatched found)
                     =KXZK\x        X Inserts at Z index in K an 'x' and reassigns to 'K'  e.g. 'ABCXC...'

M                                   M defines function g(G, H) where G index H vector (INDEX CONVERSION)
     ?!eH                           if (same col)
         5                              then +5
         ?!hH                           else { if (same row)
             ?q4%G5                             then if (last col)
                   _4                               then -4
                      1                             else +1
                       eH                       else col
   +G                               index += increment
 @J                                 J[index]

VcK2                                V loops over cK2 list of K pairs
     ,xJhNxJeN                      x returns pair members index in J
    A                               A assigns G = xJhN, H = xJeN
                  .DH5              .D returns [row, col] = [i/5,i%5] of 5xn matrix from index of H
                      .DG5          idem. of G
                -V                  Subtracts vectors (RELATIVE POSITION)
              =Z                    Assigns to 'Z'
                          pgGZ          p prints g(G, Z) return value
                              pgH_RZ    p prints g(H, _RZ) return value, and _R changes signs of Z vector

Clave de muestra / Mensaje / Salida:

Stack Overflow
Gottfried Leibniz is famous for his slogan Calculemus, which means Let us calculate. He envisioned a formal language to reduce reasoning to calculation.
lfaukvvnrbbomwpmupkoexvqkovfimaqohflcmkcdsqwbxqtlintinbehcbovttksbtybsavmormwuthrhrbkevfxebqbspdxtbfsvfrwyarfrctrhmpwkrssbtybsvurh
FinalizandoCiclos
fuente
1

C, 516

Se agregaron avances de línea para mejorar la presentación de legibilidad . (La legibilidad se fue por la ventana, me temo).

#define Z(u,v) putchar(o[u]),putchar(o[v])
#define X while((Y=getchar())>31){Y&=223;if(Y==74)Y--;if(Y<65||Y>90
P,L,A,Y,f,a,i,r,c=512,o[25],d[2],*e=o;Q(){for(i=0;o[i]!=d[0];i++);i-=(f=i%5);
for(r=0;o[r]!=d[1];r++);r-=(a=r%5);if(f==a)Z(f+(i+5)%25,a+(r+5)%25);
else if(i==r)Z((f+1)%5+i,(a+1)%5+r);else Z(a+i,f+r);}main(){X||c&(A=1<<Y-65))continue;
c|=A;*e++=Y;}A=1;Y=65;for(P=0;P<25;P++){if(!(c&A))*e++=Y;
if(++Y==74)Y++,A+=A;A+=A;}L=0;X)continue;if(L&&Y==*d)d[1]=88,Q(),*d=Y;
else d[L]=Y,L=1-L;if(!L)Q();}if(L)d[1]=88,Q();}

Ejemplo:

$ ./pf
Playfair                                    
The quick brown fox jumps over the lazy dog
QMHNPEKSCBQVTPSVEPEFTQUGDOKGAYXFRTKV
ossifrage aprensivo
fuente
1

Pitón 3, 709 705 685 664

Acepta entradas de stdin.

from string import ascii_uppercase as a
from itertools import product as d
import re
n=range
k=input()
p=input()
t=lambda x: x.upper().replace('J','I')
s=[]
for _ in t(k+a):
 if _ not in s and _ in a:
  s.append(_)
m=[s[i:i+5] for i in n(0,len(s),5)]
e={r[i]+r[j]:r[(i+1)%5]+r[(j+1)%5] for r in m for i,j in d(n(5),repeat=2) if i!=j}
e.update({c[i]+c[j]:c[(i+1)%5]+c[(j+1)%5] for c in zip(*m) for i,j in d(n(5),repeat=2) if i!=j})
e.update({m[i1][j1]+m[i2][j2]:m[i1][j2]+m[i2][j1] for i1,j1,i2,j2 in d(n(5),repeat=4) if i1!=i2 and j1!=j2})
l=re.findall(r'(.)(?:(?!\1)(.))?',''.join([_ for _ in t(p) if _ in a]))
print(''.join(e[a+(b if b else 'X')] for a,b in l))

Ejemplo:

mfukar@oxygen[/tmp]<>$ python playfair.py
Stack Overflow
The cat crept into the crypt, crapped, and crept out again.
SIRACARDFMVUICVSMORDZNAKECMZMFBCYNRDFMSVTVKBTMMY
Michael Foukarakis
fuente
También funciona perfectamente en Python 2.5 :-)
apremiante ossifrage
1

Python: 591 bytes

import sys
l=list
n=len
a=[sys.stdin.readline().upper().replace('J','I') for i in (1,2)]
b=l('ABCDEFGHIKLMNOPQRSTUVWXYZ')
def z(x):
    a=0
    if x in b:
        b.remove(x)
        a=1
    return a
c=l(filter(z,a[0]))+b
d=[x for x in a[1] if x in c]
e=1
while e<n(d):
    if d[e-1]==d[e]:
        d.insert(e,'X')
    e+=2
if n(d)%2>0:
    d+='X'
def y(i):
    z=c.index(d[i])
    return z/5,z%5
x=lambda i,j:c[(i%5)*5+(j%5)]
def w(i):
    e,f=y(i)
    g,h=y(i+1)
    if e==g:
        z=x(e,f+1)+x(g,h+1)
    elif f==h:
        z=x(e+1,f)+x(g+1,h)
    else:
        z=x(e,h)+x(g,f)
    print z,
e=0
while e<n(d):
    w(e)
    e+=2
print

Esto se usa stdinpara obtener la clave y el mensaje en ese orden. Espero que no sea una trampa usar una lista plana para almacenar la matriz de cifrado, porque eso hizo que trabajar con la matriz fuera bastante simple. Aquí hay algunos ejemplos de ejecución:

>python playfair.py
Stack Overflow
The cat crept into the crypt, crapped, and crept out again.
SI RA CA RD FM VU IC VS MO RD ZN AK EC MZ MF BC YN RD FM SV TV KB TM MY

>python playfair.py
Stack Overflow
The quick red fox jumps over the lazy brown dog.
SI OX TU KS FR GR EQ UT NH OL ER VC MO BS QZ DE VL YN FL
sadakatsu
fuente
Creo que se puede acortar za lambda x:0if b not in x else b.remove(x)or 1. También hay bastante espacio en blanco del que puede deshacerse. Eso también le permitiría moverlo directamente a la filterllamada en lugar de definirlo afuera.
Morgan Thrapp
1

Java - 791

Mi primer golf, por lo que cualquier crítica es bienvenida. Usando Java porque no debería. No parece tan malo; menos del doble del tamaño del líder actual. Esperaba que fuera más grande ya que es, bueno, Java :)

public class P{static String c(String s){return s.toUpperCase().replace('J','I').replaceAll("[^A-Z]","");}static int f(char[]a, char n){for(int i=0;i<a.length;i++)if(a[i]==n)return i;return -1;}public static void main(String[]a){int i=0,k,l;char j=0;String g=c(a[0]);char[]e,b,h=c(a[1]).toCharArray();b=new char[25];for(;j<g.length();j++)if(j==g.indexOf(g.charAt(j)))b[i++]=g.charAt(j);for(j=65;i<25;j++)if(f(b,j)<0&&j!=74)b[i++]=j;e=new char[h.length*2];for(i=0,j=0;j<h.length;){if(i%2>0&&h[j]==h[j-1])e[i++]=88;e[i++]=h[j++];}if(i%2>0)e[i++]=88;for(j=0;j<i;j+=2){k=f(b,e[j]);l=f(b,e[j+1]);if(k/5==l/5){e[j]=b[(k/5*5)+((k+1)%5)];e[j+1]=b[(l/5*5)+((l+1)%5)];}else if(k%5==l%5){e[j]=b[(k+5)%25];e[j+1]=b[(l+5)%25];}else{e[j]=b[(k/5*5)+(l%5)];e[j+1]=b[(l/5*5)+(k%5)];}}System.out.println(e);}}

Con formato automático:

public class P {
    static String c(String s) {
        return s.toUpperCase().replace('J', 'I').replaceAll("[^A-Z]", "");
    }

    static int f(char[] a, char n) {
        for (int i = 0; i < a.length; i++)
            if (a[i] == n)
                return i;
        return -1;
    }

    public static void main(String[] a) {
        int i = 0, k, l;
        char j = 0;
        String g = c(a[0]);
        char[] e, b, h = c(a[1]).toCharArray();
        b = new char[25];
        for (; j < g.length(); j++)
            if (j == g.indexOf(g.charAt(j)))
                b[i++] = g.charAt(j);
        for (j = 65; i < 25; j++)
            if (f(b, j) < 0 && j != 74)
                b[i++] = j;
        e = new char[h.length * 2];
        for (i = 0, j = 0; j < h.length;) {
            if (i % 2 > 0 && h[j] == h[j - 1])
                e[i++] = 88;
            e[i++] = h[j++];
        }
        if (i % 2 > 0)
            e[i++] = 88;
        for (j = 0; j < i; j += 2) {
            k = f(b, e[j]);
            l = f(b, e[j + 1]);
            if (k / 5 == l / 5) {
                e[j] = b[(k / 5 * 5) + ((k + 1) % 5)];
                e[j + 1] = b[(l / 5 * 5) + ((l + 1) % 5)];
            } else if (k % 5 == l % 5) {
                e[j] = b[(k + 5) % 25];
                e[j + 1] = b[(l + 5) % 25];
            } else {
                e[j] = b[(k / 5 * 5) + (l % 5)];
                e[j + 1] = b[(l / 5 * 5) + (k % 5)];
            }
        }
        System.out.println(e);
    }
}

Salida de muestra:

>java P "Stack Overflow" "The cat crept into the crypt, crapped, and crept out again."
SIRACARDFMVUICVSMORDZNAKECMZMFBCYNRDFMSVTVKBTMMY

>java P "Write a PlayFair encryption program" "Write a program that takes two lines of input and uses the first as a key phrase to encrypt the second according to the Playfair encryption technique."
RITEWFCPGMWPGEBLYTWYQTXWINOLMWVNLECAXRNBURZWXWQILEWUWYWNQTFLDINWWEMICOTPYRIKWZRMGCBPGUOGPUWOKYGIQILYPFAPTIWMDPFLETGCEWODOWDZTZ
Geobits
fuente
1

JS (nodo) - 528 466

k=n(2)+'ABCDEFGHIKLMNOPQRSTUVWXYZ',p=n(3),t=o=''
for(i=0;i<k.length;i++)if(!~t.indexOf(k[i]))t+=k[i]
for(i=0;i<p.length;){a=f(c=p[i++]),b=f(!(d=p[i])||c==d?'X':(i++,d))
if(a.x==b.x)a.y=(a.y+1)%5,b.y=(b.y+1)%5
else if(a.y==b.y)a.x=(a.x+1)%5,b.x=(b.x+1)%5
else a.x=b.x+(b.x=a.x,0)
o+=t[a.x+a.y*5]+t[b.x+b.y*5]}console.log(o)
function f(c){x=t.indexOf(c);return{x:x%5,y:x/5|0}}
function n(a){return process.argv[a].toUpperCase().replace(/[^A-Z]/g,'').replace(/J/g,'I')}

Salida de muestra:

$ node playfair "Stack Overflow" "The cat crept into the crypt, crapped, and crept out again."
SIRACARDFMVUICVSMORDZNAKECMZMFBCYNRDFMSVTVKBTMMY
$ node playfair "Lorem ipsum" "dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
CRORSDAHGAMQKPXDOFQMQAMSBSSPUPBPTDMOAHURNRCRLUAULRGNMLCPLSKDSBSBSQQAHMIGRERYMQCROREMAGDTSZIMUHAIAQRQALSGLAHSLZRQPIETAPDXRPNMSFRYMEBPZGHARKIEMIOGROIGREPUHSUPAQIMUHAPUOYRPGRLLRCRKPXDUYAINZ
zobier
fuente
Buen punto sobre el tema de expresiones regulares - Voy a ad una nota a la pregunta
quebrantahuesos aprensivos
Hay un problema con su segundo ejemplo: el par de letras en los caracteres 75 y 76 está codificado como UU. Parece que hubo una repetición de Eque deberías haberte dividido.
aprensivo ossifrage
Tienes razón, me pegué un tiro en el pie. El problema es solo mirar pares pero terminar en uno después de una inserción.
zobier
1

PHP 582

<? list($i,$k,$v)=array_map(function($v){return str_split(preg_replace('#[^A-Z]#','',strtr(strtoupper($v),'J','I')));},$argv);@$i=array_flip;$k=$i($k)+$i(range('A','Z'));unset($k['J']);$k=array_keys($k);$q=$i($k);for($i=1;$i<count($v);$i+=2){if ($v[$i-1]==$v[$i]){array_splice($v,$i,0,'X');}}if(count($v)%2)$v[]='X';for($i=1;$i<count($v);$i+=2){$c=(int)($q[$v[$i-1]]/5);$d=$q[$v[$i-1]]%5;$e=(int)($q[$v[$i]]/5);$f=$q[$v[$i]]%5;if($c==$e){$d=($d+1)%5;$f=($f+1)%5;}elseif($d==$f){$c=($c+1)%5;$e=($e+1)%5;}else{$t=$f;$f=$d;$d=$t;}$v[$i-1]=$k[$c*5+$d];$v[$i]=$k[$e*5+$f];}echo join($v);

Sin golf
Decodificador sin

salidas

$ php playfair.php "Stack Overflow" "The cat crept into the crypt, crapper, and crept out again."
SIRACARDFMVUICVSMORDZNAKECMZMFECYNRDFMSVTVKBTMMY
$ php playfair.php "This was codegolf?" "The full J answers is shorter than my preparation code :("
HIOKVGFHCMWTKZWSIYWIEPWAMWTCPNXQZKMOMEHSCPODEA
Einacio
fuente
1

Perl, 265

Muy sencillo

chomp(($k,$_)=map{uc=~y/A-Z//cdr=~y/J/I/r}<>."@{[A..Z]}",~~<>);1while$k=~s/((.).*)\2/$1/;while(/(.)((?=\1|$)|(.))/g){($a,$b,$c,$d)=map{$e=index$k,$_;5*int$e/5,$e%5}$1,$3||X;print substr$k,$_%25,1 for$a-$c?$b-$d?($a+$d,$c+$b):($a+5+$b,$c+5+$d):(++$b%5+$a,++$d%5+$c)}

Sangrado:

chomp(($k,$_)=map{uc=~y/A-Z//cdr=~y/J/I/r}<>."@{[A..Z]}",~~<>);
1while$k=~s/((.).*)\2/$1/;
while(/(.)((?=\1|$)|(.))/g){
    ($a,$b,$c,$d)=map{$e=index$k,$_;5*int$e/5,$e%5}$1,$3||X;
    print substr$k,$_%25,1 for
        $a-$c
            ?$b-$d
                ?($a+$d,$c+$b)
                :($a+5+$b,$c+5+$d)
            :(++$b%5+$a,++$d%5+$c)
}
usuario2846289
fuente
0

CoffeeScript - 610

Manifestación:

[timwolla@/data/workspace/js/PCG]coffee pcg-23276.coffee "Stack Overflow" "The cat crept into the crypt, crapped, and crept out again."
SIRACARDFMVUICVSMORDZNAKECMZMFBCYNRDFMSVTVKBTMMY

Código:

String::r=String::replace
_=(t,l)->
    for r in[0..4]
        for c in[0..4]
            return [r,c]if l is t[r][c]
K = {}
K[c]=c for c in (process.argv[2].toUpperCase().r(/J/g, 'I').r x=/([^A-Z])/g, '')
for i in[1..26]when i!=10
    c=String.fromCharCode 64+i
    K[c]=c
K=(c for c of K)
t=(K[s..s+4]for s in[0..24]by 5)
v=process.argv[3].toUpperCase().r(/J/g,'I').r(x,'').r(/(.)\1/g,'$1X$1').r /(..)/g, '$1 '
o=""
for p in v.trim().r(/\s([A-Z])$/, ' $1X').split /\s/
    [a,b]=p.split '';[d,f]=_ t,a;[e,g]=_ t,b
    o+=if d!=e&&f!=g
        t[d][g]+t[e][f]
    else if d==e
        t[d][++f%5]+t[e][++g%5]
    else
        t[++d%5][f]+t[++e%5][g]
console.log o

Versión sin golf:

search = (table, letter) ->
    for row in [0..4]
        for column in [0..4]
            return [ row, column ] if letter is table[row][column]

encrypt = (key, value) ->
    key = key.toUpperCase().replace(/J/g, 'I').replace /([^A-Z])/g, ''
    keyChars = {}
    keyChars[char] = char for char in key
    for i in [1..26] when i != 10
        char=String.fromCharCode 64 + i
        keyChars[char] = char
    keyChars = (char for char of keyChars)

    keyTable = (keyChars[start..start+4] for start in [0..24] by 5)

    value = value.toUpperCase().replace(/J/g, 'I').replace(/([^A-Z])/g, '').replace(/(.)\1/g, '$1X$1').replace /(..)/g, '$1 '
    pairs = value.trim().replace(/\s([A-Z])$/, ' $1X').split /\s/

    out = ""
    for pair in pairs
        [a,b] = pair.split ''
        [rowA, colA] = search keyTable, a
        [rowB, colB] = search keyTable, b
        if rowA!=rowB&&colA!=colB
            out += keyTable[rowA][colB]+keyTable[rowB][colA]
        else if rowA==rowB
            out += keyTable[rowA][++colA%5]+keyTable[rowB][++colB%5]
        else
            out += keyTable[++rowA%5][colA]+keyTable[++rowB%5][colB]
    out.replace /(..)/g, '$1 '

console.log encrypt process.argv[2], process.argv[3]
TimWolla
fuente