From 4c0b2182c993453836eb2a0f194d21dc07a0060b Mon Sep 17 00:00:00 2001 From: Samuel Facchinello Date: Wed, 12 Jun 2024 16:35:08 +0200 Subject: [PATCH 1/6] fix to work --- .../com/thealgorithms/ciphers/ColumnarTranspositionCipher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java b/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java index e59cfb12d816..613f0f15b4a7 100644 --- a/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java +++ b/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java @@ -116,7 +116,7 @@ private static Object[][] tableBuilder(String word) { * order to respect the Columnar Transposition Cipher Rule. */ private static int numberOfRows(String word) { - if (word.length() / keyword.length() > word.length() / keyword.length()) { + if (word.length() / keyword.length() > keyword.length() / word.length()) { return (word.length() / keyword.length()) + 1; } else { return word.length() / keyword.length(); From 3a8ee9610652080b652ba9173cd1aa2a9742124f Mon Sep 17 00:00:00 2001 From: Samuel Facchinello Date: Wed, 12 Jun 2024 16:35:26 +0200 Subject: [PATCH 2/6] add tests --- .../ColumnarTranspositionCipherTest.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java diff --git a/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java b/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java new file mode 100644 index 000000000000..49fc51b10df9 --- /dev/null +++ b/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java @@ -0,0 +1,23 @@ +package com.thealgorithms.ciphers; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +class ColumnarTranspositionCipherTest { + + String keywordForExample = "asd215"; + String wordBeingEncrypted = "This is a test of the Columnar Transposition Cipher"; + + @Test + void encrpyter() { + assertNotEquals(wordBeingEncrypted, ColumnarTranspositionCipher.encrpyter(wordBeingEncrypted, keywordForExample)); + } + + @Test + void decrypter() { + String encrypted=ColumnarTranspositionCipher.encrpyter(wordBeingEncrypted, keywordForExample); + assertEquals(wordBeingEncrypted, ColumnarTranspositionCipher.decrypter()); + } +} From af5664eb70e1985302d3171e0bba8a91a7087bc2 Mon Sep 17 00:00:00 2001 From: Samuel Facchinello Date: Wed, 12 Jun 2024 17:05:59 +0200 Subject: [PATCH 3/6] refactor --- .../ciphers/ColumnarTranspositionCipher.java | 240 ++++++------------ .../ColumnarTranspositionCipherTest.java | 31 ++- 2 files changed, 103 insertions(+), 168 deletions(-) diff --git a/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java b/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java index 613f0f15b4a7..8ba14c5e0dcf 100644 --- a/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java +++ b/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java @@ -1,197 +1,121 @@ package com.thealgorithms.ciphers; -import java.util.Objects; +import java.util.Arrays; +import java.util.Comparator; /** * Columnar Transposition Cipher Encryption and Decryption. - * - * @author freitzzz */ -public final class ColumnarTranspositionCipher { - private ColumnarTranspositionCipher() { - } +public class ColumnarTranspositionCipher { - private static String keyword; - private static Object[][] table; - private static String abecedarium; - public static final String ABECEDARIUM = "abcdefghijklmnopqrstuvwxyzABCDEFG" - + "HIJKLMNOPQRSTUVWXYZ0123456789,.;:-@"; - private static final String ENCRYPTION_FIELD = "≈"; - private static final char ENCRYPTION_FIELD_CHAR = '≈'; + private static final char PADDING_CHAR = '≈'; /** - * Encrypts a certain String with the Columnar Transposition Cipher Rule + * Encrypts a message using the Columnar Transposition Cipher with the given key. * - * @param word Word being encrypted - * @param keyword String with keyword being used - * @return a String with the word encrypted by the Columnar Transposition - * Cipher Rule + * @param message The message to encrypt. + * @param key The key to use for encryption. + * @return The encrypted message. */ - public static String encrpyter(String word, String keyword) { - ColumnarTranspositionCipher.keyword = keyword; - abecedariumBuilder(500); - table = tableBuilder(word); - Object[][] sortedTable = sortTable(table); - StringBuilder wordEncrypted = new StringBuilder(); - for (int i = 0; i < sortedTable[i].length; i++) { - for (int j = 1; j < sortedTable.length; j++) { - wordEncrypted.append(sortedTable[j][i]); - } - } - return wordEncrypted.toString(); - } + public static String encrypt(String message, String key) { + int numColumns = key.length(); + int numRows = (int) Math.ceil((double) message.length() / numColumns); - /** - * Encrypts a certain String with the Columnar Transposition Cipher Rule - * - * @param word Word being encrypted - * @param keyword String with keyword being used - * @param abecedarium String with the abecedarium being used. null for - * default one - * @return a String with the word encrypted by the Columnar Transposition - * Cipher Rule - */ - public static String encrpyter(String word, String keyword, String abecedarium) { - ColumnarTranspositionCipher.keyword = keyword; - ColumnarTranspositionCipher.abecedarium = Objects.requireNonNullElse(abecedarium, ABECEDARIUM); - table = tableBuilder(word); - Object[][] sortedTable = sortTable(table); - StringBuilder wordEncrypted = new StringBuilder(); - for (int i = 0; i < sortedTable[0].length; i++) { - for (int j = 1; j < sortedTable.length; j++) { - wordEncrypted.append(sortedTable[j][i]); + char[][] grid = new char[numRows][numColumns]; + + // Fill the grid with the message and padding characters + fillGrid(message, grid, numRows, numColumns); + + // Get the sorted column order based on the key + Integer[] order = getColumnOrder(key); + + // Read columns in sorted order to build the encrypted message + StringBuilder encryptedMessage = new StringBuilder(); + for (int col : order) { + for (int row = 0; row < numRows; row++) { + encryptedMessage.append(grid[row][col]); } } - return wordEncrypted.toString(); + + return encryptedMessage.toString(); } /** - * Decrypts a certain encrypted String with the Columnar Transposition - * Cipher Rule + * Decrypts a message that was encrypted using the Columnar Transposition Cipher with the given key. * - * @return a String decrypted with the word encrypted by the Columnar - * Transposition Cipher Rule + * @param message The encrypted message. + * @param key The key used for encryption. + * @return The decrypted message. */ - public static String decrypter() { - StringBuilder wordDecrypted = new StringBuilder(); - for (int i = 1; i < table.length; i++) { - for (Object item : table[i]) { - wordDecrypted.append(item); + public static String decrypt(String message, String key) { + int numColumns = key.length(); + int numRows = (int) Math.ceil((double) message.length() / numColumns); + + char[][] grid = new char[numRows][numColumns]; + + // Get the sorted column order based on the key + Integer[] order = getColumnOrder(key); + + // Fill the grid by columns based on the sorted order + int index = 0; + for (int col : order) { + for (int row = 0; row < numRows; row++) { + grid[row][col] = message.charAt(index++); } } - return wordDecrypted.toString().replaceAll(ENCRYPTION_FIELD, ""); - } - /** - * Builds a table with the word to be encrypted in rows by the Columnar - * Transposition Cipher Rule - * - * @return An Object[][] with the word to be encrypted filled in rows and - * columns - */ - private static Object[][] tableBuilder(String word) { - Object[][] table = new Object[numberOfRows(word) + 1][keyword.length()]; - char[] wordInChards = word.toCharArray(); - // Fils in the respective numbers - table[0] = findElements(); - int charElement = 0; - for (int i = 1; i < table.length; i++) { - for (int j = 0; j < table[i].length; j++) { - if (charElement < wordInChards.length) { - table[i][j] = wordInChards[charElement]; - charElement++; - } else { - table[i][j] = ENCRYPTION_FIELD_CHAR; + // Read the grid row by row to get the decrypted message, removing padding + StringBuilder decryptedMessage = new StringBuilder(); + for (int row = 0; row < numRows; row++) { + for (int col = 0; col < numColumns; col++) { + char c = grid[row][col]; + if (c != PADDING_CHAR) { + decryptedMessage.append(c); } } } - return table; - } - /** - * Determines the number of rows the table should have regarding the - * Columnar Transposition Cipher Rule - * - * @return an int with the number of rows that the table should have in - * order to respect the Columnar Transposition Cipher Rule. - */ - private static int numberOfRows(String word) { - if (word.length() / keyword.length() > keyword.length() / word.length()) { - return (word.length() / keyword.length()) + 1; - } else { - return word.length() / keyword.length(); - } - } - - /** - * @return charValues - */ - private static Object[] findElements() { - Object[] charValues = new Object[keyword.length()]; - for (int i = 0; i < charValues.length; i++) { - int charValueIndex = abecedarium.indexOf(keyword.charAt(i)); - charValues[i] = charValueIndex > -1 ? charValueIndex : null; - } - return charValues; + return decryptedMessage.toString(); } /** - * @return tableSorted + * Fills the grid with the message and padding characters. + * + * @param message The message to encrypt. + * @param grid The grid to fill. + * @param numRows The number of rows in the grid. + * @param numColumns The number of columns in the grid. */ - private static Object[][] sortTable(Object[][] table) { - Object[][] tableSorted = new Object[table.length][table[0].length]; - for (int i = 0; i < tableSorted.length; i++) { - System.arraycopy(table[i], 0, tableSorted[i], 0, tableSorted[i].length); - } - for (int i = 0; i < tableSorted[0].length; i++) { - for (int j = i + 1; j < tableSorted[0].length; j++) { - if ((int) tableSorted[0][i] > (int) table[0][j]) { - Object[] column = getColumn(tableSorted, tableSorted.length, i); - switchColumns(tableSorted, j, i, column); + private static void fillGrid(String message, char[][] grid, int numRows, int numColumns) { + int index = 0; + for (int row = 0; row < numRows; row++) { + for (int col = 0; col < numColumns; col++) { + if (index < message.length()) { + grid[row][col] = message.charAt(index++); + } else { + grid[row][col] = PADDING_CHAR; } } } - return tableSorted; - } - - /** - * @return columnArray - */ - private static Object[] getColumn(Object[][] table, int rows, int column) { - Object[] columnArray = new Object[rows]; - for (int i = 0; i < rows; i++) { - columnArray[i] = table[i][column]; - } - return columnArray; - } - - private static void switchColumns(Object[][] table, int firstColumnIndex, int secondColumnIndex, Object[] columnToSwitch) { - for (int i = 0; i < table.length; i++) { - table[i][secondColumnIndex] = table[i][firstColumnIndex]; - table[i][firstColumnIndex] = columnToSwitch[i]; - } } /** - * Creates an abecedarium with a specified ascii inded + * Gets the order of the columns based on the sorted key characters. * - * @param value Number of characters being used based on the ASCII Table + * @param key The key to use for sorting. + * @return An array containing the order of the columns. */ - private static void abecedariumBuilder(int value) { - StringBuilder t = new StringBuilder(); - for (int i = 0; i < value; i++) { - t.append((char) i); - } - abecedarium = t.toString(); - } + private static Integer[] getColumnOrder(String key) { + Integer[] order = new Integer[key.length()]; + Character[] keyChars = new Character[key.length()]; - private static void showTable() { - for (Object[] table1 : table) { - for (Object item : table1) { - System.out.print(item + " "); - } - System.out.println(); + for (int i = 0; i < key.length(); i++) { + order[i] = i; + keyChars[i] = key.charAt(i); } + + Arrays.sort(order, Comparator.comparingInt(o -> keyChars[o])); + return order; } public static void main(String[] args) { @@ -199,9 +123,9 @@ public static void main(String[] args) { String wordBeingEncrypted = "This is a test of the Columnar Transposition Cipher"; System.out.println("### Example of Columnar Transposition Cipher ###\n"); System.out.println("Word being encryped ->>> " + wordBeingEncrypted); - System.out.println("Word encrypted ->>> " + ColumnarTranspositionCipher.encrpyter(wordBeingEncrypted, keywordForExample)); - System.out.println("Word decryped ->>> " + ColumnarTranspositionCipher.decrypter()); - System.out.println("\n### Encrypted Table ###"); - showTable(); + String encryptedMessage = ColumnarTranspositionCipher.encrypt(wordBeingEncrypted, keywordForExample); + System.out.println("Word encrypted ->>> " + encryptedMessage); + System.out.println("Word decryped ->>> " + ColumnarTranspositionCipher.decrypt(encryptedMessage, keywordForExample)); + } } diff --git a/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java b/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java index 49fc51b10df9..04cdb7f38d3b 100644 --- a/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java +++ b/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java @@ -1,23 +1,34 @@ package com.thealgorithms.ciphers; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; class ColumnarTranspositionCipherTest { - String keywordForExample = "asd215"; - String wordBeingEncrypted = "This is a test of the Columnar Transposition Cipher"; + @ParameterizedTest + @MethodSource("provideTestCases") + void encrypt(String key, String word) { + assertNotEquals(word, ColumnarTranspositionCipher.encrypt(word, key)); + } - @Test - void encrpyter() { - assertNotEquals(wordBeingEncrypted, ColumnarTranspositionCipher.encrpyter(wordBeingEncrypted, keywordForExample)); + @ParameterizedTest + @MethodSource("provideTestCases") + void decrypt(String key, String word) { + String encrypted = ColumnarTranspositionCipher.encrypt(word, key); + assertEquals(word, ColumnarTranspositionCipher.decrypt(encrypted, key)); } - @Test - void decrypter() { - String encrypted=ColumnarTranspositionCipher.encrpyter(wordBeingEncrypted, keywordForExample); - assertEquals(wordBeingEncrypted, ColumnarTranspositionCipher.decrypter()); + private static Stream provideTestCases() { + return Stream.of(Arguments.of("asd215", "This is a test of the Columnar Transposition Cipher"), // + Arguments.of("test123456", "test"), // + Arguments.of("my long secret pass 1234567890", "short message"), // + Arguments.of("secret", "My secret message") // + ); } } From 7f441c6da1c0b35f11af2cbbbe29bb0cd119bd16 Mon Sep 17 00:00:00 2001 From: Samuel Facchinello Date: Wed, 12 Jun 2024 17:10:45 +0200 Subject: [PATCH 4/6] fix clang --- .../ciphers/ColumnarTranspositionCipherTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java b/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java index 04cdb7f38d3b..56056fa73caa 100644 --- a/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java +++ b/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java @@ -26,9 +26,9 @@ void decrypt(String key, String word) { private static Stream provideTestCases() { return Stream.of(Arguments.of("asd215", "This is a test of the Columnar Transposition Cipher"), // - Arguments.of("test123456", "test"), // - Arguments.of("my long secret pass 1234567890", "short message"), // - Arguments.of("secret", "My secret message") // + Arguments.of("test123456", "test"), // + Arguments.of("my long secret pass 1234567890", "short message"), // + Arguments.of("secret", "My secret message") // ); } } From 5e348425324bc813067b4139743bba7b35883681 Mon Sep 17 00:00:00 2001 From: Samuel Facchinello Date: Wed, 12 Jun 2024 17:13:42 +0200 Subject: [PATCH 5/6] fix clang --- .../ciphers/ColumnarTranspositionCipher.java | 3 +++ .../ciphers/ColumnarTranspositionCipherTest.java | 9 ++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java b/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java index 8ba14c5e0dcf..9fedc854b75a 100644 --- a/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java +++ b/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java @@ -10,6 +10,9 @@ public class ColumnarTranspositionCipher { private static final char PADDING_CHAR = '≈'; + private ColumnarTranspositionCipher() { + } + /** * Encrypts a message using the Columnar Transposition Cipher with the given key. * diff --git a/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java b/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java index 56056fa73caa..cb52622d168b 100644 --- a/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java +++ b/src/test/java/com/thealgorithms/ciphers/ColumnarTranspositionCipherTest.java @@ -1,14 +1,13 @@ package com.thealgorithms.ciphers; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; - class ColumnarTranspositionCipherTest { @ParameterizedTest From fd8baf4949465a7db3b9fe4933fd4c5a8954ea15 Mon Sep 17 00:00:00 2001 From: Samuel Facchinello Date: Wed, 12 Jun 2024 17:26:29 +0200 Subject: [PATCH 6/6] fix clang --- .../ciphers/ColumnarTranspositionCipher.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java b/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java index 9fedc854b75a..6f468766bfba 100644 --- a/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java +++ b/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java @@ -6,7 +6,7 @@ /** * Columnar Transposition Cipher Encryption and Decryption. */ -public class ColumnarTranspositionCipher { +public final class ColumnarTranspositionCipher { private static final char PADDING_CHAR = '≈'; @@ -120,15 +120,4 @@ private static Integer[] getColumnOrder(String key) { Arrays.sort(order, Comparator.comparingInt(o -> keyChars[o])); return order; } - - public static void main(String[] args) { - String keywordForExample = "asd215"; - String wordBeingEncrypted = "This is a test of the Columnar Transposition Cipher"; - System.out.println("### Example of Columnar Transposition Cipher ###\n"); - System.out.println("Word being encryped ->>> " + wordBeingEncrypted); - String encryptedMessage = ColumnarTranspositionCipher.encrypt(wordBeingEncrypted, keywordForExample); - System.out.println("Word encrypted ->>> " + encryptedMessage); - System.out.println("Word decryped ->>> " + ColumnarTranspositionCipher.decrypt(encryptedMessage, keywordForExample)); - - } }