Skip to content

Commit 3ccdc1b

Browse files
authored
Merge branch 'master' into sushant
2 parents 091f57d + 14a23b7 commit 3ccdc1b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+5901
-398
lines changed

.github/workflows/codeql.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ jobs:
3030
distribution: 'temurin'
3131

3232
- name: Initialize CodeQL
33-
uses: github/codeql-action/init@v3
33+
uses: github/codeql-action/init@v4
3434
with:
3535
languages: 'java-kotlin'
3636

3737
- name: Build
3838
run: mvn --batch-mode --update-snapshots verify
3939

4040
- name: Perform CodeQL Analysis
41-
uses: github/codeql-action/analyze@v3
41+
uses: github/codeql-action/analyze@v4
4242
with:
4343
category: "/language:java-kotlin"
4444

@@ -55,12 +55,12 @@ jobs:
5555
uses: actions/checkout@v5
5656

5757
- name: Initialize CodeQL
58-
uses: github/codeql-action/init@v3
58+
uses: github/codeql-action/init@v4
5959
with:
6060
languages: 'actions'
6161

6262
- name: Perform CodeQL Analysis
63-
uses: github/codeql-action/analyze@v3
63+
uses: github/codeql-action/analyze@v4
6464
with:
6565
category: "/language:actions"
6666
...

.gitpod.dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM gitpod/workspace-java-21:2025-08-25-18-17-39
1+
FROM gitpod/workspace-java-21:2025-10-06-13-14-25
22

33
ENV LLVM_SCRIPT="tmp_llvm.sh"
44

pmd-exclude.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,14 @@ com.thealgorithms.others.LinearCongruentialGenerator=UselessMainMethod
8888
com.thealgorithms.others.Luhn=UnnecessaryFullyQualifiedName,UselessMainMethod
8989
com.thealgorithms.others.Mandelbrot=UselessMainMethod,UselessParentheses
9090
com.thealgorithms.others.MiniMaxAlgorithm=UselessMainMethod,UselessParentheses
91+
com.thealgorithms.others.MosAlgorithm=UselessMainMethod
9192
com.thealgorithms.others.PageRank=UselessMainMethod,UselessParentheses
9293
com.thealgorithms.others.PerlinNoise=UselessMainMethod,UselessParentheses
9394
com.thealgorithms.others.QueueUsingTwoStacks=UselessParentheses
9495
com.thealgorithms.others.Trieac=UselessMainMethod,UselessParentheses
9596
com.thealgorithms.others.Verhoeff=UnnecessaryFullyQualifiedName,UselessMainMethod
9697
com.thealgorithms.puzzlesandgames.Sudoku=UselessMainMethod
98+
com.thealgorithms.recursion.DiceThrower=UselessMainMethod
9799
com.thealgorithms.searches.HowManyTimesRotated=UselessMainMethod
98100
com.thealgorithms.searches.InterpolationSearch=UselessParentheses
99101
com.thealgorithms.searches.KMPSearch=UselessParentheses

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@
112112
<dependency>
113113
<groupId>com.puppycrawl.tools</groupId>
114114
<artifactId>checkstyle</artifactId>
115-
<version>11.1.0</version>
115+
<version>12.0.0</version>
116116
</dependency>
117117
</dependencies>
118118
</plugin>
@@ -140,7 +140,7 @@
140140
<plugin>
141141
<groupId>org.apache.maven.plugins</groupId>
142142
<artifactId>maven-pmd-plugin</artifactId>
143-
<version>3.27.0</version>
143+
<version>3.28.0</version>
144144
<configuration>
145145
<rulesets>
146146
<ruleset>/rulesets/java/maven-pmd-plugin-default.xml</ruleset>
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
package com.thealgorithms.ciphers;
2+
3+
import java.util.HashSet;
4+
import java.util.Set;
5+
6+
/**
7+
* A Java implementation of Permutation Cipher.
8+
* It is a type of transposition cipher in which the plaintext is divided into blocks
9+
* and the characters within each block are rearranged according to a fixed permutation key.
10+
*
11+
* For example, with key {3, 1, 2} and plaintext "HELLO", the text is divided into blocks
12+
* of 3 characters: "HEL" and "LO" (with padding). The characters are then rearranged
13+
* according to the key positions.
14+
*
15+
* @author GitHub Copilot
16+
*/
17+
public class PermutationCipher {
18+
19+
private static final char PADDING_CHAR = 'X';
20+
21+
/**
22+
* Encrypts the given plaintext using the permutation cipher with the specified key.
23+
*
24+
* @param plaintext the text to encrypt
25+
* @param key the permutation key (array of integers representing positions)
26+
* @return the encrypted text
27+
* @throws IllegalArgumentException if the key is invalid
28+
*/
29+
public String encrypt(String plaintext, int[] key) {
30+
validateKey(key);
31+
32+
if (plaintext == null || plaintext.isEmpty()) {
33+
return plaintext;
34+
}
35+
36+
// Remove spaces and convert to uppercase for consistent processing
37+
String cleanText = plaintext.replaceAll("\\s+", "").toUpperCase();
38+
39+
// Pad the text to make it divisible by key length
40+
String paddedText = padText(cleanText, key.length);
41+
42+
StringBuilder encrypted = new StringBuilder();
43+
44+
// Process text in blocks of key length
45+
for (int i = 0; i < paddedText.length(); i += key.length) {
46+
String block = paddedText.substring(i, Math.min(i + key.length, paddedText.length()));
47+
encrypted.append(permuteBlock(block, key));
48+
}
49+
50+
return encrypted.toString();
51+
}
52+
53+
/**
54+
* Decrypts the given ciphertext using the permutation cipher with the specified key.
55+
*
56+
* @param ciphertext the text to decrypt
57+
* @param key the permutation key (array of integers representing positions)
58+
* @return the decrypted text
59+
* @throws IllegalArgumentException if the key is invalid
60+
*/
61+
public String decrypt(String ciphertext, int[] key) {
62+
validateKey(key);
63+
64+
if (ciphertext == null || ciphertext.isEmpty()) {
65+
return ciphertext;
66+
}
67+
68+
// Create the inverse permutation
69+
int[] inverseKey = createInverseKey(key);
70+
71+
StringBuilder decrypted = new StringBuilder();
72+
73+
// Process text in blocks of key length
74+
for (int i = 0; i < ciphertext.length(); i += key.length) {
75+
String block = ciphertext.substring(i, Math.min(i + key.length, ciphertext.length()));
76+
decrypted.append(permuteBlock(block, inverseKey));
77+
}
78+
79+
// Remove padding characters from the end
80+
return removePadding(decrypted.toString());
81+
}
82+
/**
83+
* Validates that the permutation key is valid.
84+
* A valid key must contain all integers from 1 to n exactly once, where n is the key length.
85+
*
86+
* @param key the permutation key to validate
87+
* @throws IllegalArgumentException if the key is invalid
88+
*/
89+
private void validateKey(int[] key) {
90+
if (key == null || key.length == 0) {
91+
throw new IllegalArgumentException("Key cannot be null or empty");
92+
}
93+
94+
Set<Integer> keySet = new HashSet<>();
95+
for (int position : key) {
96+
if (position < 1 || position > key.length) {
97+
throw new IllegalArgumentException("Key must contain integers from 1 to " + key.length);
98+
}
99+
if (!keySet.add(position)) {
100+
throw new IllegalArgumentException("Key must contain each position exactly once");
101+
}
102+
}
103+
}
104+
105+
/**
106+
* Pads the text with padding characters to make its length divisible by the block size.
107+
*
108+
* @param text the text to pad
109+
* @param blockSize the size of each block
110+
* @return the padded text
111+
*/
112+
private String padText(String text, int blockSize) {
113+
int remainder = text.length() % blockSize;
114+
if (remainder == 0) {
115+
return text;
116+
}
117+
118+
int paddingNeeded = blockSize - remainder;
119+
StringBuilder padded = new StringBuilder(text);
120+
for (int i = 0; i < paddingNeeded; i++) {
121+
padded.append(PADDING_CHAR);
122+
}
123+
124+
return padded.toString();
125+
}
126+
/**
127+
* Applies the permutation to a single block of text.
128+
*
129+
* @param block the block to permute
130+
* @param key the permutation key
131+
* @return the permuted block
132+
*/
133+
private String permuteBlock(String block, int[] key) {
134+
if (block.length() != key.length) {
135+
// Handle case where block is shorter than key (shouldn't happen with proper padding)
136+
block = padText(block, key.length);
137+
}
138+
139+
char[] result = new char[key.length];
140+
char[] blockChars = block.toCharArray();
141+
142+
for (int i = 0; i < key.length; i++) {
143+
// Key positions are 1-based, so subtract 1 for 0-based array indexing
144+
result[i] = blockChars[key[i] - 1];
145+
}
146+
147+
return new String(result);
148+
}
149+
150+
/**
151+
* Creates the inverse permutation key for decryption.
152+
*
153+
* @param key the original permutation key
154+
* @return the inverse key
155+
*/
156+
private int[] createInverseKey(int[] key) {
157+
int[] inverse = new int[key.length];
158+
159+
for (int i = 0; i < key.length; i++) {
160+
// The inverse key maps each position to where it should go
161+
inverse[key[i] - 1] = i + 1;
162+
}
163+
164+
return inverse;
165+
}
166+
167+
/**
168+
* Removes padding characters from the end of the decrypted text.
169+
*
170+
* @param text the text to remove padding from
171+
* @return the text without padding
172+
*/
173+
private String removePadding(String text) {
174+
if (text.isEmpty()) {
175+
return text;
176+
}
177+
178+
int i = text.length() - 1;
179+
while (i >= 0 && text.charAt(i) == PADDING_CHAR) {
180+
i--;
181+
}
182+
183+
return text.substring(0, i + 1);
184+
}
185+
186+
/**
187+
* Gets the padding character used by this cipher.
188+
*
189+
* @return the padding character
190+
*/
191+
public char getPaddingChar() {
192+
return PADDING_CHAR;
193+
}
194+
}

