Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e493eb2
Add Edmonds Blossom Algorithm (#5471)
TarunVishwakarma1 Oct 2, 2024
013d122
feat: add recursion subsets (#5503)
Tuhinm2002 Oct 2, 2024
d436910
Sorted Linked List Added (#5519)
mjk22071998 Oct 3, 2024
ea0ed23
feat: removing duplicate implementation of Dutch National Flag Sort A…
sailok Oct 3, 2024
ce6d98f
Add Merge Intervals algorithm (#5516)
Hardvan Oct 3, 2024
7b934af
Improve comments, add function documentation in BinarySearch2dArray.j…
Hardvan Oct 3, 2024
48a2980
feat: Remove duplicate implementation of Dutch National Flag Sort Alg…
sailok Oct 3, 2024
be8df21
Adds Longest Arithmetic Subsequence Implementation (#5501)
tejaswi0910 Oct 3, 2024
12ea53e
Added algorithm for swapping linkedlist nodes
Aashu-11 Oct 3, 2024
66ee59c
Add function documentation in `Sudoku.java` (#5532)
Hardvan Oct 4, 2024
41f767e
Add XOR Cipher (#5490)
lcsjunior Oct 4, 2024
de22158
Add tests for `SkylineAlgorithm.java` (#5556)
Hardvan Oct 4, 2024
5cbdb47
Add digit separation for large integers (#5543)
mjk22071998 Oct 4, 2024
b61c547
Add `Infix To Prefix` new algorithm with unit tests (#5537)
Hardvan Oct 4, 2024
ea6457b
Add `PrefixToInfix.java` new algorithm (#5552)
Hardvan Oct 4, 2024
389d1d7
feat: add conversion logic from integer to english (#5540)
sailok Oct 4, 2024
393337f
Add Tests for HillCipher (#5562)
bennybebo Oct 4, 2024
042d458
fix: change location of others to correct places (#5559)
BKarthik7 Oct 4, 2024
02ed610
Chore(deps-dev): bump org.junit.jupiter:junit-jupiter-api from 5.11.1…
dependabot[bot] Oct 4, 2024
e7c855b
Chore(deps-dev): bump org.junit.jupiter:junit-jupiter from 5.11.1 to …
dependabot[bot] Oct 4, 2024
87871ef
Chore(deps): bump org.junit:junit-bom from 5.11.1 to 5.11.2 (#5571)
dependabot[bot] Oct 4, 2024
80e99ec
Merge branch 'master' into Aashu-11-patch-2
Aashu-11 Oct 5, 2024
ce34595
Improve `TrieImp.java` comments & enhance readability (#5526)
Hardvan Oct 5, 2024
5d77c11
Merge branch 'master' into Aashu-11-patch-2
Aashu-11 Oct 5, 2024
3390273
Improve comments in `SumOfSubset.java` (#5514)
Hardvan Oct 5, 2024
f34fe4d
Enhance comments & improve readability in `LongestCommonSubsequence.j…
Hardvan Oct 5, 2024
8e4d9a9
Merge branch 'master' into Aashu-11-patch-2
Aashu-11 Oct 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 37 additions & 13 deletions DIRECTORY.md

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.11.1</version>
<version>5.11.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Expand All @@ -31,7 +31,7 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.11.1</version>
<version>5.11.2</version>
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -44,7 +44,7 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.11.1</version>
<version>5.11.2</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
36 changes: 36 additions & 0 deletions src/main/java/com/thealgorithms/Recursion/GenerateSubsets.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.thealgorithms.Recursion;

// program to find power set of a string

import java.util.ArrayList;
import java.util.List;

public final class GenerateSubsets {

private GenerateSubsets() {
throw new UnsupportedOperationException("Utility class");
}

public static List<String> subsetRecursion(String str) {
return doRecursion("", str);
}

private static List<String> doRecursion(String p, String up) {
if (up.isEmpty()) {
List<String> list = new ArrayList<>();
list.add(p);
return list;
}

// Taking the character
char ch = up.charAt(0);
// Adding the character in the recursion
List<String> left = doRecursion(p + ch, up.substring(1));
// Not adding the character in the recursion
List<String> right = doRecursion(p, up.substring(1));

left.addAll(right);

return left;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.thealgorithms.others;
package com.thealgorithms.bitmanipulation;

public class CountSetBits {

Expand Down
213 changes: 69 additions & 144 deletions src/main/java/com/thealgorithms/ciphers/HillCipher.java
Original file line number Diff line number Diff line change
@@ -1,178 +1,103 @@
package com.thealgorithms.ciphers;

import java.util.Scanner;
public class HillCipher {

/*
* Java Implementation of Hill Cipher
* Hill cipher is a polyalphabetic substitution cipher. Each letter is represented by a number
* belonging to the set Z26 where A=0 , B=1, ..... Z=25. To encrypt a message, each block of n
* letters (since matrix size is n x n) is multiplied by an invertible n × n matrix, against
* modulus 26. To decrypt the message, each block is multiplied by the inverse of the matrix used
* for encryption. The cipher key and plaintext/ciphertext are user inputs.
* @author Ojasva Jain
*/
public final class HillCipher {
private HillCipher() {
}

static Scanner userInput = new Scanner(System.in);

/* Following function encrypts the message
*/
static void encrypt(String message) {
message = message.toUpperCase();
// Get key matrix
System.out.println("Enter key matrix size");
int matrixSize = userInput.nextInt();
System.out.println("Enter Key/encryptionKey matrix ");
int[][] keyMatrix = new int[matrixSize][matrixSize];
for (int i = 0; i < matrixSize; i++) {
for (int j = 0; j < matrixSize; j++) {
keyMatrix[i][j] = userInput.nextInt();
}
}
// check if det = 0
// Encrypts the message using the key matrix
public String encrypt(String message, int[][] keyMatrix) {
message = message.toUpperCase().replaceAll("[^A-Z]", "");
int matrixSize = keyMatrix.length;
validateDeterminant(keyMatrix, matrixSize);

int[][] messageVector = new int[matrixSize][1];
String cipherText = "";
int[][] cipherMatrix = new int[matrixSize][1];
int j = 0;
while (j < message.length()) {
StringBuilder cipherText = new StringBuilder();
int[] messageVector = new int[matrixSize];
int[] cipherVector = new int[matrixSize];
int index = 0;

while (index < message.length()) {
for (int i = 0; i < matrixSize; i++) {
if (j >= message.length()) {
messageVector[i][0] = 23;
if (index < message.length()) {
messageVector[i] = message.charAt(index++) - 'A';
} else {
messageVector[i][0] = (message.charAt(j)) % 65;
messageVector[i] = 'X' - 'A'; // Padding with 'X' if needed
}
System.out.println(messageVector[i][0]);
j++;
}
int x;
int i;
for (i = 0; i < matrixSize; i++) {
cipherMatrix[i][0] = 0;

for (x = 0; x < matrixSize; x++) {
cipherMatrix[i][0] += keyMatrix[i][x] * messageVector[x][0];
for (int i = 0; i < matrixSize; i++) {
cipherVector[i] = 0;
for (int j = 0; j < matrixSize; j++) {
cipherVector[i] += keyMatrix[i][j] * messageVector[j];
}
System.out.println(cipherMatrix[i][0]);
cipherMatrix[i][0] = cipherMatrix[i][0] % 26;
}
for (i = 0; i < matrixSize; i++) {
cipherText += (char) (cipherMatrix[i][0] + 65);
cipherVector[i] = cipherVector[i] % 26;
cipherText.append((char) (cipherVector[i] + 'A'));
}
}
System.out.println("Ciphertext: " + cipherText);

return cipherText.toString();
}

// Following function decrypts a message
static void decrypt(String message) {
message = message.toUpperCase();
// Get key matrix
System.out.println("Enter key matrix size");
int n = userInput.nextInt();
System.out.println("Enter inverseKey/decryptionKey matrix ");
int[][] keyMatrix = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
keyMatrix[i][j] = userInput.nextInt();
}
}
// check if det = 0
validateDeterminant(keyMatrix, n);
// Decrypts the message using the inverse key matrix
public String decrypt(String message, int[][] inverseKeyMatrix) {
message = message.toUpperCase().replaceAll("[^A-Z]", "");
int matrixSize = inverseKeyMatrix.length;
validateDeterminant(inverseKeyMatrix, matrixSize);

StringBuilder plainText = new StringBuilder();
int[] messageVector = new int[matrixSize];
int[] plainVector = new int[matrixSize];
int index = 0;

// solving for the required plaintext message
int[][] messageVector = new int[n][1];
String plainText = "";
int[][] plainMatrix = new int[n][1];
int j = 0;
while (j < message.length()) {
for (int i = 0; i < n; i++) {
if (j >= message.length()) {
messageVector[i][0] = 23;
while (index < message.length()) {
for (int i = 0; i < matrixSize; i++) {
if (index < message.length()) {
messageVector[i] = message.charAt(index++) - 'A';
} else {
messageVector[i][0] = (message.charAt(j)) % 65;
messageVector[i] = 'X' - 'A'; // Padding with 'X' if needed
}
System.out.println(messageVector[i][0]);
j++;
}
int x;
int i;
for (i = 0; i < n; i++) {
plainMatrix[i][0] = 0;

for (x = 0; x < n; x++) {
plainMatrix[i][0] += keyMatrix[i][x] * messageVector[x][0];
for (int i = 0; i < matrixSize; i++) {
plainVector[i] = 0;
for (int j = 0; j < matrixSize; j++) {
plainVector[i] += inverseKeyMatrix[i][j] * messageVector[j];
}

plainMatrix[i][0] = plainMatrix[i][0] % 26;
}
for (i = 0; i < n; i++) {
plainText += (char) (plainMatrix[i][0] + 65);
plainVector[i] = plainVector[i] % 26;
plainText.append((char) (plainVector[i] + 'A'));
}
}
System.out.println("Plaintext: " + plainText);

return plainText.toString();
}

// Determinant calculator
public static int determinant(int[][] a, int n) {
int det = 0;
int sign = 1;
int p = 0;
int q = 0;
// Validates that the determinant of the key matrix is not zero modulo 26
private void validateDeterminant(int[][] keyMatrix, int n) {
int det = determinant(keyMatrix, n) % 26;
if (det == 0) {
throw new IllegalArgumentException("Invalid key matrix. Determinant is zero modulo 26.");
}
}

// Computes the determinant of a matrix recursively
private int determinant(int[][] matrix, int n) {
int det = 0;
if (n == 1) {
det = a[0][0];
} else {
int[][] b = new int[n - 1][n - 1];
for (int x = 0; x < n; x++) {
p = 0;
q = 0;
for (int i = 1; i < n; i++) {
for (int j = 0; j < n; j++) {
if (j != x) {
b[p][q++] = a[i][j];
if (q % (n - 1) == 0) {
p++;
q = 0;
}
}
return matrix[0][0];
}
int sign = 1;
int[][] subMatrix = new int[n - 1][n - 1];
for (int x = 0; x < n; x++) {
int subI = 0;
for (int i = 1; i < n; i++) {
int subJ = 0;
for (int j = 0; j < n; j++) {
if (j != x) {
subMatrix[subI][subJ++] = matrix[i][j];
}
}
det = det + a[0][x] * determinant(b, n - 1) * sign;
sign = -sign;
subI++;
}
det += sign * matrix[0][x] * determinant(subMatrix, n - 1);
sign = -sign;
}
return det;
}

// Function to implement Hill Cipher
static void hillCipher(String message) {
System.out.println("What do you want to process from the message?");
System.out.println("Press 1: To Encrypt");
System.out.println("Press 2: To Decrypt");
short sc = userInput.nextShort();
if (sc == 1) {
encrypt(message);
} else if (sc == 2) {
decrypt(message);
} else {
System.out.println("Invalid input, program terminated.");
}
}

static void validateDeterminant(int[][] keyMatrix, int n) {
if (determinant(keyMatrix, n) % 26 == 0) {
System.out.println("Invalid key, as determinant = 0. Program Terminated");
}
}

// Driver code
public static void main(String[] args) {
// Get the message to be encrypted
System.out.println("Enter message");
String message = userInput.nextLine();
hillCipher(message);
}
}
41 changes: 41 additions & 0 deletions src/main/java/com/thealgorithms/ciphers/XORCipher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.thealgorithms.ciphers;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HexFormat;

/**
* A simple implementation of XOR cipher that, given a key, allows to encrypt and decrypt a plaintext.
*
* @author <a href="https://github.com/lcsjunior">lcsjunior</a>
*
*/
public final class XORCipher {

private static final Charset CS_DEFAULT = StandardCharsets.UTF_8;

private XORCipher() {
}

public static byte[] xor(final byte[] inputBytes, final byte[] keyBytes) {
byte[] outputBytes = new byte[inputBytes.length];
for (int i = 0; i < inputBytes.length; ++i) {
outputBytes[i] = (byte) (inputBytes[i] ^ keyBytes[i % keyBytes.length]);
}
return outputBytes;
}

public static String encrypt(final String plainText, final String key) {
byte[] plainTextBytes = plainText.getBytes(CS_DEFAULT);
byte[] keyBytes = key.getBytes(CS_DEFAULT);
byte[] xorResult = xor(plainTextBytes, keyBytes);
return HexFormat.of().formatHex(xorResult);
}

public static String decrypt(final String cipherText, final String key) {
byte[] cipherBytes = HexFormat.of().parseHex(cipherText);
byte[] keyBytes = key.getBytes(CS_DEFAULT);
byte[] xorResult = xor(cipherBytes, keyBytes);
return new String(xorResult, CS_DEFAULT);
}
}
Loading