123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- #!/usr/bin/ruby
- #
- ## https://rosettacode.org/wiki/Playfair_cipher
- #
- 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}"
- assert_eq(black, "BM OD ZB XD NA BE KU DM UI XM MO UV IF")
- assert_eq(red, "HI DE TH EG OL DI NT HE TR EX ES TU MP")
|