Skip to content

Instantly share code, notes, and snippets.

@hierynomus
Created May 29, 2012 11:57
Show Gist options
  • Save hierynomus/2828045 to your computer and use it in GitHub Desktop.
Save hierynomus/2828045 to your computer and use it in GitHub Desktop.
PlayFair Cipher in Scala
object PlayFair {
type Cipher = Map[(Int, Int), Char]
def buildCipher(p: String) : Cipher = (for (x <- 0 to 4; y <- 0 to 4) yield (x,y)).zip(chars(p)).toMap
def makeCompatible(s: String) = s toUpperCase() replace('J', 'I') filter(_.isLetter)
def chars(a: String) = {
val p = makeCompatible(a) filter { var s = Set[Char](); x => val b = s(x); s += x; !b }
p ++ ('A' to 'Z' filter (c => c != 'J' && !(p contains c)))
}
def lookup(x: Char, c: Cipher) : (Int, Int) = c.find(_._2 == x).get._1
def get(x: Int, y: Int, c: Cipher) = c((x % 5, y % 5))
def code(a: Char, b: Char, d: Int, c: Cipher) = {
val ((ax, ay), (bx, by)) = (lookup(a, c), lookup(b, c))
if (ay == by) List(get(ax + d, ay, c), get(bx + d, by, c))
else if (ax == bx) List(get(ax, ay + d, c), get(bx, by + d, c))
else List(get(ax, by, c), get(bx, ay, c))
}
def encode(t: String, p: String) = doEncode(makeCompatible(t).toList, buildCipher(p)) mkString
def decode(t: String, p: String) = doDecode(t.toUpperCase, buildCipher(p))
def doEncode(t: List[Char], c: Cipher) : List[Char] = t match {
case x :: Nil => doEncode(x :: List('X'), c)
case x :: y :: xs => if (x == y) doEncode(x :: List('X'), c) ++ doEncode(y :: xs, c)
else code(x, y, 1, c) ++ doEncode(xs, c)
case Nil => Nil
}
def doDecode(t: String, c: Cipher) : String = t grouped(2) flatMap (x => code (x(0), x(1), -1, c)) mkString
}
@svdberg
Copy link

svdberg commented May 29, 2012

See https://gist.github.com/2828223 for an equally unreadable Haskell variant ;) :P

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment