Skip to content

Commit 5f6af15

Browse files
authored
Merge branch 'master' into feature/tournament-sort
2 parents bc1bd33 + 0837424 commit 5f6af15

File tree

7 files changed

+343
-2
lines changed

7 files changed

+343
-2
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
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.0.0</version>
23+
<version>6.0.1</version>
2424
<type>pom</type>
2525
<scope>import</scope>
2626
</dependency>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.thealgorithms.graph;
2+
3+
/**
4+
* An implementation of the Stoer-Wagner algorithm to find the global minimum cut of an undirected, weighted graph.
5+
* A minimum cut is a partition of the graph's vertices into two disjoint sets with the minimum possible edge weight
6+
* sum connecting the two sets.
7+
*
8+
* Wikipedia: https://en.wikipedia.org/wiki/Stoer%E2%80%93Wagner_algorithm
9+
* Time Complexity: O(V^3) where V is the number of vertices.
10+
*/
11+
public class StoerWagner {
12+
13+
/**
14+
* Finds the minimum cut in the given undirected, weighted graph.
15+
*
16+
* @param graph An adjacency matrix representing the graph. graph[i][j] is the weight of the edge between i and j.
17+
* @return The weight of the minimum cut.
18+
*/
19+
public int findMinCut(int[][] graph) {
20+
int n = graph.length;
21+
if (n < 2) {
22+
return 0;
23+
}
24+
25+
int[][] currentGraph = new int[n][n];
26+
for (int i = 0; i < n; i++) {
27+
System.arraycopy(graph[i], 0, currentGraph[i], 0, n);
28+
}
29+
30+
int minCut = Integer.MAX_VALUE;
31+
boolean[] merged = new boolean[n];
32+
33+
for (int phase = 0; phase < n - 1; phase++) {
34+
boolean[] inSetA = new boolean[n];
35+
int[] weights = new int[n];
36+
int prev = -1;
37+
int last = -1;
38+
39+
for (int i = 0; i < n - phase; i++) {
40+
int maxWeight = -1;
41+
int currentVertex = -1;
42+
43+
for (int j = 0; j < n; j++) {
44+
if (!merged[j] && !inSetA[j] && weights[j] > maxWeight) {
45+
maxWeight = weights[j];
46+
currentVertex = j;
47+
}
48+
}
49+
50+
if (currentVertex == -1) {
51+
// This can happen if the graph is disconnected.
52+
return 0;
53+
}
54+
55+
prev = last;
56+
last = currentVertex;
57+
inSetA[last] = true;
58+
59+
for (int j = 0; j < n; j++) {
60+
if (!merged[j] && !inSetA[j]) {
61+
weights[j] += currentGraph[last][j];
62+
}
63+
}
64+
}
65+
66+
minCut = Math.min(minCut, weights[last]);
67+
68+
// Merge 'last' vertex into 'prev' vertex
69+
for (int i = 0; i < n; i++) {
70+
currentGraph[prev][i] += currentGraph[last][i];
71+
currentGraph[i][prev] = currentGraph[prev][i];
72+
}
73+
merged[last] = true;
74+
}
75+
76+
return minCut;
77+
}
78+
}

src/main/java/com/thealgorithms/maths/Area.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,25 @@ public static double surfaceAreaSphere(final double radius) {
4848
return 4 * Math.PI * radius * radius;
4949
}
5050

51+
/**
52+
* Calculate the surface area of a pyramid with a square base.
53+
*
54+
* @param sideLength side length of the square base
55+
* @param slantHeight slant height of the pyramid
56+
* @return surface area of the given pyramid
57+
*/
58+
public static double surfaceAreaPyramid(final double sideLength, final double slantHeight) {
59+
if (sideLength <= 0) {
60+
throw new IllegalArgumentException("Must be a positive sideLength");
61+
}
62+
if (slantHeight <= 0) {
63+
throw new IllegalArgumentException("Must be a positive slantHeight");
64+
}
65+
double baseArea = sideLength * sideLength;
66+
double lateralSurfaceArea = 2 * sideLength * slantHeight;
67+
return baseArea + lateralSurfaceArea;
68+
}
69+
5170
/**
5271
* Calculate the area of a rectangle.
5372
*

src/main/java/com/thealgorithms/maths/JugglerSequence.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public static void jugglerSequence(int inputNumber) {
4343
seq.add(n + "");
4444
}
4545
String res = String.join(",", seq);
46-
System.out.println(res);
46+
System.out.print(res + "\n");
4747
}
4848

4949
// Driver code
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.thealgorithms.physics;
2+
3+
/**
4+
* Implements Coulomb's Law for electrostatics.
5+
* Provides simple static methods to calculate electrostatic force and circular orbit velocity.
6+
*
7+
* @author [Priyanshu Singh](https://github.com/Priyanshu1303d)
8+
* @see <a href="https://en.wikipedia.org/wiki/Coulomb%27s_law">Wikipedia</a>
9+
*/
10+
public final class CoulombsLaw {
11+
12+
/** Coulomb's constant in N·m²/C² */
13+
public static final double COULOMBS_CONSTANT = 8.9875517923e9;
14+
15+
/**
16+
* Private constructor to prevent instantiation of this utility class.
17+
*/
18+
private CoulombsLaw() {
19+
}
20+
21+
/**
22+
* Calculates the electrostatic force vector exerted by one charge on another.
23+
* The returned vector is the force *on* the second charge (q2).
24+
*
25+
* @param q1 Charge of the first particle (in Coulombs).
26+
* @param x1 X-position of the first particle (m).
27+
* @param y1 Y-position of the first particle (m).
28+
* @param q2 Charge of the second particle (in Coulombs).
29+
* @param x2 X-position of the second particle (m).
30+
* @param y2 Y-position of the second particle (m).
31+
* @return A double array `[fx, fy]` representing the force vector on the second charge.
32+
*/
33+
public static double[] calculateForceVector(double q1, double x1, double y1, double q2, double x2, double y2) {
34+
// Vector from 1 to 2
35+
double dx = x2 - x1;
36+
double dy = y2 - y1;
37+
double distanceSq = dx * dx + dy * dy;
38+
39+
// If particles are at the same position, force is zero to avoid division by zero.
40+
if (distanceSq == 0) {
41+
return new double[] {0, 0};
42+
}
43+
44+
double distance = Math.sqrt(distanceSq);
45+
// Force magnitude: k * (q1 * q2) / r^2
46+
// A positive result is repulsive (pushes q2 away from q1).
47+
// A negative result is attractive (pulls q2 toward q1).
48+
double forceMagnitude = COULOMBS_CONSTANT * q1 * q2 / distanceSq;
49+
50+
// Calculate the components of the force vector
51+
// (dx / distance) is the unit vector pointing from 1 to 2.
52+
double fx = forceMagnitude * (dx / distance);
53+
double fy = forceMagnitude * (dy / distance);
54+
55+
return new double[] {fx, fy};
56+
}
57+
58+
/**
59+
* Calculates the speed required for a stable circular orbit of a charged particle
60+
* around a central charge (e.g., an electron orbiting a nucleus).
61+
*
62+
* @param centralCharge The charge of the central body (in Coulombs).
63+
* @param orbitingCharge The charge of the orbiting body (in Coulombs).
64+
* @param orbitingMass The mass of the orbiting body (in kg).
65+
* @param radius The radius of the orbit (in m).
66+
* @return The orbital speed (in m/s).
67+
* @throws IllegalArgumentException if mass or radius are not positive.
68+
*/
69+
public static double calculateCircularOrbitVelocity(double centralCharge, double orbitingCharge, double orbitingMass, double radius) {
70+
if (orbitingMass <= 0 || radius <= 0) {
71+
throw new IllegalArgumentException("Orbiting mass and radius must be positive.");
72+
}
73+
74+
// We only need the magnitude of the force, which is always positive.
75+
double forceMagnitude = Math.abs(COULOMBS_CONSTANT * centralCharge * orbitingCharge) / (radius * radius);
76+
77+
// F_c = m * v^2 / r => v = sqrt(F_c * r / m)
78+
return Math.sqrt(forceMagnitude * radius / orbitingMass);
79+
}
80+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.thealgorithms.graph;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import org.junit.jupiter.api.Test;
6+
7+
/**
8+
* Unit tests for the StoerWagner global minimum cut algorithm.
9+
*
10+
* These tests verify correctness of the implementation across
11+
* several graph configurations: simple, complete, disconnected,
12+
* and small edge cases.
13+
*/
14+
public class StoerWagnerTest {
15+
16+
@Test
17+
public void testSimpleGraph() {
18+
int[][] graph = {{0, 3, 2, 0}, {3, 0, 1, 4}, {2, 1, 0, 5}, {0, 4, 5, 0}};
19+
StoerWagner algo = new StoerWagner();
20+
assertEquals(5, algo.findMinCut(graph)); // Correct minimum cut = 5
21+
}
22+
23+
@Test
24+
public void testTriangleGraph() {
25+
int[][] graph = {{0, 2, 3}, {2, 0, 4}, {3, 4, 0}};
26+
StoerWagner algo = new StoerWagner();
27+
assertEquals(5, algo.findMinCut(graph)); // min cut = 5
28+
}
29+
30+
@Test
31+
public void testDisconnectedGraph() {
32+
int[][] graph = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
33+
StoerWagner algo = new StoerWagner();
34+
assertEquals(0, algo.findMinCut(graph)); // Disconnected graph => cut = 0
35+
}
36+
37+
@Test
38+
public void testCompleteGraph() {
39+
int[][] graph = {{0, 1, 1, 1}, {1, 0, 1, 1}, {1, 1, 0, 1}, {1, 1, 1, 0}};
40+
StoerWagner algo = new StoerWagner();
41+
assertEquals(3, algo.findMinCut(graph)); // Each vertex connected to all others
42+
}
43+
44+
@Test
45+
public void testSingleVertex() {
46+
int[][] graph = {{0}};
47+
StoerWagner algo = new StoerWagner();
48+
assertEquals(0, algo.findMinCut(graph)); // Only one vertex
49+
}
50+
51+
@Test
52+
public void testTwoVertices() {
53+
int[][] graph = {{0, 7}, {7, 0}};
54+
StoerWagner algo = new StoerWagner();
55+
assertEquals(7, algo.findMinCut(graph)); // Only one edge, cut weight = 7
56+
}
57+
58+
@Test
59+
public void testSquareGraphWithDiagonal() {
60+
int[][] graph = {{0, 2, 0, 2}, {2, 0, 3, 0}, {0, 3, 0, 4}, {2, 0, 4, 0}};
61+
StoerWagner algo = new StoerWagner();
62+
assertEquals(4, algo.findMinCut(graph)); // verified manually
63+
}
64+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package com.thealgorithms.physics;
2+
3+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4+
import static org.junit.jupiter.api.Assertions.assertEquals;
5+
import static org.junit.jupiter.api.Assertions.assertThrows;
6+
7+
import org.junit.jupiter.api.DisplayName;
8+
import org.junit.jupiter.api.Test;
9+
10+
/**
11+
* Unit tests for the CoulombsLaw utility class.
12+
*/
13+
final class CoulombsLawTest {
14+
15+
// A small tolerance (delta) for comparing floating-point numbers
16+
private static final double DELTA = 1e-9;
17+
private static final double K = CoulombsLaw.COULOMBS_CONSTANT;
18+
19+
@Test
20+
@DisplayName("Test repulsive force between two charges on the x-axis")
21+
void testSimpleRepulsiveForce() {
22+
// Two positive 1C charges, 1 meter apart.
23+
// Force on q2 should be F = K*1*1 / 1^2 = K, directed away from q1 (positive x)
24+
double[] forceOnB = CoulombsLaw.calculateForceVector(1.0, 0, 0, 1.0, 1, 0);
25+
assertArrayEquals(new double[] {K, 0.0}, forceOnB, DELTA);
26+
27+
// Force on q1 should be equal and opposite (negative x)
28+
double[] forceOnA = CoulombsLaw.calculateForceVector(1.0, 1, 0, 1.0, 0, 0);
29+
assertArrayEquals(new double[] {-K, 0.0}, forceOnA, DELTA);
30+
}
31+
32+
@Test
33+
@DisplayName("Test attractive force between two charges on the x-axis")
34+
void testSimpleAttractiveForce() {
35+
// One positive 1C, one negative -1C, 1 meter apart.
36+
// Force on q2 should be F = K*1*(-1) / 1^2 = -K, directed toward q1 (negative x)
37+
double[] forceOnB = CoulombsLaw.calculateForceVector(1.0, 0, 0, -1.0, 1, 0);
38+
assertArrayEquals(new double[] {-K, 0.0}, forceOnB, DELTA);
39+
}
40+
41+
@Test
42+
@DisplayName("Test electrostatic force in a 2D plane (repulsive)")
43+
void test2DRepulsiveForce() {
44+
// q1 at (0,0) with charge +2C
45+
// q2 at (3,4) with charge +1C
46+
// Distance is 5 meters.
47+
double magnitude = K * 2.0 * 1.0 / 25.0; // 2K/25
48+
// Unit vector from 1 to 2 is (3/5, 4/5)
49+
double expectedFx = magnitude * (3.0 / 5.0); // 6K / 125
50+
double expectedFy = magnitude * (4.0 / 5.0); // 8K / 125
51+
52+
double[] forceOnB = CoulombsLaw.calculateForceVector(2.0, 0, 0, 1.0, 3, 4);
53+
assertArrayEquals(new double[] {expectedFx, expectedFy}, forceOnB, DELTA);
54+
}
55+
56+
@Test
57+
@DisplayName("Test overlapping charges should result in zero force")
58+
void testOverlappingCharges() {
59+
double[] force = CoulombsLaw.calculateForceVector(1.0, 1.5, -2.5, -1.0, 1.5, -2.5);
60+
assertArrayEquals(new double[] {0.0, 0.0}, force, DELTA);
61+
}
62+
63+
@Test
64+
@DisplayName("Test circular orbit velocity with simple values")
65+
void testCircularOrbitVelocity() {
66+
// v = sqrt( (K*1*1 / 1^2) * 1 / 1 ) = sqrt(K)
67+
double velocity = CoulombsLaw.calculateCircularOrbitVelocity(1.0, 1.0, 1.0, 1.0);
68+
assertEquals(Math.sqrt(K), velocity, DELTA);
69+
}
70+
71+
@Test
72+
@DisplayName("Test orbital velocity for a Hydrogen atom (Bohr model)")
73+
void testHydrogenAtomVelocity() {
74+
// Charge of a proton
75+
double protonCharge = 1.602176634e-19;
76+
// Charge of an electron
77+
double electronCharge = -1.602176634e-19;
78+
// Mass of an electron
79+
double electronMass = 9.1093837e-31;
80+
// Bohr radius (avg distance)
81+
double bohrRadius = 5.29177e-11;
82+
83+
double expectedVelocity = 2.1876917e6;
84+
85+
double velocity = CoulombsLaw.calculateCircularOrbitVelocity(protonCharge, electronCharge, electronMass, bohrRadius);
86+
// Use a wider delta for this real-world calculation
87+
assertEquals(expectedVelocity, velocity, 1.0);
88+
}
89+
90+
@Test
91+
@DisplayName("Test invalid inputs for orbital velocity throw exception")
92+
void testInvalidOrbitalVelocityInputs() {
93+
// Non-positive mass
94+
assertThrows(IllegalArgumentException.class, () -> CoulombsLaw.calculateCircularOrbitVelocity(1, 1, 0, 100));
95+
assertThrows(IllegalArgumentException.class, () -> CoulombsLaw.calculateCircularOrbitVelocity(1, 1, -1, 100));
96+
// Non-positive radius
97+
assertThrows(IllegalArgumentException.class, () -> CoulombsLaw.calculateCircularOrbitVelocity(1, 1, 1, 0));
98+
assertThrows(IllegalArgumentException.class, () -> CoulombsLaw.calculateCircularOrbitVelocity(1, 1, 1, -100));
99+
}
100+
}

0 commit comments

Comments
 (0)