Skip to content

Commit 67df287

Browse files
Merge branch 'master' into feat/self-organizing-list
2 parents 3cab177 + 56e2699 commit 67df287

47 files changed

Lines changed: 1840 additions & 341 deletions

Some content is hidden

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

.github/dependabot.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,20 @@ updates:
55
directory: "/"
66
schedule:
77
interval: "weekly"
8+
cooldown:
9+
default-days: 7
810

911
- package-ecosystem: "github-actions"
1012
directory: "/.github/workflows/"
1113
schedule:
1214
interval: "daily"
15+
cooldown:
16+
default-days: 7
1317

1418
- package-ecosystem: "maven"
1519
directory: "/"
1620
schedule:
1721
interval: "daily"
22+
cooldown:
23+
default-days: 7
1824
...

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
steps:
1111
- uses: actions/checkout@v7
1212
- name: Set up JDK
13-
uses: actions/setup-java@v5
13+
uses: actions/setup-java@v5.7.0
1414
with:
1515
java-version: 21
1616
distribution: 'temurin'

.github/workflows/codeql.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,21 @@ jobs:
2424
uses: actions/checkout@v7
2525

2626
- name: Set up JDK
27-
uses: actions/setup-java@v5
27+
uses: actions/setup-java@v5.7.0
2828
with:
2929
java-version: 21
3030
distribution: 'temurin'
3131

3232
- name: Initialize CodeQL
33-
uses: github/codeql-action/init@v4
33+
uses: github/codeql-action/init@v4.37.6
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@v4
41+
uses: github/codeql-action/analyze@v4.37.6
4242
with:
4343
category: "/language:java-kotlin"
4444

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

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

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

.github/workflows/infer.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- uses: actions/checkout@v7
1919

2020
- name: Set up JDK
21-
uses: actions/setup-java@v5
21+
uses: actions/setup-java@v5.7.0
2222
with:
2323
java-version: 21
2424
distribution: 'temurin'

.github/workflows/project_structure.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
runs-on: ubuntu-latest
1717
steps:
1818
- uses: actions/checkout@v7
19-
- uses: actions/setup-python@v6
19+
- uses: actions/setup-python@v7.0.0
2020
with:
2121
python-version: '3.13'
2222

.github/workflows/stale.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
pull-requests: write
1212
runs-on: ubuntu-latest
1313
steps:
14-
- uses: actions/stale@v10
14+
- uses: actions/stale@v11.0.0
1515
with:
1616
stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution!'
1717
close-issue-message: 'Please reopen this issue once you have made the required changes. If you need help, feel free to ask in our [Discord](https://the-algorithms.com/discord) server or ping one of the maintainers here. Thank you for your contribution!'

pom.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<dependency>
2121
<groupId>org.junit</groupId>
2222
<artifactId>junit-bom</artifactId>
23-
<version>6.1.0</version>
23+
<version>6.1.3</version>
2424
<type>pom</type>
2525
<scope>import</scope>
2626
</dependency>
@@ -53,7 +53,7 @@
5353
<dependency>
5454
<groupId>org.apache.commons</groupId>
5555
<artifactId>commons-collections4</artifactId>
56-
<version>4.5.0</version>
56+
<version>4.6.0</version>
5757
</dependency>
5858
</dependencies>
5959

@@ -112,14 +112,14 @@
112112
<dependency>
113113
<groupId>com.puppycrawl.tools</groupId>
114114
<artifactId>checkstyle</artifactId>
115-
<version>13.6.0</version>
115+
<version>13.10.0</version>
116116
</dependency>
117117
</dependencies>
118118
</plugin>
119119
<plugin>
120120
<groupId>com.github.spotbugs</groupId>
121121
<artifactId>spotbugs-maven-plugin</artifactId>
122-
<version>4.10.2.0</version>
122+
<version>4.10.3.0</version>
123123
<configuration>
124124
<excludeFilterFile>spotbugs-exclude.xml</excludeFilterFile>
125125
<includeTests>true</includeTests>

