Jump to content

Vigenère cipher: Difference between revisions

No edit summary
Line 2,986:
=={{header|Scala}}==
Valid characters for messages: A through Z, zero, 1 to 9, and full-stop (.)
<lang scala>import scala.language.implicitConversions
object Vigenere {
def encrypt(msg: String, key: String) : String = {
var result: String = ""
var j = 0
 
for (i <- 0 to msg.length - 1) {
//
val c = msg.charAt(i)
// Translate Special Chars to Names
if (c >= 'A' && c <= 'Z') {
// --------------------------------
result += ((c + key.charAt(j) - 2 * 'A') % 26 + 'A').toChar
//
j = (j + 1) % key.length
class VText
}
}
 
return result
class KeyText( key:String ) extends VText {
override def toString = key
}
 
object KeyText {
def apply(k:String) = new KeyText( "[^A-Z]*".r.replaceAllIn(k.toUpperCase,"") )
}
 
 
class PlainText( message:String ) extends VText {
override def toString = {
"[^A-Z]*".r.replaceAllIn(message.toUpperCase,"")
.replaceAll("FULLSTOP",".")
.replaceAll("CERO","0")
.replaceAll("EINZ","1")
.replaceAll("ZWEI","2")
.replaceAll("TRES","3")
.replaceAll("CUATRO","4")
.replaceAll("CINQ","5")
.replaceAll("SECHS","6")
.replaceAll("SIETE","7")
.replaceAll("HUIT","8")
.replaceAll("NEUF","9")
}
def toRawString = message
}
object PlainText {
def apply(k:String) = new PlainText( k.toList.map(_.toString).map {
case "0" => "CERO"
case "1" => "EINZ"
case "2" => "ZWEI"
case "3" => "TRES"
case "4" => "CUATRO"
case "5" => "CINQ"
case "6" => "SECHS"
case "7" => "SIETE"
case "8" => "HUIT"
case "9" => "NEUF"
case "." => "FULLSTOP"
case a:String => "[^A-Z]*".r.replaceAllIn(a.toUpperCase,"")
}.mkString )
}
 
def decrypt(msg: String, key: String) : String = {
var result: String = ""
var j = 0
 
for (i <- 0 to msg.length - 1) {
class CipherText( cipher:String ) extends VText {
val c = msg.charAt(i)
override def toString = cipher
if (c >= 'A' && c <= 'Z') {
}
result += ((c - key.charAt(j) + 26) % 26 + 'A').toChar
 
j = (j + 1) % key.length
object CipherText {
}
def apply(k:String) = new CipherText(
"[^A-Z]*".r.replaceAllIn(k.toUpperCase,"")
)
}
 
 
//
// The Vigenère Cipher
// -------------------
//
def vcipher( key:KeyText )( plaintext:PlainText ) : CipherText = {
val k = key.toString
val p = plaintext.toRawString
val kp = (k * (p.length / k.length + 1)) zip (p)
CipherText( (for( t <- kp; k = (t._1 - 'A'); p = (t._2 - 'A'); a = 'A' + (p + k) % 26 ) yield (a.toChar)).mkString )
}
 
def vdecipher( key:KeyText )( ciphertext:CipherText ) : PlainText = {
val k = key.toString
val c = ciphertext.toString
val kc = (k * (c.length / k.length + 1)) zip (c)
 
PlainText( (for( t <- kc; k = (t._1 - 'A'); c = (t._2 - 'A'); a = 'A' + (26 + c - k) % 26 ) yield (a.toChar)).mkString )
}
 
 
// Use Implicits to overcome the ambiguity problem of overloaded partial functions
implicit def VTextToString( v:VText ) : String = v match {
case k:KeyText => k.toString
case p:PlainText => p.toString
case c:CipherText => c.toString
case _ => ""
}
implicit def StringToKeyText( s:String ) = KeyText(s)
implicit def StringToPlainText( s:String ) = PlainText(s)
implicit def StringToCipherText( s:String ) = CipherText(s)
 
 
 
// Validate cipher/decipher
assert( vcipher("LEMON")("ATTACKATDAWN").toString == "LXFOPVEFRNHR" )
assert( vdecipher("LEMON")("LXFOPVEFRNHR").toString == "ATTACKATDAWN" )
 
 
// A quick test
val todaysKey = "lemon"
val todaysCipher = vcipher(todaysKey) _
val todaysDecipher = vdecipher(todaysKey) _
 
val plaintext = "Attack at 0620."
val ciphertext = todaysCipher(plaintext)
 
println( " Message: " + plaintext + "\n" )
println( "Enciphered: " + ciphertext + "\n" )
println( "Deciphered: " + todaysDecipher( ciphertext ) + "\n" )
</lang>
{{out}}
<pre> Message: Attack at 0620.
 
Enciphered: LXFOPVEFQRCSESPSWLKRTGQFBQYXZFESB
 
Deciphered: ATTACKAT0620.
</pre>
===Alternate Scala implementation===
This version first creates a sequence of characters from A to Z and a "flattened" Vigenere Square. It then encodes or decodes by just indexing between these two sequences. The code does no error checking, as well as encoding all lower case letters as upper case.
 
<lang scala>object Vigenere {
 
val key = "LEMON"
val chars = 'A' to 'Z'
 
private def rotate(p: Int, s: IndexedSeq[Char]) = s.drop(p) ++ s.take(p)
val vSquare = (for (i <- Range(0, 25)) yield rotate(i, chars)).flatten
 
def encrypt(s: String) = enrOrDecode(0, s.toUpperCase, encode)
def decrypt(s: String) = enrOrDecode(0, s.toUpperCase, decode)
 
private def enrOrDecode(i: Int , in: String, op:(Char, Int) => Char): String = {
if (in.length == 0) in else {
val index = if (i == key.length) 0 else i
(if (chars.contains(in.head)) op(in.head, index) else in.head) + enrOrDecode(index + 1, in.tail, op)
}
}
 
return result
private def encode(c: Char, index: Int): Char = {
vSquare((c - 'A') * 26 + key(index) - 'A')
}
}
 
println("Encrypt text ABC => " + Vigenere.encrypt("ABC", "KEY"))
private def decode(c: Char, index: Int) = {
println("Decrypt text KFA => " + Vigenere.decrypt("KFA", "KEY"))
val baseIndex = (key(index) - 'A') * 26
val nextIndex = vSquare.indexOf(c, baseIndex)
chars(nextIndex - baseIndex)
}
}
</lang>
 
<lang scala>val text = "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!"
val encoded = Vigenere.encrypt(text)
val decoded = Vigenere.decrypt(text)
println("Plain text => " + text)
println("Cipher text => " + encoded)
println("Decrypted => " + decoded)</lang>
 
{{out}}
<pre>scala> Encrypt text ABC => KFA
<pre>plain text => Beware the Jabberwock, my son! The jaws that bite, the claws that catch!
scala> Decrypt text KFA => ABC</pre>
cipher text => MIIOEP FVR NMPOPVICPV, AL WAB! XTS UEIG ELMH MMFS, XTS NPMKF XTOG GMHPS!
decrypted => BEWARE THE JABBERWOCK, MY SON! THE JAWS THAT BITE, THE CLAWS THAT CATCH!</pre>
 
=={{header|Seed7}}==
Cookies help us deliver our services. By using our services, you agree to our use of cookies.