diff --git a/pom.xml b/pom.xml index 2122e6660da3..9049b21e3ba6 100644 --- a/pom.xml +++ b/pom.xml @@ -71,8 +71,7 @@ maven-compiler-plugin 3.14.1 - 21 - 21 + 21 -Xlint:all -Xlint:-auxiliaryclass diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/PartitionProblem.java b/src/main/java/com/thealgorithms/dynamicprogramming/PartitionProblem.java index 49c4a0a3a008..8c72fa347f50 100644 --- a/src/main/java/com/thealgorithms/dynamicprogramming/PartitionProblem.java +++ b/src/main/java/com/thealgorithms/dynamicprogramming/PartitionProblem.java @@ -1,3 +1,5 @@ +package com.thealgorithms.dynamicprogramming; +import java.util.Arrays; /** * @author Md Asif Joardar * @@ -13,11 +15,6 @@ * * The time complexity of the solution is O(n × sum) and requires O(n × sum) space */ - -package com.thealgorithms.dynamicprogramming; - -import java.util.Arrays; - public final class PartitionProblem { private PartitionProblem() { } diff --git a/src/main/java/com/thealgorithms/geometry/Haversine.java b/src/main/java/com/thealgorithms/geometry/Haversine.java new file mode 100644 index 000000000000..fa1799e9f076 --- /dev/null +++ b/src/main/java/com/thealgorithms/geometry/Haversine.java @@ -0,0 +1,49 @@ +package com.thealgorithms.geometry; +/** + * This Class implements the Haversine formula to calculate the distance between two points on a sphere (like Earth) from their latitudes and longitudes. + * + * The Haversine formula is used in navigation and mapping to find the great-circle distance, + * which is the shortest distance between two points along the surface of a sphere. It is often + * used to calculate the "as the crow flies" distance between two geographical locations. + * + * The formula is reliable for all distances, including small ones, and avoids issues with + * numerical instability that can affect other methods. + * + * @see "https://en.wikipedia.org/wiki/Haversine_formula" - Wikipedia + */ +public final class Haversine { + + // Average radius of Earth in kilometers + private static final double EARTH_RADIUS_KM = 6371.0; + + /** + * Private constructor to prevent instantiation of this utility class. + */ + private Haversine() { + } + + /** + * Calculates the great-circle distance between two points on the earth + * (specified in decimal degrees). + * + * @param lat1 Latitude of the first point in decimal degrees. + * @param lon1 Longitude of the first point in decimal degrees. + * @param lat2 Latitude of the second point in decimal degrees. + * @param lon2 Longitude of the second point in decimal degrees. + * @return The distance between the two points in kilometers. + */ + public static double haversine(double lat1, double lon1, double lat2, double lon2) { + // Convert latitude and longitude from degrees to radians + double dLat = Math.toRadians(lat2 - lat1); + double dLon = Math.toRadians(lon2 - lon1); + + double lat1Rad = Math.toRadians(lat1); + double lat2Rad = Math.toRadians(lat2); + + // Apply the Haversine formula + double a = Math.pow(Math.sin(dLat / 2), 2) + Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1Rad) * Math.cos(lat2Rad); + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + + return EARTH_RADIUS_KM * c; + } +} diff --git a/src/test/java/com/thealgorithms/geometry/HaversineTest.java b/src/test/java/com/thealgorithms/geometry/HaversineTest.java new file mode 100644 index 000000000000..b4dcca30a8ac --- /dev/null +++ b/src/test/java/com/thealgorithms/geometry/HaversineTest.java @@ -0,0 +1,60 @@ +package com.thealgorithms.geometry; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.stream.Stream; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +/** + * Unit tests for the Haversine formula implementation. + * This class uses parameterized tests to verify the distance calculation + * between various geographical coordinates. + */ +final class HaversineTest { + + // A small tolerance for comparing double values, since floating-point + // arithmetic is not always exact. A 1km tolerance is reasonable for these distances. + private static final double DELTA = 1.0; + + /** + * Provides test cases for the haversine distance calculation. + * Each argument contains: lat1, lon1, lat2, lon2, and the expected distance in kilometers. + * + * @return a stream of arguments for the parameterized test. + */ + static Stream haversineTestProvider() { + return Stream.of( + // Case 1: Distance between Paris, France and Tokyo, Japan + Arguments.of(48.8566, 2.3522, 35.6895, 139.6917, 9712.0), + + // Case 2: Distance between New York, USA and London, UK + Arguments.of(40.7128, -74.0060, 51.5074, -0.1278, 5570.0), + + // Case 3: Zero distance (same point) + Arguments.of(52.5200, 13.4050, 52.5200, 13.4050, 0.0), + + // Case 4: Antipodal points (opposite sides of the Earth) + // Should be approximately half the Earth's circumference (PI * radius) + Arguments.of(0.0, 0.0, 0.0, 180.0, 20015.0)); + } + + /** + * Tests the haversine method with various sets of coordinates. + * + * @param lat1 Latitude of the first point. + * @param lon1 Longitude of the first point. + * @param lat2 Latitude of the second point. + * @param lon2 Longitude of the second point. + * @param expectedDistance The expected distance in kilometers. + */ + @ParameterizedTest + @MethodSource("haversineTestProvider") + @DisplayName("Test Haversine distance calculation for various coordinates") + void testHaversine(double lat1, double lon1, double lat2, double lon2, double expectedDistance) { + double actualDistance = Haversine.haversine(lat1, lon1, lat2, lon2); + assertEquals(expectedDistance, actualDistance, DELTA); + } +}