# Define the Polybius matrix

# Creating the same 4x10 matrix to use as the Polybius square for decryption.
polybius <- matrix(c(" ", "Z", "M", "D", " ", "K", "W", "Q", " ", "G", 
                     "V", " ", "A", " ", "R", " ", "E", " ", "T", "O", 
                     " ", "J", "I", "S", "B", "P", "Y", " ", "F", " ", 
                     "L", " ", " ", "C", " ", "U", "H", "N", " ", "X"), 
                   nrow = 4, byrow = TRUE)

# Assign row and column labels to easily reference the grid.
rownames(polybius) <- 0:3
colnames(polybius) <- 0:9

# Display the Polybius grid for reference.
polybius

# Start of Decryption Task


# Step 1: Define the given ciphertext for decryption


# Define the ciphertext which consists of encoded pairs representing characters in the Polybius matrix.
cipher_values <- c("24160", "63616", "14162", "61935", "14163", "71602", "26222", "33719", "18008")


# Step 2: Combine the ciphertext into a single sequence


# Join all elements of the ciphertext into a continuous string.
cipher_combined <- paste(cipher_values, collapse = "")


# Step 3: Decrypt the ciphertext


# Initialize an empty vector to collect the decrypted characters.
decrypted_chars <- c()

# Loop through each pair of numbers in the combined ciphertext.
for (x in seq(1, nchar(cipher_combined), by = 2)) {
  # Extract the row and column from each pair of digits.
  row <- as.integer(substr(cipher_combined, x, x))
  col <- as.integer(substr(cipher_combined, x + 1, x + 1))
  
  # Verify that row and column values are within the correct range.
  if (!is.na(row) && !is.na(col) && row >= 0 && row <= 3 && col >= 0 && col <= 9) {
    # Retrieve the corresponding character from the Polybius grid and append it to the decrypted text.
    character <- polybius[row + 1, col + 1]
    decrypted_chars <- c(decrypted_chars, character)
  } else {
    # Handle invalid indices by appending a placeholder symbol.
    decrypted_chars <- c(decrypted_chars, "!")
  }
}


# Step 4: Combine decrypted characters into a single string


# Combine all the characters into a single plaintext string.
plaintext <- paste(decrypted_chars, collapse = "")


# Step 5: Display the decrypted message


# Print the final decrypted plaintext message.
plaintext

#Q.2 ---> Solution 
# Define the message and keyword
msg <- "RAISETHEFLAG"  # Input plaintext message
key <- "APPLE"         # Keyword for encryption

msg_letters <- unlist(strsplit(msg, ""))  # Split the message into individual characters
key_letters <- unlist(strsplit(key, ""))  # Split the keyword into individual characters

msg_coords <- numeric()  # Initialize vector for storing message coordinates
for (char in msg_letters) {  # Loop through each character in the message
  for (row in 0:3) {
    for (col in 0:9) {
      if (polybius[row + 1, col + 1] == char) {  # Match character in Polybius matrix
        msg_coords <- c(msg_coords, row * 10 + col)  # Compute numeric coordinates
      }
    }
  }
}

repeated_key <- rep(key_letters, length.out = length(msg_letters))  # Repeat keyword
key_coords <- numeric()  # Initialize vector for storing keyword coordinates
for (char in repeated_key) {  # Loop through each repeated character
  for (row in 0:3) {
    for (col in 0:9) {
      if (polybius[row + 1, col + 1] == char) {  # Match character in Polybius matrix
        key_coords <- c(key_coords, row * 10 + col)  # Compute numeric coordinates
      }
    }
  }
}

cipher_coords <- numeric()  # Initialize vector for ciphertext coordinates
i <- 1
while (i <= length(msg_coords)) {  # Use a while loop for encryption
  cipher_coords <- c(cipher_coords, msg_coords[i] + key_coords[i])  # Add coordinates
  i <- i + 1
}

ciphertext <- paste(cipher_coords, collapse = "")  # Combine coordinates into a single string
final_blocks <- c()  # Initialize vector for ciphertext blocks
start <- 1
while (start <= nchar(ciphertext)) {  # Use while loop to split into blocks
  block <- substring(ciphertext, start, start + 4)  # Extract 5-character block
  if (nchar(block) < 5) {  # Add padding if the block is shorter than 5 characters
    block <- paste0(block, paste(sample(0:9, 5 - nchar(block), replace = TRUE), collapse = ""))
  }
  final_blocks <- c(final_blocks, block)  # Append block to final output
  start <- start + 5
}

final_blocks

#Q.3 ---> Solution 
cipher <- "48521 82559 53320 83151 44382 13349 40352 42260 48521 84349 48343 23518"
key <- "LEMON"  # Keyword used for decryption

# Clean and process the ciphertext
cipher_clean <- gsub(" ", "", cipher)  # Remove spaces from ciphertext
cipher_pairs <- c()  # Initialize an empty vector for pairs

start <- 1
while (start < nchar(cipher_clean)) {  # Use a while loop to extract 2-digit pairs
  pair <- substr(cipher_clean, start, start + 1)  # Extract 2 characters at a time
  cipher_pairs <- c(cipher_pairs, as.numeric(pair))  # Append to vector as numeric
  start <- start + 2
}

key_nums <- numeric()  # Initialize vector for keyword numeric equivalents
for (k in unlist(strsplit(key, ""))) {  # Loop through each character in the keyword
  for (r in 0:3) {
    for (c in 0:9) {
      if (polybius[r + 1, c + 1] == k) {  # Match character in Polybius matrix
        key_nums <- c(key_nums, r * 10 + c)  # Append numeric equivalent
      }
    }
  }
}

deciphered_text <- ""  # Initialize an empty string for the plaintext
key_len <- length(key_nums)  # Length of the keyword's numeric sequence

for (i in seq_along(cipher_pairs)) {  # Loop through all ciphertext pairs
  c_val <- cipher_pairs[i]  # Current ciphertext pair value
  k_val <- key_nums[(i - 1) %% key_len + 1]  # Cycle through keyword numeric values
  
  # Adjust cipher value by subtracting keyword numeric value
  adjusted <- c_val - k_val
  if (adjusted < 0) {  # Handle negative values by wrapping around
    adjusted <- adjusted + 40
  }
  
  # Extract row and column from adjusted value
  a <- adjusted %/% 10  # Integer division for row
  b <- adjusted %% 10   # Modulo operation for column
  
  # Fetch the corresponding letter from the Polybius matrix
  letter <- polybius[a + 1, b + 1]
  if (letter != " ") {  # Ignore spaces in the matrix
    deciphered_text <- paste0(deciphered_text, letter)  # Append the letter to plaintext
  }
}

deciphered_text  # Expected Output: "THEWISEWARRIORAVOIDSTHEBATTLEJ"