src/main/scala/CryptoSquare.scala

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
case class CryptoSquare() {
  type PlainText = String
  type NormalizedPlainText = String
  type TextSquare = List[String]
  type CipherCharSquare = List[Seq[Char]]
  type CipherSquare = List[String]
  type CipherText = String
  type NormalizedCipherText = String

  def normalizePlaintext(text: PlainText): NormalizedPlainText =
    text.trim.filter(_.isLetterOrDigit).toLowerCase

  def squareSize(text: PlainText): Int =
    math.sqrt(normalizePlaintext(text).length).ceil.toInt

  def plaintextSegments(text: PlainText): TextSquare = {
    val clean = normalizePlaintext(text)
    if (clean.isEmpty) Nil else clean.grouped(squareSize(clean)).toList
  }

  private def transpose(strings: TextSquare): CipherCharSquare = strings match {
    case Nil => Nil
    case xs: TextSquare =>
      xs.map { _.headOption.getOrElse() }.mkString ::
      transpose( xs.map {_.tail}.filterNot(_.isEmpty))
  }

  private def cipherChars(text: PlainText): CipherCharSquare =
    transpose(plaintextSegments(text))

  def ciphertext(text: PlainText): CipherText = cipherChars(text).flatten.mkString

  def normalizedCiphertext(text: PlainText): NormalizedCipherText =
    cipherChars(text).map(_.mkString).mkString(" ")
}

@abo64 thinks this looks great

Comments


You're not logged in right now. Please login via GitHub to comment