Caesar’s Cipher

Is there something that explains the code for this exercise line by line? Also, why on earth would they use i and j as the variable names when we are dealing with characters? Up until now I don’t remember seeing a for-in loop that looks like “0 …< message.count”. I have scored 100% on all of the quizzes up this point but am completely baffled at this exercise. I just don’t understand what is going on and I can’t seem to find any documentation explaining it. I’m totally stuck. Can anyone point me in the right direction or perhaps suggest a companion guidebook for swift or even a more rudimentary course?

var alphabet: [Character] = [“a”, “b”, “c”, “d”, “e”, “f”, “g”, “h”, “i”, “j”, “k”, “l”, “m”, “n”, “o”, “p”, “q”, “r”, “s”, “t”, “u”, “v”, “w”, “x”, “y”, “z”]

var secretMessage = “Codecademy”.lowercased()

var message = Array(secretMessage)

for i in 0 …< message.count {

for j in 0 …< alphabet.count {

if message[i] == alphabet[j] {
    
  message[i] = alphabet[(j+3) % 26]
  break
  
}

}

}

i and j are very common index variable names when looping through indices of collections (like arrays and strings). Notice that there is a distinction of iterating over values of a collection itself and iterating over the indices.

In terms of what is going on there’s at least 2 considerations to consider.

  • what’s going on in technical terms with regards to the swift language (you can use swift docs and an interactive terminal to play with patterns that seem unfamiliar, or you can step through the code with a debugger as well).
  • what’s going on on a “high” level, i.e. what is the goal of the program. In which Caesar’s Cipher is sometimes introduced in intro to cryptography as a very naive form of encryption (or also sometimes given as a programming exercise without explanation of why anyone might care). In which case you should try to research on the concept from that angle.
  • (and in simple terms the Caesar Cipher just “scrambles” messages by shifting all the letters in one direction of the alphabet modulo the size of the alphabet).

In very basic terms, we want to send a message m over an open network. We have a send() and receive() function from two connected parties. Since it is an open network, there is no guarantee that an adversary cannot read our message. So if we send(m), by the time our target gets m, the contents might have been spied on. This naive cipher makes it at least one step harder, now we have this cipher function cipher(m) = e where e is our encrypted message. When we send(e) now the adversary has to do extra work if they want to read on the message. And although this exercise can be cracked very simply, conceptually if we have a strong encryption function we can make stronger guarantees about the security of our message sending.

1 Like

Lol, I was writing a long comment whining about the following line

message[i] = alphabet[(j+3) % 26]

Since I could not understand why it helps to save the day, but I will leave the explanation here for those who may find it helpful.

If we use %, then (e.g. j = 24)

message[i] = alphabet[(24 + 3) % 26]

Quick math tells us that 27 / 26 = 1 and 1 as remainder. As a result of % the only value left is the remainder (!), that’s why the console will show ‘a’ ((24 + 3) % 26 = 1 (1)) if we entered ‘x’ (24).

What I really struggle to understand (did not find any info in swift documentation regarding the count property)
for i in 0 ..< message.count {...}
Why we do not need to additionally tell the program that we are iterating through the message array?
I thought that count property returns only an Int which represents the number of elements in array, in other words, for me the line
for i in 0 ..< message.count {...}
can be read as
for i in 0 ..< (any number) {...}
without any reference to the message array, since message.count returns only a number

I’d appreciate if anyone could comment on that.

Count is a property of a collection so it gives you the size. You’re correct that this is just iterating through indexes, and so at best you can only index into some array.

If you just wanted to iterate through just the messages, you could do for message in messages.

If you need both consider enumerated()
for (index, message) in messages.enumerated()