#Sneha babariya (2409818)


# Task 1.1: Define the Polybius matrix
# The Polybius cipher matrix maps letters to unique numeric codes based on their position.
# Each letter is identified by its row and column indices.
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)  # Create a 4x10 matrix, filling row by row.

# Add row and column labels to make it easier to interpret the matrix and access elements.
rownames(polybius) <- 0:3  # Label rows as 0 to 3 (zero-based indexing).
colnames(polybius) <- 0:9  # Label columns as 0 to 9.

# Display the Polybius matrix to verify its structure and ensure it's correctly defined.
print("Polybius Matrix:")
print(polybius)

#__________________________________________________________________________________________________

#Task 2.1 Decrypt the Given Ciphertext Using the Polybius Matrix 
# Objective: Decrypt the given ciphertext using the Polybius matrix to produce readable plaintext.


# The given ciphertext is a set of numbers representing character positions.
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 = "")


# This will store the characters of the decrypted message.
decrypted_message <- c()

# For each pair of digits, extract the row and column and find the corresponding character in the Polybius matrix.
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 that the row and column are within the valid range of the Polybius matrix.
  if (!is.na(row) && !is.na(col) && row >= 0 && row <= 3 && col >= 0 && col <= 9) {
    # Retrieve the character from the Polybius matrix.
    character <- polybius[row + 1, col + 1]  # Adjust for 1-based indexing in R.
    # Append the character to the decrypted message.
    decrypted_message <- c(decrypted_message, character)
  } else {
    # If the indices are invalid, add a placeholder character (!).
    decrypted_message <- c(decrypted_message, "!")
  }
}

#  Combine all the decrypted characters into the final message.
# Combine all characters into a single string.
plaintext <- paste(decrypted_message, collapse = "")

#Task 2.1 Display the decrypted message.
print("Decrypted Message:")
print(plaintext)



#Task 2.2 Encrypt the Message Using the Keyword "APPLE"
# Objective: Encrypt the message "RAISETHEFLAG" using the keyword "APPLE" to generate a numeric ciphertext.

# Define the message and the keyword.
# The message to encrypt is "RAISETHEFLAG" and the keyword is "APPLE".
message_to_encrypt <- "RAISETHEFLAG"
keyword <- "APPLE"

#  Get numeric codes for each character.
# Helper function to get the numeric code for each letter based on the Polybius matrix.
get_letter_code <- function(letter) {
  # Find the row and column index of the letter in the Polybius matrix.
  pos <- which(polybius == letter, arr.ind = TRUE)
  
  # If the letter exists in the matrix, return its row and column as a combined numeric code.
  if (length(pos) > 0) {
    return(c(pos[1] - 1, pos[2] - 1))  # Convert to 0-based indexing for consistency.
  }
  return(NA)  # Return NA if the letter is not found.
}

#  Convert each character in the message and the keyword to its numeric code.
# Split message and keyword into individual characters.
message_chars <- strsplit(message_to_encrypt, "")[[1]]
keyword_chars <- strsplit(keyword, "")[[1]]

# Get the numeric coordinates for each character in the message and keyword.
message_coords <- lapply(message_chars, get_letter_code)
keyword_coords <- lapply(rep(keyword_chars, length.out = length(message_chars)), get_letter_code)

#  Encrypt the message by adjusting with the keyword codes.
# Initialize an empty vector to store the encrypted result.
encrypted_result <- c()

# Loop through the message and keyword coordinates.
for (i in 1:length(message_coords)) {
  # Get the current message coordinates and corresponding keyword coordinates.
  msg_coord <- message_coords[[i]]
  key_coord <- keyword_coords[[i]]
  
  # Adjust the message coordinates using the keyword coordinates.
  new_row <- (msg_coord[1] + key_coord[1]) %% 4
  new_col <- (msg_coord[2] + key_coord[2]) %% 10
  
  # Combine the adjusted row and column into a single numeric code.
  new_code <- paste0(new_row, new_col)
  encrypted_result <- c(encrypted_result, new_code)
}

#  Format the encrypted ciphertext into groups of 5 digits.
# Combine the encrypted codes into a single string.
combined_encrypted <- paste(encrypted_result, collapse = "")
finaltext <- c()

# Split the combined string into segments of 5 characters.
for (j in seq(1, nchar(combined_encrypted), by = 5)) {
  part <- substr(combined_encrypted, j, j + 4)
  # If the group has fewer than 5 characters, add random digits to pad.
  if (nchar(part) < 5) {
    part <- paste0(part, paste0(sample(0:9, 5 - nchar(part), replace = TRUE), collapse = ""))
  }
  finaltext <- c(finaltext, part)
}


# Task 2.3 Decrypt the Ciphertext Using the Polybius Matrix 
# Objective: Decrypt the given ciphertext using the Polybius matrix.

# Define the ciphertext to be decrypted.
ciphertext <- c("48521", "82559", "53320", "83151", "44382", "13349", "40352", "42260", "48521", "84349", "48343", "23518")

# Combine the ciphertext into a single sequence of numbers.
combined_ciphertext <- paste(ciphertext, collapse = "")

#  Split the combined ciphertext into pairs of digits.
# Extract all pairs of two consecutive digits.
extracted_pairs <- c()
for (i in seq(1, nchar(combined_ciphertext), by = 2)) {
  extracted_pairs <- c(extracted_pairs, substr(combined_ciphertext, i, i + 1))
}


#Task 2.3 Decrypt the Encrypted Message Using the Keyword "LEMON"

# Ciphertext and keyword
ciphertext <- "48521 82559 53320 83151 44382 13349 40352 42260 48521 84349 48343 23518"
keyword <- "LEMON"

# Convert keyword to numeric values
keyword_numeric <- c()
for (char in unlist(strsplit(keyword, ""))) {
  match <- which(polybius == char, arr.ind = TRUE)
  if (nrow(match) > 0) {
    row <- match[1, 1] - 1  # Adjust for 0-based index
    col <- match[1, 2] - 1
    keyword_numeric <- c(keyword_numeric, row * 10 + col)
  }
}

# Split ciphertext into pairs
ciphertext_clean <- gsub(" ", "", ciphertext)
ciphertext_digits <- as.numeric(unlist(strsplit(ciphertext_clean, "")))
ciphertext_pairs <- matrix(ciphertext_digits, ncol = 2, byrow = TRUE)

# Decrypt ciphertext
plaintext <- ""
keyword_length <- length(keyword_numeric)

for (i in seq_len(nrow(ciphertext_pairs))) {
  cipher_value <- as.numeric(paste0(ciphertext_pairs[i, 1], ciphertext_pairs[i, 2]))
  key_adjustment <- keyword_numeric[(i - 1) %% keyword_length + 1]
  adjusted_value <- cipher_value - key_adjustment
  
  row <- floor(adjusted_value / 10)
  col <- adjusted_value %% 10
  
  if (row >= 0 && row <= 3 && col >= 0 && col <= 9) {
    letter <- polybius[row + 1, col + 1]
    if (letter != " ") {
      plaintext <- paste0(plaintext, letter)
    }
  }
}

print(plaintext)


#Task 2.2 Display the final formatted encrypted message.
print("Encrypted Message with Keyword 'APPLE':")
print(finaltext)


#TAsk 2.3 Display the decrypted message.
print("Decrypted Message:")
print(plaintext)

