# Kush Patel (2409544)

# Task 1: Define the Polybius Cipher Matrix
Polybius <- matrix(c(
  ' ', 'Z', 'M', 'D', ' ', 'K', 'W', 'Q', ' ', 'G',  # Row 0
  'V', ' ', 'A', ' ', 'R', ' ', 'E', ' ', 'T', 'O',  # Row 1
  ' ', 'J', 'I', 'S', 'B', 'P', 'Y', ' ', 'F', ' ',  # Row 2
  'L', ' ', ' ', 'C', ' ', 'U', 'H', 'N', ' ', 'X'   # Row 3
), nrow = 4, byrow = TRUE)

# Assign row names (0 to 3) and column names (0 to 9) 
rownames(Polybius) <- 0:3
colnames(Polybius) <- 0:9

# Print the Polybius cipher matrix to verify
cat("Polybius Matrix:\n")
print(Polybius)
#--------------------------------------------------------------------------------------------------
#Task 2
#Task 2.1 Define the ciphertext
ciphertext <- c("24160", "63616", "14162", "61935", "14163", "71602", "26222", "33719", "18008")

# Combine all segments of the ciphertext into a single long string of digits.
combined_ciphertext <- paste(ciphertext, collapse = "")

# Initialize an empty string for the decrypted message.
decrypted_message <- ""

# Loop through the combined ciphertext, taking two digits at a time.
for (i in seq(1, nchar(combined_ciphertext), by = 2)) {
  # Extract the row and column from the current pair of digits.
  row <- as.integer(substr(combined_ciphertext, i, i))
  col <- as.integer(substr(combined_ciphertext, i + 1, i + 1))
  
  # Validate row and column indices and retrieve the character from the matrix.
  if (!is.na(row) && !is.na(col) && row >= 0 && row <= 3 && col >= 0 && col <= 9) {
    # Adjust for 1-based indexing and get the character.
    character <- Polybius[row + 1, col + 1]
    decrypted_message <- paste0(decrypted_message, character)
  } else {
    # Append a placeholder for invalid indices.
    decrypted_message <- paste0(decrypted_message, "!")
  }
}

# Display the decrypted message.
cat("Decrypted Message:\n")
cat(decrypted_message, "\n")



# Task 2.2: Encrypt a Message with the Keyword "APPLE"
message <- "RAISETHEFLAG"
keyword <- "APPLE"

# Function to get the row and column of a letter from the Polybius matrix.
get_position <- function(letter) {
  pos <- which(Polybius == letter, arr.ind = TRUE)
  if (length(pos) > 0) {
    return(c(pos[1] - 1, pos[2] - 1))  # Return 0-based row and column indices.
  }
  return(c(NA, NA))  # Return NA if the letter is not in the matrix.
}

# Split the message and keyword into individual characters.
message_chars <- unlist(strsplit(message, ""))
keyword_chars <- unlist(strsplit(keyword, ""))

# Repeat the keyword to match the length of the message.
extended_keyword <- rep(keyword_chars, length.out = length(message_chars))

# Generate positions for message and keyword characters.
message_positions <- t(sapply(message_chars, get_position))
keyword_positions <- t(sapply(extended_keyword, get_position))

# Encrypt the message by combining positions from the message and keyword.
encrypted_codes <- apply(cbind(message_positions, keyword_positions), 1, function(pos) {
  new_row <- (pos[1] + pos[3]) %% 4
  new_col <- (pos[2] + pos[4]) %% 10
  sprintf("%d%d", new_row, new_col)
})

# Combine the encrypted codes into a single string.
encrypted_message <- paste(encrypted_codes, collapse = "")

# Format the encrypted message into groups of 5 characters.
formatted_encrypted <- gsub("(.{5})", "\\1 ", encrypted_message)

# Display the encrypted message.
cat("\nEncrypted Message with Keyword 'APPLE':\n", formatted_encrypted, "\n")



#Task 2.3: Input ciphertext and the decryption keyword
ciphertext <- "48521 82559 53320 83151 44382 13349 40352 42260 48521 84349 48343 23518"
keyword <- "LEMON"

# Step 1: Convert the ciphertext into pairs
ciphertext_clean <- gsub(" ", "", ciphertext)  # Remove spaces
ciphertext_pairs <- strsplit(ciphertext_clean, "")[[1]]
ciphertext_pairs <- as.numeric(ciphertext_pairs)

# Step 2: Create a vector of numeric values for the keyword
keyword_numeric <- c()
for (char in strsplit(keyword, "")[[1]]) {
  match_position <- which(Polybius == char, arr.ind = TRUE)
  if (nrow(match_position) > 0) {
    # Calculate numeric value: row * 10 + column
    row <- match_position[1, 1] - 1  # Row (adjust for 0-based)
    col <- match_position[1, 2] - 1  # Column (adjust for 0-based)
    keyword_numeric <- c(keyword_numeric, row * 10 + col)
  }
}

# Step 3: Decrypt the ciphertext
plaintext <- ""
keyword_length <- length(keyword_numeric)

for (i in seq(1, length(ciphertext_pairs), by = 2)) {
  # Combine two digits from the ciphertext
  cipher_value <- ciphertext_pairs[i] * 10 + ciphertext_pairs[i + 1]
  
  # Adjust using the keyword
  key_adjustment <- keyword_numeric[((i - 1) %/% 2) %% keyword_length + 1]
  adjusted_value <- cipher_value - key_adjustment
  
  # Get row and column
  row <- floor(adjusted_value / 10)
  col <- adjusted_value %% 10
  
  # Add character to plaintext if within bounds
  if (!is.na(row) && row >= 0 && row <= 3 && !is.na(col) && col >= 0 && col <= 9) {
    letter <- Polybius[row + 1, col + 1]
    if (letter != " ") {
      plaintext <- paste0(plaintext, letter)
    }
  }
}

# Print the final plaintext
cat("Decrypted plaintext:\n", plaintext, "\n")