src/main/java/com/thealgorithms/datastructures/trees/BSTRecursiveGeneric.java

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
* </p>
1414
*
1515
* @author [Madhur Panwar](<a href="https://github.com/mdrpanwar">git-Madhur Panwar</a>)
16+
* @author [Udaya Krishnan M](<a href="https://github.com/UdayaKrishnanM/">git-Udaya Krishnan M</a>) {added prettyDisplay() method}
1617
*/
1718
public class BSTRecursiveGeneric<T extends Comparable<T>> {
1819

@@ -28,6 +29,29 @@ public BSTRecursiveGeneric() {
2829
root = null;
2930
}
3031

32+
/**
33+
* Displays the tree is a structed format
34+
*/
35+
public void prettyDisplay() {
36+
prettyDisplay(root, 0);
37+
}
38+
39+
private void prettyDisplay(Node<T> node, int level) {
40+
if (node == null) {
41+
return;
42+
}
43+
prettyDisplay(node.right, level + 1);
44+
if (level != 0) {
45+
for (int i = 0; i < level - 1; i++) {
46+
System.out.print("|\t");
47+
}
48+
System.out.println("|---->" + node.data);
49+
} else {
50+
System.out.println(node.data);
51+
}
52+
prettyDisplay(node.left, level + 1);
53+
}
54+
3155
/**
3256
* main function for testing
3357
*/
@@ -38,7 +62,12 @@ public static void main(String[] args) {
3862

3963
integerTree.add(5);
4064
integerTree.add(10);
41-
integerTree.add(9);
65+
integerTree.add(-9);
66+
integerTree.add(4);
67+
integerTree.add(3);
68+
integerTree.add(1);
69+
System.out.println("Pretty Display of current tree is:");
70+
integerTree.prettyDisplay();
4271
assert !integerTree.find(4)
4372
: "4 is not yet present in BST";
4473
assert integerTree.find(10)
@@ -54,16 +83,21 @@ public static void main(String[] args) {
5483
assert integerTree.find(70)
5584
: "70 was inserted but not found";
5685
/*
57-
Will print in following order
58-
5 10 20 70
86+
Will print in following order
87+
5 10 20 70
5988
*/
89+
System.out.println("Pretty Display of current tree is:");
90+
integerTree.prettyDisplay();
6091
integerTree.inorder();
92+
System.out.println("Pretty Display of current tree is:");
93+
integerTree.prettyDisplay();
6194
System.out.println();
6295
System.out.println("Testing for string data...");
6396
// String
6497
BSTRecursiveGeneric<String> stringTree = new BSTRecursiveGeneric<String>();
6598

6699
stringTree.add("banana");
100+
stringTree.add("apple");
67101
stringTree.add("pineapple");
68102
stringTree.add("date");
69103
assert !stringTree.find("girl")
@@ -80,11 +114,15 @@ public static void main(String[] args) {
80114
stringTree.add("hills");
81115
assert stringTree.find("hills")
82116
: "hills was inserted but not found";
117+
System.out.println("Pretty Display of current tree is:");
118+
stringTree.prettyDisplay();
83119
/*
84120
Will print in following order
85121
banana hills india pineapple
86122
*/
87123
stringTree.inorder();
124+
System.out.println("Pretty Display of current tree is:");
125+
stringTree.prettyDisplay();
88126
}
89127

90128
/**

0 commit comments

Comments
 (0)