playfair_cipher.sf 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #!/usr/bin/ruby
  2. #
  3. ## https://rosettacode.org/wiki/Playfair_cipher
  4. #
  5. func playfair(key, from = 'J', to = (from == 'J' ? 'I' : '')) {
  6. func canon(str) {
  7. str.gsub(/[^[:alpha:]]/, '').uc.gsub(from, to)
  8. }
  9. var m = canon(key + ('A'..'Z' -> join)).chars.uniq.slices(5)
  10. var :ENC = gather {
  11. m.each { |r|
  12. for i,j in (^r ~X ^r) {
  13. i == j && next
  14. take(Pair("#{r[i]}#{r[j]}", "#{r[(i+1)%5]}#{r[(j+1)%5]}"))
  15. }
  16. }
  17. ^5 -> each { |k|
  18. var c = m.map {|a| a[k] }
  19. for i,j in (^c ~X ^c) {
  20. i == j && next
  21. take(Pair("#{c[i]}#{c[j]}", "#{c[(i+1)%5]}#{c[(j+1)%5]}"))
  22. }
  23. }
  24. cartesian([^5, ^5, ^5, ^5], {|i1,j1,i2,j2|
  25. i1 == i2 && next
  26. j1 == j2 && next
  27. take(Pair("#{m[i1][j1]}#{m[i2][j2]}", "#{m[i1][j2]}#{m[i2][j1]}"))
  28. })
  29. }.map { (.key, .value) }...
  30. var DEC = ENC.flip
  31. func enc(red) {
  32. gather {
  33. var str = canon(red)
  34. while (var m = (str =~ /(.)(?(?=\1)|(.?))/g)) {
  35. take("#{m[0]}#{m[1] == '' ? 'X' : m[1]}")
  36. }
  37. }.map { ENC{_} }.join(' ')
  38. }
  39. func dec(black) {
  40. canon(black).split(2).map { DEC{_} }.join(' ')
  41. }
  42. return(enc, dec)
  43. }
  44. var (encode, decode) = playfair('Playfair example')
  45. var orig = "Hide the gold in...the TREESTUMP!!!"
  46. say " orig:\t#{orig}"
  47. var black = encode(orig)
  48. say "black:\t#{black}"
  49. var red = decode(black)
  50. say " red:\t#{red}"
  51. assert_eq(black, "BM OD ZB XD NA BE KU DM UI XM MO UV IF")
  52. assert_eq(red, "HI DE TH EG OL DI NT HE TR EX ES TU MP")