# Question 1
# Define the Polybius matrix
# Create a Polybius matrix with characters arranged row by row.
# Each cell contains a character from the cipher. The matrix dimensions are 4 rows and 10 columns.

polybius <- matrix(c(" ", "Z", "M", "D", " ", "K", "W", "Q", " ", "G", # First row of the matrix
                     "V", " ", "A", " ", "R", " ", "E", " ", "T", "O", # Second row of the matrix
                     " ", "J", "I", "S", "B", "P", "Y", " ", "F", " ", # Third row of the matrix
                     "L", " ", " ", "C", " ", "U", "H", "N", " ", "X"), # Fourth row of the matrix
                   nrow = 4, byrow = TRUE)                              # Arrange the matrix with 4 rows and fill by rows.


# Assign row names to the matrix. These row names represent the 0-based indexing for rows (0 to 3).
rownames(polybius) <- 0:3                                                        # Assign row names 


# Assign column names to the matrix. These column names represent the 0-based indexing for columns (0 to 9).
colnames(polybius) <- 0:9                                                        # Assign column names


# Display the Polybius matrix for reference. This allows you to see how characters are mapped to row and column indices.
polybius



#Question 2
# Step 1: Encrypt the message using the keyword "APPLE"
# Define the message and keyword to be used for encryption
message <- c("R", "A", "I", "S", "E", "T", "H", "E", "F", "L", "A", "G")
keyword <- c("A", "P", "P", "L", "E")


# Step 2: Get the coordinates for the message and keyword using the Polybius matrix
# Define a function to find the row and column coordinates of a character in the Polybius matrix.
# This function takes a single character as input and searches the matrix.
get_coordinates <- function(char) {
  for (i in 1:4) {
    for (j in 1:10) {
      if (polybius[i, j] == char) {
        return(c(i - 1, j - 1))  # Convert to 0-based indexing
      }
    }
  }
  return(NA)  # Return NA if character not found
}

# Get coordinates for the message
message_coords <- lapply(message, get_coordinates)
# Get coordinates for the keyword, using it cyclically
keyword_length <- length(keyword)
keyword_coords <- lapply(rep(keyword, length.out = length(message)), get_coordinates)

# Step 3: Encrypt the message using keyword adjustment
ciphertext <- c()

for (i in 1:length(message)) {
  message_coord <- message_coords[[i]]
  keyword_coord <- keyword_coords[[i]]
  
  # Adjust the coordinates using keyword
  adjusted_row <- (message_coord[1] + keyword_coord[1]) %% 4
  adjusted_col <- (message_coord[2] + keyword_coord[2]) %% 10
  
  # Combine row and column into the cipher code
  code <- paste0(adjusted_row, adjusted_col)
  ciphertext <- c(ciphertext, code)
}

# Step 4: Combine ciphertext into a single string and split into groups of 5 digits
ciphertext_string <- paste(ciphertext, collapse = "")
finaltext <- c()
for (i in seq(1, nchar(ciphertext_string), by = 5)) {
  group <- substr(ciphertext_string, i, i + 4)
  finaltext <- c(finaltext, group)
}

# Step 5: Print the final encrypted message
finaltext



#Question 3
# Input ciphertext and the decryption keyword

ciphertext <- "48521 82559 53320 83151 44382 13349 40352 42260 48521 84349 48343 23518"

# Define the keyword
keyword <- "LEMON"

# Split the ciphertext into pairs of digits
ciphertext_pairs <- as.numeric(unlist(strsplit(gsub(" ", "", ciphertext), ""))) # Flattened into pairs


# Convert the keyword to numeric values using the Polybius matrix
keyword_numeric <- c()
for (char in unlist(strsplit(keyword, ""))) {
  for (row in 0:3) {
    for (col in 0:9) {
      if (polybius[row + 1, col + 1] == char) {
        keyword_numeric <- c(keyword_numeric, row * 10 + col)
      }
    }
  }
}

# Initialize variables
plaintext <- "" # To store the final plaintext
keyword_length <- length(keyword_numeric)

# Decryption loop
for (i in seq(1, length(ciphertext_pairs), by = 2)) {
  # Get the current ciphertext pair and keyword adjustment
  cipher_value <- as.numeric(paste0(ciphertext_pairs[i], ciphertext_pairs[i + 1])) # Combine two digits
  key_adjustment <- keyword_numeric[((i - 1) %/% 2) %% keyword_length + 1] # Cycle through the keyword
  
  # Adjust the cipher value
  adjusted_value <- cipher_value - key_adjustment
  
  # Determine row and column
  row <- floor(adjusted_value / 10) # First digit is the row
  col <- adjusted_value %% 10       # Second digit is the column
  
  # Ensure valid indices
  if (row >= 0 && row <= 3 && col >= 0 && col <= 9) {
    # Fetch the letter from the Polybius matrix
    letter <- polybius[row + 1, col + 1] # +1 for R indexing
    if (letter != " ") { # Ignore spaces
      plaintext <- paste0(plaintext, letter)
    }
  }
}

# Print the final plaintext
plaintext

