4
\$\begingroup\$

I've worked out a functioning Vigenère encryption in Scala, and while it doesn't seem like my code is too hideous, I'm sure I could make it more functional and Scala-esque. Primarily, it seems like:

  1. I've made the full key with a for-expression / zipWithIndex, I'm wondering if this is the best way to do this though. Would it be better to do this inside the encipher() function? Using an anonymous function? The way I have it now works, but I'm curious if there's a way to do so that'd be more in line with Scala best practices.
  2. The actual encryption portion, specifically the output for case (c, i), is sort of messy/convoluted, and it seems like there might be a better way to do it.

Of course, I'll be grateful for any feedback. Definitely still getting my feet wet with Scala, and any help getting into a more functional state of mind would be appreciated.

object Vigenere {
// alphabet for use throughout object
private val alphabet = ('A' to 'Z').toList
//empty array to be filled with fillTabula() function
private var tabulaRecta = Array.ofDim[Char](26, 26)
/* fills the tabula recta array
** creates 26 rows of alphabets, each alphabet shifted
** left by one letter each iteration */
def fillTabula() = {
 for (row <- 0 to 25) {
 for (col <- 0 to 25) {
 tabulaRecta(row)(col) = alphabet((row + col) % 26)
 }
 } 
}
/* create the full key by repeating the key until its as long
** as the plaintext. */
def makeFullkey(key: String, text:String): String = {
 val fkey = for (c <- text.zipWithIndex) yield c match {
 case (c, i) => key(i % key.length)
 }
 return fkey.mkString
}
def encipher(key: String, text:String): String = {
 // fill the tabula recta
 fillTabula()
 val fkey = makeFullkey(key, text)
 /* to encipher, zip the plaintext to return each letter with
 ** its index. if it's a space, just add space to ciphertext.
 ** if it's not a space, find the corresponding row in the 
 ** tabula recta, then go to the appropriate column to
 ** return the ciphertext character.
 ** the second case here is a mess, there's got to be a nicer way. */ 
 val ciphertext = for (c <- text.zipWithIndex) yield c match {
 case (' ', _) => ' '
 case (c, i) => tabulaRecta(alphabet.indexOf(fkey(i)))(alphabet.indexOf(c))
 }
 return ciphertext.mkString
}
def main(args: Array[String]) {
 val Array(text, key) = args
 println("Plaintext: " + text)
 println("Key: " + key)
 println("Ciphertext: " + encipher(key.toUpperCase, text.toUpperCase))
}
}

Edit: I realized that I could make the fullkey using zipWithIndex as well, and also found a better place to use toUpperCase. I've changed the code and updated my question accordingly.

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Jul 27, 2015 at 23:30
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I'm not a scala/fp expert but here is my 2 cents.

Your code reads very much like you have read the definition on wikipedia and translated it into scala. As the wikipedia definition is written as a human implemented algorithm you end up with a very procedural approach.

A few specific things:

  • tabulaRecta - this is constant, making it a var is a massive code smell
  • makeFullkey - you use zipWithIndex but don't use c, just use index
  • why can't tabulaRecta be a function?
  • why create a fullKey - can't you compute the key char as a function?
answered Jul 28, 2015 at 21:00
\$\endgroup\$
3
  • \$\begingroup\$ Hmm, I honestly have no idea how I'd go about making tabulaRecta into a function at this point, I'd certainly prefer it being a val too. I'm sure you're right about the fullKey thing too. I used zipWithIndex on the fullKey so as to avoid using an accumulating counter variable, but I'm sure there's a better way to do that too. Thanks for giving me some stuff to think about! \$\endgroup\$ Commented Jul 29, 2015 at 16:01
  • \$\begingroup\$ Let me know if want more help, I can post some actual code as well. I thought it best just to give you pointers to start with. \$\endgroup\$ Commented Jul 29, 2015 at 16:37
  • \$\begingroup\$ Appreciate it! I'll see what I can come up with and come back if I can't figure anything out. \$\endgroup\$ Commented Jul 29, 2015 at 16:42

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.