编写一个Playfair加密程序


20

编写一个程序,该程序需要两行输入,并根据Playfair加密技术将第一行用作关键字来加密第二行。

Wikipedia详细描述了Playfair加密,但是为了避免歧义,这里有一个简短的摘要:

1.生成密钥表:

用替换J关键字中出现的所有I,然后去除所有非字母字符和重复字符。插入5×5加密表中,用其余的字母填充剩余的单元格(除非J;我们不喜欢J)。

例:

                                        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.准备要加密的消息

将每个替换JI,剥离所有非字母字符并分成对,使用可以X将包含相同字母的任何对断开两次。如果结尾的字母数为奇数,请X在末尾添加。(请注意:数字必须完整拼写-ONETWOTHREE,等等-但是你可以认为这已经为你做了。)

例:

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.加密

依次对每对字母进行加密。如果它们在键表的不同行和列中,请用找到另一个字母的列中同一行的字母替换每个字母(例如,VMEILZGQ)。如果它们在同一行(或一列)中,请选择右边(或下面)的两个字符,并在必要时进行环绕(例如OEVRZGKP)。

例:

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

此过程产生的字符串是加密的消息,您的程序应将其输出。

规则:

  • 输入的文本和键可以从 stdin从命令行参数或其他此类来源获得。不允许使用硬编码输入。
  • 您的程序必须同时接受密码短语和消息的大小写文本。
  • 加密的输出可以是大写或小写。
  • 您的程序应接受长度至少为64个字符的关键短语以及至少16 KB的消息文本。
  • 您不需要处理非ASCII输入。
  • 您可能会忽略XX在加密过程中出现字母对的可能性。
  • 无需在程序的输出中添加空格。
  • 您的答案应包括程序产生的消息,关键字短语和加密输出的示例。
  • 这是一场代码挑战赛,因此答案最短的代码(以字节为单位)将获胜。

注意:请记住,如果连续出现在同一对字母中,则只需要中断连续字母。因此,例如MASSACHUSETTS应加密为MA SX SA CH US ET TSS必须拆分双精度对象,而T不必拆分双精度对象。


8
“我们不喜欢J”您是否对APL有相似的看法?
algorithmhark

蠢货!(虽然我想它的名称中缺少J是值得称赞的。)
尖锐的ossifrage

关于输入要求,是否允许使用函数参数?(不确定这是否构成“硬编码”)是否可以,我们是否可以假定键不包含换行符(最好也包含明文)?如果不是这样,则与stdin相比,命令行args可能更可行。
AlliedEnvy 2014年

Answers:


13

ĴI *,536 431 417 380 263 218 203 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
)

(来自@algorithmshark的广泛建议)

示例使用:

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

正确分割输入:

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

* 代替每个JI吧?


2
我们不喜欢J,但我很漂亮!
Vereos 2014年

哇,这真是太好了。
吱吱作响的ossifrage

虽然第一个版本在我看来有点像巫术,但最新版本是纯巫毒。令人印象深刻的减少。
Geobits 2014年

流行音乐流行音乐,观看击键动作!如果有人想解释这种巫毒术的工作原理,请点击这里;在没有严重局促的情况下,答案太长了。
algorithmhark

我现在喜欢J :-)
吱吱作响的ossifrage 2014年

7

Ruby,461 411 366 359 352 346 330个字符

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]]}*''

感谢@daniero节省了...错误,很多字节。\ o /

这是未完成的代码:

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

以下是一些示例输出:

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

看起来不错,但是还有改进的余地:chars假设您使用的是Ruby 2,则第一行无需“广播” 到数组中。您还可以将其&用作set运算符,而不是tr:(t=->s{s.gsub(?j,?i).upcase.chars&[*?A..?Z]}节省了7个字节)。接下来的两行可以用k,m=[1,2].map{t[gets.chop]}(note chop而不是chomp)之类的东西连接起来。
daniero'1

使用&还消除了uniq以后的需要。而chars到阵列的情况也适用于第6行
达尼罗

@daniero对,这是很久以前完成的,所以我可能还有很多改进。感谢您的提示;时间再来看看!
门把手

是的,我看到了:)我偶然发现了这个挑战,我立即想在Ruby中尝试一下,直到看到您的答案为止。代码的复杂性让我不知所措,但是我不得不看看:)
daniero'1

@daniero不幸的是,tr&1号线不起作用,因为m不能uniq指明分数。但是,k.uniq可以缩短为(k&k)(关闭1个字节)。
门把手

4

C:495个 401 355 341字符

到目前为止,这只是一个粗略的草图。我应该至少可以刮掉一百个字符。

已实现的目标:一百多个字符(截至目前为154个)已从代码中神秘消失。

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

带有一些令人愉快的空格:

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

我在即将入睡的时候编写了程序的第一次迭代,因此它有很多多余的无意义的语句等等。大多数问题已得到纠正,但是在相当多的领域中,绝对有可能进行改进。


1
好吧,这让我的努力看起来非常糟糕!期待看到您可以使用它多远:-)
吱吱作响的ossifrage

2

Matlab-458个字符

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

一些例子:

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

2

哈斯克尔-711

演示:

[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

码:

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))

大版本:

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"

2

腐霉病-111

太迟了,我只想分享。这是 编码器解码器

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

说明:

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

示例键/消息/输出:

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

1

C,516

添加了换行符,以提高可读性。(恐怕要从窗口中走出去了。)

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

例:

$ ./pf
Playfair                                    
The quick brown fox jumps over the lazy dog
QMHNPEKSCBQVTPSVEPEFTQUGDOKGAYXFRTKV

1

Python 3中,709 705 685 664

接受来自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))

例:

mfukar@oxygen[/tmp]<>$ python playfair.py
Stack Overflow
The cat crept into the crypt, crapped, and crept out again.
SIRACARDFMVUICVSMORDZNAKECMZMFBCYNRDFMSVTVKBTMMY

也可以在Python 2.5中完美运行:-)
挤压ossifrage 2014年

1

Python:591字节

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

这用于stdin按该顺序获取密钥和消息。我希望使用平面列表存储加密矩阵不会欺骗,因为这使得使用矩阵非常简单。这是一些示例运行:

>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

相信您可以缩短zlambda x:0if b not in x else b.remove(x)or 1。您还可以消除很多空白。这也可以让您直接将其移至filter调用中,而无需在外部进行定义。
摩根·塔普

1

爪哇-791

我第一次打高尔夫球,欢迎提出任何批评。使用Java是因为我不应该这样做。看起来还不错。不到目前领导者人数的两倍。我期望它会更大,因为它是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);}}

使用自动格式:

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

样本输出:

>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

1

JS(节点)-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')}

样本输出:

$ 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

关于正则表达式问题的要点–我将对该问题进行注释
抑制ossifrage

您的第二个示例存在问题-字符75和76处的一对字母编码为UU。似乎有重复的情况E,您应该分开。
吱吱作响的ossifrage

你说得对,我开枪打死自己。问题在于仅查看配对,但在插入后最终以一对结束。
zobier 2014年

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);

非高尔夫
解码器

输出

$ 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

1

佩尔265

非常简单。

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)}

缩进:

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)
}

0

CoffeeScript-610

演示:

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

码:

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

非高尔夫版本:

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]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.