Caesar Cipher Challenge

So a few months ago, I had an old homework assignment for school in which I had to make a Caesar Cypher encrypting machine. I already did it, and I would like to see some of the solutions some of you come up with for this. To make it fair to you guys, here are all of the original instructions that I was given for this assignment:

MINI LESSON ON CHARACTERS

Every character has an associated number with it, according to the table of ASCII values. Capital letter 'A' corresponds to 65 , 'B' to 66 , … , 'Z' to 90 .

That means you can perform mathematical operations on characters, and you get a numeric result. To get the result as a character, you just cast it to a char after doing your operation.

Example :

char newLetter = (char)(‘A’ + 2) => newLetter holds the char ‘C’

But there’s a catch .

If you add 2 to Z, you want it loop back to B. But, 92 (i.e. 90 + 2) is not the ASCII value for Y, it’s the ASCII value for ‘\’.

There’s a solution for this:

Before doing your mathematical operation on your character, subtract 65 from the character . Now ‘A’ will correspond to 0, ‘B’ to 1, etc.

Do your desired math operations, and then mod the result by 26 to make sure your answer is between 0 and 25.

Add 65 to get the character back to its numeric ASCII value, and cast it to a char .

THE LAB

A Caesar cipher, named after Julius Caesar, is a simple algorithm for encrypting secret messages. It is a type of substitution cipher in which each letter is the message is replaced by a letter some fixed number of positions down the alphabet.

Example:

If using a left shift of 3, D would be replaced by A, E would become B, and so on.

If using a right shift of 2, D would be replaced by F, E would become G, and so on.

Write a method named encode that takes in a String representing secret message (without spaces) and an int representing how many positions to shift the letters by to encode, and returns the encoded version of the message. You can assume it will always be a right shift.

In the main method, ask the user for a secret message to encode, and then print out their encoded message using the encode method.

Examples:

encode("CAT", 2) returns ECV

encode("MEETMEATTHREE", 5) returns RJJYRJFYYMWJJ

encode("ZOOM", 3) returns CRRP ``

Lastly, here’s the sample input and output:
Output = Enter your secret message and an amount to shift by:
Input = MEETMEATTHREE 5
Output = Encoded message: RJJYRJFYYMWJJ

Here’s the original answer for this problem:

import java.util.Scanner;

public class CaesarCipher {
  public static void main(String[] args) {
    Scanner sneaky = new Scanner(System.in);
    System.out.println("Enter your secret message and an amount to shift by:");
    String definitelyNotASecretMessage = sneaky.next();
    int shifting = sneaky.nextInt();
    String hacks = encode(definitelyNotASecretMessage, shifting);
    System.out.println("Encoded message: " + hacks);
  }
  public static String encode(String spy, int times) {
    String hackerSteve = spy;
    for (int i = times; i > 0; i--) {
      String hackerWalter = "";
      for (int h = 0; h < hackerSteve.length(); h++ ) {
        char iSpilledWaterOnMyLaptop = (char)(((((hackerSteve.charAt(h)) - 65) + 1) % 26) + 65);
        hackerWalter += "" + iSpilledWaterOnMyLaptop;
      }
      hackerSteve = hackerWalter;
    }
    return hackerSteve; 
  }
}

That was the correct code needed to get the assignment right, but before I ended up here, I got a little creative and ended up with this alternate solution:

import java.util.Scanner;

public class CaesarCipher {
  public static void main(String[] args) {
    Scanner sneaky = new Scanner(System.in);
    System.out.println("Enter your secret message and an amount to shift by:");
    String definitelyNotASecretMessage = sneaky.next();
    int shifting = sneaky.nextInt();
    String hacks = encode(definitelyNotASecretMessage, shifting);
    System.out.println("Encoded message: " + hacks);
  }
  public static String encode(String spy, int times) {
    String hackerSteve = spy;
    String alphabet = "?abcdefghijklmnopqrstuvwxyzab";
    alphabet = alphabet.toUpperCase();
    for (int i = times; i > 0; i--) {
      String hackerJake = "";
      for (int h = 0; h < hackerSteve.length(); h++) {
        hackerJake += "" + alphabet.charAt((alphabet.indexOf(hackerSteve.charAt(h))) + 1);
      }
      hackerSteve = hackerJake;
    }
    return hackerSteve;
  }
}
 
