Created
September 29, 2016 20:06
-
-
Save volodymyr-korolyov/6333ecbe4f86904e32c0ca06658698b3 to your computer and use it in GitHub Desktop.
Scala solution to http://www.meetup.com/functional-kats-cork/events/234061670/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package cipher | |
import Function.tupled | |
object CipherTable { | |
// Key char -> Plain char -> Encoded char | |
val encodingTable = ('a' to 'z') | |
.map(col => col -> ('a' to 'z').zip((col to 'z') ++ ('a' until col)).toMap) | |
.toMap | |
// Key char -> Encoded char -> Plain char | |
val decodingTable = encodingTable.map { | |
case (col, rowToValue) => (col, rowToValue.map(_.swap)) | |
} | |
def encodeChar(plainChar: Char, keyChar: Char) = encodingTable(keyChar)(plainChar) | |
def decodeChar(encodedChar: Char, keyChar: Char) = decodingTable(keyChar)(encodedChar) | |
} | |
object Cipher { | |
def processText(f: (Char, Char) => Char)(text: String, key: String) = { | |
lazy val keywordStream: Stream[Char] = key.toStream #::: keywordStream | |
text.zip(keywordStream).map(tupled(f)).mkString | |
} | |
def encode = processText(CipherTable.encodeChar) _ | |
def decode = processText(CipherTable.decodeChar) _ | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package cipher | |
import org.scalacheck.Prop._ | |
import org.scalacheck.Gen._ | |
import org.scalacheck.{Gen, Properties} | |
import org.scalacheck.Prop.forAll | |
object CipherSpecification extends Properties("Alphabet Cipher") { | |
def alphaText: Gen[String] = nonEmptyListOf(alphaLowerChar).map(_.mkString) | |
property("Decode encoded value") = forAll(alphaText, alphaText) { (text: String, key: String) => | |
val encodedText = Cipher.encode(text, key) | |
val decodedText = Cipher.decode(encodedText, key) | |
text.equals(decodedText) | |
} | |
def trivialKey: Gen[String] = nonEmptyListOf(const('a')).map(_.mkString) | |
property("Trivial key encodes to the same value") = forAll(alphaText, trivialKey) { (text: String, key: String) => | |
val encodedText = Cipher.encode(text, key) | |
text.equals(encodedText) | |
} | |
// Danger: unstable test below!!! | |
// Fails when key is longer than text and starts with 'a...a'. Example: text="meet" key="aaaazzz" | |
def nonTrivialKey: Gen[String] = alphaText.suchThat(!_.matches("a+")) | |
property("Encodes to a different value") = forAll(alphaText, nonTrivialKey) { (text: String, key: String) => | |
val encodedText = Cipher.encode(text, key) | |
!text.equals(encodedText) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment