#TASK 1


# Step 1: Define the Polybius matrix
# The Polybius square is a 4x10 grid of characters used for encryption.
# Each character is assigned a unique position in the grid (row and column).
# Spaces and some letters are included to fill the grid.


Polybius <- matrix(
  c(" ", "Z", "M ", "D", " ", "K", "W", "Q", " ", "G",  # First row
    "V", " ", "A", " ", "R", " ", "E", " ", "T", "O",   # Second row
    " ", "J", "I", "S", "B", "P", "Y", " ", "F", " ",   # Third row
    "L", " ", " ", "C", " ", "U", "H", "N", " ", "X"),  # Fourth row
  nrow = 4, byrow = TRUE  # Specify that the matrix has 4 rows and fill it row by row
)



# Display the Polybius matrix as output to verify its correctness
print("Polybius matrix:")
print(Polybius)



# Assign row and column names for easier reference
# Rows are labeled 0, 1, 2, 3 and columns are labeled 0–9 to simulate the Polybius coordinate system.
rownames(Polybius) <- 0:3
colnames(Polybius) <- 0:9



# Print the Polybius matrix with the assigned row and column names for clarity
Polybius  # Output the matrix



# Step 2: Encrypt the message
# Define the plaintext message to be encrypted
# This is the message we want to encode into a sequence of coordinates.
message <- "CAPTURETHEFORT"



# Break the message into individual characters
# The `substring` function extracts one character at a time and stores them in a vector.
message_vector <- substring(message, 1:nchar(message), 1:nchar(message))



# Print the vector to confirm the message has been split into individual characters
print(message_vector)



# Initialize an empty vector to store the encrypted coordinates (ciphertext)
ciphertext <- c()



# Loop through each character in the message to encrypt it
for (char in message_vector) {
  # Nested loops to iterate through the Polybius matrix
  # Outer loop: Go through each row of the matrix
  for (i in 1:nrow(Polybius)) {
    # Inner loop: Go through each column of the matrix
    for (j in 1:ncol(Polybius)) {
      # Check if the current matrix cell matches the character to be encrypted
      if (Polybius[i, j] == char) {
        # If a match is found, determine its coordinates
        # Adjust row and column indices to be 0-indexed (as specified by Polybius rules)
        code <- paste0(i - 1, j - 1)
        
        # Add the resulting code to the ciphertext vector
        ciphertext <- c(ciphertext, code)
      }
    }
  }
}



# Print the resulting ciphertext as a vector of coordinate pairs
# Each pair represents a character from the original message.
print("Ciphertext vector:")
print(ciphertext)



# Step 3: Format the ciphertext into groups of 5 characters
# Combine the coordinates into a single string for formatting
# The `paste` function joins the elements of the vector into one continuous string.
ciphertext_str <- paste(ciphertext, collapse = "")



# Initialize an empty string to store the final formatted ciphertext
finaltext <- ""



# Split the ciphertext string into groups of 5 characters for readability
# Use a loop to extract substrings of 5 characters at a time.
for (i in seq(1, nchar(ciphertext_str), by = 5)) {
  # Extract a substring of 5 characters starting at position `i`
  group <- substr(ciphertext_str, i, i + 4)
  
  
  
  # If the last group is less than 5 characters, pad it with random digits
  # This ensures all groups have exactly 5 characters.
  if (nchar(group) < 5) {
    # Generate random digits (0–9) to fill the group
    padding <- paste0(sample(0:9, 5 - nchar(group), replace = TRUE), collapse = "")
    group <- paste0(group, padding)  # Add the padding to the group
  }
  
  # Add the formatted group to the finaltext
  finaltext <- c(finaltext, group)
}



# Print the final formatted ciphertext as an array of groups
# Each group contains 5 characters for easier reading.
print("Formatted Finaltext:")
print(finaltext)




#TASK 2


# 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


