diff --git a/16_vigenere.lua b/16_vigenere.lua new file mode 100644 index 0000000..5a60ce3 --- /dev/null +++ b/16_vigenere.lua @@ -0,0 +1,64 @@ +-- The Vigenère cipher is a way to encrypt text, where a key is +-- repeated for the length of the plaintext and the alphabetical +-- position of the keyword letter determines the amount the letter of +-- the plaintext is shifted by. For example, for plaintext "FOO" and +-- key "BAR", the first letter of the cipher text would be G, the +-- result of shifting the letter F (first letter of the plaintext) +-- over by 1 (the zero-based alphabetical position of B, first letter +-- of the key). +-- +-- Implement a function to encode a message with a given keyword. The +-- message should be converted to upper-case and any non-alphabetical +-- characters should be discarded. +-- +-- Solution -------------------------------------------------------------------- +local a_value = 65 + +function apply_shift(letter, shift) + local shifted = (letter - a_value + shift) % 26 + return a_value + shifted +end + +function vigenere_encode(plaintext, keyword) + local key = {} + for i = 1, #keyword do + local shift = string.byte(keyword, i) - a_value + table.insert(key, shift) + end + + plaintext = string.gsub(string.upper(plaintext), "%A+", "") + ciphertext = "" + for i = 1, #plaintext do + local letter = string.byte(plaintext, i) + local shift = key[(i - 1) % #key + 1] + local shifted = apply_shift(letter, shift) + ciphertext = ciphertext .. string.char(shifted) + end + + return ciphertext +end + +-- Tests ----------------------------------------------------------------------- + +local luaunit = require("luaunit.luaunit") + +function test_encoding_of_foo_with_key_BAR() + luaunit.assertEquals(vigenere_encode("FOO", "BAR"), "GOF") +end + +function test_encoding_of_the_quick_brown_fox_with_key_JUMPSOVER() + local plaintext = "The quick brown fox" + local key = "JUMPSOVER" + local expected = "CBQFMWXOSAIICXCS" + luaunit.assertEquals(vigenere_encode(plaintext, key), expected) +end + +function test_encoding_longer_phrase_with_key_LEAR() + local plaintext = + "They dined on mince and slices of quince, which they ate with a runcible spoon." + local key = "LEAR" + local expected = "ELEPOMNVOSNDTRCVLRDJWMCVDSFHFMNTPAHZNLTYPCAKPAIKSERLYGISWISGZSN" + luaunit.assertEquals(vigenere_encode(plaintext, key), expected) +end + +os.exit(luaunit.LuaUnit.run())