ADFGVX cipher: Difference between revisions
Content added Content deleted
(Created new draft task, ADFGVX cipher, and added a Wren solution.) |
|||
Line 21: | 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. |
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> |
<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}}== |
=={{header|Wren}}== |