RosettaCodeData/Task/Playfair-cipher/NetRexx/playfair-cipher.netrexx
2023-07-01 13:44:08 -04:00

165 lines
4.9 KiB
Text

/* NetRexx */
options replace format comments java crossref symbols nobinary
-- input arguments:
-- encipher/decipher IQ-switch key text
-- encipher/decipher -
-- a character E, D (default E; . is an alias for E)
-- IQ-switch -
-- a character I, Q (default I for I==J, Q for exclude Q; . is an alias for I)
-- key -
-- the cipher key - default plugh_xyzzy (really just PLUGHXYZ)
-- text -
-- the text to encipher/decipher
runSample(arg)
return
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method cipher(d_, km, digraphs) public static
if d_.upper() = 'D' then d_ = -1 -- encode or decode adjustment
else d_ = +1
cipherText = ''
loop dw = 1 to digraphs.words()
-- process the digraphs one at a time
digraph = digraphs.word(dw)
cl = ''
cr = ''
-- get each letter from the digraph
parse digraph dl +1 dr
loop r_ = 1 to km[0] while (cl cr).words() < 4
-- locate the row/col of each letter in the cipher matrix
clx = km[r_].wordpos(dl)
crx = km[r_].wordpos(dr)
if clx > 0 then cl = r_ clx
if crx > 0 then cr = r_ crx
end r_
-- process the digraph's rows, columns or rectangles
select
when cl.word(1) = cr.word(1) then do
-- a row
rx = cl.word(1)
clx = cl.word(2) + d_
crx = cr.word(2) + d_
if clx > 5 then clx = 1 -- wrap
if crx > 5 then crx = 1
if clx < 1 then clx = 5
if crx < 1 then crx = 5
cy = km[rx].word(clx) || km[rx].word(crx)
cipherText = cipherText cy
end
when cl.word(2) = cr.word(2) then do
-- a column
cx = cl.word(2)
rlx = cl.word(1) + d_
rrx = cr.word(1) + d_
if rlx > 5 then rlx = 1 -- wrap
if rrx > 5 then rrx = 1
if rlx < 1 then rlx = 5
if rrx < 1 then rrx = 5
cy = km[rlx].word(cx) || km[rrx].word(cx)
cipherText = cipherText cy
end
otherwise do
-- a rectangle
r1 = cl.word(1)
r2 = cr.word(1)
cy = km[r1].word(cr.word(2)) || km[r2].word(cl.word(2))
cipherText = cipherText cy
end
end
end dw
return cipherText.strip()
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method encipher(km, digraphs) public static
return cipher('E', km, digraphs)
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method decipher(km, digraphs) public static
return cipher('D', km, digraphs)
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method getDigraphs(text, IorQ, ED) private static
a2z = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
if ED.upper() \= 'D' then eks = 'X'
else eks = ''
tp = text.upper().translate('', a2z)
text = text.upper().translate(' '.copies(tp.length()), tp).space(0)
rtext = ''
ll = ''
loop while text \= ''
parse text lc +1 text
if ll \= lc then rtext = rtext || lc
else rtext = rtext || eks || lc
ll = lc
end
-- I == J or remove Q fixup
if IorQ \= 'Q' then
parse 'J I' IorQ sc .
else
sc = ''
rtext = rtext.changestr(IorQ, sc)
if rtext.length() // 2 \= 0 then rtext = rtext || eks
digraphs = ''
loop while rtext \= ''
parse rtext digraph +2 rtext
digraphs = digraphs digraph
end
return digraphs.space()
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method getKey(key, IorQ) private static
a2z = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
kp = (key || a2z).upper()
kr = ''
loop while kp \= ''
parse kp xx +1 kp
if \xx.datatype('u') then iterate
kr = kr xx
kp = kp.changestr(xx, '')
end
if IorQ = 'I' | IorQ = 'J' | IorQ = '' then
kr = kr.changestr('J', '')
else
kr = kr.changestr('Q', '')
return kr.space()
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method getKeyMatrix(kr) private static
km = ''
loop r_ = 1 while kr \= ''
parse kr kp +10 kr
km[0] = r_
km[r_] = kp
end r_
return km
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
method runSample(arg) private static
parse arg ciph IorQ key text
if ciph = '' | ciph = '.' then ciph = 'E'
if IorQ = '' | IorQ = '.' then IorQ = 'I'
if key = '' | key = '.' then key = 'plugh_xyzzy'
if text = '' | text = '.' then text = 'NetRexx; not just a programing language for kings & queens!'
kr = getKey(key.space(0), IorQ)
km = getKeyMatrix(kr)
digraphs = getDigraphs(text, IorQ, ciph)
-- fixup for a Q in the text when Q is excluded (substitute K for Q)
if IorQ.upper = 'Q' then digraphs = digraphs.changestr('Q', 'K')
if ciph = 'E' then say text
say digraphs
if ciph.upper() = 'E' then
say encipher(km, digraphs)
else
say decipher(km, digraphs)
return