Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
101
Task/ADFGVX-cipher/Nim/adfgvx-cipher.nim
Normal file
101
Task/ADFGVX-cipher/Nim/adfgvx-cipher.nim
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue