Skip to content

Commit a516bb5

Browse files
Merge branch 'master' into fix-7456-group-palindrome-implementations
2 parents 1c68b09 + 0e001b7 commit a516bb5

9 files changed

Lines changed: 243 additions & 156 deletions

File tree

src/main/java/com/thealgorithms/conversions/Base64.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,15 @@ public static byte[] decode(String input) {
119119

120120
// Validate padding: '=' can only appear at the end (last 1 or 2 chars)
121121
int firstPadding = input.indexOf('=');
122-
if (firstPadding != -1 && firstPadding < input.length() - 2) {
123-
throw new IllegalArgumentException("Padding '=' can only appear at the end (last 1 or 2 characters)");
122+
if (firstPadding != -1) {
123+
if (firstPadding < input.length() - 2) {
124+
throw new IllegalArgumentException("Padding '=' can only appear at the end (last 1 or 2 characters)");
125+
}
126+
for (int i = firstPadding; i < input.length(); i++) {
127+
if (input.charAt(i) != '=') {
128+
throw new IllegalArgumentException("A padding '=' must not be followed by a non-padding character");
129+
}
130+
}
124131
}
125132

126133
List<Byte> result = new ArrayList<>();

src/main/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithm.java

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.thealgorithms.datastructures.graphs;
22

33
import java.util.Arrays;
4+
import java.util.PriorityQueue;
45

56
/**
67
* Dijkstra's algorithm for finding the shortest path from a single source vertex to all other vertices in a graph.
@@ -18,6 +19,21 @@ public DijkstraAlgorithm(int vertexCount) {
1819
this.vertexCount = vertexCount;
1920
}
2021

22+
private static class Node implements Comparable<Node> {
23+
int id;
24+
int distance;
25+
26+
Node(int id, int distance) {
27+
this.id = id;
28+
this.distance = distance;
29+
}
30+
31+
@Override
32+
public int compareTo(Node other) {
33+
return Integer.compare(this.distance, other.distance);
34+
}
35+
}
36+
2137
/**
2238
* Executes Dijkstra's algorithm on the provided graph to find the shortest paths from the source vertex to all other vertices.
2339
*
@@ -36,18 +52,25 @@ public int[] run(int[][] graph, int source) {
3652

3753
int[] distances = new int[vertexCount];
3854
boolean[] processed = new boolean[vertexCount];
55+
PriorityQueue<Node> unprocessed = new PriorityQueue<>();
3956

4057
Arrays.fill(distances, Integer.MAX_VALUE);
41-
Arrays.fill(processed, false);
4258
distances[source] = 0;
59+
unprocessed.add(new Node(source, 0));
60+
61+
while (!unprocessed.isEmpty()) {
62+
Node current = unprocessed.poll();
63+
int u = current.id;
4364

44-
for (int count = 0; count < vertexCount - 1; count++) {
45-
int u = getMinDistanceVertex(distances, processed);
65+
if (processed[u]) {
66+
continue;
67+
}
4668
processed[u] = true;
4769

4870
for (int v = 0; v < vertexCount; v++) {
4971
if (!processed[v] && graph[u][v] != 0 && distances[u] != Integer.MAX_VALUE && distances[u] + graph[u][v] < distances[v]) {
5072
distances[v] = distances[u] + graph[u][v];
73+
unprocessed.add(new Node(v, distances[v]));
5174
}
5275
}
5376
}
@@ -56,27 +79,6 @@ public int[] run(int[][] graph, int source) {
5679
return distances;
5780
}
5881

59-
/**
60-
* Finds the vertex with the minimum distance value from the set of vertices that have not yet been processed.
61-
*
62-
* @param distances The array of current shortest distances from the source vertex.
63-
* @param processed The array indicating whether each vertex has been processed.
64-
* @return The index of the vertex with the minimum distance value.
65-
*/
66-
private int getMinDistanceVertex(int[] distances, boolean[] processed) {
67-
int min = Integer.MAX_VALUE;
68-
int minIndex = -1;
69-
70-
for (int v = 0; v < vertexCount; v++) {
71-
if (!processed[v] && distances[v] <= min) {
72-
min = distances[v];
73-
minIndex = v;
74-
}
75-
}
76-
77-
return minIndex;
78-
}
79-
8082
/**
8183
* Prints the shortest distances from the source vertex to all other vertices.
8284
*

src/main/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithm.java

Lines changed: 0 additions & 66 deletions
This file was deleted.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.thealgorithms.maths;
2+
3+
/**
4+
* Two numbers are Friendly if they share the same abundancy index,
5+
* which is the ratio of the sum of divisors to the number itself.
6+
* Example: 6 and 28 are friendly because sigma(6)/6 = 2 and sigma(28)/28 = 2
7+
*
8+
* @see <a href="https://en.wikipedia.org/wiki/Friendly_number">
9+
* Wikipedia: Friendly Number</a>
10+
*
11+
* @author Vraj Prajapati @Rosander0
12+
*/
13+
public final class FriendlyNumber {
14+
15+
private FriendlyNumber() {
16+
// Utility class
17+
}
18+
19+
private static int sumOfDivisors(final int number) {
20+
int sum = 0;
21+
final int root = (int) Math.sqrt(number);
22+
for (int i = 1; i <= root; i++) {
23+
if (number % i == 0) {
24+
sum += i;
25+
final int other = number / i;
26+
if (other != i) {
27+
sum += other;
28+
}
29+
}
30+
}
31+
return sum;
32+
}
33+
34+
/**
35+
* Checks whether two numbers are Friendly Numbers.
36+
*
37+
* @param a First number (must be positive)
38+
* @param b Second number (must be positive)
39+
* @return true if a and b are friendly numbers, false otherwise
40+
*/
41+
public static boolean areFriendly(final int a, final int b) {
42+
if (a <= 0 || b <= 0) {
43+
return false;
44+
}
45+
final long sigmaA = sumOfDivisors(a);
46+
final long sigmaB = sumOfDivisors(b);
47+
return sigmaA * b == sigmaB * a;
48+
}
49+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.thealgorithms.maths;
2+
3+
/**
4+
* Sociable numbers are natural numbers that form a cyclic sequence where the
5+
* sum of proper divisors of each number equals the next number in the sequence,
6+
* with the sequence eventually returning to the starting number.
7+
* Amicable numbers are a special case of sociable numbers with a cycle length of 2.
8+
* Example: (12496, 14288, 15472, 14536, 14264) is a sociable cycle of length 5.
9+
*
10+
* @author Vraj Prajapati (@Rosander0)
11+
* @see <a href="https://en.wikipedia.org/wiki/Sociable_number">Wikipedia: Sociable Number</a>
12+
* @see AmicableNumber
13+
*/
14+
public final class SociableNumber {
15+
16+
private SociableNumber() {
17+
// Utility class
18+
}
19+
20+
/**
21+
* Calculates the sum of proper divisors of a number
22+
* (all divisors excluding the number itself).
23+
*
24+
* @param number the number to calculate proper divisors sum for
25+
* @return sum of proper divisors, or 0 if number is less than or equal to 1
26+
*/
27+
static int sumOfProperDivisors(final int number) {
28+
if (number <= 1) {
29+
return 0;
30+
}
31+
int sum = 1; // 1 is a proper divisor of every number > 1
32+
final int root = (int) Math.sqrt(number);
33+
for (int i = 2; i <= root; i++) {
34+
if (number % i == 0) {
35+
final int other = number / i;
36+
sum += i;
37+
if (other != i) {
38+
sum += other;
39+
}
40+
}
41+
}
42+
return sum;
43+
}
44+
45+
/**
46+
* Checks whether a number is part of a sociable cycle of a given length.
47+
* Starting from the given number, it follows the chain of proper divisor
48+
* sums and checks if it returns to the starting number in exactly cycleLength steps.
49+
*
50+
* @param number the starting number (must be positive)
51+
* @param cycleLength the expected cycle length (must be greater than 1)
52+
* @return true if the number is part of a sociable cycle of given length, false otherwise
53+
*/
54+
public static boolean isSociable(final int number, final int cycleLength) {
55+
if (number <= 0 || cycleLength <= 1) {
56+
return false;
57+
}
58+
int current = number;
59+
for (int i = 0; i < cycleLength; i++) {
60+
current = sumOfProperDivisors(current);
61+
if (current == number) {
62+
return i == cycleLength - 1;
63+
}
64+
}
65+
return false;
66+
}
67+
}

src/test/java/com/thealgorithms/conversions/Base64Test.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ void testInvalidPaddingPosition() {
127127
assertThrows(IllegalArgumentException.class, () -> Base64.decode("Q=QQ"));
128128
assertThrows(IllegalArgumentException.class, () -> Base64.decode("Q=Q="));
129129
assertThrows(IllegalArgumentException.class, () -> Base64.decode("=QQQ"));
130+
assertThrows(IllegalArgumentException.class, () -> Base64.decode("QQ=Q"));
131+
assertThrows(IllegalArgumentException.class, () -> Base64.decode("AB=C"));
132+
assertThrows(IllegalArgumentException.class, () -> Base64.decode("AB=A"));
130133
}
131134

132135
@Test

src/test/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithmTest.java

Lines changed: 0 additions & 64 deletions
This file was deleted.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.thealgorithms.maths;
2+
// author: Vraj Prajapati @Rosander0
3+
4+
import static org.junit.jupiter.api.Assertions.assertFalse;
5+
import static org.junit.jupiter.api.Assertions.assertTrue;
6+
7+
import org.junit.jupiter.api.Test;
8+
9+
public class FriendlyNumberTest {
10+
11+
@Test
12+
public void testFriendlyNumbers() {
13+
// 6 and 28 are friendly (abundancy index = 2)
14+
assertTrue(FriendlyNumber.areFriendly(6, 28));
15+
// Every number is friendly with itself
16+
assertTrue(FriendlyNumber.areFriendly(6, 6));
17+
assertTrue(FriendlyNumber.areFriendly(1, 1));
18+
}
19+
20+
@Test
21+
public void testNonFriendlyNumbers() {
22+
assertFalse(FriendlyNumber.areFriendly(6, 10));
23+
assertFalse(FriendlyNumber.areFriendly(10, 15));
24+
assertFalse(FriendlyNumber.areFriendly(4, 9));
25+
}
26+
27+
@Test
28+
public void testInvalidInputs() {
29+
assertFalse(FriendlyNumber.areFriendly(0, 6));
30+
assertFalse(FriendlyNumber.areFriendly(-1, 6));
31+
assertFalse(FriendlyNumber.areFriendly(6, -1));
32+
}
33+
}

0 commit comments

Comments
 (0)