// Steve is a nimrod, Jake is a coffee addict 

I’m interested to see what people think of my alternate solution. and/or what other ways there are to end up with the right solution.
Good luck on this, and I’m excited to see what you come up with!

const caesar=(s, k)=>{
  const upper='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  const lower='abcdefghijklmnopqrstuvwxyz';
  return s.replace(/[a-z]/g,c=>lower[(lower.indexOf(c)+k)%26]).replace(/[A-Z]/g,c=>upper[(upper.indexOf(c)+k)%26])
}

I’d work on fewer ‘magic numbers’, clearer variable names, and more flexibility:

use std::io;
const NUM_LETTERS: u8 = 26;

fn main() {
  println!("Enter message to encode:");
  let mut user_message = String::new();
  io::stdin().read_line(&mut user_message).expect("I/O Failure!");

  println!("Enter shift size:");
  let mut shift = String::new();
  io::stdin().read_line(&mut shift).expect("I/O Failure!");
  let mut shift = shift.trim().parse::<u8>().unwrap();

  println!("Encode or Decode:");
  let mut encode_or_decode = String::new();
  io::stdin().read_line(&mut encode_or_decode).expect("I/O Failure!");
  if encode_or_decode.trim().to_uppercase() == "DECODE" {
    shift = NUM_LETTERS - shift;
  }
  
  let encoded_message = user_message
    .to_uppercase()
    .chars()
    .map(|c| {
      if c.is_alphabetic() {
        (((c as u8 -'A' as u8) + shift) % NUM_LETTERS + 'A' as u8) as char
      } else {
        c
      }
    })
    .collect::<String>();
  println!("\nEncoded Message:\n{}", encoded_message);
}
function encode(str, shift) {
    if (shift == 0) 
        return str;
    const LOWER_LIMIT = 65;
    const UPPER_LIMIT = 90;
    return str.split("")
                .map(item => {
        			let c = item.charCodeAt(0);
                    if (c >= LOWER_LIMIT && c <= UPPER_LIMIT) {
                        let shiftedC = c + shift;
                        while (shiftedC > UPPER_LIMIT || shiftedC < LOWER_LIMIT) {
                          shiftedC += Math.sign(shift) * -26;
                        }
                        return String.fromCharCode(shiftedC);
                    } else {
                        return item;
                    }
                }).join("");
}

I added spoiler tags to yours so that someone can’t just copy-paste it, since the Caeser Cipher is one for the JavaScript section certification projects.

Why this complicated while loop instead of just using a mod operator? Mod is faster and clearer.

What are those, what do they certify you for, and where can I attempt them?

You’re correct, it’s just that I tried to write this solution very fast, so didn’t spend much time on it.

Java solution (it’s a bit faster than one from the first post)

public class CaesarOptimized {
    public static void main(String[] args) {
        if (args.length != 2)
            System.out.println("Usage: program message shift");
        String msg = args[0];
        int shift = Integer.valueOf(args[1]);
        System.out.println(msg);
        System.out.println(String.format("Encoded message: %s", encode(msg, shift)));
    }

    public static String encode(String msg, int shift) {
        char[] chars = msg.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            chars[i] = (char)((chars[i] - 65 + shift) % 26 + 65);
        }
        return new String(chars);
    }
}

Its a question of style, but I like showing where the ‘magic numbers’ 26 and 65 come from.

Just to make it easier for future me to remember how the code works and to make it easier for a new person to read the code.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.