spotbugs-exclude.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@
5959
<Match>
6060
<Bug pattern="AT_STALE_THREAD_WRITE_OF_PRIMITIVE" />
6161
</Match>
62+
<Match>
63+
<Bug pattern="NP_NULL_PARAM_DEREF_NONVIRTUAL" />
64+
</Match>
65+
<Match>
66+
<Bug pattern="NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS" />
67+
</Match>
6268
<!-- fb-contrib -->
6369
<Match>
6470
<Bug pattern="LSC_LITERAL_STRING_COMPARISON" />

src/main/java/com/thealgorithms/ciphers/Caesar.java

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
* @author khalil2535
1010
*/
1111
public class Caesar {
12-
private static char normalizeShift(final int shift) {
13-
return (char) (shift % 26);
12+
private static int normalizeShift(final int shift) {
13+
return ((shift % 26) + 26) % 26;
1414
}
1515

1616
/**
@@ -22,21 +22,18 @@ private static char normalizeShift(final int shift) {
2222
public String encode(String message, int shift) {
2323
StringBuilder encoded = new StringBuilder();
2424

25-
final char shiftChar = normalizeShift(shift);
25+
final int shiftChar = normalizeShift(shift);
2626

2727
final int length = message.length();
2828
for (int i = 0; i < length; i++) {
29-
// int current = message.charAt(i); //using char to shift characters because
30-
// ascii
31-
// is in-order latin alphabet
32-
char current = message.charAt(i); // Java law : char + int = char
29+
final char current = message.charAt(i);
3330

3431
if (isCapitalLatinLetter(current)) {
35-
current += shiftChar;
36-
encoded.append((char) (current > 'Z' ? current - 26 : current)); // 26 = number of latin letters
32+
final int shifted = current + shiftChar;
33+
encoded.append((char) (shifted > 'Z' ? shifted - 26 : shifted)); // 26 = number of latin letters
3734
} else if (isSmallLatinLetter(current)) {
38-
current += shiftChar;
39-
encoded.append((char) (current > 'z' ? current - 26 : current)); // 26 = number of latin letters
35+
final int shifted = current + shiftChar;
36+
encoded.append((char) (shifted > 'z' ? shifted - 26 : shifted)); // 26 = number of latin letters
4037
} else {
4138
encoded.append(current);
4239
}
@@ -53,17 +50,17 @@ public String encode(String message, int shift) {
5350
public String decode(String encryptedMessage, int shift) {
5451
StringBuilder decoded = new StringBuilder();
5552

56-
final char shiftChar = normalizeShift(shift);
53+
final int shiftChar = normalizeShift(shift);
5754

5855
final int length = encryptedMessage.length();
5956
for (int i = 0; i < length; i++) {
60-
char current = encryptedMessage.charAt(i);
57+
final char current = encryptedMessage.charAt(i);
6158
if (isCapitalLatinLetter(current)) {
62-
current -= shiftChar;
63-
decoded.append((char) (current < 'A' ? current + 26 : current)); // 26 = number of latin letters
59+
final int shifted = current - shiftChar;
60+
decoded.append((char) (shifted < 'A' ? shifted + 26 : shifted)); // 26 = number of latin letters
6461
} else if (isSmallLatinLetter(current)) {
65-
current -= shiftChar;
66-
decoded.append((char) (current < 'a' ? current + 26 : current)); // 26 = number of latin letters
62+
final int shifted = current - shiftChar;
63+
decoded.append((char) (shifted < 'a' ? shifted + 26 : shifted)); // 26 = number of latin letters
6764
} else {
6865
decoded.append(current);
6966
}

src/main/java/com/thealgorithms/ciphers/RailFenceCipher.java

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.thealgorithms.ciphers;
22

3-
import java.util.Arrays;
4-
53
/**
64
* The rail fence cipher (also called a zigzag cipher) is a classical type of transposition cipher.
75
* It derives its name from the manner in which encryption is performed, in analogy to a fence built with horizontal rails.
@@ -14,28 +12,27 @@ public class RailFenceCipher {
1412
// Encrypts the input string using the rail fence cipher method with the given number of rails.
1513
public String encrypt(String str, int rails) {
1614

15+
checkInput(str, rails);
16+
1717
// Base case of single rail or rails are more than the number of characters in the string
1818
if (rails == 1 || rails >= str.length()) {
1919
return str;
2020
}
2121

22-
// Boolean flag to determine if the movement is downward or upward in the rail matrix.
22+
// Boolean flag to determine if the movement is downward or upward in the rail pattern.
2323
boolean down = true;
24-
// Create a 2D array to represent the rails (rows) and the length of the string (columns).
25-
char[][] strRail = new char[rails][str.length()];
26-
27-
// Initialize all positions in the rail matrix with a placeholder character ('\n').
24+
// Collect the characters of every rail separately. Using one buffer per rail (instead of a
25+
// rails x length matrix with a placeholder character) keeps every character of the input,
26+
// including characters that would otherwise be indistinguishable from the placeholder.
27+
StringBuilder[] railBuffers = new StringBuilder[rails];
2828
for (int i = 0; i < rails; i++) {
29-
Arrays.fill(strRail[i], '\n');
29+
railBuffers[i] = new StringBuilder();
3030
}
3131

32-
int row = 0; // Start at the first row
33-
int col = 0; // Start at the first column
32+
int row = 0; // Start at the first rail
3433

35-
int i = 0;
36-
37-
// Fill the rail matrix with characters from the string based on the rail pattern.
38-
while (col < str.length()) {
34+
// Distribute the characters of the string over the rails following the zigzag pattern.
35+
for (int i = 0; i < str.length(); i++) {
3936
// Change direction to down when at the first row.
4037
if (row == 0) {
4138
down = true;
@@ -45,33 +42,28 @@ else if (row == rails - 1) {
4542
down = false;
4643
}
4744

48-
// Place the character in the current position of the rail matrix.
49-
strRail[row][col] = str.charAt(i);
50-
col++; // Move to the next column.
45+
// Append the character to the rail it belongs to.
46+
railBuffers[row].append(str.charAt(i));
5147
// Move to the next row based on the direction.
5248
if (down) {
5349
row++;
5450
} else {
5551
row--;
5652
}
57-
58-
i++;
5953
}
6054

61-
// Construct the encrypted string by reading characters row by row.
62-
StringBuilder encryptedString = new StringBuilder();
63-
for (char[] chRow : strRail) {
64-
for (char ch : chRow) {
65-
if (ch != '\n') {
66-
encryptedString.append(ch);
67-
}
68-
}
55+
// Construct the encrypted string by reading the rails top to bottom.
56+
StringBuilder encryptedString = new StringBuilder(str.length());
57+
for (StringBuilder railBuffer : railBuffers) {
58+
encryptedString.append(railBuffer);
6959
}
7060
return encryptedString.toString();
7161
}
7262
// Decrypts the input string using the rail fence cipher method with the given number of rails.
7363
public String decrypt(String str, int rails) {
7464

65+
checkInput(str, rails);
66+
7567
// Base case of single rail or rails are more than the number of characters in the string
7668
if (rails == 1 || rails >= str.length()) {
7769
return str;
@@ -144,4 +136,14 @@ else if (row == rails - 1) {
144136

145137
return decryptedString.toString();
146138
}
139+
140+
// Rejects inputs the zigzag pattern is not defined for.
141+
private static void checkInput(String str, int rails) {
142+
if (str == null) {
143+
throw new IllegalArgumentException("Input string must not be null");
144+
}
145+
if (rails <= 0) {
146+
throw new IllegalArgumentException("Number of rails must be positive, but was " + rails);
147+
}
148+
}
147149
}

0 commit comments

Comments
 (0)