Advertisement
vuzi

Caesar decoder

Apr 18th, 2015
251
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 2.58 KB | None | 0 0
  1. package fr.vuzi.decoder
  2.  
  3. import scala.collection.mutable.Map;
  4. import java.lang.StringBuilder;
  5.  
  6. class CeasarDecoder(base: String) {
  7.  
  8.   val _base : Map[Char, Double] = getFrequence(base);
  9.  
  10.   /**
  11.    * Get the frequence of all the letters contained in the given sequence
  12.    */
  13.   def getFrequence(s: String):Map[Char, Double] = {
  14.  
  15.     // Compute the number of letter and occurences
  16.     val (i, occurences) = s.foldLeft[(Int, Map[Char, Int])](0, Map.empty) {
  17.       case ((i, acc), char) if char.isLetter || char == ' ' =>   // If the char is a letter or a space
  18.         val c = char.toLower;
  19.         (i + 1, acc += (c -> (acc.get(c).getOrElse(0) + 1)))
  20.       case (acc, char) => acc
  21.     }
  22.    
  23.     // Compute the frequence
  24.     return occurences.foldLeft[Map[Char, Double]](Map.empty) {
  25.       (frequences, occ) => {
  26.         frequences += (occ._1 -> occ._2 / i.doubleValue())
  27.       }
  28.     }
  29.    
  30.   }
  31.  
  32.   /**
  33.    * Decrypt the given string using the provided value
  34.    */
  35.   def decrypt(s:String, dec:Int):String = {
  36.    
  37.     return s.foldLeft("") {
  38.       case (acc, char) if char.isLetter =>
  39.         val c =  (char.toLower + dec).toChar;
  40.         if(c > 'z')
  41.             acc + (c - 'z' + 'a' - 1).toChar // Greater than z, force back to the start of the alphabet
  42.         else
  43.             acc + c.toChar  // Append the char
  44.       case (acc, char) => acc + char // Not a letter, ignore and append to
  45.     }
  46.    
  47.   }
  48.  
  49.   /**
  50.    * Compute the entropy between the given string and the base
  51.    * string of the object
  52.    */
  53.   private def getEntropy(s:String):Double = {
  54.     val (i, entropy) = s.foldLeft[(Int, Double)]((0, 0D)) {
  55.       case ((i, entropy), char) if char.isLetter => (
  56.         i+1,                                                   // Number of letter to decode
  57.         entropy + Math.log(_base.getOrElse(char.toLower, 0D))  // Total entropy
  58.       )
  59.       case ((i, entropy), char) => (i, entropy)                // Ignore if not a letter
  60.     };
  61.      
  62.     return -entropy / Math.log(2D) / i; // Compute entropy, then return it
  63.   }
  64.  
  65.   /**
  66.    * Decode the given string
  67.    */
  68.   def decode(toDecrypt: String, result:String => Unit) {
  69.     // Get all the entropies
  70.     val decryptedEntropies:Map[Double,String] = Map();
  71.  
  72.     for(i <- 0 until 26) {
  73.       val decrypted = this.decrypt(toDecrypt, i);
  74.       val entropy = this.getEntropy(decrypted);
  75.  
  76.       println("[" + i + "] " + decrypted + " : " + entropy);
  77.  
  78.       decryptedEntropies += (entropy -> decrypted);
  79.     }
  80.  
  81.     // Return the result with the minimum entropy
  82.     result(decryptedEntropies.minBy(_._1)._2);
  83.   }
  84.  
  85. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement