Last active
December 18, 2015 18:39
-
-
Save maasg/5827815 to your computer and use it in GitHub Desktop.
Scala solution to TopCoder practice problem "Decipher": http://community.topcoder.com/stat?c=problem_statement&pm=4674&rd=7227
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
import scala.collection.SortedSet | |
import scala.collection.SortedMap | |
// Attempts to decipher an encripted message by matching the frequency of letters in the message vs an ordered frequency key | |
object Decipher { | |
// calculates a decoding table in the form (encoded->decoded) | |
def codex(encoded:String, freq: String):Map[Char,Char] = { | |
// Transforms the encoded string in a frequency map char->frequecy(int). Note that white spaces are removed | |
val charFreqMap = encoded.filter(_!=' ').foldLeft(Map[Char,Int]())((x,y) => {val freq = x.getOrElse(y,0)+1; x + ((y,freq))}) | |
// Transforms the character frequency map into a Map of frequencies into the order set of chars with that frequency | |
// E.g. 2->('A','B'), 3->'Z',... | |
val freqMap = charFreqMap.foldLeft(Map[Int,SortedSet[Char]]())((map,elem) => elem match {case (k,v) => {val sameCharFreq = map.getOrElse(v,SortedSet[Char]()) + k; map + ((v, sameCharFreq))}}) | |
//Creates a sequence of characters ordered by their frequency in descendent order. | |
//Characters with the same frequency are ordered alphabetically (by virtue of the SortedSet they where collected into) | |
val orderedByFrequency = freqMap.keys.toList.sortWith(_>_).map(freqMap).flatten | |
//Returns a decoding map by matching the ordered-by-frequency char sequence with the provided key. | |
//Space support is added to this map | |
(orderedByFrequency zip freq).toMap + (' ' -> ' ') | |
} | |
def decipher(encoded:Array[String], frequencyOrder:String):Array[String] = { | |
// Creates a single string concatenating the String array provided. Used to calculate the decoding function | |
val stringConcat = encoded.mkString("") | |
// Creates a decoding map from the single string and the frequency key (also a string) | |
val decoder = codex(stringConcat, frequencyOrder) | |
// Decode every string in the input array with the calculated decoding map | |
encoded.map(st => st.map(decoder)) | |
} | |
val encoded = Array("RAZVLHAR KNW CNR", "HEA HNFMNSAR NFAK") | |
decipher( encoded ,"EORTPNFHSCDIWG") // res0: Array[String] = Array(REGISTER NOW FOR, THE TOPCODER OPEN) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment