เขียนโปรแกรมการเข้ารหัส 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. เตรียมข้อความที่จะเข้ารหัส

แทนที่ทุกตัวJด้วยI, ดึงอักขระที่ไม่ใช่ตัวอักษรทั้งหมดและแยกออกเป็นคู่โดยใช้Xเพื่อแยกคู่ที่มีตัวอักษรเดียวกันสองครั้ง หากคุณมีตัวอักษรแปลก ๆ ให้เพิ่มXที่ส่วนท้าย (หมายเหตุ: ตัวเลขจะต้องมีการสะกดออกมาในแบบเต็ม - ONE, TWO, THREEฯลฯ - แต่คุณสามารถสมมตินี้ได้รับการทำมาแล้วสำหรับคุณ.)

ตัวอย่าง:

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. การเข้ารหัส

เข้ารหัสตัวอักษรแต่ละคู่ตามลำดับ ถ้าพวกเขาอยู่ในแถวที่แตกต่างกันและคอลัมน์ของตารางที่สำคัญแทนแต่ละคนมีตัวอักษรจากแถวเดียวกันในคอลัมน์ที่ตัวอักษรตัวอื่น ๆ จะพบ (เช่นVMEI, LZGQ) หากอยู่ในแถวเดียวกัน (หรือคอลัมน์) ให้เลือกอักขระสองตัวทางด้านขวา (หรือด้านล่าง) ทันทีล้อมรอบหากจำเป็น (เช่นOEVR, ZGKP )

ตัวอย่าง:

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 TS- คู่Sจะต้องแยก แต่คู่Tไม่ได้


8
"เราไม่ชอบJ" คุณเก็บความรู้สึกที่คล้ายกันเกี่ยวกับ APL หรือไม่?
algorithmshark

ไม่รู้! (ถึงแม้ว่าการขาด J ในชื่อของมันจะเป็นที่น่าเชื่อถือ แต่ก็ถือว่าเป็นเช่นนั้น)
35714 sossamish

เกี่ยวกับข้อกำหนดของอินพุตฟังก์ชันอาร์กิวเมนต์อนุญาตหรือไม่ (ไม่แน่ใจว่าสิ่งนี้ถือเป็น "การเข้ารหัสอย่างหนัก") ถ้าไม่เราสามารถสันนิษฐานได้หรือไม่ว่าคีย์นั้นไม่มีการขึ้นบรรทัดใหม่ ถ้าไม่บรรทัดคำสั่ง args อาจทำงานได้ดีกว่า stdin
AlliedEnvy

คำตอบ:


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
)

(พร้อมคำแนะนำมากมายจาก @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

* แทนที่ทุกอันJด้วยI, จริงไหม?


2
เราไม่ชอบ J แต่ฉันสวย!
Vereos

ว้าวนี่เป็นสิ่งพิเศษ
ossifrage คลื่นไส้

ในขณะที่รุ่นแรกมองบิตเช่นคาถาให้ฉันนี้ล่าสุดวูดูบริสุทธิ์ การลดที่น่าประทับใจมาก
Geobits

ป๊อปป๊อปป๊อปดูการกดแป้นหล่น! หากใครต้องการคำอธิบายวิธีการทำงานของเวทมนตร์วูดูนี้เป็นที่นี่คือการเชื่อมโยง ; นานเกินไปที่จะตอบคำถามโดยไม่เกิดอาการตะคริว
algorithmshark

ฉันชอบ J ตอนนี้ :-)
squeamish ossifrage

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 /

นี่คือรหัส ungolfed:

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 และคุณสามารถใช้&เป็นตัวดำเนินการชุดแทนtr: t=->s{s.gsub(?j,?i).upcase.chars&[*?A..?Z]}(บันทึก 7 ไบต์) บรรทัดถัดไปสองบรรทัดสามารถรวมกับสิ่งที่ต้องการk,m=[1,2].map{t[gets.chop]}(โน้ตchopแทนchomp)
daniero

การใช้&ยังช่วยลดความจำเป็นในuniqภายหลัง และการcharsเรียงตัวอาเรย์ยังใช้กับบรรทัดที่ 6
daniero

@daniero ใช่นี่เป็นเวลาที่ผ่านมาแล้วดังนั้นอาจมีการปรับปรุงอีกมากมายที่ฉันสามารถทำได้ ขอบคุณสำหรับเคล็ดลับ; เวลาที่จะกลับมาอีกครั้ง!
Doorknob

ใช่ฉันเห็นว่า :) ฉันสะดุดกับความท้าทายและฉันต้องการที่จะแทงมันในทับทิมทันทีจนกระทั่งฉันเห็นคำตอบของคุณ .. ความซับซ้อนของรหัสประเภททำให้ฉันกลัว แต่ฉันต้องรับ ดู :)
daniero

@daniero แต่น่าเสียดายที่trไป&ที่บรรทัด 1 ไม่ทำงานเพราะmไม่สามารถuniqified อย่างไรก็ตามk.uniqสามารถย่อให้สั้นลงได้(k&k)(1 ไบต์)
Doorknob

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
นี่ทำให้ความพยายามของฉันดูแย่มาก !! มองไปข้างหน้าเพื่อดูว่าคุณสามารถไปได้ไกลแค่ไหนด้วย :-)
squeamish 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

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

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

เพิ่ม Linefeeds เพื่อการปรับปรุง การนำเสนอที่อ่านง่ายขึ้น (ความชัดเจนปรากฏออกไปนอกหน้าต่างฉันกลัว)

#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 :-)
squeamish ossifrage

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

ผมเชื่อว่าคุณสามารถร่นไปz lambda x:0if b not in x else b.remove(x)or 1นอกจากนี้ยังมีช่องว่างมากมายที่คุณสามารถกำจัดได้ ซึ่งจะช่วยให้คุณย้ายไปยังการfilterโทรโดยตรงแทนที่จะกำหนดไว้ด้านนอก
Morgan Thrapp

1

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

จุดดีเกี่ยวกับปัญหา regex - ฉันจะโฆษณาบันทึกคำถาม
squeamish ossifrage

มีปัญหากับตัวอย่างที่สองของคุณ - คู่ของตัวอักษรที่ตัวละครที่ 75 และ 76 UUจะถูกเข้ารหัสเป็น ดูเหมือนว่ามีการทำซ้ำEที่คุณควรจะแยก
ossifrage คลื่นไส้

ถูกต้องฉันยิงตัวเองที่เท้า ปัญหาเกิดจากการดูคู่เท่านั้น แต่จบลงทีละหนึ่งหลังจากการแทรก
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);

ถอดรหัสUngolfed

เอาท์พุท

$ 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

Perl, 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]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.