Last active
December 22, 2020 04:14
-
-
Save obrassard/7aca7a90077be0ff90e0d44ee0f5d785 to your computer and use it in GitHub Desktop.
Kotlin implementation of a Caesar cypher decoder utility (See https://en.wikipedia.org/wiki/Caesar_cipher)
This file contains hidden or 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 kotlin.collections.HashMap | |
fun main() { | |
with(CaesarCypherDecoder()) { | |
val message = decode("QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD", 'K', 'H') | |
println("Decoded message : $message") | |
bruteForce("CZGGJ RJMGY DI V NZXMZODQZ HVIIZM") | |
} | |
} | |
/** | |
* Caesar cypher decoder. | |
* See https://en.wikipedia.org/wiki/Caesar_cipher | |
*/ | |
class CaesarCypherDecoder { | |
private var alphabet: List<Char> = ArrayList<Char>().apply { | |
for (i in 0..25) this.add('A'+i) | |
} | |
fun decode(cypher: String, from: Char, to:Char): String { | |
val shift = from.toUpperCase() - to.toUpperCase() | |
return decode(cypher, shiftAlphabet(shift)) | |
} | |
fun decode(cypher: String, shift: Int) = decode(cypher, shiftAlphabet(shift)) | |
fun bruteForce(cypher: String): Map<Int, String> { | |
val candidates : Map<Int, String> = HashMap<Int, String>().apply { | |
for (i in 1..25) { | |
put(i, decode(cypher, i)) | |
} | |
} | |
println(candidates) | |
return candidates | |
} | |
private fun decode(cypher: String, charMap:Map<Char,Char>): String { | |
val sanitizedMessage = cypher.toUpperCase() | |
if (sanitizedMessage.any { !alphabet.contains(it) && it != ' ' }) | |
throw IllegalArgumentException("'$cypher' contains invalid characters") | |
val builder = StringBuilder() | |
for (c in sanitizedMessage) { | |
builder.append(charMap[c]) | |
} | |
return builder.toString() | |
} | |
private fun shiftAlphabet(shift: Int): Map<Char, Char> { | |
val map: MutableMap<Char,Char> = hashMapOf(' ' to ' ') | |
for (c in alphabet) { | |
val newpos = Math.floorMod((alphabet.indexOf(c) + shift), alphabet.size) | |
map[c] = alphabet[newpos] | |
} | |
return map | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment