60 lines
1.4 KiB
Plaintext
60 lines
1.4 KiB
Plaintext
func playfair(key, from = 'J', to = (from == 'J' ? 'I' : '')) {
|
|
|
|
func canon(str) {
|
|
str.gsub(/[^[:alpha:]]/, '').uc.gsub(from, to)
|
|
}
|
|
|
|
var m = canon(key + ('A'..'Z' -> join)).chars.uniq.slices(5)
|
|
|
|
var :ENC = gather {
|
|
m.each { |r|
|
|
for i,j in (^r ~X ^r) {
|
|
i == j && next
|
|
take(Pair("#{r[i]}#{r[j]}", "#{r[(i+1)%5]}#{r[(j+1)%5]}"))
|
|
}
|
|
}
|
|
|
|
^5 -> each { |k|
|
|
var c = m.map {|a| a[k] }
|
|
for i,j in (^c ~X ^c) {
|
|
i == j && next
|
|
take(Pair("#{c[i]}#{c[j]}", "#{c[(i+1)%5]}#{c[(j+1)%5]}"))
|
|
}
|
|
}
|
|
|
|
cartesian([^5, ^5, ^5, ^5], {|i1,j1,i2,j2|
|
|
i1 == i2 && next
|
|
j1 == j2 && next
|
|
take(Pair("#{m[i1][j1]}#{m[i2][j2]}", "#{m[i1][j2]}#{m[i2][j1]}"))
|
|
})
|
|
}.map { (.key, .value) }...
|
|
|
|
var DEC = ENC.flip
|
|
|
|
func enc(red) {
|
|
gather {
|
|
var str = canon(red)
|
|
while (var m = (str =~ /(.)(?(?=\1)|(.?))/g)) {
|
|
take("#{m[0]}#{m[1] == '' ? 'X' : m[1]}")
|
|
}
|
|
}.map { ENC{_} }.join(' ')
|
|
}
|
|
|
|
func dec(black) {
|
|
canon(black).split(2).map { DEC{_} }.join(' ')
|
|
}
|
|
|
|
return(enc, dec)
|
|
}
|
|
|
|
var (encode, decode) = playfair('Playfair example')
|
|
|
|
var orig = "Hide the gold in...the TREESTUMP!!!"
|
|
say " orig:\t#{orig}"
|
|
|
|
var black = encode(orig)
|
|
say "black:\t#{black}"
|
|
|
|
var red = decode(black)
|
|
say " red:\t#{red}"
|