ADFGVX cipher: Difference between revisions

(Created new draft task, ADFGVX cipher, and added a Wren solution.)
 
Line 21:
These should then be used to encrypt the plaintext: '''ATTACKAT1200AM''' and decrypt the resulting cipher text. Display here the results of both operations.
<br><br>
 
=={{header|Nim}}==
{{trans|Wren}}
It started as a translation, but actually we use a different method, better suited to Nim, to encrypt and decrypt. And there are many other differences. Output is similar though.
 
<lang Nim>import algorithm, random, sequtils, strutils, sugar, tables
 
const Adfgvx = "ADFGVX"
 
type PolybiusSquare = array[6, array[6, char]]
 
 
iterator items(p: PolybiusSquare): (int, int, char) =
## Yield Polybius square characters preceded by row and column numbers.
for r in 0..5:
for c in 0..5:
yield (r, c, p[r][c])
 
 
proc initPolybiusSquare(): PolybiusSquare =
## Initialize a 6x6 Polybius square.
var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
alphabet.shuffle()
for r in 0..5:
for c in 0..5:
result[r][c] = alphabet[6 * r + c]
 
 
proc createKey(n: Positive): string =
## Create a key using a word from "unixdict.txt".
doAssert n in 7..12, "Key should be within 7 and 12 letters long."
let candidates = collect(newSeq):
for word in "unixdict.txt".lines:
if word.len == n and
word.deduplicate().len == n and
word.allCharsInSet(Letters + Digits): word
result = candidates[rand(candidates.high)].toUpperAscii
 
 
func encrypt(plainText: string; polybius: PolybiusSquare; key: string): string =
## Encrypt "plaintext" using the given Polybius square and the given key.
 
# Replace characters by row+column letters.
var str: string
for ch in plainText:
for (r, c, val) in polybius:
if val == ch:
str.add Adfgvx[r] & Adfgvx[c]
 
# Build ordered table of columns and sort it by key value.
var cols: OrderedTable[char, string]
for i, ch in str:
let tkey = key[i mod key.len]
cols.mgetOrPut(tkey, "").add ch
cols.sort(cmp)
 
# Build cipher text from sorted column table values.
for s in cols.values:
result.addSep(" ")
result.add s
 
 
func decrypt(cipherText: string; polybius: PolybiusSquare; key: string): string =
## Decrypt "cipherText" using the given Polybius square and the given key.
 
# Build list of columns.
let skey = sorted(key)
var cols = newSeq[string](key.len)
var idx = 0
for col in cipherText.split(' '):
cols[key.find(skey[idx])] = col
inc idx
 
# Build string of row+column values.
var str: string
for i in 0..key.high:
for col in cols:
if i < col.len: str.add col[i]
 
# Build plain text from row+column values.
for i in countup(0, str.len - 2, 2):
let r = Adfgvx.find(str[i])
let c = Adfgvx.find(str[i+1])
result.add polybius[r][c]
 
 
randomize()
 
var polybius = initPolybiusSquare()
echo "6 x 6 Polybius square:\n"
echo " | A D F G V X"
echo "---------------"
for i, row in polybius:
echo Adfgvx[i], " | ", row.join(" ")
 
let key = createKey(9)
echo "\nThe key is ", key
 
const PlainText = "ATTACKAT1200AM"
echo "\nPlaintext : ", PlainText
 
let cipherText = PlainText.encrypt(polybius, key)
echo "\nEncrypted : ", cipherText
 
let plainText = cipherText.decrypt(polybius, key)
echo "\nDecrypted : ", plainText</lang>
 
{{out}}
<pre>6 x 6 Polybius square:
 
| A D F G V X
---------------
A | U 1 C N H F
D | E M 4 R S G
F | P I 8 9 6 5
G | X 2 Z B 7 K
V | A 3 Y V O D
X | 0 W Q T J L
 
The key is PHAGOCYTE
 
Plaintext : ATTACKAT1200AM
 
Encrypted : XXX GXA ADD GVA AGD XAX VFGD AAA VGV
 
Decrypted : ATTACKAT1200AM</pre>
 
=={{header|Wren}}==
Anonymous user