Skip to content

Commit 2409209

Browse files
author
prayas7102
committed
Merge branch 'LowestSetBit' of https://github.com/prayas7102/Java into LowestSetBit
2 parents 8ef5e80 + 6d35639 commit 2409209

26 files changed

+861
-185
lines changed

DIRECTORY.md

+23-11
Large diffs are not rendered by default.

src/main/java/com/thealgorithms/others/CountSetBits.java renamed to src/main/java/com/thealgorithms/bitmanipulation/CountSetBits.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.thealgorithms.others;
1+
package com.thealgorithms.bitmanipulation;
22

33
public class CountSetBits {
44

Original file line numberDiff line numberDiff line change
@@ -1,178 +1,103 @@
11
package com.thealgorithms.ciphers;
22

3-
import java.util.Scanner;
3+
public class HillCipher {
44

5-
/*
6-
* Java Implementation of Hill Cipher
7-
* Hill cipher is a polyalphabetic substitution cipher. Each letter is represented by a number
8-
* belonging to the set Z26 where A=0 , B=1, ..... Z=25. To encrypt a message, each block of n
9-
* letters (since matrix size is n x n) is multiplied by an invertible n × n matrix, against
10-
* modulus 26. To decrypt the message, each block is multiplied by the inverse of the matrix used
11-
* for encryption. The cipher key and plaintext/ciphertext are user inputs.
12-
* @author Ojasva Jain
13-
*/
14-
public final class HillCipher {
15-
private HillCipher() {
16-
}
17-
18-
static Scanner userInput = new Scanner(System.in);
19-
20-
/* Following function encrypts the message
21-
*/
22-
static void encrypt(String message) {
23-
message = message.toUpperCase();
24-
// Get key matrix
25-
System.out.println("Enter key matrix size");
26-
int matrixSize = userInput.nextInt();
27-
System.out.println("Enter Key/encryptionKey matrix ");
28-
int[][] keyMatrix = new int[matrixSize][matrixSize];
29-
for (int i = 0; i < matrixSize; i++) {
30-
for (int j = 0; j < matrixSize; j++) {
31-
keyMatrix[i][j] = userInput.nextInt();
32-
}
33-
}
34-
// check if det = 0
5+
// Encrypts the message using the key matrix
6+
public String encrypt(String message, int[][] keyMatrix) {
7+
message = message.toUpperCase().replaceAll("[^A-Z]", "");
8+
int matrixSize = keyMatrix.length;
359
validateDeterminant(keyMatrix, matrixSize);
3610

37-
int[][] messageVector = new int[matrixSize][1];
38-
String cipherText = "";
39-
int[][] cipherMatrix = new int[matrixSize][1];
40-
int j = 0;
41-
while (j < message.length()) {
11+
StringBuilder cipherText = new StringBuilder();
12+
int[] messageVector = new int[matrixSize];
13+
int[] cipherVector = new int[matrixSize];
14+
int index = 0;
15+
16+
while (index < message.length()) {
4217
for (int i = 0; i < matrixSize; i++) {
43-
if (j >= message.length()) {
44-
messageVector[i][0] = 23;
18+
if (index < message.length()) {
19+
messageVector[i] = message.charAt(index++) - 'A';
4520
} else {
46-
messageVector[i][0] = (message.charAt(j)) % 65;
21+
messageVector[i] = 'X' - 'A'; // Padding with 'X' if needed
4722
}
48-
System.out.println(messageVector[i][0]);
49-
j++;
5023
}
51-
int x;
52-
int i;
53-
for (i = 0; i < matrixSize; i++) {
54-
cipherMatrix[i][0] = 0;
5524

56-
for (x = 0; x < matrixSize; x++) {
57-
cipherMatrix[i][0] += keyMatrix[i][x] * messageVector[x][0];
25+
for (int i = 0; i < matrixSize; i++) {
26+
cipherVector[i] = 0;
27+
for (int j = 0; j < matrixSize; j++) {
28+
cipherVector[i] += keyMatrix[i][j] * messageVector[j];
5829
}
59-
System.out.println(cipherMatrix[i][0]);
60-
cipherMatrix[i][0] = cipherMatrix[i][0] % 26;
61-
}
62-
for (i = 0; i < matrixSize; i++) {
63-
cipherText += (char) (cipherMatrix[i][0] + 65);
30+
cipherVector[i] = cipherVector[i] % 26;
31+
cipherText.append((char) (cipherVector[i] + 'A'));
6432
}
6533
}
66-
System.out.println("Ciphertext: " + cipherText);
34+
35+
return cipherText.toString();
6736
}
6837

69-
// Following function decrypts a message
70-
static void decrypt(String message) {
71-
message = message.toUpperCase();
72-
// Get key matrix
73-
System.out.println("Enter key matrix size");
74-
int n = userInput.nextInt();
75-
System.out.println("Enter inverseKey/decryptionKey matrix ");
76-
int[][] keyMatrix = new int[n][n];
77-
for (int i = 0; i < n; i++) {
78-
for (int j = 0; j < n; j++) {
79-
keyMatrix[i][j] = userInput.nextInt();
80-
}
81-
}
82-
// check if det = 0
83-
validateDeterminant(keyMatrix, n);
38+
// Decrypts the message using the inverse key matrix
39+
public String decrypt(String message, int[][] inverseKeyMatrix) {
40+
message = message.toUpperCase().replaceAll("[^A-Z]", "");
41+
int matrixSize = inverseKeyMatrix.length;
42+
validateDeterminant(inverseKeyMatrix, matrixSize);
43+
44+
StringBuilder plainText = new StringBuilder();
45+
int[] messageVector = new int[matrixSize];
46+
int[] plainVector = new int[matrixSize];
47+
int index = 0;
8448

85-
// solving for the required plaintext message
86-
int[][] messageVector = new int[n][1];
87-
String plainText = "";
88-
int[][] plainMatrix = new int[n][1];
89-
int j = 0;
90-
while (j < message.length()) {
91-
for (int i = 0; i < n; i++) {
92-
if (j >= message.length()) {
93-
messageVector[i][0] = 23;
49+
while (index < message.length()) {
50+
for (int i = 0; i < matrixSize; i++) {
51+
if (index < message.length()) {
52+
messageVector[i] = message.charAt(index++) - 'A';
9453
} else {
95-
messageVector[i][0] = (message.charAt(j)) % 65;
54+
messageVector[i] = 'X' - 'A'; // Padding with 'X' if needed
9655
}
97-
System.out.println(messageVector[i][0]);
98-
j++;
9956
}
100-
int x;
101-
int i;
102-
for (i = 0; i < n; i++) {
103-
plainMatrix[i][0] = 0;
10457

105-
for (x = 0; x < n; x++) {
106-
plainMatrix[i][0] += keyMatrix[i][x] * messageVector[x][0];
58+
for (int i = 0; i < matrixSize; i++) {
59+
plainVector[i] = 0;
60+
for (int j = 0; j < matrixSize; j++) {
61+
plainVector[i] += inverseKeyMatrix[i][j] * messageVector[j];
10762
}
108-
109-
plainMatrix[i][0] = plainMatrix[i][0] % 26;
110-
}
111-
for (i = 0; i < n; i++) {
112-
plainText += (char) (plainMatrix[i][0] + 65);
63+
plainVector[i] = plainVector[i] % 26;
64+
plainText.append((char) (plainVector[i] + 'A'));
11365
}
11466
}
115-
System.out.println("Plaintext: " + plainText);
67+
68+
return plainText.toString();
11669
}
11770

118-
// Determinant calculator
119-
public static int determinant(int[][] a, int n) {
120-
int det = 0;
121-
int sign = 1;
122-
int p = 0;
123-
int q = 0;
71+
// Validates that the determinant of the key matrix is not zero modulo 26
72+
private void validateDeterminant(int[][] keyMatrix, int n) {
73+
int det = determinant(keyMatrix, n) % 26;
74+
if (det == 0) {
75+
throw new IllegalArgumentException("Invalid key matrix. Determinant is zero modulo 26.");
76+
}
77+
}
12478

79+
// Computes the determinant of a matrix recursively
80+
private int determinant(int[][] matrix, int n) {
81+
int det = 0;
12582
if (n == 1) {
126-
det = a[0][0];
127-
} else {
128-
int[][] b = new int[n - 1][n - 1];
129-
for (int x = 0; x < n; x++) {
130-
p = 0;
131-
q = 0;
132-
for (int i = 1; i < n; i++) {
133-
for (int j = 0; j < n; j++) {
134-
if (j != x) {
135-
b[p][q++] = a[i][j];
136-
if (q % (n - 1) == 0) {
137-
p++;
138-
q = 0;
139-
}
140-
}
83+
return matrix[0][0];
84+
}
85+
int sign = 1;
86+
int[][] subMatrix = new int[n - 1][n - 1];
87+
for (int x = 0; x < n; x++) {
88+
int subI = 0;
89+
for (int i = 1; i < n; i++) {
90+
int subJ = 0;
91+
for (int j = 0; j < n; j++) {
92+
if (j != x) {
93+
subMatrix[subI][subJ++] = matrix[i][j];
14194
}
14295
}
143-
det = det + a[0][x] * determinant(b, n - 1) * sign;
144-
sign = -sign;
96+
subI++;
14597
}
98+
det += sign * matrix[0][x] * determinant(subMatrix, n - 1);
99+
sign = -sign;
146100
}
147101
return det;
148102
}
149-
150-
// Function to implement Hill Cipher
151-
static void hillCipher(String message) {
152-
System.out.println("What do you want to process from the message?");
153-
System.out.println("Press 1: To Encrypt");
154-
System.out.println("Press 2: To Decrypt");
155-
short sc = userInput.nextShort();
156-
if (sc == 1) {
157-
encrypt(message);
158-
} else if (sc == 2) {
159-
decrypt(message);
160-
} else {
161-
System.out.println("Invalid input, program terminated.");
162-
}
163-
}
164-
165-
static void validateDeterminant(int[][] keyMatrix, int n) {
166-
if (determinant(keyMatrix, n) % 26 == 0) {
167-
System.out.println("Invalid key, as determinant = 0. Program Terminated");
168-
}
169-
}
170-
171-
// Driver code
172-
public static void main(String[] args) {
173-
// Get the message to be encrypted
174-
System.out.println("Enter message");
175-
String message = userInput.nextLine();
176-
hillCipher(message);
177-
}
178103
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.thealgorithms.ciphers;
2+
3+
import java.nio.charset.Charset;
4+
import java.nio.charset.StandardCharsets;
5+
import java.util.HexFormat;
6+
7+
/**
8+
* A simple implementation of XOR cipher that, given a key, allows to encrypt and decrypt a plaintext.
9+
*
10+
* @author <a href="https://github.com/lcsjunior">lcsjunior</a>
11+
*
12+
*/
13+
public final class XORCipher {
14+
15+
private static final Charset CS_DEFAULT = StandardCharsets.UTF_8;
16+
17+
private XORCipher() {
18+
}
19+
20+
public static byte[] xor(final byte[] inputBytes, final byte[] keyBytes) {
21+
byte[] outputBytes = new byte[inputBytes.length];
22+
for (int i = 0; i < inputBytes.length; ++i) {
23+
outputBytes[i] = (byte) (inputBytes[i] ^ keyBytes[i % keyBytes.length]);
24+
}
25+
return outputBytes;
26+
}
27+
28+
public static String encrypt(final String plainText, final String key) {
29+
byte[] plainTextBytes = plainText.getBytes(CS_DEFAULT);
30+
byte[] keyBytes = key.getBytes(CS_DEFAULT);
31+
byte[] xorResult = xor(plainTextBytes, keyBytes);
32+
return HexFormat.of().formatHex(xorResult);
33+
}
34+
35+
public static String decrypt(final String cipherText, final String key) {
36+
byte[] cipherBytes = HexFormat.of().parseHex(cipherText);
37+
byte[] keyBytes = key.getBytes(CS_DEFAULT);
38+
byte[] xorResult = xor(cipherBytes, keyBytes);
39+
return new String(xorResult, CS_DEFAULT);
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.thealgorithms.conversions;
2+
3+
import java.util.Map;
4+
5+
public final class IntegerToEnglish {
6+
private static final Map<Integer, String> BASE_NUMBERS_MAP = Map.ofEntries(Map.entry(0, ""), Map.entry(1, "One"), Map.entry(2, "Two"), Map.entry(3, "Three"), Map.entry(4, "Four"), Map.entry(5, "Five"), Map.entry(6, "Six"), Map.entry(7, "Seven"), Map.entry(8, "Eight"), Map.entry(9, "Nine"),
7+
Map.entry(10, "Ten"), Map.entry(11, "Eleven"), Map.entry(12, "Twelve"), Map.entry(13, "Thirteen"), Map.entry(14, "Fourteen"), Map.entry(15, "Fifteen"), Map.entry(16, "Sixteen"), Map.entry(17, "Seventeen"), Map.entry(18, "Eighteen"), Map.entry(19, "Nineteen"), Map.entry(20, "Twenty"),
8+
Map.entry(30, "Thirty"), Map.entry(40, "Forty"), Map.entry(50, "Fifty"), Map.entry(60, "Sixty"), Map.entry(70, "Seventy"), Map.entry(80, "Eighty"), Map.entry(90, "Ninety"), Map.entry(100, "Hundred"));
9+
10+
private static final Map<Integer, String> THOUSAND_POWER_MAP = Map.ofEntries(Map.entry(1, "Thousand"), Map.entry(2, "Million"), Map.entry(3, "Billion"));
11+
12+
private IntegerToEnglish() {
13+
}
14+
15+
/**
16+
converts numbers < 1000 to english words
17+
*/
18+
private static String convertToWords(int number) {
19+
int remainder = number % 100;
20+
21+
String result;
22+
23+
if (remainder <= 20) {
24+
result = BASE_NUMBERS_MAP.get(remainder);
25+
} else if (BASE_NUMBERS_MAP.containsKey(remainder)) {
26+
result = BASE_NUMBERS_MAP.get(remainder);
27+
} else {
28+
int tensDigit = remainder / 10;
29+
int onesDigit = remainder % 10;
30+
31+
result = String.format("%s %s", BASE_NUMBERS_MAP.get(tensDigit * 10), BASE_NUMBERS_MAP.get(onesDigit));
32+
}
33+
34+
int hundredsDigit = number / 100;
35+
36+
if (hundredsDigit > 0) {
37+
result = String.format("%s %s%s", BASE_NUMBERS_MAP.get(hundredsDigit), BASE_NUMBERS_MAP.get(100), result.isEmpty() ? "" : " " + result);
38+
}
39+
40+
return result;
41+
}
42+
43+
/**
44+
Only convert groups of three digit if they are non-zero
45+
*/
46+
public static String integerToEnglishWords(int number) {
47+
if (number == 0) {
48+
return "Zero";
49+
}
50+
51+
StringBuilder result = new StringBuilder();
52+
53+
int index = 0;
54+
55+
while (number > 0) {
56+
int remainder = number % 1000;
57+
number /= 1000;
58+
59+
if (remainder > 0) {
60+
String subResult = convertToWords(remainder);
61+
62+
if (!subResult.isEmpty()) {
63+
if (!result.isEmpty()) {
64+
result.insert(0, subResult + " " + THOUSAND_POWER_MAP.get(index) + " ");
65+
} else {
66+
if (index > 0) {
67+
result = new StringBuilder(subResult + " " + THOUSAND_POWER_MAP.get(index));
68+
} else {
69+
result = new StringBuilder(subResult);
70+
}
71+
}
72+
}
73+
}
74+
75+
index++;
76+
}
77+
78+
return result.toString();
79+
}
80+
}

0 commit comments

Comments
 (0)