diff --git a/.github/workflows/clang-format-lint.yml b/.github/workflows/clang-format-lint.yml
index 588c05e42e8f..dac697511de1 100644
--- a/.github/workflows/clang-format-lint.yml
+++ b/.github/workflows/clang-format-lint.yml
@@ -9,7 +9,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- - uses: DoozyX/clang-format-lint-action@v0.18
+ - uses: DoozyX/clang-format-lint-action@v0.20
with:
source: './src'
extensions: 'java'
diff --git a/.gitpod.dockerfile b/.gitpod.dockerfile
index f426f0921028..ea6d32a5a377 100644
--- a/.gitpod.dockerfile
+++ b/.gitpod.dockerfile
@@ -1,4 +1,4 @@
-FROM gitpod/workspace-java-21:2024-09-11-00-04-27
+FROM gitpod/workspace-java-21:2025-02-10-10-54-28
ENV LLVM_SCRIPT="tmp_llvm.sh"
diff --git a/DIRECTORY.md b/DIRECTORY.md
index 01e031b58581..fe9e440da3e2 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -5,6 +5,7 @@
* com
* thealgorithms
* audiofilters
+ * [EMAFilter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/audiofilters/EMAFilter.java)
* [IIRFilter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/audiofilters/IIRFilter.java)
* backtracking
* [AllPathsFromSourceToTarget](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/backtracking/AllPathsFromSourceToTarget.java)
@@ -107,6 +108,7 @@
* [IPConverter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/IPConverter.java)
* [IPv6Converter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/IPv6Converter.java)
* [MorseCodeConverter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/MorseCodeConverter.java)
+ * [NumberToWords](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/NumberToWords.java)
* [OctalToBinary](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/OctalToBinary.java)
* [OctalToDecimal](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/OctalToDecimal.java)
* [OctalToHexadecimal](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/OctalToHexadecimal.java)
@@ -116,6 +118,7 @@
* [TurkishToLatinConversion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/TurkishToLatinConversion.java)
* [UnitConversions](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/UnitConversions.java)
* [UnitsConverter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/UnitsConverter.java)
+ * [WordsToNumber](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/WordsToNumber.java)
* datastructures
* bags
* [Bag](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/bags/Bag.java)
@@ -147,6 +150,7 @@
* [ConnectedComponent](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/ConnectedComponent.java)
* [Cycles](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/Cycles.java)
* [DijkstraAlgorithm](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithm.java)
+ * [DijkstraOptimizedAlgorithm](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithm.java)
* [EdmondsBlossomAlgorithm](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/EdmondsBlossomAlgorithm.java)
* [FloydWarshall](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/FloydWarshall.java)
* [FordFulkerson](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/FordFulkerson.java)
@@ -159,6 +163,7 @@
* [MatrixGraphs](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/MatrixGraphs.java)
* [PrimMST](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/PrimMST.java)
* [TarjansAlgorithm](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/TarjansAlgorithm.java)
+ * [UndirectedAdjacencyListGraph](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/UndirectedAdjacencyListGraph.java)
* [WelshPowell](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/WelshPowell.java)
* hashmap
* hashing
@@ -316,6 +321,7 @@
* [SubsetSum](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/SubsetSum.java)
* [SubsetSumSpaceOptimized](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/SubsetSumSpaceOptimized.java)
* [SumOfSubset](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/SumOfSubset.java)
+ * [TreeMatching](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/TreeMatching.java)
* [Tribonacci](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/Tribonacci.java)
* [UniquePaths](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/UniquePaths.java)
* [UniqueSubsequencesCount](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/UniqueSubsequencesCount.java)
@@ -329,6 +335,7 @@
* [MidpointEllipse](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/geometry/MidpointEllipse.java)
* [Point](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/geometry/Point.java)
* graph
+ * [ConstrainedShortestPath](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/graph/ConstrainedShortestPath.java)
* [StronglyConnectedComponentOptimized](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/graph/StronglyConnectedComponentOptimized.java)
* greedyalgorithms
* [ActivitySelection](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/ActivitySelection.java)
@@ -404,6 +411,7 @@
* [GCD](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/GCD.java)
* [GCDRecursion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/GCDRecursion.java)
* [GenericRoot](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/GenericRoot.java)
+ * [GoldbachConjecture](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/GoldbachConjecture.java)
* [HarshadNumber](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/HarshadNumber.java)
* [HeronsFormula](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/HeronsFormula.java)
* [JosephusProblem](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/JosephusProblem.java)
@@ -415,18 +423,14 @@
* [LeastCommonMultiple](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/LeastCommonMultiple.java)
* [LeonardoNumber](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/LeonardoNumber.java)
* [LinearDiophantineEquationsSolver](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/LinearDiophantineEquationsSolver.java)
- * [LiouvilleLambdaFunction](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/LiouvilleLambdaFunction.java)
* [LongDivision](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/LongDivision.java)
* [LucasSeries](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/LucasSeries.java)
* [MagicSquare](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/MagicSquare.java)
- * [MatrixRank](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/MatrixRank.java)
- * [MatrixUtil](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/MatrixUtil.java)
+ * [MathBuilder](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/MathBuilder.java)
* [MaxValue](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/MaxValue.java)
* [Means](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Means.java)
* [Median](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Median.java)
- * [MillerRabinPrimalityCheck](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/MillerRabinPrimalityCheck.java)
* [MinValue](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/MinValue.java)
- * [MobiusFunction](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/MobiusFunction.java)
* [Mode](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Mode.java)
* [NonRepeatingElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/NonRepeatingElement.java)
* [NthUglyNumber](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/NthUglyNumber.java)
@@ -443,8 +447,13 @@
* [Pow](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Pow.java)
* [PowerOfTwoOrNot](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/PowerOfTwoOrNot.java)
* [PowerUsingRecursion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/PowerUsingRecursion.java)
- * [PrimeCheck](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/PrimeCheck.java)
- * [PrimeFactorization](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/PrimeFactorization.java)
+ * Prime
+ * [LiouvilleLambdaFunction](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Prime/LiouvilleLambdaFunction.java)
+ * [MillerRabinPrimalityCheck](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Prime/MillerRabinPrimalityCheck.java)
+ * [MobiusFunction](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Prime/MobiusFunction.java)
+ * [PrimeCheck](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Prime/PrimeCheck.java)
+ * [PrimeFactorization](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Prime/PrimeFactorization.java)
+ * [SquareFreeInteger](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Prime/SquareFreeInteger.java)
* [PronicNumber](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/PronicNumber.java)
* [PythagoreanTriple](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/PythagoreanTriple.java)
* [QuadraticEquationSolver](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/QuadraticEquationSolver.java)
@@ -454,7 +463,6 @@
* [SieveOfEratosthenes](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/SieveOfEratosthenes.java)
* [SimpsonIntegration](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/SimpsonIntegration.java)
* [SolovayStrassenPrimalityTest](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/SolovayStrassenPrimalityTest.java)
- * [SquareFreeInteger](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/SquareFreeInteger.java)
* [SquareRootWithBabylonianMethod](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/SquareRootWithBabylonianMethod.java)
* [SquareRootWithNewtonRaphsonMethod](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/SquareRootWithNewtonRaphsonMethod.java)
* [StandardDeviation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/StandardDeviation.java)
@@ -470,21 +478,27 @@
* [VampireNumber](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/VampireNumber.java)
* [VectorCrossProduct](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/VectorCrossProduct.java)
* [Volume](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/Volume.java)
- * matrixexponentiation
- * [Fibonacci](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/matrixexponentiation/Fibonacci.java)
+ * matrix
+ * [InverseOfMatrix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/matrix/InverseOfMatrix.java)
+ * matrixexponentiation
+ * [Fibonacci](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/matrix/matrixexponentiation/Fibonacci.java)
+ * [MatrixRank](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/matrix/MatrixRank.java)
+ * [MatrixTranspose](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/matrix/MatrixTranspose.java)
+ * [MedianOfMatrix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/matrix/MedianOfMatrix.java)
+ * [MirrorOfMatrix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/matrix/MirrorOfMatrix.java)
+ * [PrintAMatrixInSpiralOrder](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/matrix/PrintAMatrixInSpiralOrder.java)
+ * [RotateMatrixBy90Degrees](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/matrix/RotateMatrixBy90Degrees.java)
+ * utils
+ * [MatrixUtil](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/matrix/utils/MatrixUtil.java)
* misc
* [ColorContrastRatio](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/ColorContrastRatio.java)
- * [InverseOfMatrix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/InverseOfMatrix.java)
* [MapReduce](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/MapReduce.java)
- * [MatrixTranspose](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/MatrixTranspose.java)
- * [MedianOfMatrix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/MedianOfMatrix.java)
* [MedianOfRunningArray](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/MedianOfRunningArray.java)
* [MedianOfRunningArrayByte](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/MedianOfRunningArrayByte.java)
* [MedianOfRunningArrayDouble](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/MedianOfRunningArrayDouble.java)
* [MedianOfRunningArrayFloat](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/MedianOfRunningArrayFloat.java)
* [MedianOfRunningArrayInteger](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/MedianOfRunningArrayInteger.java)
* [MedianOfRunningArrayLong](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/MedianOfRunningArrayLong.java)
- * [MirrorOfMatrix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/MirrorOfMatrix.java)
* [PalindromePrime](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/PalindromePrime.java)
* [PalindromeSinglyLinkedList](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/PalindromeSinglyLinkedList.java)
* [RangeInSortedArray](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/RangeInSortedArray.java)
@@ -492,7 +506,6 @@
* [Sparsity](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/Sparsity.java)
* [ThreeSumProblem](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/ThreeSumProblem.java)
* [TwoSumProblem](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/TwoSumProblem.java)
- * [WordBoggle](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/misc/WordBoggle.java)
* others
* [ArrayLeftRotation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/ArrayLeftRotation.java)
* [ArrayRightRotation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/ArrayRightRotation.java)
@@ -508,7 +521,6 @@
* [CRCAlgorithm](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/CRCAlgorithm.java)
* [Damm](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/Damm.java)
* [Dijkstra](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/Dijkstra.java)
- * [FibbonaciSeries](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/FibbonaciSeries.java)
* [FloydTriangle](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/FloydTriangle.java)
* [GaussLegendre](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/GaussLegendre.java)
* [HappyNumbersSeq](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/HappyNumbersSeq.java)
@@ -533,14 +545,16 @@
* [QueueUsingTwoStacks](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/QueueUsingTwoStacks.java)
* [RemoveDuplicateFromString](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/RemoveDuplicateFromString.java)
* [ReverseStackUsingRecursion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/ReverseStackUsingRecursion.java)
- * [RotateMatrixBy90Degrees](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/RotateMatrixBy90Degrees.java)
* [SkylineProblem](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/SkylineProblem.java)
- * [Sudoku](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/Sudoku.java)
- * [TowerOfHanoi](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/TowerOfHanoi.java)
* [TwoPointers](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/TwoPointers.java)
* [Verhoeff](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/Verhoeff.java)
- * Recursion
- * [GenerateSubsets](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/Recursion/GenerateSubsets.java)
+ * puzzlesandgames
+ * [Sudoku](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/puzzlesandgames/Sudoku.java)
+ * [TowerOfHanoi](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/puzzlesandgames/TowerOfHanoi.java)
+ * [WordBoggle](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/puzzlesandgames/WordBoggle.java)
+ * recursion
+ * [FibonacciSeries](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/recursion/FibonacciSeries.java)
+ * [GenerateSubsets](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/recursion/GenerateSubsets.java)
* scheduling
* [AgingScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/AgingScheduling.java)
* diskscheduling
@@ -618,6 +632,7 @@
* [CombSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CombSort.java)
* [CountingSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CountingSort.java)
* [CycleSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CycleSort.java)
+ * [DarkSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DarkSort.java)
* [DualPivotQuickSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DualPivotQuickSort.java)
* [DutchNationalFlagSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DutchNationalFlagSort.java)
* [ExchangeSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/ExchangeSort.java)
@@ -713,11 +728,14 @@
* [WordLadder](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/strings/WordLadder.java)
* zigZagPattern
* [ZigZagPattern](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/strings/zigZagPattern/ZigZagPattern.java)
+ * tree
+ * [HeavyLightDecomposition](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/tree/HeavyLightDecomposition.java)
* test
* java
* com
* thealgorithms
* audiofilters
+ * [EMAFilterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/audiofilters/EMAFilterTest.java)
* [IIRFilterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/audiofilters/IIRFilterTest.java)
* backtracking
* [AllPathsFromSourceToTargetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/backtracking/AllPathsFromSourceToTargetTest.java)
@@ -814,6 +832,7 @@
* [IPConverterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/IPConverterTest.java)
* [IPv6ConverterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/IPv6ConverterTest.java)
* [MorseCodeConverterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/MorseCodeConverterTest.java)
+ * [NumberToWordsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/NumberToWordsTest.java)
* [OctalToBinaryTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/OctalToBinaryTest.java)
* [OctalToDecimalTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/OctalToDecimalTest.java)
* [OctalToHexadecimalTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/OctalToHexadecimalTest.java)
@@ -822,6 +841,7 @@
* [TurkishToLatinConversionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/TurkishToLatinConversionTest.java)
* [UnitConversionsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/UnitConversionsTest.java)
* [UnitsConverterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/UnitsConverterTest.java)
+ * [WordsToNumberTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/WordsToNumberTest.java)
* datastructures
* bag
* [BagTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/bag/BagTest.java)
@@ -849,6 +869,7 @@
* [BipartiteGraphDFSTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/BipartiteGraphDFSTest.java)
* [BoruvkaAlgorithmTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithmTest.java)
* [DijkstraAlgorithmTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraAlgorithmTest.java)
+ * [DijkstraOptimizedAlgorithmTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithmTest.java)
* [EdmondsBlossomAlgorithmTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/EdmondsBlossomAlgorithmTest.java)
* [FloydWarshallTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/FloydWarshallTest.java)
* [FordFulkersonTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/FordFulkersonTest.java)
@@ -988,6 +1009,7 @@
* [SubsetSumSpaceOptimizedTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/SubsetSumSpaceOptimizedTest.java)
* [SubsetSumTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/SubsetSumTest.java)
* [SumOfSubsetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/SumOfSubsetTest.java)
+ * [TreeMatchingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/TreeMatchingTest.java)
* [TribonacciTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/TribonacciTest.java)
* [UniquePathsTests](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/UniquePathsTests.java)
* [UniqueSubsequencesCountTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/UniqueSubsequencesCountTest.java)
@@ -1000,6 +1022,7 @@
* [MidpointCircleTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/geometry/MidpointCircleTest.java)
* [MidpointEllipseTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/geometry/MidpointEllipseTest.java)
* graph
+ * [ConstrainedShortestPathTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/graph/ConstrainedShortestPathTest.java)
* [StronglyConnectedComponentOptimizedTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/graph/StronglyConnectedComponentOptimizedTest.java)
* greedyalgorithms
* [ActivitySelectionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/ActivitySelectionTest.java)
@@ -1070,6 +1093,7 @@
* [GCDRecursionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/GCDRecursionTest.java)
* [GCDTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/GCDTest.java)
* [GenericRootTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/GenericRootTest.java)
+ * [GoldbachConjectureTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/GoldbachConjectureTest.java)
* [HarshadNumberTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/HarshadNumberTest.java)
* [HeronsFormulaTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/HeronsFormulaTest.java)
* [JosephusProblemTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/JosephusProblemTest.java)
@@ -1078,17 +1102,13 @@
* [KrishnamurthyNumberTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/KrishnamurthyNumberTest.java)
* [LeastCommonMultipleTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/LeastCommonMultipleTest.java)
* [LeonardoNumberTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/LeonardoNumberTest.java)
- * [LiouvilleLambdaFunctionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/LiouvilleLambdaFunctionTest.java)
* [LongDivisionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/LongDivisionTest.java)
* [LucasSeriesTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/LucasSeriesTest.java)
- * [MatrixRankTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/MatrixRankTest.java)
- * [MatrixUtilTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/MatrixUtilTest.java)
+ * [MathBuilderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/MathBuilderTest.java)
* [MaxValueTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/MaxValueTest.java)
* [MeansTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/MeansTest.java)
* [MedianTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/MedianTest.java)
- * [MillerRabinPrimalityCheckTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/MillerRabinPrimalityCheckTest.java)
* [MinValueTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/MinValueTest.java)
- * [MobiusFunctionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/MobiusFunctionTest.java)
* [ModeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/ModeTest.java)
* [NonRepeatingElementTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/NonRepeatingElementTest.java)
* [NthUglyNumberTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/NthUglyNumberTest.java)
@@ -1104,8 +1124,12 @@
* [PowerOfTwoOrNotTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/PowerOfTwoOrNotTest.java)
* [PowerUsingRecursionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/PowerUsingRecursionTest.java)
* [PowTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/PowTest.java)
- * [PrimeCheckTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/PrimeCheckTest.java)
- * [PrimeFactorizationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/PrimeFactorizationTest.java)
+ * prime
+ * [LiouvilleLambdaFunctionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/prime/LiouvilleLambdaFunctionTest.java)
+ * [MillerRabinPrimalityCheckTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/prime/MillerRabinPrimalityCheckTest.java)
+ * [MobiusFunctionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/prime/MobiusFunctionTest.java)
+ * [PrimeCheckTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/prime/PrimeCheckTest.java)
+ * [PrimeFactorizationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/prime/PrimeFactorizationTest.java)
* [PronicNumberTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/PronicNumberTest.java)
* [PythagoreanTripleTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/PythagoreanTripleTest.java)
* [QuadraticEquationSolverTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/QuadraticEquationSolverTest.java)
@@ -1126,15 +1150,20 @@
* [TestArmstrong](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/TestArmstrong.java)
* [TwinPrimeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/TwinPrimeTest.java)
* [UniformNumbersTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/UniformNumbersTest.java)
+ * [VampireNumberTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/VampireNumberTest.java)
* [VolumeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/VolumeTest.java)
+ * matrix
+ * [InverseOfMatrixTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/matrix/InverseOfMatrixTest.java)
+ * [MatrixRankTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/matrix/MatrixRankTest.java)
+ * [MatrixTransposeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/matrix/MatrixTransposeTest.java)
+ * [MatrixUtilTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/matrix/MatrixUtilTest.java)
+ * [MedianOfMatrixTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/matrix/MedianOfMatrixTest.java)
+ * [MirrorOfMatrixTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/matrix/MirrorOfMatrixTest.java)
+ * [TestPrintMatrixInSpiralOrder](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/matrix/TestPrintMatrixInSpiralOrder.java)
* misc
* [ColorContrastRatioTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/ColorContrastRatioTest.java)
- * [InverseOfMatrixTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/InverseOfMatrixTest.java)
* [MapReduceTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/MapReduceTest.java)
- * [MatrixTransposeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/MatrixTransposeTest.java)
- * [MedianOfMatrixtest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/MedianOfMatrixtest.java)
* [MedianOfRunningArrayTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/MedianOfRunningArrayTest.java)
- * [MirrorOfMatrixTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/MirrorOfMatrixTest.java)
* [PalindromePrimeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/PalindromePrimeTest.java)
* [PalindromeSinglyLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/PalindromeSinglyLinkedListTest.java)
* [RangeInSortedArrayTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/RangeInSortedArrayTest.java)
@@ -1142,7 +1171,6 @@
* [SparsityTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/SparsityTest.java)
* [ThreeSumProblemTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/ThreeSumProblemTest.java)
* [TwoSumProblemTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/TwoSumProblemTest.java)
- * [WordBoggleTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/WordBoggleTest.java)
* others
* [ArrayLeftRotationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/ArrayLeftRotationTest.java)
* [ArrayRightRotationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/ArrayRightRotationTest.java)
@@ -1170,13 +1198,16 @@
* [RemoveDuplicateFromStringTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/RemoveDuplicateFromStringTest.java)
* [ReverseStackUsingRecursionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/ReverseStackUsingRecursionTest.java)
* [SkylineProblemTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/SkylineProblemTest.java)
- * [SudokuTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/SudokuTest.java)
* [TestPrintMatrixInSpiralOrder](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/TestPrintMatrixInSpiralOrder.java)
- * [TowerOfHanoiTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/TowerOfHanoiTest.java)
* [TwoPointersTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/TwoPointersTest.java)
* [WorstFitCPUTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/WorstFitCPUTest.java)
- * Recursion
- * [GenerateSubsetsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/Recursion/GenerateSubsetsTest.java)
+ * puzzlesandgames
+ * [SudokuTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/puzzlesandgames/SudokuTest.java)
+ * [TowerOfHanoiTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/puzzlesandgames/TowerOfHanoiTest.java)
+ * [WordBoggleTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/puzzlesandgames/WordBoggleTest.java)
+ * recursion
+ * [FibonacciSeriesTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/recursion/FibonacciSeriesTest.java)
+ * [GenerateSubsetsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/recursion/GenerateSubsetsTest.java)
* scheduling
* [AgingSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/AgingSchedulingTest.java)
* diskscheduling
@@ -1255,6 +1286,7 @@
* [CombSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CombSortTest.java)
* [CountingSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CountingSortTest.java)
* [CycleSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CycleSortTest.java)
+ * [DarkSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/DarkSortTest.java)
* [DualPivotQuickSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/DualPivotQuickSortTest.java)
* [DutchNationalFlagSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/DutchNationalFlagSortTest.java)
* [ExchangeSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/ExchangeSortTest.java)
@@ -1346,3 +1378,5 @@
* [WordLadderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/strings/WordLadderTest.java)
* zigZagPattern
* [ZigZagPatternTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/strings/zigZagPattern/ZigZagPatternTest.java)
+ * tree
+ * [HeavyLightDecompositionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/tree/HeavyLightDecompositionTest.java)
diff --git a/pmd-exclude.properties b/pmd-exclude.properties
index f6ee88196962..1848412c9d30 100644
--- a/pmd-exclude.properties
+++ b/pmd-exclude.properties
@@ -1,29 +1,19 @@
-com.thealgorithms.bitmanipulation.SingleBitOperations=UselessParentheses
com.thealgorithms.ciphers.AffineCipher=UselessParentheses
-com.thealgorithms.ciphers.ColumnarTranspositionCipher=UnnecessaryFullyQualifiedName
com.thealgorithms.ciphers.DES=UselessParentheses
-com.thealgorithms.ciphers.HillCipher=UselessParentheses
com.thealgorithms.ciphers.RSA=UselessParentheses
com.thealgorithms.conversions.AnyBaseToAnyBase=UselessParentheses
com.thealgorithms.conversions.AnytoAny=UselessParentheses
-com.thealgorithms.conversions.HexToOct=UselessParentheses
-com.thealgorithms.conversions.IntegerToRoman=UnnecessaryFullyQualifiedName
-com.thealgorithms.datastructures.crdt.LWWElementSet=UselessParentheses
com.thealgorithms.datastructures.crdt.Pair=UnusedPrivateField
com.thealgorithms.datastructures.graphs.AStar=UselessParentheses
com.thealgorithms.datastructures.graphs.AdjacencyMatrixGraph=CollapsibleIfStatements,UnnecessaryFullyQualifiedName,UselessParentheses
com.thealgorithms.datastructures.graphs.BipartiteGraphDFS=CollapsibleIfStatements
-com.thealgorithms.datastructures.graphs.Kruskal=UselessParentheses
com.thealgorithms.datastructures.hashmap.hashing.HashMapCuckooHashing=UselessParentheses
com.thealgorithms.datastructures.heaps.FibonacciHeap=UselessParentheses
-com.thealgorithms.datastructures.heaps.HeapElement=UselessParentheses
com.thealgorithms.datastructures.heaps.HeapNode=UselessParentheses
com.thealgorithms.datastructures.lists.DoublyLinkedList=UselessParentheses
com.thealgorithms.datastructures.lists.SearchSinglyLinkedListRecursion=UselessParentheses
com.thealgorithms.datastructures.lists.SinglyLinkedList=UnusedLocalVariable
com.thealgorithms.datastructures.queues.PriorityQueue=UselessParentheses
-com.thealgorithms.datastructures.stacks.NodeStack=UnnecessaryFullyQualifiedName,UnusedFormalParameter
-com.thealgorithms.datastructures.stacks.StackArray=UselessParentheses
com.thealgorithms.datastructures.trees.CheckBinaryTreeIsValidBST=UselessParentheses
com.thealgorithms.datastructures.trees.SegmentTree=UselessParentheses
com.thealgorithms.devutils.nodes.LargeTreeNode=UselessParentheses
@@ -32,9 +22,6 @@ com.thealgorithms.devutils.nodes.SimpleTreeNode=UselessParentheses
com.thealgorithms.devutils.nodes.TreeNode=UselessParentheses
com.thealgorithms.divideandconquer.ClosestPair=UnnecessaryFullyQualifiedName,UselessParentheses
com.thealgorithms.divideandconquer.Point=UselessParentheses
-com.thealgorithms.dynamicprogramming.MatrixChainMultiplication=UselessParentheses
-com.thealgorithms.dynamicprogramming.ShortestSuperSequence=UselessParentheses
-com.thealgorithms.dynamicprogramming.UniquePaths=UnnecessarySemicolon
com.thealgorithms.dynamicprogramming.WineProblem=UselessParentheses
com.thealgorithms.maths.BinomialCoefficient=UselessParentheses
com.thealgorithms.maths.Complex=UselessParentheses
@@ -46,45 +33,32 @@ com.thealgorithms.maths.KaprekarNumbers=UselessParentheses
com.thealgorithms.maths.KeithNumber=UselessParentheses
com.thealgorithms.maths.LeonardoNumber=UselessParentheses
com.thealgorithms.maths.LinearDiophantineEquationsSolver=UselessParentheses
-com.thealgorithms.maths.MatrixUtil=UselessParentheses
com.thealgorithms.maths.RomanNumeralUtil=UselessParentheses
com.thealgorithms.maths.SecondMinMax=UselessParentheses
com.thealgorithms.maths.SecondMinMaxTest=UnnecessaryFullyQualifiedName
com.thealgorithms.maths.StandardDeviation=UselessParentheses
com.thealgorithms.maths.SumOfArithmeticSeries=UselessParentheses
com.thealgorithms.maths.TrinomialTriangle=UselessParentheses
-com.thealgorithms.maths.VampireNumber=CollapsibleIfStatements
com.thealgorithms.maths.Volume=UselessParentheses
-com.thealgorithms.matrixexponentiation.Fibonacci=UnnecessaryFullyQualifiedName
com.thealgorithms.misc.Sparsity=UselessParentheses
-com.thealgorithms.misc.ThreeSumProblem=UselessParentheses
-com.thealgorithms.misc.WordBoggle=UselessParentheses
com.thealgorithms.others.CRC16=UselessParentheses
com.thealgorithms.others.Damm=UnnecessaryFullyQualifiedName
com.thealgorithms.others.Luhn=UnnecessaryFullyQualifiedName
com.thealgorithms.others.Mandelbrot=UselessParentheses
-com.thealgorithms.others.MaximumSumOfDistinctSubarraysWithLengthK=CollapsibleIfStatements
com.thealgorithms.others.MiniMaxAlgorithm=UselessParentheses
com.thealgorithms.others.PageRank=UselessParentheses
com.thealgorithms.others.PerlinNoise=UselessParentheses
com.thealgorithms.others.QueueUsingTwoStacks=UselessParentheses
-com.thealgorithms.others.QueueWithStack=UselessParentheses
com.thealgorithms.others.Trieac=UselessParentheses
com.thealgorithms.others.Verhoeff=UnnecessaryFullyQualifiedName
com.thealgorithms.searches.InterpolationSearch=UselessParentheses
com.thealgorithms.searches.KMPSearch=UselessParentheses
-com.thealgorithms.searches.LinearSearchThread=EmptyCatchBlock
com.thealgorithms.searches.RabinKarpAlgorithm=UselessParentheses
com.thealgorithms.sorts.CircleSort=EmptyControlStatement
-com.thealgorithms.sorts.CombSort=UselessParentheses
com.thealgorithms.sorts.DutchNationalFlagSort=UselessParentheses
-com.thealgorithms.sorts.LinkListSort=EmptyControlStatement,UnusedLocalVariable
com.thealgorithms.sorts.MergeSortNoExtraSpace=UselessParentheses
-com.thealgorithms.sorts.PigeonholeSort=UselessParentheses
com.thealgorithms.sorts.RadixSort=UselessParentheses
com.thealgorithms.sorts.WiggleSort=UselessParentheses
com.thealgorithms.stacks.PostfixToInfix=UselessParentheses
com.thealgorithms.strings.HorspoolSearch=UnnecessaryFullyQualifiedName,UselessParentheses
-com.thealgorithms.strings.MyAtoi=UselessParentheses
com.thealgorithms.strings.Palindrome=UselessParentheses
-com.thealgorithms.strings.Solution=CollapsibleIfStatements
diff --git a/pom.xml b/pom.xml
index 402193e165ef..04128a7a3430 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@
UTF-82121
- 3.26.3
+ 3.27.3
@@ -20,7 +20,7 @@
org.junitjunit-bom
- 5.11.3
+ 5.12.2pomimport
@@ -31,7 +31,6 @@
org.junit.jupiterjunit-jupiter
- 5.11.3test
@@ -43,15 +42,7 @@
org.mockitomockito-core
- 5.14.2
- test
-
-
-
-
- org.junit.jupiter
- junit-jupiter-api
- 5.11.3
+ 5.17.0test
@@ -62,7 +53,7 @@
org.apache.commonscommons-collections4
- 4.5.0-M2
+ 4.5.0
@@ -70,7 +61,7 @@
maven-surefire-plugin
- 3.5.2
+ 3.5.3
@@ -78,7 +69,7 @@
org.apache.maven.pluginsmaven-compiler-plugin
- 3.13.0
+ 3.14.02121
@@ -87,7 +78,6 @@
-Xlint:-auxiliaryclass-Xlint:-rawtypes-Xlint:-unchecked
- -Xlint:-lossy-conversions-Werror
@@ -95,7 +85,7 @@
org.jacocojacoco-maven-plugin
- 0.8.12
+ 0.8.13
@@ -125,14 +115,14 @@
com.puppycrawl.toolscheckstyle
- 10.20.1
+ 10.23.1com.github.spotbugsspotbugs-maven-plugin
- 4.8.6.6
+ 4.9.3.0spotbugs-exclude.xmltrue
@@ -140,12 +130,12 @@
com.mebigfatguy.fb-contribfb-contrib
- 7.6.8
+ 7.6.9com.h3xstream.findsecbugsfindsecbugs-plugin
- 1.13.0
+ 1.14.0
diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml
index 14bc5dfe9439..3b77ced1a13e 100644
--- a/spotbugs-exclude.xml
+++ b/spotbugs-exclude.xml
@@ -41,9 +41,6 @@
-
-
-
@@ -86,6 +83,9 @@
+
+
+
@@ -117,9 +117,6 @@
-
-
-
diff --git a/src/main/java/com/thealgorithms/backtracking/ArrayCombination.java b/src/main/java/com/thealgorithms/backtracking/ArrayCombination.java
index 6569896bd1b7..f8cd0c40c20e 100644
--- a/src/main/java/com/thealgorithms/backtracking/ArrayCombination.java
+++ b/src/main/java/com/thealgorithms/backtracking/ArrayCombination.java
@@ -48,7 +48,7 @@ private static void combine(List> combinations, List curr
for (int i = start; i < n; i++) {
current.add(i);
combine(combinations, current, i + 1, n, k);
- current.removeLast(); // Backtrack
+ current.remove(current.size() - 1); // Backtrack
}
}
}
diff --git a/src/main/java/com/thealgorithms/ciphers/Caesar.java b/src/main/java/com/thealgorithms/ciphers/Caesar.java
index 61c444cf6463..23535bc2b5d2 100644
--- a/src/main/java/com/thealgorithms/ciphers/Caesar.java
+++ b/src/main/java/com/thealgorithms/ciphers/Caesar.java
@@ -9,6 +9,9 @@
* @author khalil2535
*/
public class Caesar {
+ private static char normalizeShift(final int shift) {
+ return (char) (shift % 26);
+ }
/**
* Encrypt text by shifting every Latin char by add number shift for ASCII
@@ -19,7 +22,7 @@ public class Caesar {
public String encode(String message, int shift) {
StringBuilder encoded = new StringBuilder();
- shift %= 26;
+ final char shiftChar = normalizeShift(shift);
final int length = message.length();
for (int i = 0; i < length; i++) {
@@ -29,10 +32,10 @@ public String encode(String message, int shift) {
char current = message.charAt(i); // Java law : char + int = char
if (isCapitalLatinLetter(current)) {
- current += shift;
+ current += shiftChar;
encoded.append((char) (current > 'Z' ? current - 26 : current)); // 26 = number of latin letters
} else if (isSmallLatinLetter(current)) {
- current += shift;
+ current += shiftChar;
encoded.append((char) (current > 'z' ? current - 26 : current)); // 26 = number of latin letters
} else {
encoded.append(current);
@@ -50,16 +53,16 @@ public String encode(String message, int shift) {
public String decode(String encryptedMessage, int shift) {
StringBuilder decoded = new StringBuilder();
- shift %= 26;
+ final char shiftChar = normalizeShift(shift);
final int length = encryptedMessage.length();
for (int i = 0; i < length; i++) {
char current = encryptedMessage.charAt(i);
if (isCapitalLatinLetter(current)) {
- current -= shift;
+ current -= shiftChar;
decoded.append((char) (current < 'A' ? current + 26 : current)); // 26 = number of latin letters
} else if (isSmallLatinLetter(current)) {
- current -= shift;
+ current -= shiftChar;
decoded.append((char) (current < 'a' ? current + 26 : current)); // 26 = number of latin letters
} else {
decoded.append(current);
diff --git a/src/main/java/com/thealgorithms/conversions/NumberToWords.java b/src/main/java/com/thealgorithms/conversions/NumberToWords.java
new file mode 100644
index 000000000000..e39c5b2dea86
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/NumberToWords.java
@@ -0,0 +1,100 @@
+package com.thealgorithms.conversions;
+
+import java.math.BigDecimal;
+
+/**
+ A Java-based utility for converting numeric values into their English word
+ representations. Whether you need to convert a small number, a large number
+ with millions and billions, or even a number with decimal places, this utility
+ has you covered.
+ *
+ */
+public final class NumberToWords {
+
+ private NumberToWords() {
+ }
+
+ private static final String[] UNITS = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
+
+ private static final String[] TENS = {"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
+
+ private static final String[] POWERS = {"", "Thousand", "Million", "Billion", "Trillion"};
+
+ private static final String ZERO = "Zero";
+ private static final String POINT = " Point";
+ private static final String NEGATIVE = "Negative ";
+
+ public static String convert(BigDecimal number) {
+ if (number == null) {
+ return "Invalid Input";
+ }
+
+ // Check for negative sign
+ boolean isNegative = number.signum() < 0;
+
+ // Split the number into whole and fractional parts
+ BigDecimal[] parts = number.abs().divideAndRemainder(BigDecimal.ONE);
+ BigDecimal wholePart = parts[0]; // Keep whole part as BigDecimal
+ String fractionalPartStr = parts[1].compareTo(BigDecimal.ZERO) > 0 ? parts[1].toPlainString().substring(2) : ""; // Get fractional part only if it exists
+
+ // Convert whole part to words
+ StringBuilder result = new StringBuilder();
+ if (isNegative) {
+ result.append(NEGATIVE);
+ }
+ result.append(convertWholeNumberToWords(wholePart));
+
+ // Convert fractional part to words
+ if (!fractionalPartStr.isEmpty()) {
+ result.append(POINT);
+ for (char digit : fractionalPartStr.toCharArray()) {
+ int digitValue = Character.getNumericValue(digit);
+ result.append(" ").append(digitValue == 0 ? ZERO : UNITS[digitValue]);
+ }
+ }
+
+ return result.toString().trim();
+ }
+
+ private static String convertWholeNumberToWords(BigDecimal number) {
+ if (number.compareTo(BigDecimal.ZERO) == 0) {
+ return ZERO;
+ }
+
+ StringBuilder words = new StringBuilder();
+ int power = 0;
+
+ while (number.compareTo(BigDecimal.ZERO) > 0) {
+ // Get the last three digits
+ BigDecimal[] divisionResult = number.divideAndRemainder(BigDecimal.valueOf(1000));
+ int chunk = divisionResult[1].intValue();
+
+ if (chunk > 0) {
+ String chunkWords = convertChunk(chunk);
+ if (power > 0) {
+ words.insert(0, POWERS[power] + " ");
+ }
+ words.insert(0, chunkWords + " ");
+ }
+
+ number = divisionResult[0]; // Continue with the remaining part
+ power++;
+ }
+
+ return words.toString().trim();
+ }
+
+ private static String convertChunk(int number) {
+ String chunkWords;
+
+ if (number < 20) {
+ chunkWords = UNITS[number];
+ } else if (number < 100) {
+ chunkWords = TENS[number / 10] + (number % 10 > 0 ? " " + UNITS[number % 10] : "");
+ } else {
+ chunkWords = UNITS[number / 100] + " Hundred" + (number % 100 > 0 ? " " + convertChunk(number % 100) : "");
+ }
+
+ return chunkWords;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/conversions/WordsToNumber.java b/src/main/java/com/thealgorithms/conversions/WordsToNumber.java
new file mode 100644
index 000000000000..e2b81a0f4b47
--- /dev/null
+++ b/src/main/java/com/thealgorithms/conversions/WordsToNumber.java
@@ -0,0 +1,343 @@
+package com.thealgorithms.conversions;
+
+import java.io.Serial;
+import java.math.BigDecimal;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ A Java-based utility for converting English word representations of numbers
+ into their numeric form. This utility supports whole numbers, decimals,
+ large values up to trillions, and even scientific notation where applicable.
+ It ensures accurate parsing while handling edge cases like negative numbers,
+ improper word placements, and ambiguous inputs.
+ *
+ */
+
+public final class WordsToNumber {
+
+ private WordsToNumber() {
+ }
+
+ private enum NumberWord {
+ ZERO("zero", 0),
+ ONE("one", 1),
+ TWO("two", 2),
+ THREE("three", 3),
+ FOUR("four", 4),
+ FIVE("five", 5),
+ SIX("six", 6),
+ SEVEN("seven", 7),
+ EIGHT("eight", 8),
+ NINE("nine", 9),
+ TEN("ten", 10),
+ ELEVEN("eleven", 11),
+ TWELVE("twelve", 12),
+ THIRTEEN("thirteen", 13),
+ FOURTEEN("fourteen", 14),
+ FIFTEEN("fifteen", 15),
+ SIXTEEN("sixteen", 16),
+ SEVENTEEN("seventeen", 17),
+ EIGHTEEN("eighteen", 18),
+ NINETEEN("nineteen", 19),
+ TWENTY("twenty", 20),
+ THIRTY("thirty", 30),
+ FORTY("forty", 40),
+ FIFTY("fifty", 50),
+ SIXTY("sixty", 60),
+ SEVENTY("seventy", 70),
+ EIGHTY("eighty", 80),
+ NINETY("ninety", 90);
+
+ private final String word;
+ private final int value;
+
+ NumberWord(String word, int value) {
+ this.word = word;
+ this.value = value;
+ }
+
+ public static Integer getValue(String word) {
+ for (NumberWord num : values()) {
+ if (word.equals(num.word)) {
+ return num.value;
+ }
+ }
+ return null;
+ }
+ }
+
+ private enum PowerOfTen {
+ THOUSAND("thousand", new BigDecimal("1000")),
+ MILLION("million", new BigDecimal("1000000")),
+ BILLION("billion", new BigDecimal("1000000000")),
+ TRILLION("trillion", new BigDecimal("1000000000000"));
+
+ private final String word;
+ private final BigDecimal value;
+
+ PowerOfTen(String word, BigDecimal value) {
+ this.word = word;
+ this.value = value;
+ }
+
+ public static BigDecimal getValue(String word) {
+ for (PowerOfTen power : values()) {
+ if (word.equals(power.word)) {
+ return power.value;
+ }
+ }
+ return null;
+ }
+ }
+
+ public static String convert(String numberInWords) {
+ if (numberInWords == null) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.NULL_INPUT, "");
+ }
+
+ ArrayDeque wordDeque = preprocessWords(numberInWords);
+ BigDecimal completeNumber = convertWordQueueToBigDecimal(wordDeque);
+
+ return completeNumber.toString();
+ }
+
+ public static BigDecimal convertToBigDecimal(String numberInWords) {
+ String conversionResult = convert(numberInWords);
+ return new BigDecimal(conversionResult);
+ }
+
+ private static ArrayDeque preprocessWords(String numberInWords) {
+ String[] wordSplitArray = numberInWords.trim().split("[ ,-]");
+ ArrayDeque wordDeque = new ArrayDeque<>();
+ for (String word : wordSplitArray) {
+ if (word.isEmpty()) {
+ continue;
+ }
+ wordDeque.add(word.toLowerCase());
+ }
+ if (wordDeque.isEmpty()) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.NULL_INPUT, "");
+ }
+ return wordDeque;
+ }
+
+ private static void handleConjunction(boolean prevNumWasHundred, boolean prevNumWasPowerOfTen, ArrayDeque wordDeque) {
+ if (wordDeque.isEmpty()) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.INVALID_CONJUNCTION, "");
+ }
+
+ String nextWord = wordDeque.pollFirst();
+ String afterNextWord = wordDeque.peekFirst();
+
+ wordDeque.addFirst(nextWord);
+
+ Integer number = NumberWord.getValue(nextWord);
+
+ boolean isPrevWordValid = prevNumWasHundred || prevNumWasPowerOfTen;
+ boolean isNextWordValid = number != null && (number >= 10 || afterNextWord == null || "point".equals(afterNextWord));
+
+ if (!isPrevWordValid || !isNextWordValid) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.INVALID_CONJUNCTION, "");
+ }
+ }
+
+ private static BigDecimal handleHundred(BigDecimal currentChunk, String word, boolean prevNumWasPowerOfTen) {
+ boolean currentChunkIsZero = currentChunk.compareTo(BigDecimal.ZERO) == 0;
+ if (currentChunk.compareTo(BigDecimal.TEN) >= 0 || prevNumWasPowerOfTen) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNEXPECTED_WORD, word);
+ }
+ if (currentChunkIsZero) {
+ currentChunk = currentChunk.add(BigDecimal.ONE);
+ }
+ return currentChunk.multiply(BigDecimal.valueOf(100));
+ }
+
+ private static void handlePowerOfTen(List chunks, BigDecimal currentChunk, BigDecimal powerOfTen, String word, boolean prevNumWasPowerOfTen) {
+ boolean currentChunkIsZero = currentChunk.compareTo(BigDecimal.ZERO) == 0;
+ if (currentChunkIsZero || prevNumWasPowerOfTen) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNEXPECTED_WORD, word);
+ }
+ BigDecimal nextChunk = currentChunk.multiply(powerOfTen);
+
+ if (!(chunks.isEmpty() || isAdditionSafe(chunks.getLast(), nextChunk))) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNEXPECTED_WORD, word);
+ }
+ chunks.add(nextChunk);
+ }
+
+ private static BigDecimal handleNumber(Collection chunks, BigDecimal currentChunk, String word, Integer number) {
+ boolean currentChunkIsZero = currentChunk.compareTo(BigDecimal.ZERO) == 0;
+ if (number == 0 && !(currentChunkIsZero && chunks.isEmpty())) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNEXPECTED_WORD, word);
+ }
+ BigDecimal bigDecimalNumber = BigDecimal.valueOf(number);
+
+ if (!currentChunkIsZero && !isAdditionSafe(currentChunk, bigDecimalNumber)) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNEXPECTED_WORD, word);
+ }
+ return currentChunk.add(bigDecimalNumber);
+ }
+
+ private static void handlePoint(Collection chunks, BigDecimal currentChunk, ArrayDeque wordDeque) {
+ boolean currentChunkIsZero = currentChunk.compareTo(BigDecimal.ZERO) == 0;
+ if (!currentChunkIsZero) {
+ chunks.add(currentChunk);
+ }
+
+ String decimalPart = convertDecimalPart(wordDeque);
+ chunks.add(new BigDecimal(decimalPart));
+ }
+
+ private static void handleNegative(boolean isNegative) {
+ if (isNegative) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.MULTIPLE_NEGATIVES, "");
+ }
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.INVALID_NEGATIVE, "");
+ }
+
+ private static BigDecimal convertWordQueueToBigDecimal(ArrayDeque wordDeque) {
+ BigDecimal currentChunk = BigDecimal.ZERO;
+ List chunks = new ArrayList<>();
+
+ boolean isNegative = "negative".equals(wordDeque.peek());
+ if (isNegative) {
+ wordDeque.poll();
+ }
+
+ boolean prevNumWasHundred = false;
+ boolean prevNumWasPowerOfTen = false;
+
+ while (!wordDeque.isEmpty()) {
+ String word = wordDeque.poll();
+
+ switch (word) {
+ case "and" -> {
+ handleConjunction(prevNumWasHundred, prevNumWasPowerOfTen, wordDeque);
+ continue;
+ }
+ case "hundred" -> {
+ currentChunk = handleHundred(currentChunk, word, prevNumWasPowerOfTen);
+ prevNumWasHundred = true;
+ continue;
+ }
+ default -> {
+
+ }
+ }
+ prevNumWasHundred = false;
+
+ BigDecimal powerOfTen = PowerOfTen.getValue(word);
+ if (powerOfTen != null) {
+ handlePowerOfTen(chunks, currentChunk, powerOfTen, word, prevNumWasPowerOfTen);
+ currentChunk = BigDecimal.ZERO;
+ prevNumWasPowerOfTen = true;
+ continue;
+ }
+ prevNumWasPowerOfTen = false;
+
+ Integer number = NumberWord.getValue(word);
+ if (number != null) {
+ currentChunk = handleNumber(chunks, currentChunk, word, number);
+ continue;
+ }
+
+ switch (word) {
+ case "point" -> {
+ handlePoint(chunks, currentChunk, wordDeque);
+ currentChunk = BigDecimal.ZERO;
+ continue;
+ }
+ case "negative" -> {
+ handleNegative(isNegative);
+ }
+ default -> {
+
+ }
+ }
+
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNKNOWN_WORD, word);
+ }
+
+ if (currentChunk.compareTo(BigDecimal.ZERO) != 0) {
+ chunks.add(currentChunk);
+ }
+
+ BigDecimal completeNumber = combineChunks(chunks);
+ return isNegative ? completeNumber.multiply(BigDecimal.valueOf(-1))
+ :
+ completeNumber;
+ }
+
+ private static boolean isAdditionSafe(BigDecimal currentChunk, BigDecimal number) {
+ int chunkDigitCount = currentChunk.toString().length();
+ int numberDigitCount = number.toString().length();
+ return chunkDigitCount > numberDigitCount;
+ }
+
+ private static String convertDecimalPart(ArrayDeque wordDeque) {
+ StringBuilder decimalPart = new StringBuilder(".");
+
+ while (!wordDeque.isEmpty()) {
+ String word = wordDeque.poll();
+ Integer number = NumberWord.getValue(word);
+ if (number == null) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.UNEXPECTED_WORD_AFTER_POINT, word);
+ }
+ decimalPart.append(number);
+ }
+
+ boolean missingNumbers = decimalPart.length() == 1;
+ if (missingNumbers) {
+ throw new WordsToNumberException(WordsToNumberException.ErrorType.MISSING_DECIMAL_NUMBERS, "");
+ }
+ return decimalPart.toString();
+ }
+
+ private static BigDecimal combineChunks(List chunks) {
+ BigDecimal completeNumber = BigDecimal.ZERO;
+ for (BigDecimal chunk : chunks) {
+ completeNumber = completeNumber.add(chunk);
+ }
+ return completeNumber;
+ }
+ }
+
+ class WordsToNumberException extends RuntimeException {
+
+ @Serial private static final long serialVersionUID = 1L;
+
+ enum ErrorType {
+ NULL_INPUT("'null' or empty input provided"),
+ UNKNOWN_WORD("Unknown Word: "),
+ UNEXPECTED_WORD("Unexpected Word: "),
+ UNEXPECTED_WORD_AFTER_POINT("Unexpected Word (after Point): "),
+ MISSING_DECIMAL_NUMBERS("Decimal part is missing numbers."),
+ MULTIPLE_NEGATIVES("Multiple 'Negative's detected."),
+ INVALID_NEGATIVE("Incorrect 'negative' placement"),
+ INVALID_CONJUNCTION("Incorrect 'and' placement");
+
+ private final String message;
+
+ ErrorType(String message) {
+ this.message = message;
+ }
+
+ public String formatMessage(String details) {
+ return "Invalid Input. " + message + (details.isEmpty() ? "" : details);
+ }
+ }
+
+ public final ErrorType errorType;
+
+ WordsToNumberException(ErrorType errorType, String details) {
+ super(errorType.formatMessage(details));
+ this.errorType = errorType;
+ }
+
+ public ErrorType getErrorType() {
+ return errorType;
+ }
+ }
diff --git a/src/main/java/com/thealgorithms/datastructures/crdt/LWWElementSet.java b/src/main/java/com/thealgorithms/datastructures/crdt/LWWElementSet.java
index 2c6ce8a427d1..d33bd3ee84d9 100644
--- a/src/main/java/com/thealgorithms/datastructures/crdt/LWWElementSet.java
+++ b/src/main/java/com/thealgorithms/datastructures/crdt/LWWElementSet.java
@@ -1,53 +1,33 @@
package com.thealgorithms.datastructures.crdt;
+import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
/**
- * Last-Write-Wins Element Set (LWWElementSet) is a state-based CRDT (Conflict-free Replicated Data Type)
- * designed for managing sets in a distributed and concurrent environment. It supports the addition and removal
- * of elements, using timestamps to determine the order of operations. The set is split into two subsets:
- * the add set for elements to be added and the remove set for elements to be removed.
+ * Last-Write-Wins Element Set (LWWElementSet) is a state-based CRDT (Conflict-free Replicated Data
+ * Type) designed for managing sets in a distributed and concurrent environment. It supports the
+ * addition and removal of elements, using timestamps to determine the order of operations. The set
+ * is split into two subsets: the add set for elements to be added and the remove set for elements
+ * to be removed. The LWWElementSet ensures that the most recent operation (based on the timestamp)
+ * wins in the case of concurrent operations.
*
- * @author itakurah (Niklas Hoefflin) (https://github.com/itakurah)
- * @see Conflict-free_replicated_data_type
- * @see itakurah (Niklas Hoefflin)
+ * @param The type of the elements in the LWWElementSet.
+ * @author itakurah (GitHub), Niklas Hoefflin (LinkedIn)
+ * @see Conflict free
+ * replicated data type (Wikipedia)
+ * @see A comprehensive study of
+ * Convergent and Commutative Replicated Data Types
*/
-
-class Element {
- String key;
- int timestamp;
- Bias bias;
+class LWWElementSet {
+ final Map> addSet;
+ final Map> removeSet;
/**
- * Constructs a new Element with the specified key, timestamp and bias.
- *
- * @param key The key of the element.
- * @param timestamp The timestamp associated with the element.
- * @param bias The bias of the element (ADDS or REMOVALS).
- */
- Element(String key, int timestamp, Bias bias) {
- this.key = key;
- this.timestamp = timestamp;
- this.bias = bias;
- }
-}
-
-enum Bias {
- /**
- * ADDS bias for the add set.
- * REMOVALS bias for the remove set.
- */
- ADDS,
- REMOVALS
-}
-
-class LWWElementSet {
- private final Map addSet;
- private final Map removeSet;
-
- /**
- * Constructs an empty LWWElementSet.
+ * Constructs an empty LWWElementSet. This constructor initializes the addSet and removeSet as
+ * empty HashMaps. The addSet stores elements that are added, and the removeSet stores elements
+ * that are removed.
*/
LWWElementSet() {
this.addSet = new HashMap<>();
@@ -55,84 +35,92 @@ class LWWElementSet {
}
/**
- * Adds an element to the addSet.
+ * Adds an element to the addSet with the current timestamp. This method stores the element in the
+ * addSet, ensuring that the element is added to the set with an associated timestamp that
+ * represents the time of the addition.
*
- * @param e The element to be added.
+ * @param key The key of the element to be added.
*/
- public void add(Element e) {
- addSet.put(e.key, e);
+ public void add(T key) {
+ addSet.put(key, new Element<>(key, Instant.now()));
}
/**
- * Removes an element from the removeSet.
+ * Removes an element by adding it to the removeSet with the current timestamp. This method adds
+ * the element to the removeSet, marking it as removed with the current timestamp.
*
- * @param e The element to be removed.
+ * @param key The key of the element to be removed.
*/
- public void remove(Element e) {
- if (lookup(e)) {
- removeSet.put(e.key, e);
- }
+ public void remove(T key) {
+ removeSet.put(key, new Element<>(key, Instant.now()));
}
/**
- * Checks if an element is in the LWWElementSet by comparing timestamps in the addSet and removeSet.
+ * Checks if an element is in the LWWElementSet. An element is considered present if it exists in
+ * the addSet and either does not exist in the removeSet, or its add timestamp is later than any
+ * corresponding remove timestamp.
*
- * @param e The element to be checked.
- * @return True if the element is present, false otherwise.
+ * @param key The key of the element to be checked.
+ * @return {@code true} if the element is present in the set (i.e., its add timestamp is later
+ * than its remove timestamp, or it is not in the remove set), {@code false} otherwise (i.e.,
+ * the element has been removed or its remove timestamp is later than its add timestamp).
*/
- public boolean lookup(Element e) {
- Element inAddSet = addSet.get(e.key);
- Element inRemoveSet = removeSet.get(e.key);
+ public boolean lookup(T key) {
+ Element inAddSet = addSet.get(key);
+ Element inRemoveSet = removeSet.get(key);
- return (inAddSet != null && (inRemoveSet == null || inAddSet.timestamp > inRemoveSet.timestamp));
+ return inAddSet != null && (inRemoveSet == null || inAddSet.timestamp.isAfter(inRemoveSet.timestamp));
}
/**
- * Compares the LWWElementSet with another LWWElementSet to check if addSet and removeSet are a subset.
+ * Merges another LWWElementSet into this set. This method takes the union of both the add-sets
+ * and remove-sets from the two sets, resolving conflicts by keeping the element with the latest
+ * timestamp. If an element appears in both the add-set and remove-set of both sets, the one with
+ * the later timestamp will be retained.
*
- * @param other The LWWElementSet to compare.
- * @return True if the set is subset, false otherwise.
+ * @param other The LWWElementSet to merge with the current set.
*/
- public boolean compare(LWWElementSet other) {
- return other.addSet.keySet().containsAll(addSet.keySet()) && other.removeSet.keySet().containsAll(removeSet.keySet());
+ public void merge(LWWElementSet other) {
+ for (Map.Entry> entry : other.addSet.entrySet()) {
+ addSet.merge(entry.getKey(), entry.getValue(), this::resolveConflict);
+ }
+ for (Map.Entry> entry : other.removeSet.entrySet()) {
+ removeSet.merge(entry.getKey(), entry.getValue(), this::resolveConflict);
+ }
}
/**
- * Merges another LWWElementSet into this set by resolving conflicts based on timestamps.
+ * Resolves conflicts between two elements by selecting the one with the later timestamp. This
+ * method is used when merging two LWWElementSets to ensure that the most recent operation (based
+ * on timestamps) is kept.
*
- * @param other The LWWElementSet to merge.
+ * @param e1 The first element.
+ * @param e2 The second element.
+ * @return The element with the later timestamp.
*/
- public void merge(LWWElementSet other) {
- for (Element e : other.addSet.values()) {
- if (!addSet.containsKey(e.key) || compareTimestamps(addSet.get(e.key), e)) {
- addSet.put(e.key, e);
- }
- }
-
- for (Element e : other.removeSet.values()) {
- if (!removeSet.containsKey(e.key) || compareTimestamps(removeSet.get(e.key), e)) {
- removeSet.put(e.key, e);
- }
- }
+ private Element resolveConflict(Element e1, Element e2) {
+ return e1.timestamp.isAfter(e2.timestamp) ? e1 : e2;
}
+}
+
+/**
+ * Represents an element in the LWWElementSet, consisting of a key and a timestamp. This class is
+ * used to store the elements in both the add and remove sets with their respective timestamps.
+ *
+ * @param The type of the key associated with the element.
+ */
+class Element {
+ T key;
+ Instant timestamp;
/**
- * Compares timestamps of two elements based on their bias (ADDS or REMOVALS).
+ * Constructs a new Element with the specified key and timestamp.
*
- * @param e The first element.
- * @param other The second element.
- * @return True if the first element's timestamp is greater or the bias is ADDS and timestamps are equal.
+ * @param key The key of the element.
+ * @param timestamp The timestamp associated with the element.
*/
- public boolean compareTimestamps(Element e, Element other) {
- if (e.bias != other.bias) {
- throw new IllegalArgumentException("Invalid bias value");
- }
- Bias bias = e.bias;
- int timestampComparison = Integer.compare(e.timestamp, other.timestamp);
-
- if (timestampComparison == 0) {
- return bias != Bias.ADDS;
- }
- return timestampComparison < 0;
+ Element(T key, Instant timestamp) {
+ this.key = key;
+ this.timestamp = timestamp;
}
}
diff --git a/src/main/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithm.java b/src/main/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithm.java
new file mode 100644
index 000000000000..a686b808a970
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithm.java
@@ -0,0 +1,66 @@
+package com.thealgorithms.datastructures.graphs;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.TreeSet;
+import org.apache.commons.lang3.tuple.Pair;
+
+/**
+ * Dijkstra's algorithm for finding the shortest path from a single source vertex to all other vertices in a graph.
+ */
+public class DijkstraOptimizedAlgorithm {
+
+ private final int vertexCount;
+
+ /**
+ * Constructs a Dijkstra object with the given number of vertices.
+ *
+ * @param vertexCount The number of vertices in the graph.
+ */
+ public DijkstraOptimizedAlgorithm(int vertexCount) {
+ this.vertexCount = vertexCount;
+ }
+
+ /**
+ * Executes Dijkstra's algorithm on the provided graph to find the shortest paths from the source vertex to all other vertices.
+ *
+ * The graph is represented as an adjacency matrix where {@code graph[i][j]} represents the weight of the edge from vertex {@code i}
+ * to vertex {@code j}. A value of 0 indicates no edge exists between the vertices.
+ *
+ * @param graph The graph represented as an adjacency matrix.
+ * @param source The source vertex.
+ * @return An array where the value at each index {@code i} represents the shortest distance from the source vertex to vertex {@code i}.
+ * @throws IllegalArgumentException if the source vertex is out of range.
+ */
+ public int[] run(int[][] graph, int source) {
+ if (source < 0 || source >= vertexCount) {
+ throw new IllegalArgumentException("Incorrect source");
+ }
+
+ int[] distances = new int[vertexCount];
+ boolean[] processed = new boolean[vertexCount];
+ Set> unprocessed = new TreeSet<>();
+
+ Arrays.fill(distances, Integer.MAX_VALUE);
+ Arrays.fill(processed, false);
+ distances[source] = 0;
+ unprocessed.add(Pair.of(0, source));
+
+ while (!unprocessed.isEmpty()) {
+ Pair distanceAndU = unprocessed.iterator().next();
+ unprocessed.remove(distanceAndU);
+ int u = distanceAndU.getRight();
+ processed[u] = true;
+
+ for (int v = 0; v < vertexCount; v++) {
+ if (!processed[v] && graph[u][v] != 0 && distances[u] != Integer.MAX_VALUE && distances[u] + graph[u][v] < distances[v]) {
+ unprocessed.remove(Pair.of(distances[v], v));
+ distances[v] = distances[u] + graph[u][v];
+ unprocessed.add(Pair.of(distances[v], v));
+ }
+ }
+ }
+
+ return distances;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/datastructures/graphs/UndirectedAdjacencyListGraph.java b/src/main/java/com/thealgorithms/datastructures/graphs/UndirectedAdjacencyListGraph.java
new file mode 100644
index 000000000000..8aafc1ef3368
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/graphs/UndirectedAdjacencyListGraph.java
@@ -0,0 +1,69 @@
+package com.thealgorithms.datastructures.graphs;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+
+public class UndirectedAdjacencyListGraph {
+ private ArrayList> adjacencyList = new ArrayList<>();
+
+ /**
+ * Adds a new node to the graph by adding an empty HashMap for its neighbors.
+ * @return the index of the newly added node in the adjacency list
+ */
+ public int addNode() {
+ adjacencyList.add(new HashMap<>());
+ return adjacencyList.size() - 1;
+ }
+
+ /**
+ * Adds an undirected edge between the origin node (@orig) and the destination node (@dest) with the specified weight.
+ * If the edge already exists, no changes are made.
+ * @param orig the index of the origin node
+ * @param dest the index of the destination node
+ * @param weight the weight of the edge between @orig and @dest
+ * @return true if the edge was successfully added, false if the edge already exists or if any node index is invalid
+ */
+ public boolean addEdge(int orig, int dest, int weight) {
+ int numNodes = adjacencyList.size();
+ if (orig >= numNodes || dest >= numNodes || orig < 0 || dest < 0) {
+ return false;
+ }
+
+ if (adjacencyList.get(orig).containsKey(dest)) {
+ return false;
+ }
+
+ adjacencyList.get(orig).put(dest, weight);
+ adjacencyList.get(dest).put(orig, weight);
+ return true;
+ }
+
+ /**
+ * Returns the set of all adjacent nodes (neighbors) for the given node.
+ * @param node the index of the node whose neighbors are to be retrieved
+ * @return a HashSet containing the indices of all neighboring nodes
+ */
+ public HashSet getNeighbors(int node) {
+ return new HashSet<>(adjacencyList.get(node).keySet());
+ }
+
+ /**
+ * Returns the weight of the edge between the origin node (@orig) and the destination node (@dest).
+ * If no edge exists, returns null.
+ * @param orig the index of the origin node
+ * @param dest the index of the destination node
+ * @return the weight of the edge between @orig and @dest, or null if no edge exists
+ */
+ public Integer getEdgeWeight(int orig, int dest) {
+ return adjacencyList.get(orig).getOrDefault(dest, null);
+ }
+
+ /**
+ * Returns the number of nodes currently in the graph.
+ * @return the number of nodes in the graph
+ */
+ public int size() {
+ return adjacencyList.size();
+ }
+}
diff --git a/src/main/java/com/thealgorithms/datastructures/lists/CountSinglyLinkedListRecursion.java b/src/main/java/com/thealgorithms/datastructures/lists/CountSinglyLinkedListRecursion.java
index 4c1ffe9d3ea4..b58d51e7e5fe 100644
--- a/src/main/java/com/thealgorithms/datastructures/lists/CountSinglyLinkedListRecursion.java
+++ b/src/main/java/com/thealgorithms/datastructures/lists/CountSinglyLinkedListRecursion.java
@@ -12,7 +12,7 @@ public class CountSinglyLinkedListRecursion extends SinglyLinkedList {
* @param head the head node of the list segment being counted.
* @return the count of nodes from the given head node onward.
*/
- private int countRecursion(Node head) {
+ private int countRecursion(SinglyLinkedListNode head) {
return head == null ? 0 : 1 + countRecursion(head.next);
}
diff --git a/src/main/java/com/thealgorithms/datastructures/lists/MergeSortedSinglyLinkedList.java b/src/main/java/com/thealgorithms/datastructures/lists/MergeSortedSinglyLinkedList.java
index a16b202c4505..4e99642fccd8 100644
--- a/src/main/java/com/thealgorithms/datastructures/lists/MergeSortedSinglyLinkedList.java
+++ b/src/main/java/com/thealgorithms/datastructures/lists/MergeSortedSinglyLinkedList.java
@@ -42,12 +42,12 @@ public static SinglyLinkedList merge(SinglyLinkedList listA, SinglyLinkedList li
throw new NullPointerException("Input lists must not be null.");
}
- Node headA = listA.getHead();
- Node headB = listB.getHead();
+ SinglyLinkedListNode headA = listA.getHead();
+ SinglyLinkedListNode headB = listB.getHead();
int size = listA.size() + listB.size();
- Node head = new Node();
- Node tail = head;
+ SinglyLinkedListNode head = new SinglyLinkedListNode();
+ SinglyLinkedListNode tail = head;
while (headA != null && headB != null) {
if (headA.value <= headB.value) {
tail.next = headA;
diff --git a/src/main/java/com/thealgorithms/datastructures/lists/QuickSortLinkedList.java b/src/main/java/com/thealgorithms/datastructures/lists/QuickSortLinkedList.java
index 08fe674b47f4..f018781ada70 100644
--- a/src/main/java/com/thealgorithms/datastructures/lists/QuickSortLinkedList.java
+++ b/src/main/java/com/thealgorithms/datastructures/lists/QuickSortLinkedList.java
@@ -105,7 +105,7 @@
public class QuickSortLinkedList {
private final SinglyLinkedList list; // The linked list to be sorted
- private Node head; // Head of the list
+ private SinglyLinkedListNode head; // Head of the list
/**
* Constructor that initializes the QuickSortLinkedList with a given linked list.
@@ -136,19 +136,19 @@ public void sortList() {
* @param head The head node of the list to sort
* @return The head node of the sorted linked list
*/
- private Node sortList(Node head) {
+ private SinglyLinkedListNode sortList(SinglyLinkedListNode head) {
if (head == null || head.next == null) {
return head;
}
- Node pivot = head;
+ SinglyLinkedListNode pivot = head;
head = head.next;
pivot.next = null;
- Node lessHead = new Node();
- Node lessTail = lessHead;
- Node greaterHead = new Node();
- Node greaterTail = greaterHead;
+ SinglyLinkedListNode lessHead = new SinglyLinkedListNode();
+ SinglyLinkedListNode lessTail = lessHead;
+ SinglyLinkedListNode greaterHead = new SinglyLinkedListNode();
+ SinglyLinkedListNode greaterTail = greaterHead;
while (head != null) {
if (head.value < pivot.value) {
@@ -164,14 +164,14 @@ private Node sortList(Node head) {
lessTail.next = null;
greaterTail.next = null;
- Node sortedLess = sortList(lessHead.next);
- Node sortedGreater = sortList(greaterHead.next);
+ SinglyLinkedListNode sortedLess = sortList(lessHead.next);
+ SinglyLinkedListNode sortedGreater = sortList(greaterHead.next);
if (sortedLess == null) {
pivot.next = sortedGreater;
return pivot;
} else {
- Node current = sortedLess;
+ SinglyLinkedListNode current = sortedLess;
while (current.next != null) {
current = current.next;
}
diff --git a/src/main/java/com/thealgorithms/datastructures/lists/ReverseKGroup.java b/src/main/java/com/thealgorithms/datastructures/lists/ReverseKGroup.java
index c9a5c1df9870..9b9464d388b5 100644
--- a/src/main/java/com/thealgorithms/datastructures/lists/ReverseKGroup.java
+++ b/src/main/java/com/thealgorithms/datastructures/lists/ReverseKGroup.java
@@ -14,10 +14,10 @@
*
*
* The implementation contains:
- * - {@code length(Node head)}: A method to calculate the length of the linked list.
- * - {@code reverse(Node head, int count, int k)}: A helper method that reverses the nodes
+ * - {@code length(SinglyLinkedListNode head)}: A method to calculate the length of the linked list.
+ * - {@code reverse(SinglyLinkedListNode head, int count, int k)}: A helper method that reverses the nodes
* in the linked list in groups of k.
- * - {@code reverseKGroup(Node head, int k)}: The main method that initiates the reversal
+ * - {@code reverseKGroup(SinglyLinkedListNode head, int k)}: The main method that initiates the reversal
* process by calling the reverse method.
*
*
@@ -38,8 +38,8 @@ public class ReverseKGroup {
* @param head The head node of the linked list.
* @return The total number of nodes in the linked list.
*/
- public int length(Node head) {
- Node curr = head;
+ public int length(SinglyLinkedListNode head) {
+ SinglyLinkedListNode curr = head;
int count = 0;
while (curr != null) {
curr = curr.next;
@@ -56,14 +56,14 @@ public int length(Node head) {
* @param k The size of the group to reverse.
* @return The new head of the reversed linked list segment.
*/
- public Node reverse(Node head, int count, int k) {
+ public SinglyLinkedListNode reverse(SinglyLinkedListNode head, int count, int k) {
if (count < k) {
return head;
}
- Node prev = null;
+ SinglyLinkedListNode prev = null;
int count1 = 0;
- Node curr = head;
- Node next = null;
+ SinglyLinkedListNode curr = head;
+ SinglyLinkedListNode next = null;
while (curr != null && count1 < k) {
next = curr.next;
curr.next = prev;
@@ -85,7 +85,7 @@ public Node reverse(Node head, int count, int k) {
* @param k The size of the group to reverse.
* @return The head of the modified linked list after reversal.
*/
- public Node reverseKGroup(Node head, int k) {
+ public SinglyLinkedListNode reverseKGroup(SinglyLinkedListNode head, int k) {
int count = length(head);
return reverse(head, count, k);
}
diff --git a/src/main/java/com/thealgorithms/datastructures/lists/RotateSinglyLinkedLists.java b/src/main/java/com/thealgorithms/datastructures/lists/RotateSinglyLinkedLists.java
index 7676cc343653..47ee5397097c 100644
--- a/src/main/java/com/thealgorithms/datastructures/lists/RotateSinglyLinkedLists.java
+++ b/src/main/java/com/thealgorithms/datastructures/lists/RotateSinglyLinkedLists.java
@@ -38,12 +38,12 @@ public class RotateSinglyLinkedLists {
* @param k The number of positions to rotate the list to the right.
* @return The head of the rotated linked list.
*/
- public Node rotateRight(Node head, int k) {
+ public SinglyLinkedListNode rotateRight(SinglyLinkedListNode head, int k) {
if (head == null || head.next == null || k == 0) {
return head;
}
- Node curr = head;
+ SinglyLinkedListNode curr = head;
int len = 1;
while (curr.next != null) {
curr = curr.next;
diff --git a/src/main/java/com/thealgorithms/datastructures/lists/SearchSinglyLinkedListRecursion.java b/src/main/java/com/thealgorithms/datastructures/lists/SearchSinglyLinkedListRecursion.java
index a40e9b2a1a66..4ac2de422595 100644
--- a/src/main/java/com/thealgorithms/datastructures/lists/SearchSinglyLinkedListRecursion.java
+++ b/src/main/java/com/thealgorithms/datastructures/lists/SearchSinglyLinkedListRecursion.java
@@ -30,7 +30,7 @@ public class SearchSinglyLinkedListRecursion extends SinglyLinkedList {
* @param key the integer value to be searched for.
* @return {@code true} if the value `key` is present in the list; otherwise, {@code false}.
*/
- private boolean searchRecursion(Node node, int key) {
+ private boolean searchRecursion(SinglyLinkedListNode node, int key) {
return (node != null && (node.value == key || searchRecursion(node.next, key)));
}
diff --git a/src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedList.java b/src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedList.java
index eb6cdf48f58b..ff4af4437cc7 100644
--- a/src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedList.java
+++ b/src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedList.java
@@ -12,7 +12,7 @@ public class SinglyLinkedList implements Iterable {
/**
* Head refer to the front of the list
*/
- private Node head;
+ private SinglyLinkedListNode head;
/**
* Size of SinglyLinkedList
@@ -33,7 +33,7 @@ public SinglyLinkedList() {
* @param head the head node of list
* @param size the size of list
*/
- public SinglyLinkedList(Node head, int size) {
+ public SinglyLinkedList(SinglyLinkedListNode head, int size) {
this.head = head;
this.size = size;
}
@@ -44,8 +44,8 @@ public SinglyLinkedList(Node head, int size) {
*
*/
public boolean detectLoop() {
- Node currentNodeFast = head;
- Node currentNodeSlow = head;
+ SinglyLinkedListNode currentNodeFast = head;
+ SinglyLinkedListNode currentNodeSlow = head;
while (currentNodeFast != null && currentNodeFast.next != null) {
currentNodeFast = currentNodeFast.next.next;
currentNodeSlow = currentNodeSlow.next;
@@ -61,12 +61,12 @@ public boolean detectLoop() {
* If the length of the list is even then return item number length/2
* @return middle node of the list
*/
- public Node middle() {
+ public SinglyLinkedListNode middle() {
if (head == null) {
return null;
}
- Node firstCounter = head;
- Node secondCounter = firstCounter.next;
+ SinglyLinkedListNode firstCounter = head;
+ SinglyLinkedListNode secondCounter = firstCounter.next;
while (secondCounter != null && secondCounter.next != null) {
firstCounter = firstCounter.next;
secondCounter = secondCounter.next.next;
@@ -82,15 +82,15 @@ public void swapNodes(int valueFirst, int valueSecond) {
if (valueFirst == valueSecond) {
return;
}
- Node previousA = null;
- Node currentA = head;
+ SinglyLinkedListNode previousA = null;
+ SinglyLinkedListNode currentA = head;
while (currentA != null && currentA.value != valueFirst) {
previousA = currentA;
currentA = currentA.next;
}
- Node previousB = null;
- Node currentB = head;
+ SinglyLinkedListNode previousB = null;
+ SinglyLinkedListNode currentB = head;
while (currentB != null && currentB.value != valueSecond) {
previousB = currentB;
currentB = currentB.next;
@@ -117,7 +117,7 @@ public void swapNodes(int valueFirst, int valueSecond) {
}
// Swap next pointer
- Node temp = currentA.next;
+ var temp = currentA.next;
currentA.next = currentB.next;
currentB.next = temp;
}
@@ -126,12 +126,12 @@ public void swapNodes(int valueFirst, int valueSecond) {
* Reverse a singly linked list[Iterative] from a given node till the end
*
*/
- public Node reverseListIter(Node node) {
- Node prev = null;
- Node curr = node;
+ public SinglyLinkedListNode reverseListIter(SinglyLinkedListNode node) {
+ SinglyLinkedListNode prev = null;
+ SinglyLinkedListNode curr = node;
while (curr != null && curr.next != null) {
- Node next = curr.next;
+ var next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
@@ -149,13 +149,13 @@ public Node reverseListIter(Node node) {
* Reverse a singly linked list[Recursive] from a given node till the end
*
*/
- public Node reverseListRec(Node head) {
+ public SinglyLinkedListNode reverseListRec(SinglyLinkedListNode head) {
if (head == null || head.next == null) {
return head;
}
- Node prev = null;
- Node h2 = reverseListRec(head.next);
+ SinglyLinkedListNode prev = null;
+ SinglyLinkedListNode h2 = reverseListRec(head.next);
head.next.next = head;
head.next = prev;
@@ -167,7 +167,7 @@ public Node reverseListRec(Node head) {
* Clear all nodes in the list
*/
public void clear() {
- Node cur = head;
+ SinglyLinkedListNode cur = head;
while (cur != null) {
cur = cur.next;
}
@@ -198,7 +198,7 @@ public int size() {
*
* @return head of the list.
*/
- public Node getHead() {
+ public SinglyLinkedListNode getHead() {
return head;
}
@@ -206,7 +206,7 @@ public Node getHead() {
* Set head of the list.
*
*/
- public void setHead(Node head) {
+ public void setHead(SinglyLinkedListNode head) {
this.head = head;
}
@@ -249,10 +249,10 @@ public String toString() {
}
public void deleteDuplicates() {
- Node pred = head;
+ SinglyLinkedListNode pred = head;
// predecessor = the node
// having sublist of its duplicates
- Node newHead = head;
+ SinglyLinkedListNode newHead = head;
while (newHead != null) {
// if it's a beginning of duplicates sublist
// skip all duplicates
@@ -273,7 +273,7 @@ public void deleteDuplicates() {
}
public void print() {
- Node temp = head;
+ SinglyLinkedListNode temp = head;
while (temp != null && temp.next != null) {
System.out.print(temp.value + "->");
temp = temp.next;
@@ -310,7 +310,7 @@ public void insert(int data) {
*/
public void insertNth(int data, int position) {
checkBounds(position, 0, size);
- Node newNode = new Node(data);
+ SinglyLinkedListNode newNode = new SinglyLinkedListNode(data);
if (head == null) {
/* the list is empty */
head = newNode;
@@ -325,7 +325,7 @@ public void insertNth(int data, int position) {
return;
}
- Node cur = head;
+ SinglyLinkedListNode cur = head;
for (int i = 0; i < position - 1; ++i) {
cur = cur.next;
}
@@ -359,7 +359,7 @@ public void deleteNth(int position) {
size--;
return;
}
- Node cur = head;
+ SinglyLinkedListNode cur = head;
for (int i = 0; i < position - 1; ++i) {
cur = cur.next;
}
@@ -376,7 +376,7 @@ public void deleteNth(int position) {
*/
public int getNth(int index) {
checkBounds(index, 0, size - 1);
- Node cur = head;
+ SinglyLinkedListNode cur = head;
for (int i = 0; i < index; ++i) {
cur = cur.next;
}
@@ -440,7 +440,7 @@ public static void main(String[] arg) {
}
SinglyLinkedList instance = new SinglyLinkedList();
- Node head = new Node(0, new Node(2, new Node(3, new Node(3, new Node(4)))));
+ SinglyLinkedListNode head = new SinglyLinkedListNode(0, new SinglyLinkedListNode(2, new SinglyLinkedListNode(3, new SinglyLinkedListNode(3, new SinglyLinkedListNode(4)))));
instance.setHead(head);
instance.deleteDuplicates();
instance.print();
@@ -452,7 +452,7 @@ public Iterator iterator() {
}
private class SinglyLinkedListIterator implements Iterator {
- private Node current;
+ private SinglyLinkedListNode current;
SinglyLinkedListIterator() {
current = head;
@@ -474,43 +474,3 @@ public Integer next() {
}
}
}
-
-/**
- * This class is the nodes of the SinglyLinked List. They consist of a value and
- * a pointer to the node after them.
- */
-class Node {
-
- /**
- * The value of the node
- */
- int value;
-
- /**
- * Point to the next node
- */
- Node next;
-
- Node() {
- }
-
- /**
- * Constructor
- *
- * @param value Value to be put in the node
- */
- Node(int value) {
- this(value, null);
- }
-
- /**
- * Constructor
- *
- * @param value Value to be put in the node
- * @param next Reference to the next node
- */
- Node(int value, Node next) {
- this.value = value;
- this.next = next;
- }
-}
diff --git a/src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedListNode.java b/src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedListNode.java
new file mode 100644
index 000000000000..d0a06369215a
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedListNode.java
@@ -0,0 +1,34 @@
+package com.thealgorithms.datastructures.lists;
+
+/**
+ * This class is the nodes of the SinglyLinked List. They consist of a value and
+ * a pointer to the node after them.
+ */
+class SinglyLinkedListNode {
+
+ int value;
+ SinglyLinkedListNode next = null;
+
+ SinglyLinkedListNode() {
+ }
+
+ /**
+ * Constructor
+ *
+ * @param value Value to be put in the node
+ */
+ SinglyLinkedListNode(int value) {
+ this(value, null);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param value Value to be put in the node
+ * @param next Reference to the next node
+ */
+ SinglyLinkedListNode(int value, SinglyLinkedListNode next) {
+ this.value = value;
+ this.next = next;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequenceNLogN.java b/src/main/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequenceNLogN.java
new file mode 100644
index 000000000000..7bc0855e0566
--- /dev/null
+++ b/src/main/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequenceNLogN.java
@@ -0,0 +1,75 @@
+package com.thealgorithms.dynamicprogramming;
+
+/**
+ * Implementation of the Longest Increasing Subsequence (LIS) problem using
+ * an O(n log n) dynamic programming solution enhanced with binary search.
+ *
+ * @author Vusal Huseynov (https://github.com/huseynovvusal)
+ */
+public final class LongestIncreasingSubsequenceNLogN {
+ private LongestIncreasingSubsequenceNLogN() {
+ }
+
+ /**
+ * Finds the index of the smallest element in the array that is greater than
+ * or equal to the target using binary search. The search is restricted to
+ * the first `size` elements of the array.
+ *
+ * @param arr The array to search in (assumed to be sorted up to `size`).
+ * @param size The number of valid elements in the array.
+ * @param target The target value to find the lower bound for.
+ * @return The index of the lower bound.
+ */
+ private static int lowerBound(int[] arr, int target, int size) {
+ int l = 0;
+ int r = size;
+
+ while (l < r) {
+ int mid = l + (r - l) / 2;
+
+ if (target > arr[mid]) {
+ // Move right if target is greater than mid element
+ l = mid + 1;
+ } else {
+ // Move left if target is less than or equal to mid element
+ r = mid;
+ }
+ }
+
+ // Return the index where the target can be inserted
+ return l;
+ }
+
+ /**
+ * Calculates the length of the Longest Increasing Subsequence (LIS) in the given array.
+ *
+ * @param arr The input array of integers.
+ * @return The length of the LIS.
+ */
+ public static int lengthOfLIS(int[] arr) {
+ if (arr == null || arr.length == 0) {
+ return 0; // Return 0 for empty or null arrays
+ }
+
+ // tails[i] - the smallest end element of an increasing subsequence of length i+1
+ int[] tails = new int[arr.length];
+ // size - the length of the longest increasing subsequence found so far
+ int size = 0;
+
+ for (int x : arr) {
+ // Find the position to replace or extend the subsequence
+ int index = lowerBound(tails, x, size);
+
+ // Update the tails array with the current element
+ tails[index] = x;
+
+ // If the element extends the subsequence, increase the size
+ if (index == size) {
+ size++;
+ }
+ }
+
+ // Return the length of the LIS
+ return size;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/TreeMatching.java b/src/main/java/com/thealgorithms/dynamicprogramming/TreeMatching.java
new file mode 100644
index 000000000000..9fd82ccaf078
--- /dev/null
+++ b/src/main/java/com/thealgorithms/dynamicprogramming/TreeMatching.java
@@ -0,0 +1,78 @@
+package com.thealgorithms.dynamicprogramming;
+
+import com.thealgorithms.datastructures.graphs.UndirectedAdjacencyListGraph;
+
+/**
+ * This class implements the algorithm for calculating the maximum weighted matching in a tree.
+ * The tree is represented as an undirected graph with weighted edges.
+ *
+ * Problem Description:
+ * Given an undirected tree G = (V, E) with edge weights γ: E → N and a root r ∈ V,
+ * the goal is to find a maximum weight matching M ⊆ E such that no two edges in M
+ * share a common vertex. The sum of the weights of the edges in M, ∑ e∈M γ(e), should be maximized.
+ * For more Information: Matching (graph theory)
+ *
+ * @author Deniz Altunkapan
+ */
+public class TreeMatching {
+
+ private UndirectedAdjacencyListGraph graph;
+ private int[][] dp;
+
+ /**
+ * Constructor that initializes the graph and the DP table.
+ *
+ * @param graph The graph that represents the tree and is used for the matching algorithm.
+ */
+ public TreeMatching(UndirectedAdjacencyListGraph graph) {
+ this.graph = graph;
+ this.dp = new int[graph.size()][2];
+ }
+
+ /**
+ * Calculates the maximum weighted matching for the tree, starting from the given root node.
+ *
+ * @param root The index of the root node of the tree.
+ * @param parent The index of the parent node (used for recursion).
+ * @return The maximum weighted matching for the tree, starting from the root node.
+ *
+ */
+ public int getMaxMatching(int root, int parent) {
+ if (root < 0 || root >= graph.size()) {
+ throw new IllegalArgumentException("Invalid root: " + root);
+ }
+ maxMatching(root, parent);
+ return Math.max(dp[root][0], dp[root][1]);
+ }
+
+ /**
+ * Recursively computes the maximum weighted matching for a node, assuming that the node
+ * can either be included or excluded from the matching.
+ *
+ * @param node The index of the current node for which the matching is calculated.
+ * @param parent The index of the parent node (to avoid revisiting the parent node during recursion).
+ */
+ private void maxMatching(int node, int parent) {
+ dp[node][0] = 0;
+ dp[node][1] = 0;
+
+ int sumWithoutEdge = 0;
+ for (int adjNode : graph.getNeighbors(node)) {
+ if (adjNode == parent) {
+ continue;
+ }
+ maxMatching(adjNode, node);
+ sumWithoutEdge += Math.max(dp[adjNode][0], dp[adjNode][1]);
+ }
+
+ dp[node][0] = sumWithoutEdge;
+
+ for (int adjNode : graph.getNeighbors(node)) {
+ if (adjNode == parent) {
+ continue;
+ }
+ int weight = graph.getEdgeWeight(node, adjNode);
+ dp[node][1] = Math.max(dp[node][1], sumWithoutEdge - Math.max(dp[adjNode][0], dp[adjNode][1]) + dp[adjNode][0] + weight);
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/graph/ConstrainedShortestPath.java b/src/main/java/com/thealgorithms/graph/ConstrainedShortestPath.java
new file mode 100644
index 000000000000..f397989911d9
--- /dev/null
+++ b/src/main/java/com/thealgorithms/graph/ConstrainedShortestPath.java
@@ -0,0 +1,123 @@
+package com.thealgorithms.graph;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This class implements a solution for the Constrained Shortest Path Problem (CSPP).
+ * also known as Shortest Path Problem with Resource Constraints (SPPRC).
+ * The goal is to find the shortest path between two nodes while ensuring that
+ * the resource constraint is not exceeded.
+ *
+ * @author Deniz Altunkapan
+ */
+public class ConstrainedShortestPath {
+
+ /**
+ * Represents a graph using an adjacency list.
+ * This graph is designed for the Constrained Shortest Path Problem (CSPP).
+ */
+ public static class Graph {
+
+ private List> adjacencyList;
+
+ public Graph(int numNodes) {
+ adjacencyList = new ArrayList<>();
+ for (int i = 0; i < numNodes; i++) {
+ adjacencyList.add(new ArrayList<>());
+ }
+ }
+
+ /**
+ * Adds an edge to the graph.
+ * @param from the starting node
+ * @param to the ending node
+ * @param cost the cost of the edge
+ * @param resource the resource required to traverse the edge
+ */
+ public void addEdge(int from, int to, int cost, int resource) {
+ adjacencyList.get(from).add(new Edge(from, to, cost, resource));
+ }
+
+ /**
+ * Gets the edges that are adjacent to a given node.
+ * @param node the node to get the edges for
+ * @return the list of edges adjacent to the node
+ */
+ public List getEdges(int node) {
+ return adjacencyList.get(node);
+ }
+
+ /**
+ * Gets the number of nodes in the graph.
+ * @return the number of nodes
+ */
+ public int getNumNodes() {
+ return adjacencyList.size();
+ }
+
+ public record Edge(int from, int to, int cost, int resource) {
+ }
+ }
+
+ private Graph graph;
+ private int maxResource;
+
+ /**
+ * Constructs a CSPSolver with the given graph and maximum resource constraint.
+ *
+ * @param graph the graph representing the problem
+ * @param maxResource the maximum allowable resource
+ */
+ public ConstrainedShortestPath(Graph graph, int maxResource) {
+ this.graph = graph;
+ this.maxResource = maxResource;
+ }
+
+ /**
+ * Solves the CSP to find the shortest path from the start node to the target node
+ * without exceeding the resource constraint.
+ *
+ * @param start the starting node
+ * @param target the target node
+ * @return the minimum cost to reach the target node within the resource constraint,
+ * or -1 if no valid path exists
+ */
+ public int solve(int start, int target) {
+ int numNodes = graph.getNumNodes();
+ int[][] dp = new int[maxResource + 1][numNodes];
+
+ // Initialize dp table with maximum values
+ for (int i = 0; i <= maxResource; i++) {
+ Arrays.fill(dp[i], Integer.MAX_VALUE);
+ }
+ dp[0][start] = 0;
+
+ // Dynamic Programming: Iterate over resources and nodes
+ for (int r = 0; r <= maxResource; r++) {
+ for (int u = 0; u < numNodes; u++) {
+ if (dp[r][u] == Integer.MAX_VALUE) {
+ continue;
+ }
+ for (Graph.Edge edge : graph.getEdges(u)) {
+ int v = edge.to();
+ int cost = edge.cost();
+ int resource = edge.resource();
+
+ if (r + resource <= maxResource) {
+ dp[r + resource][v] = Math.min(dp[r + resource][v], dp[r][u] + cost);
+ }
+ }
+ }
+ }
+
+ // Find the minimum cost to reach the target node
+ int minCost = Integer.MAX_VALUE;
+ for (int r = 0; r <= maxResource; r++) {
+ minCost = Math.min(minCost, dp[r][target]);
+ }
+
+ return minCost == Integer.MAX_VALUE ? -1 : minCost;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/graph/TravelingSalesman.java b/src/main/java/com/thealgorithms/graph/TravelingSalesman.java
new file mode 100644
index 000000000000..14bf89f57cf3
--- /dev/null
+++ b/src/main/java/com/thealgorithms/graph/TravelingSalesman.java
@@ -0,0 +1,155 @@
+package com.thealgorithms.graph;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * This class provides solutions to the Traveling Salesman Problem (TSP) using both brute-force and dynamic programming approaches.
+ * For more information, see Wikipedia.
+ * @author Deniz Altunkapan
+ */
+
+public final class TravelingSalesman {
+
+ // Private constructor to prevent instantiation
+ private TravelingSalesman() {
+ }
+
+ /**
+ * Solves the Traveling Salesman Problem (TSP) using brute-force approach.
+ * This method generates all possible permutations of cities, calculates the total distance for each route, and returns the shortest distance found.
+ *
+ * @param distanceMatrix A square matrix where element [i][j] represents the distance from city i to city j.
+ * @return The shortest possible route distance visiting all cities exactly once and returning to the starting city.
+ */
+ public static int bruteForce(int[][] distanceMatrix) {
+ if (distanceMatrix.length <= 1) {
+ return 0;
+ }
+
+ List cities = new ArrayList<>();
+ for (int i = 1; i < distanceMatrix.length; i++) {
+ cities.add(i);
+ }
+
+ List> permutations = generatePermutations(cities);
+ int minDistance = Integer.MAX_VALUE;
+
+ for (List permutation : permutations) {
+ List route = new ArrayList<>();
+ route.add(0);
+ route.addAll(permutation);
+ int currentDistance = calculateDistance(distanceMatrix, route);
+ if (currentDistance < minDistance) {
+ minDistance = currentDistance;
+ }
+ }
+
+ return minDistance;
+ }
+
+ /**
+ * Computes the total distance of a given route.
+ *
+ * @param distanceMatrix A square matrix where element [i][j] represents the
+ * distance from city i to city j.
+ * @param route A list representing the order in which the cities are visited.
+ * @return The total distance of the route, or Integer.MAX_VALUE if the route is invalid.
+ */
+ public static int calculateDistance(int[][] distanceMatrix, List route) {
+ int distance = 0;
+ for (int i = 0; i < route.size() - 1; i++) {
+ int d = distanceMatrix[route.get(i)][route.get(i + 1)];
+ if (d == Integer.MAX_VALUE) {
+ return Integer.MAX_VALUE;
+ }
+ distance += d;
+ }
+ int returnDist = distanceMatrix[route.get(route.size() - 1)][route.get(0)];
+ return (returnDist == Integer.MAX_VALUE) ? Integer.MAX_VALUE : distance + returnDist;
+ }
+
+ /**
+ * Generates all permutations of a given list of cities.
+ *
+ * @param cities A list of cities to permute.
+ * @return A list of all possible permutations.
+ */
+ private static List> generatePermutations(List cities) {
+ List> permutations = new ArrayList<>();
+ permute(cities, 0, permutations);
+ return permutations;
+ }
+
+ /**
+ * Recursively generates permutations using backtracking.
+ *
+ * @param arr The list of cities.
+ * @param k The current index in the permutation process.
+ * @param output The list to store generated permutations.
+ */
+ private static void permute(List arr, int k, List> output) {
+ if (k == arr.size()) {
+ output.add(new ArrayList<>(arr));
+ return;
+ }
+ for (int i = k; i < arr.size(); i++) {
+ Collections.swap(arr, i, k);
+ permute(arr, k + 1, output);
+ Collections.swap(arr, i, k);
+ }
+ }
+
+ /**
+ * Solves the Traveling Salesman Problem (TSP) using dynamic programming with the Held-Karp algorithm.
+ *
+ * @param distanceMatrix A square matrix where element [i][j] represents the distance from city i to city j.
+ * @return The shortest possible route distance visiting all cities exactly once and returning to the starting city.
+ * @throws IllegalArgumentException if the input matrix is not square.
+ */
+ public static int dynamicProgramming(int[][] distanceMatrix) {
+ if (distanceMatrix.length == 0) {
+ return 0;
+ }
+ int n = distanceMatrix.length;
+
+ for (int[] row : distanceMatrix) {
+ if (row.length != n) {
+ throw new IllegalArgumentException("Matrix must be square");
+ }
+ }
+
+ int[][] dp = new int[n][1 << n];
+ for (int[] row : dp) {
+ Arrays.fill(row, Integer.MAX_VALUE);
+ }
+ dp[0][1] = 0;
+
+ for (int mask = 1; mask < (1 << n); mask++) {
+ for (int u = 0; u < n; u++) {
+ if ((mask & (1 << u)) == 0 || dp[u][mask] == Integer.MAX_VALUE) {
+ continue;
+ }
+ for (int v = 0; v < n; v++) {
+ if ((mask & (1 << v)) != 0 || distanceMatrix[u][v] == Integer.MAX_VALUE) {
+ continue;
+ }
+ int newMask = mask | (1 << v);
+ dp[v][newMask] = Math.min(dp[v][newMask], dp[u][mask] + distanceMatrix[u][v]);
+ }
+ }
+ }
+
+ int minDistance = Integer.MAX_VALUE;
+ int fullMask = (1 << n) - 1;
+ for (int i = 1; i < n; i++) {
+ if (dp[i][fullMask] != Integer.MAX_VALUE && distanceMatrix[i][0] != Integer.MAX_VALUE) {
+ minDistance = Math.min(minDistance, dp[i][fullMask] + distanceMatrix[i][0]);
+ }
+ }
+
+ return minDistance == Integer.MAX_VALUE ? 0 : minDistance;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/maths/AbsoluteMax.java b/src/main/java/com/thealgorithms/maths/AbsoluteMax.java
index d0c3db3790a3..c32a408b6609 100644
--- a/src/main/java/com/thealgorithms/maths/AbsoluteMax.java
+++ b/src/main/java/com/thealgorithms/maths/AbsoluteMax.java
@@ -17,7 +17,7 @@ public static int getMaxValue(int... numbers) {
}
int absMax = numbers[0];
for (int i = 1; i < numbers.length; i++) {
- if (Math.abs(numbers[i]) > Math.abs(absMax)) {
+ if (Math.abs(numbers[i]) > Math.abs(absMax) || (Math.abs(numbers[i]) == Math.abs(absMax) && numbers[i] > absMax)) {
absMax = numbers[i];
}
}
diff --git a/src/main/java/com/thealgorithms/maths/AbsoluteMin.java b/src/main/java/com/thealgorithms/maths/AbsoluteMin.java
index 1ffe6d2e81bc..1b9575a330dd 100644
--- a/src/main/java/com/thealgorithms/maths/AbsoluteMin.java
+++ b/src/main/java/com/thealgorithms/maths/AbsoluteMin.java
@@ -19,7 +19,7 @@ public static int getMinValue(int... numbers) {
var absMinWrapper = new Object() { int value = numbers[0]; };
- Arrays.stream(numbers).skip(1).filter(number -> Math.abs(number) < Math.abs(absMinWrapper.value)).forEach(number -> absMinWrapper.value = number);
+ Arrays.stream(numbers).skip(1).filter(number -> Math.abs(number) <= Math.abs(absMinWrapper.value)).forEach(number -> absMinWrapper.value = Math.min(absMinWrapper.value, number));
return absMinWrapper.value;
}
diff --git a/src/main/java/com/thealgorithms/maths/AliquotSum.java b/src/main/java/com/thealgorithms/maths/AliquotSum.java
index 0dbc58bed605..996843b56826 100644
--- a/src/main/java/com/thealgorithms/maths/AliquotSum.java
+++ b/src/main/java/com/thealgorithms/maths/AliquotSum.java
@@ -56,7 +56,7 @@ public static int getAliquotSum(int n) {
// if n is a perfect square then its root was added twice in above loop, so subtracting root
// from sum
if (root == (int) root) {
- sum -= root;
+ sum -= (int) root;
}
return sum;
}
diff --git a/src/main/java/com/thealgorithms/maths/Armstrong.java b/src/main/java/com/thealgorithms/maths/Armstrong.java
index ff4ae027a0b7..9a7a014ec99f 100644
--- a/src/main/java/com/thealgorithms/maths/Armstrong.java
+++ b/src/main/java/com/thealgorithms/maths/Armstrong.java
@@ -10,6 +10,7 @@
* An Armstrong number is often called a Narcissistic number.
*
* @author satyabarghav
+ * @modifier rahul katteda - (13/01/2025) - [updated the logic for getting total number of digits]
*/
public class Armstrong {
@@ -20,14 +21,16 @@ public class Armstrong {
* @return {@code true} if the given number is an Armstrong number, {@code false} otherwise
*/
public boolean isArmstrong(int number) {
+ if (number < 0) {
+ return false; // Negative numbers cannot be Armstrong numbers
+ }
long sum = 0;
- String temp = Integer.toString(number); // Convert the given number to a string
- int power = temp.length(); // Extract the length of the number (number of digits)
+ int totalDigits = (int) Math.log10(number) + 1; // get the length of the number (number of digits)
long originalNumber = number;
while (originalNumber > 0) {
long digit = originalNumber % 10;
- sum += (long) Math.pow(digit, power); // The digit raised to the power of the number of digits and added to the sum.
+ sum += (long) Math.pow(digit, totalDigits); // The digit raised to the power of total number of digits and added to the sum.
originalNumber /= 10;
}
diff --git a/src/main/java/com/thealgorithms/maths/Average.java b/src/main/java/com/thealgorithms/maths/Average.java
index 6b9c20162da1..a550a7f6504d 100644
--- a/src/main/java/com/thealgorithms/maths/Average.java
+++ b/src/main/java/com/thealgorithms/maths/Average.java
@@ -37,7 +37,7 @@ public static double average(double[] numbers) {
* @return the average of the given numbers
* @throws IllegalArgumentException if the input array is {@code null} or empty
*/
- public static double average(int[] numbers) {
+ public static long average(int[] numbers) {
if (numbers == null || numbers.length == 0) {
throw new IllegalArgumentException("Numbers array cannot be empty or null");
}
@@ -45,6 +45,6 @@ public static double average(int[] numbers) {
for (int number : numbers) {
sum += number;
}
- return (double) (sum / numbers.length);
+ return sum / numbers.length;
}
}
diff --git a/src/main/java/com/thealgorithms/maths/GoldbachConjecture.java b/src/main/java/com/thealgorithms/maths/GoldbachConjecture.java
new file mode 100644
index 000000000000..4e962722ba88
--- /dev/null
+++ b/src/main/java/com/thealgorithms/maths/GoldbachConjecture.java
@@ -0,0 +1,30 @@
+package com.thealgorithms.maths;
+
+import static com.thealgorithms.maths.Prime.PrimeCheck.isPrime;
+
+/**
+ * This is a representation of the unsolved problem of Goldbach's Projection, according to which every
+ * even natural number greater than 2 can be written as the sum of 2 prime numbers
+ * More info: https://en.wikipedia.org/wiki/Goldbach%27s_conjecture
+ * @author Vasilis Sarantidis (https://github.com/BILLSARAN)
+ */
+
+public final class GoldbachConjecture {
+ private GoldbachConjecture() {
+ }
+ public record Result(int number1, int number2) {
+ }
+
+ public static Result getPrimeSum(int number) {
+ if (number <= 2 || number % 2 != 0) {
+ throw new IllegalArgumentException("Number must be even and greater than 2.");
+ }
+
+ for (int i = 0; i <= number / 2; i++) {
+ if (isPrime(i) && isPrime(number - i)) {
+ return new Result(i, number - i);
+ }
+ }
+ throw new IllegalStateException("No valid prime sum found."); // Should not occur
+ }
+}
diff --git a/src/main/java/com/thealgorithms/maths/MathBuilder.java b/src/main/java/com/thealgorithms/maths/MathBuilder.java
new file mode 100644
index 000000000000..1cf3d8b7fc9a
--- /dev/null
+++ b/src/main/java/com/thealgorithms/maths/MathBuilder.java
@@ -0,0 +1,503 @@
+package com.thealgorithms.maths;
+
+import java.text.DecimalFormat;
+import java.util.Random;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * Author: Sadiul Hakim : https://github.com/sadiul-hakim
+ * Profession: Backend Engineer
+ * Date: Oct 20, 2024
+ */
+public final class MathBuilder {
+ private final double result;
+
+ private MathBuilder(Builder builder) {
+ this.result = builder.number;
+ }
+
+ // Returns final result
+ public double get() {
+ return result;
+ }
+
+ // Return result in long
+ public long toLong() {
+ try {
+ if (Double.isNaN(result)) {
+ throw new IllegalArgumentException("Cannot convert NaN to long!");
+ }
+ if (result == Double.POSITIVE_INFINITY) {
+ return Long.MAX_VALUE;
+ }
+ if (result == Double.NEGATIVE_INFINITY) {
+ return Long.MIN_VALUE;
+ }
+ if (result > Long.MAX_VALUE) {
+ return Long.MAX_VALUE;
+ }
+ if (result < Long.MIN_VALUE) {
+ return Long.MIN_VALUE;
+ }
+ return Math.round(result);
+ } catch (Exception ex) {
+ return 0;
+ }
+ }
+
+ public static class Builder {
+ private double number;
+ private double sideNumber;
+ private boolean inParenthesis;
+ private double memory = 0;
+
+ public Builder() {
+ number = 0;
+ }
+
+ public Builder(double num) {
+ number = num;
+ }
+
+ public Builder add(double num) {
+ if (inParenthesis) {
+ sideNumber += num;
+ } else {
+ number += num;
+ }
+ return this;
+ }
+
+ // Takes a number and a condition, only does the operation if condition is true.
+ public Builder addIf(double num, BiFunction condition) {
+ if (!condition.apply(number, num)) {
+ return this;
+ }
+ if (inParenthesis) {
+ sideNumber += num;
+ } else {
+ number += num;
+ }
+ return this;
+ }
+
+ public Builder minus(double num) {
+ if (inParenthesis) {
+ sideNumber -= num;
+ } else {
+ number -= num;
+ }
+ return this;
+ }
+
+ // Takes a number and a condition, only does the operation if condition is true.
+ public Builder minusIf(double num, BiFunction condition) {
+ if (!condition.apply(number, num)) {
+ return this;
+ }
+ if (inParenthesis) {
+ sideNumber -= num;
+ } else {
+ number -= num;
+ }
+ return this;
+ }
+
+ // Generates a random number and sets to NUMBER
+ public Builder rand(long seed) {
+ if (number != 0) {
+ throw new RuntimeException("Number must be zero for random assignment!");
+ }
+ Random random = new Random();
+ number = random.nextDouble(seed);
+ return this;
+ }
+
+ // Takes PI value and sets to NUMBER
+ public Builder pi() {
+ if (number != 0) {
+ throw new RuntimeException("Number must be zero for PI assignment!");
+ }
+ number = Math.PI;
+ return this;
+ }
+
+ // Takes E value and sets to NUMBER
+ public Builder e() {
+ if (number != 0) {
+ throw new RuntimeException("Number must be zero for E assignment!");
+ }
+ number = Math.E;
+ return this;
+ }
+
+ public Builder randomInRange(double min, double max) {
+ if (number != 0) {
+ throw new RuntimeException("Number must be zero for random assignment!");
+ }
+ Random random = new Random();
+ number = min + (max - min) * random.nextDouble();
+ return this;
+ }
+
+ public Builder toDegrees() {
+ if (inParenthesis) {
+ sideNumber = Math.toDegrees(sideNumber);
+ } else {
+ number = Math.toDegrees(number);
+ }
+ return this;
+ }
+
+ public Builder max(double num) {
+ if (inParenthesis) {
+ sideNumber = Math.max(sideNumber, num);
+ } else {
+ number = Math.max(number, num);
+ }
+ return this;
+ }
+
+ public Builder min(double num) {
+ if (inParenthesis) {
+ sideNumber = Math.min(sideNumber, num);
+ } else {
+ number = Math.min(number, num);
+ }
+ return this;
+ }
+
+ public Builder multiply(double num) {
+ if (inParenthesis) {
+ sideNumber *= num;
+ } else {
+ number *= num;
+ }
+ return this;
+ }
+
+ // Takes a number and a condition, only does the operation if condition is true.
+ public Builder multiplyIf(double num, BiFunction condition) {
+ if (!condition.apply(number, num)) {
+ return this;
+ }
+ if (inParenthesis) {
+ sideNumber *= num;
+ } else {
+ number *= num;
+ }
+ return this;
+ }
+
+ public Builder divide(double num) {
+ if (num == 0) {
+ return this;
+ }
+ if (inParenthesis) {
+ sideNumber /= num;
+ } else {
+ number /= num;
+ }
+ return this;
+ }
+
+ // Takes a number and a condition, only does the operation if condition is true.
+ public Builder divideIf(double num, BiFunction condition) {
+ if (num == 0) {
+ return this;
+ }
+ if (!condition.apply(number, num)) {
+ return this;
+ }
+ if (inParenthesis) {
+ sideNumber /= num;
+ } else {
+ number /= num;
+ }
+ return this;
+ }
+
+ public Builder mod(double num) {
+ if (inParenthesis) {
+ sideNumber %= num;
+ } else {
+ number %= num;
+ }
+ return this;
+ }
+
+ // Takes a number and a condition, only does the operation if condition is true.
+ public Builder modIf(double num, BiFunction condition) {
+ if (!condition.apply(number, num)) {
+ return this;
+ }
+ if (inParenthesis) {
+ sideNumber %= num;
+ } else {
+ number %= num;
+ }
+ return this;
+ }
+
+ public Builder pow(double num) {
+ if (inParenthesis) {
+ sideNumber = Math.pow(sideNumber, num);
+ } else {
+ number = Math.pow(number, num);
+ }
+ return this;
+ }
+
+ public Builder sqrt() {
+ if (inParenthesis) {
+ sideNumber = Math.sqrt(sideNumber);
+ } else {
+ number = Math.sqrt(number);
+ }
+ return this;
+ }
+
+ public Builder round() {
+ if (inParenthesis) {
+ sideNumber = Math.round(sideNumber);
+ } else {
+ number = Math.round(number);
+ }
+ return this;
+ }
+
+ public Builder floor() {
+ if (inParenthesis) {
+ sideNumber = Math.floor(sideNumber);
+ } else {
+ number = Math.floor(number);
+ }
+ return this;
+ }
+
+ public Builder ceil() {
+ if (inParenthesis) {
+ sideNumber = Math.ceil(sideNumber);
+ } else {
+ number = Math.ceil(number);
+ }
+ return this;
+ }
+
+ public Builder abs() {
+ if (inParenthesis) {
+ sideNumber = Math.abs(sideNumber);
+ } else {
+ number = Math.abs(number);
+ }
+ return this;
+ }
+
+ public Builder cbrt() {
+ if (inParenthesis) {
+ sideNumber = Math.cbrt(sideNumber);
+ } else {
+ number = Math.cbrt(number);
+ }
+ return this;
+ }
+
+ public Builder log() {
+ if (inParenthesis) {
+ sideNumber = Math.log(sideNumber);
+ } else {
+ number = Math.log(number);
+ }
+ return this;
+ }
+
+ public Builder log10() {
+ if (inParenthesis) {
+ sideNumber = Math.log10(sideNumber);
+ } else {
+ number = Math.log10(number);
+ }
+ return this;
+ }
+
+ public Builder sin() {
+ if (inParenthesis) {
+ sideNumber = Math.sin(sideNumber);
+ } else {
+ number = Math.sin(number);
+ }
+ return this;
+ }
+
+ public Builder cos() {
+ if (inParenthesis) {
+ sideNumber = Math.cos(sideNumber);
+ } else {
+ number = Math.cos(number);
+ }
+ return this;
+ }
+
+ public Builder tan() {
+ if (inParenthesis) {
+ sideNumber = Math.tan(sideNumber);
+ } else {
+ number = Math.tan(number);
+ }
+ return this;
+ }
+
+ public Builder sinh() {
+ if (inParenthesis) {
+ sideNumber = Math.sinh(sideNumber);
+ } else {
+ number = Math.sinh(number);
+ }
+ return this;
+ }
+
+ public Builder cosh() {
+ if (inParenthesis) {
+ sideNumber = Math.cosh(sideNumber);
+ } else {
+ number = Math.cosh(number);
+ }
+ return this;
+ }
+
+ public Builder tanh() {
+ if (inParenthesis) {
+ sideNumber = Math.tanh(sideNumber);
+ } else {
+ number = Math.tanh(number);
+ }
+ return this;
+ }
+
+ public Builder exp() {
+ if (inParenthesis) {
+ sideNumber = Math.exp(sideNumber);
+ } else {
+ number = Math.exp(number);
+ }
+ return this;
+ }
+
+ public Builder toRadians() {
+ if (inParenthesis) {
+ sideNumber = Math.toRadians(sideNumber);
+ } else {
+ number = Math.toRadians(number);
+ }
+ return this;
+ }
+
+ // Remembers the NUMBER
+ public Builder remember() {
+ memory = number;
+ return this;
+ }
+
+ // Recalls the NUMBER
+ public Builder recall(boolean cleanMemory) {
+ number = memory;
+ if (cleanMemory) {
+ memory = 0;
+ }
+ return this;
+ }
+
+ // Recalls the NUMBER on condition
+ public Builder recallIf(Function condition, boolean cleanMemory) {
+ if (!condition.apply(number)) {
+ return this;
+ }
+ number = memory;
+ if (cleanMemory) {
+ memory = 0;
+ }
+ return this;
+ }
+
+ // Replaces NUMBER with given number
+ public Builder set(double num) {
+ if (number != 0) {
+ throw new RuntimeException("Number must be zero to set!");
+ }
+ number = num;
+ return this;
+ }
+
+ // Replaces NUMBER with given number on condition
+ public Builder setIf(double num, BiFunction condition) {
+ if (number != 0) {
+ throw new RuntimeException("Number must be zero to set!");
+ }
+ if (condition.apply(number, num)) {
+ number = num;
+ }
+ return this;
+ }
+
+ // Prints current NUMBER
+ public Builder print() {
+ System.out.println("MathBuilder Result :: " + number);
+ return this;
+ }
+
+ public Builder openParenthesis(double num) {
+ sideNumber = num;
+ inParenthesis = true;
+ return this;
+ }
+
+ public Builder closeParenthesisAndPlus() {
+ number += sideNumber;
+ inParenthesis = false;
+ sideNumber = 0;
+ return this;
+ }
+
+ public Builder closeParenthesisAndMinus() {
+ number -= sideNumber;
+ inParenthesis = false;
+ sideNumber = 0;
+ return this;
+ }
+
+ public Builder closeParenthesisAndMultiply() {
+ number *= sideNumber;
+ inParenthesis = false;
+ sideNumber = 0;
+ return this;
+ }
+
+ public Builder closeParenthesisAndDivide() {
+ number /= sideNumber;
+ inParenthesis = false;
+ sideNumber = 0;
+ return this;
+ }
+
+ public Builder format(String format) {
+ DecimalFormat formater = new DecimalFormat(format);
+ String num = formater.format(number);
+ number = Double.parseDouble(num);
+ return this;
+ }
+
+ public Builder format(int decimalPlace) {
+ String pattern = "."
+ + "#".repeat(decimalPlace);
+ DecimalFormat formater = new DecimalFormat(pattern);
+ String num = formater.format(number);
+ number = Double.parseDouble(num);
+ return this;
+ }
+
+ public MathBuilder build() {
+ return new MathBuilder(this);
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/maths/PerfectNumber.java b/src/main/java/com/thealgorithms/maths/PerfectNumber.java
index 2a935b067094..f299d08e5d27 100644
--- a/src/main/java/com/thealgorithms/maths/PerfectNumber.java
+++ b/src/main/java/com/thealgorithms/maths/PerfectNumber.java
@@ -63,7 +63,7 @@ public static boolean isPerfectNumber2(int n) {
// if n is a perfect square then its root was added twice in above loop, so subtracting root
// from sum
if (root == (int) root) {
- sum -= root;
+ sum -= (int) root;
}
return sum == n;
diff --git a/src/main/java/com/thealgorithms/maths/LiouvilleLambdaFunction.java b/src/main/java/com/thealgorithms/maths/Prime/LiouvilleLambdaFunction.java
similarity index 93%
rename from src/main/java/com/thealgorithms/maths/LiouvilleLambdaFunction.java
rename to src/main/java/com/thealgorithms/maths/Prime/LiouvilleLambdaFunction.java
index c0f55f5e3485..73535b3aedae 100644
--- a/src/main/java/com/thealgorithms/maths/LiouvilleLambdaFunction.java
+++ b/src/main/java/com/thealgorithms/maths/Prime/LiouvilleLambdaFunction.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.maths.Prime;
/*
* Java program for liouville lambda function
@@ -24,7 +24,7 @@ private LiouvilleLambdaFunction() {
* -1 when number has odd number of prime factors
* @throws IllegalArgumentException when number is negative
*/
- static int liouvilleLambda(int number) {
+ public static int liouvilleLambda(int number) {
if (number <= 0) {
// throw exception when number is less than or is zero
throw new IllegalArgumentException("Number must be greater than zero.");
diff --git a/src/main/java/com/thealgorithms/maths/MillerRabinPrimalityCheck.java b/src/main/java/com/thealgorithms/maths/Prime/MillerRabinPrimalityCheck.java
similarity index 98%
rename from src/main/java/com/thealgorithms/maths/MillerRabinPrimalityCheck.java
rename to src/main/java/com/thealgorithms/maths/Prime/MillerRabinPrimalityCheck.java
index f889213abfcb..debe3a214a32 100644
--- a/src/main/java/com/thealgorithms/maths/MillerRabinPrimalityCheck.java
+++ b/src/main/java/com/thealgorithms/maths/Prime/MillerRabinPrimalityCheck.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.maths.Prime;
import java.util.Random;
diff --git a/src/main/java/com/thealgorithms/maths/MobiusFunction.java b/src/main/java/com/thealgorithms/maths/Prime/MobiusFunction.java
similarity index 96%
rename from src/main/java/com/thealgorithms/maths/MobiusFunction.java
rename to src/main/java/com/thealgorithms/maths/Prime/MobiusFunction.java
index 915d0d9a6dae..3d4e4eff0f03 100644
--- a/src/main/java/com/thealgorithms/maths/MobiusFunction.java
+++ b/src/main/java/com/thealgorithms/maths/Prime/MobiusFunction.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.maths.Prime;
/*
* Java program for mobius function
@@ -25,7 +25,7 @@ private MobiusFunction() {
* 0 when number has repeated prime factor
* -1 when number has odd number of prime factors
*/
- static int mobius(int number) {
+ public static int mobius(int number) {
if (number <= 0) {
// throw exception when number is less than or is zero
throw new IllegalArgumentException("Number must be greater than zero.");
diff --git a/src/main/java/com/thealgorithms/maths/PrimeCheck.java b/src/main/java/com/thealgorithms/maths/Prime/PrimeCheck.java
similarity index 98%
rename from src/main/java/com/thealgorithms/maths/PrimeCheck.java
rename to src/main/java/com/thealgorithms/maths/Prime/PrimeCheck.java
index 628a819aeba4..91c490f70aef 100644
--- a/src/main/java/com/thealgorithms/maths/PrimeCheck.java
+++ b/src/main/java/com/thealgorithms/maths/Prime/PrimeCheck.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.maths.Prime;
import java.util.Scanner;
diff --git a/src/main/java/com/thealgorithms/maths/PrimeFactorization.java b/src/main/java/com/thealgorithms/maths/Prime/PrimeFactorization.java
similarity index 95%
rename from src/main/java/com/thealgorithms/maths/PrimeFactorization.java
rename to src/main/java/com/thealgorithms/maths/Prime/PrimeFactorization.java
index 9ac50fd9043b..e12002b3d8c7 100644
--- a/src/main/java/com/thealgorithms/maths/PrimeFactorization.java
+++ b/src/main/java/com/thealgorithms/maths/Prime/PrimeFactorization.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.maths.Prime;
/*
* Authors:
diff --git a/src/main/java/com/thealgorithms/maths/SquareFreeInteger.java b/src/main/java/com/thealgorithms/maths/Prime/SquareFreeInteger.java
similarity index 97%
rename from src/main/java/com/thealgorithms/maths/SquareFreeInteger.java
rename to src/main/java/com/thealgorithms/maths/Prime/SquareFreeInteger.java
index 22e9fee00605..15c0a8a691cd 100644
--- a/src/main/java/com/thealgorithms/maths/SquareFreeInteger.java
+++ b/src/main/java/com/thealgorithms/maths/Prime/SquareFreeInteger.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.maths.Prime;
/*
* Java program for Square free integer
* This class has a function which checks
diff --git a/src/main/java/com/thealgorithms/maths/TwinPrime.java b/src/main/java/com/thealgorithms/maths/TwinPrime.java
index ef8de0d1018e..f4e546a2d7a4 100644
--- a/src/main/java/com/thealgorithms/maths/TwinPrime.java
+++ b/src/main/java/com/thealgorithms/maths/TwinPrime.java
@@ -9,6 +9,8 @@
*
* */
+import com.thealgorithms.maths.Prime.PrimeCheck;
+
public final class TwinPrime {
private TwinPrime() {
}
diff --git a/src/main/java/com/thealgorithms/maths/VampireNumber.java b/src/main/java/com/thealgorithms/maths/VampireNumber.java
index 8820f8a23f70..45bb9a587778 100644
--- a/src/main/java/com/thealgorithms/maths/VampireNumber.java
+++ b/src/main/java/com/thealgorithms/maths/VampireNumber.java
@@ -1,78 +1,48 @@
package com.thealgorithms.maths;
import java.util.ArrayList;
-import java.util.Collections;
/**
- * n number theory, a vampire number (or true vampire number) is a composite
+ * In number theory, a vampire number (or true vampire number) is a composite
* natural number with an even number of digits, that can be factored into two
* natural numbers each with half as many digits as the original number and not
* both with trailing zeroes, where the two factors contain precisely all the
* digits of the original number, in any order, counting multiplicity. The first
- * vampire number is 1260 = 21 × 60. *
+ * vampire number is 1260 = 21 × 60.
*
- *
+ * @see Vampire number on Wikipedia
*/
public final class VampireNumber {
+ // Forbid instantiation.
private VampireNumber() {
}
- public static void main(String[] args) {
- test(10, 1000);
- }
-
- static void test(int startValue, int stopValue) {
- int countofRes = 1;
- StringBuilder res = new StringBuilder();
-
- for (int i = startValue; i <= stopValue; i++) {
- for (int j = i; j <= stopValue; j++) {
- // System.out.println(i+ " "+ j);
- if (isVampireNumber(i, j, true)) {
- countofRes++;
- res.append("").append(countofRes).append(": = ( ").append(i).append(",").append(j).append(" = ").append(i * j).append(")").append("\n");
- }
- }
- }
- System.out.println(res);
- }
-
- static boolean isVampireNumber(int a, int b, boolean noPseudoVamireNumbers) {
- // this is for pseudoVampireNumbers pseudovampire number need not be of length n/2 digits
- // for example 126 = 6 x 21
- if (noPseudoVamireNumbers) {
- if (a * 10 <= b || b * 10 <= a) {
- return false;
- }
+ static boolean isVampireNumber(int a, int b, boolean ignorePseudoVampireNumbers) {
+ // Pseudo vampire numbers don't have to be of n/2 digits. E.g., 126 = 6 x 21 is such a number.
+ if (ignorePseudoVampireNumbers && String.valueOf(a).length() != String.valueOf(b).length()) {
+ return false;
}
- String mulDigits = splitIntoDigits(a * b, 0);
- String faktorDigits = splitIntoDigits(a, b);
+ String mulDigits = splitIntoSortedDigits(a * b);
+ String factorDigits = splitIntoSortedDigits(a, b);
- return mulDigits.equals(faktorDigits);
+ return mulDigits.equals(factorDigits);
}
- // methode to Split the numbers to Digits
- static String splitIntoDigits(int num, int num2) {
- StringBuilder res = new StringBuilder();
-
+ // Method to split a pair of numbers to digits and sort them in the ascending order.
+ static String splitIntoSortedDigits(int... nums) {
+ // Collect all digits in a list.
ArrayList digits = new ArrayList<>();
- while (num > 0) {
- digits.add(num % 10);
- num /= 10;
- }
- while (num2 > 0) {
- digits.add(num2 % 10);
- num2 /= 10;
- }
- Collections.sort(digits);
- for (int i : digits) {
- res.append(i);
+ for (int num : nums) {
+ while (num > 0) {
+ digits.add(num % 10);
+ num /= 10;
+ }
}
+ // Sort all digits and convert to String.
+ StringBuilder res = new StringBuilder();
+ digits.stream().sorted().forEach(res::append);
return res.toString();
}
}
diff --git a/src/main/java/com/thealgorithms/misc/InverseOfMatrix.java b/src/main/java/com/thealgorithms/matrix/InverseOfMatrix.java
similarity index 98%
rename from src/main/java/com/thealgorithms/misc/InverseOfMatrix.java
rename to src/main/java/com/thealgorithms/matrix/InverseOfMatrix.java
index 706feab0c69d..13e795a91297 100644
--- a/src/main/java/com/thealgorithms/misc/InverseOfMatrix.java
+++ b/src/main/java/com/thealgorithms/matrix/InverseOfMatrix.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.misc;
+package com.thealgorithms.matrix;
/**
* This class provides methods to compute the inverse of a square matrix
diff --git a/src/main/java/com/thealgorithms/maths/MatrixRank.java b/src/main/java/com/thealgorithms/matrix/MatrixRank.java
similarity index 77%
rename from src/main/java/com/thealgorithms/maths/MatrixRank.java
rename to src/main/java/com/thealgorithms/matrix/MatrixRank.java
index 7a628b92dccb..6692b6c37c60 100644
--- a/src/main/java/com/thealgorithms/maths/MatrixRank.java
+++ b/src/main/java/com/thealgorithms/matrix/MatrixRank.java
@@ -1,4 +1,6 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.matrix;
+
+import static com.thealgorithms.matrix.utils.MatrixUtil.validateInputMatrix;
/**
* This class provides a method to compute the rank of a matrix.
@@ -63,47 +65,6 @@ private static double[][] deepCopy(double[][] matrix) {
return matrixCopy;
}
- private static void validateInputMatrix(double[][] matrix) {
- if (matrix == null) {
- throw new IllegalArgumentException("The input matrix cannot be null");
- }
- if (matrix.length == 0) {
- throw new IllegalArgumentException("The input matrix cannot be empty");
- }
- if (!hasValidRows(matrix)) {
- throw new IllegalArgumentException("The input matrix cannot have null or empty rows");
- }
- if (isJaggedMatrix(matrix)) {
- throw new IllegalArgumentException("The input matrix cannot be jagged");
- }
- }
-
- private static boolean hasValidRows(double[][] matrix) {
- for (double[] row : matrix) {
- if (row == null || row.length == 0) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * @brief Checks if the input matrix is a jagged matrix.
- * Jagged matrix is a matrix where the number of columns in each row is not the same.
- *
- * @param matrix The input matrix
- * @return True if the input matrix is a jagged matrix, false otherwise
- */
- private static boolean isJaggedMatrix(double[][] matrix) {
- int numColumns = matrix[0].length;
- for (double[] row : matrix) {
- if (row.length != numColumns) {
- return true;
- }
- }
- return false;
- }
-
/**
* @brief The pivot row is the row in the matrix that is used to eliminate other rows and reduce the matrix to its row echelon form.
* The pivot row is selected as the first row (from top to bottom) where the value in the current column (the pivot column) is not zero.
diff --git a/src/main/java/com/thealgorithms/misc/MatrixTranspose.java b/src/main/java/com/thealgorithms/matrix/MatrixTranspose.java
similarity index 97%
rename from src/main/java/com/thealgorithms/misc/MatrixTranspose.java
rename to src/main/java/com/thealgorithms/matrix/MatrixTranspose.java
index 743682780b01..f91ebc10b8a9 100644
--- a/src/main/java/com/thealgorithms/misc/MatrixTranspose.java
+++ b/src/main/java/com/thealgorithms/matrix/MatrixTranspose.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.misc;
+package com.thealgorithms.matrix;
/**
*
diff --git a/src/main/java/com/thealgorithms/misc/MedianOfMatrix.java b/src/main/java/com/thealgorithms/matrix/MedianOfMatrix.java
similarity index 95%
rename from src/main/java/com/thealgorithms/misc/MedianOfMatrix.java
rename to src/main/java/com/thealgorithms/matrix/MedianOfMatrix.java
index edeedbbee540..c710c60a2d2a 100644
--- a/src/main/java/com/thealgorithms/misc/MedianOfMatrix.java
+++ b/src/main/java/com/thealgorithms/matrix/MedianOfMatrix.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.misc;
+package com.thealgorithms.matrix;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/src/main/java/com/thealgorithms/matrix/MirrorOfMatrix.java b/src/main/java/com/thealgorithms/matrix/MirrorOfMatrix.java
new file mode 100644
index 000000000000..3a3055f38732
--- /dev/null
+++ b/src/main/java/com/thealgorithms/matrix/MirrorOfMatrix.java
@@ -0,0 +1,36 @@
+package com.thealgorithms.matrix;
+
+// Problem Statement
+
+import com.thealgorithms.matrix.utils.MatrixUtil;
+
+/*
+We have given an array of m x n (where m is the number of rows and n is the number of columns).
+Print the new matrix in such a way that the new matrix is the mirror image of the original matrix.
+
+The Original matrix is: | The Mirror matrix is:
+1 2 3 | 3 2 1
+4 5 6 | 6 5 4
+7 8 9 | 9 8 7
+
+@author - Aman (https://github.com/Aman28801)
+*/
+
+public final class MirrorOfMatrix {
+ private MirrorOfMatrix() {
+ }
+
+ public static double[][] mirrorMatrix(final double[][] originalMatrix) {
+ MatrixUtil.validateInputMatrix(originalMatrix);
+
+ int numRows = originalMatrix.length;
+ int numCols = originalMatrix[0].length;
+
+ double[][] mirroredMatrix = new double[numRows][numCols];
+
+ for (int i = 0; i < numRows; i++) {
+ mirroredMatrix[i] = MatrixUtil.reverseRow(originalMatrix[i]);
+ }
+ return mirroredMatrix;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/matrix/PrintAMatrixInSpiralOrder.java b/src/main/java/com/thealgorithms/matrix/PrintAMatrixInSpiralOrder.java
new file mode 100644
index 000000000000..2757da1f9023
--- /dev/null
+++ b/src/main/java/com/thealgorithms/matrix/PrintAMatrixInSpiralOrder.java
@@ -0,0 +1,53 @@
+package com.thealgorithms.matrix;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PrintAMatrixInSpiralOrder {
+ /**
+ * Search a key in row and column wise sorted matrix
+ *
+ * @param matrix matrix to be searched
+ * @param row number of rows matrix has
+ * @param col number of columns matrix has
+ * @author Sadiul Hakim : https://github.com/sadiul-hakim
+ */
+ public List print(int[][] matrix, int row, int col) {
+
+ // r traverses matrix row wise from first
+ int r = 0;
+ // c traverses matrix column wise from first
+ int c = 0;
+ int i;
+ List result = new ArrayList<>();
+ while (r < row && c < col) {
+ // print first row of matrix
+ for (i = c; i < col; i++) {
+ result.add(matrix[r][i]);
+ }
+ // increase r by one because first row printed
+ r++;
+ // print last column
+ for (i = r; i < row; i++) {
+ result.add(matrix[i][col - 1]);
+ }
+ // decrease col by one because last column has been printed
+ col--;
+ // print rows from last except printed elements
+ if (r < row) {
+ for (i = col - 1; i >= c; i--) {
+ result.add(matrix[row - 1][i]);
+ }
+ row--;
+ }
+ // print columns from first except printed elements
+ if (c < col) {
+ for (i = row - 1; i >= r; i--) {
+ result.add(matrix[i][c]);
+ }
+ c++;
+ }
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/others/RotateMatrixBy90Degrees.java b/src/main/java/com/thealgorithms/matrix/RotateMatrixBy90Degrees.java
similarity index 98%
rename from src/main/java/com/thealgorithms/others/RotateMatrixBy90Degrees.java
rename to src/main/java/com/thealgorithms/matrix/RotateMatrixBy90Degrees.java
index 6ad0ef024342..9a7f255282ac 100644
--- a/src/main/java/com/thealgorithms/others/RotateMatrixBy90Degrees.java
+++ b/src/main/java/com/thealgorithms/matrix/RotateMatrixBy90Degrees.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.others;
+package com.thealgorithms.matrix;
import java.util.Scanner;
/**
diff --git a/src/main/java/com/thealgorithms/matrix/SolveSystem.java b/src/main/java/com/thealgorithms/matrix/SolveSystem.java
new file mode 100644
index 000000000000..9e683bc4dc5c
--- /dev/null
+++ b/src/main/java/com/thealgorithms/matrix/SolveSystem.java
@@ -0,0 +1,71 @@
+package com.thealgorithms.matrix;
+
+/**
+ * This class implements an algorithm for solving a system of equations of the form Ax=b using gaussian elimination and back substitution.
+ *
+ * @link Gaussian Elimination Wiki
+ * @see InverseOfMatrix finds the full of inverse of a matrice, but is not required to solve a system.
+ */
+public final class SolveSystem {
+ private SolveSystem() {
+ }
+
+ /**
+ * Problem: Given a matrix A and vector b, solve the linear system Ax = b for the vector x.\
+ *
+ * This OVERWRITES the input matrix to save on memory
+ *
+ * @param matrix - a square matrix of doubles
+ * @param constants - an array of constant
+ * @return solutions
+ */
+ public static double[] solveSystem(double[][] matrix, double[] constants) {
+ final double tol = 0.00000001; // tolerance for round off
+ for (int k = 0; k < matrix.length - 1; k++) {
+ // find the largest value in column (to avoid zero pivots)
+ double maxVal = Math.abs(matrix[k][k]);
+ int maxIdx = k;
+ for (int j = k + 1; j < matrix.length; j++) {
+ if (Math.abs(matrix[j][k]) > maxVal) {
+ maxVal = matrix[j][k];
+ maxIdx = j;
+ }
+ }
+ if (Math.abs(maxVal) < tol) {
+ // hope the matrix works out
+ continue;
+ }
+ // swap rows
+ double[] temp = matrix[k];
+ matrix[k] = matrix[maxIdx];
+ matrix[maxIdx] = temp;
+ double tempConst = constants[k];
+ constants[k] = constants[maxIdx];
+ constants[maxIdx] = tempConst;
+ for (int i = k + 1; i < matrix.length; i++) {
+ // compute multipliers and save them in the column
+ matrix[i][k] /= matrix[k][k];
+ for (int j = k + 1; j < matrix.length; j++) {
+ matrix[i][j] -= matrix[i][k] * matrix[k][j];
+ }
+ constants[i] -= matrix[i][k] * constants[k];
+ }
+ }
+ // back substitution
+ double[] x = new double[constants.length];
+ System.arraycopy(constants, 0, x, 0, constants.length);
+ for (int i = matrix.length - 1; i >= 0; i--) {
+ double sum = 0;
+ for (int j = i + 1; j < matrix.length; j++) {
+ sum += matrix[i][j] * x[j];
+ }
+ x[i] = constants[i] - sum;
+ if (Math.abs(matrix[i][i]) > tol) {
+ x[i] /= matrix[i][i];
+ } else {
+ throw new IllegalArgumentException("Matrix was found to be singular");
+ }
+ }
+ return x;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/matrix/matrixexponentiation/Fibonacci.java b/src/main/java/com/thealgorithms/matrix/matrixexponentiation/Fibonacci.java
new file mode 100644
index 000000000000..85852713b9ba
--- /dev/null
+++ b/src/main/java/com/thealgorithms/matrix/matrixexponentiation/Fibonacci.java
@@ -0,0 +1,42 @@
+package com.thealgorithms.matrix.matrixexponentiation;
+
+import com.thealgorithms.matrix.utils.MatrixUtil;
+import java.math.BigDecimal;
+
+/**
+ * @author Anirudh Buvanesh (https://github.com/anirudhb11) For more information
+ * see https://www.geeksforgeeks.org/matrix-exponentiation/
+ *
+ */
+public final class Fibonacci {
+ private Fibonacci() {
+ }
+
+ // Exponentiation matrix for Fibonacci sequence
+ private static final BigDecimal ONE = BigDecimal.valueOf(1);
+ private static final BigDecimal ZERO = BigDecimal.valueOf(0);
+
+ private static final BigDecimal[][] FIB_MATRIX = {{ONE, ONE}, {ONE, ZERO}};
+ private static final BigDecimal[][] IDENTITY_MATRIX = {{ONE, ZERO}, {ZERO, ONE}};
+
+ /**
+ * Calculates the fibonacci number using matrix exponentiaition technique
+ *
+ * @param n The input n for which we have to determine the fibonacci number
+ * Outputs the nth * fibonacci number
+ * @return a 2 X 1 array as { {F_n+1}, {F_n} }
+ */
+ public static BigDecimal[][] fib(int n) {
+ if (n == 0) {
+ return IDENTITY_MATRIX;
+ } else {
+ BigDecimal[][] cachedResult = fib(n / 2);
+ BigDecimal[][] matrixExpResult = MatrixUtil.multiply(cachedResult, cachedResult).get();
+ if (n % 2 == 0) {
+ return matrixExpResult;
+ } else {
+ return MatrixUtil.multiply(FIB_MATRIX, matrixExpResult).get();
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/maths/MatrixUtil.java b/src/main/java/com/thealgorithms/matrix/utils/MatrixUtil.java
similarity index 62%
rename from src/main/java/com/thealgorithms/maths/MatrixUtil.java
rename to src/main/java/com/thealgorithms/matrix/utils/MatrixUtil.java
index 7e462f92e185..5ff9e37f6b9a 100644
--- a/src/main/java/com/thealgorithms/maths/MatrixUtil.java
+++ b/src/main/java/com/thealgorithms/matrix/utils/MatrixUtil.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.matrix.utils;
import java.math.BigDecimal;
import java.util.Optional;
@@ -10,6 +10,7 @@
* @date: 31 October 2021 (Sunday)
*/
public final class MatrixUtil {
+
private MatrixUtil() {
}
@@ -18,11 +19,52 @@ private static boolean isValid(final BigDecimal[][] matrix) {
}
private static boolean hasEqualSizes(final BigDecimal[][] matrix1, final BigDecimal[][] matrix2) {
- return (isValid(matrix1) && isValid(matrix2) && matrix1.length == matrix2.length && matrix1[0].length == matrix2[0].length);
+ return isValid(matrix1) && isValid(matrix2) && matrix1.length == matrix2.length && matrix1[0].length == matrix2[0].length;
}
private static boolean canMultiply(final BigDecimal[][] matrix1, final BigDecimal[][] matrix2) {
- return (isValid(matrix1) && isValid(matrix2) && matrix1[0].length == matrix2.length);
+ return isValid(matrix1) && isValid(matrix2) && matrix1[0].length == matrix2.length;
+ }
+
+ public static void validateInputMatrix(double[][] matrix) {
+ if (matrix == null) {
+ throw new IllegalArgumentException("The input matrix cannot be null");
+ }
+ if (matrix.length == 0) {
+ throw new IllegalArgumentException("The input matrix cannot be empty");
+ }
+ if (!hasValidRows(matrix)) {
+ throw new IllegalArgumentException("The input matrix cannot have null or empty rows");
+ }
+ if (isJaggedMatrix(matrix)) {
+ throw new IllegalArgumentException("The input matrix cannot be jagged");
+ }
+ }
+
+ private static boolean hasValidRows(double[][] matrix) {
+ for (double[] row : matrix) {
+ if (row == null || row.length == 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @brief Checks if the input matrix is a jagged matrix.
+ * Jagged matrix is a matrix where the number of columns in each row is not the same.
+ *
+ * @param matrix The input matrix
+ * @return True if the input matrix is a jagged matrix, false otherwise
+ */
+ private static boolean isJaggedMatrix(double[][] matrix) {
+ int numColumns = matrix[0].length;
+ for (double[] row : matrix) {
+ if (row.length != numColumns) {
+ return true;
+ }
+ }
+ return false;
}
private static Optional operate(final BigDecimal[][] matrix1, final BigDecimal[][] matrix2, final BiFunction operation) {
@@ -80,4 +122,12 @@ public static Optional multiply(final BigDecimal[][] matrix1, fi
return Optional.of(result);
}
+
+ public static double[] reverseRow(final double[] inRow) {
+ double[] res = new double[inRow.length];
+ for (int i = 0; i < inRow.length; ++i) {
+ res[i] = inRow[inRow.length - 1 - i];
+ }
+ return res;
+ }
}
diff --git a/src/main/java/com/thealgorithms/matrixexponentiation/Fibonacci.java b/src/main/java/com/thealgorithms/matrixexponentiation/Fibonacci.java
deleted file mode 100644
index afd34933047a..000000000000
--- a/src/main/java/com/thealgorithms/matrixexponentiation/Fibonacci.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.thealgorithms.matrixexponentiation;
-
-import java.util.Scanner;
-
-/**
- * @author Anirudh Buvanesh (https://github.com/anirudhb11) For more information
- * see https://www.geeksforgeeks.org/matrix-exponentiation/
- *
- */
-public final class Fibonacci {
- private Fibonacci() {
- }
-
- // Exponentiation matrix for Fibonacci sequence
- private static final int[][] FIB_MATRIX = {{1, 1}, {1, 0}};
- private static final int[][] IDENTITY_MATRIX = {{1, 0}, {0, 1}};
- // First 2 fibonacci numbers
- private static final int[][] BASE_FIB_NUMBERS = {{1}, {0}};
-
- /**
- * Performs multiplication of 2 matrices
- *
- * @param matrix1
- * @param matrix2
- * @return The product of matrix1 and matrix2
- */
- private static int[][] matrixMultiplication(int[][] matrix1, int[][] matrix2) {
- // Check if matrices passed can be multiplied
- int rowsInMatrix1 = matrix1.length;
- int columnsInMatrix1 = matrix1[0].length;
-
- int rowsInMatrix2 = matrix2.length;
- int columnsInMatrix2 = matrix2[0].length;
-
- assert columnsInMatrix1 == rowsInMatrix2;
- int[][] product = new int[rowsInMatrix1][columnsInMatrix2];
- for (int rowIndex = 0; rowIndex < rowsInMatrix1; rowIndex++) {
- for (int colIndex = 0; colIndex < columnsInMatrix2; colIndex++) {
- int matrixEntry = 0;
- for (int intermediateIndex = 0; intermediateIndex < columnsInMatrix1; intermediateIndex++) {
- matrixEntry += matrix1[rowIndex][intermediateIndex] * matrix2[intermediateIndex][colIndex];
- }
- product[rowIndex][colIndex] = matrixEntry;
- }
- }
- return product;
- }
-
- /**
- * Calculates the fibonacci number using matrix exponentiaition technique
- *
- * @param n The input n for which we have to determine the fibonacci number
- * Outputs the nth * fibonacci number
- * @return a 2 X 1 array as { {F_n+1}, {F_n} }
- */
- public static int[][] fib(int n) {
- if (n == 0) {
- return Fibonacci.IDENTITY_MATRIX;
- } else {
- int[][] cachedResult = fib(n / 2);
- int[][] matrixExpResult = matrixMultiplication(cachedResult, cachedResult);
- if (n % 2 == 0) {
- return matrixExpResult;
- } else {
- return matrixMultiplication(Fibonacci.FIB_MATRIX, matrixExpResult);
- }
- }
- }
-
- public static void main(String[] args) {
- // Returns [0, 1, 1, 2, 3, 5 ..] for n = [0, 1, 2, 3, 4, 5.. ]
- Scanner sc = new Scanner(System.in);
- int n = sc.nextInt();
- int[][] result = matrixMultiplication(fib(n), BASE_FIB_NUMBERS);
- System.out.println("Fib(" + n + ") = " + result[1][0]);
- sc.close();
- }
-}
diff --git a/src/main/java/com/thealgorithms/misc/MirrorOfMatrix.java b/src/main/java/com/thealgorithms/misc/MirrorOfMatrix.java
deleted file mode 100644
index 89dfce3fe049..000000000000
--- a/src/main/java/com/thealgorithms/misc/MirrorOfMatrix.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.thealgorithms.misc;
-
-// Problem Statement
-/*
-We have given an array of m x n (where m is the number of rows and n is the number of columns).
-Print the new matrix in such a way that the new matrix is the mirror image of the original matrix.
-
-The Original matrix is: | The Mirror matrix is:
-1 2 3 | 3 2 1
-4 5 6 | 6 5 4
-7 8 9 | 9 8 7
-
-@author - Aman (https://github.com/Aman28801)
-*/
-
-public final class MirrorOfMatrix {
- private MirrorOfMatrix() {
- }
-
- public static int[][] mirrorMatrix(final int[][] originalMatrix) {
- if (originalMatrix == null) {
- // Handle invalid input
- return null;
- }
- if (originalMatrix.length == 0) {
- return new int[0][0];
- }
-
- checkInput(originalMatrix);
-
- int numRows = originalMatrix.length;
- int numCols = originalMatrix[0].length;
-
- int[][] mirroredMatrix = new int[numRows][numCols];
-
- for (int i = 0; i < numRows; i++) {
- mirroredMatrix[i] = reverseRow(originalMatrix[i]);
- }
- return mirroredMatrix;
- }
- private static int[] reverseRow(final int[] inRow) {
- int[] res = new int[inRow.length];
- for (int i = 0; i < inRow.length; ++i) {
- res[i] = inRow[inRow.length - 1 - i];
- }
- return res;
- }
-
- private static void checkInput(final int[][] matrix) {
- // Check if all rows have the same number of columns
- for (int i = 1; i < matrix.length; i++) {
- if (matrix[i].length != matrix[0].length) {
- throw new IllegalArgumentException("The input is not a matrix.");
- }
- }
- }
-}
diff --git a/src/main/java/com/thealgorithms/others/KochSnowflake.java b/src/main/java/com/thealgorithms/others/KochSnowflake.java
index 46b8edb1f177..10986aabec4f 100644
--- a/src/main/java/com/thealgorithms/others/KochSnowflake.java
+++ b/src/main/java/com/thealgorithms/others/KochSnowflake.java
@@ -105,7 +105,7 @@ public static BufferedImage getKochSnowflake(int imageWidth, int steps) {
double offsetX = imageWidth / 10.;
double offsetY = imageWidth / 3.7;
Vector2 vector1 = new Vector2(offsetX, offsetY);
- Vector2 vector2 = new Vector2(imageWidth / 2, Math.sin(Math.PI / 3) * imageWidth * 0.8 + offsetY);
+ Vector2 vector2 = new Vector2(imageWidth / 2.0, Math.sin(Math.PI / 3.0) * imageWidth * 0.8 + offsetY);
Vector2 vector3 = new Vector2(imageWidth - offsetX, offsetY);
ArrayList initialVectors = new ArrayList();
initialVectors.add(vector1);
diff --git a/src/main/java/com/thealgorithms/others/PrintAMatrixInSpiralOrder.java b/src/main/java/com/thealgorithms/others/PrintAMatrixInSpiralOrder.java
index ddc37a916cbf..abfdd006879e 100644
--- a/src/main/java/com/thealgorithms/others/PrintAMatrixInSpiralOrder.java
+++ b/src/main/java/com/thealgorithms/others/PrintAMatrixInSpiralOrder.java
@@ -12,43 +12,33 @@ public class PrintAMatrixInSpiralOrder {
* @param col number of columns matrix has
* @author Sadiul Hakim : https://github.com/sadiul-hakim
*/
-
public List print(int[][] matrix, int row, int col) {
-
// r traverses matrix row wise from first
int r = 0;
// c traverses matrix column wise from first
int c = 0;
int i;
-
List result = new ArrayList<>();
-
while (r < row && c < col) {
// print first row of matrix
for (i = c; i < col; i++) {
result.add(matrix[r][i]);
}
-
// increase r by one because first row printed
r++;
-
// print last column
for (i = r; i < row; i++) {
result.add(matrix[i][col - 1]);
}
-
// decrease col by one because last column has been printed
col--;
-
// print rows from last except printed elements
if (r < row) {
for (i = col - 1; i >= c; i--) {
result.add(matrix[row - 1][i]);
}
-
row--;
}
-
// print columns from first except printed elements
if (c < col) {
for (i = row - 1; i >= r; i--) {
diff --git a/src/main/java/com/thealgorithms/others/Sudoku.java b/src/main/java/com/thealgorithms/puzzlesandgames/Sudoku.java
similarity index 99%
rename from src/main/java/com/thealgorithms/others/Sudoku.java
rename to src/main/java/com/thealgorithms/puzzlesandgames/Sudoku.java
index 0e88aee46f4d..fce665c4de00 100644
--- a/src/main/java/com/thealgorithms/others/Sudoku.java
+++ b/src/main/java/com/thealgorithms/puzzlesandgames/Sudoku.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.others;
+package com.thealgorithms.puzzlesandgames;
/**
* A class that provides methods to solve Sudoku puzzles of any n x n size
diff --git a/src/main/java/com/thealgorithms/others/TowerOfHanoi.java b/src/main/java/com/thealgorithms/puzzlesandgames/TowerOfHanoi.java
similarity index 98%
rename from src/main/java/com/thealgorithms/others/TowerOfHanoi.java
rename to src/main/java/com/thealgorithms/puzzlesandgames/TowerOfHanoi.java
index 7017ed03f843..72e9a14ac070 100644
--- a/src/main/java/com/thealgorithms/others/TowerOfHanoi.java
+++ b/src/main/java/com/thealgorithms/puzzlesandgames/TowerOfHanoi.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.others;
+package com.thealgorithms.puzzlesandgames;
import java.util.List;
diff --git a/src/main/java/com/thealgorithms/misc/WordBoggle.java b/src/main/java/com/thealgorithms/puzzlesandgames/WordBoggle.java
similarity index 98%
rename from src/main/java/com/thealgorithms/misc/WordBoggle.java
rename to src/main/java/com/thealgorithms/puzzlesandgames/WordBoggle.java
index 8b629d68209b..ca1430f744ab 100644
--- a/src/main/java/com/thealgorithms/misc/WordBoggle.java
+++ b/src/main/java/com/thealgorithms/puzzlesandgames/WordBoggle.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.misc;
+package com.thealgorithms.puzzlesandgames;
import java.util.ArrayList;
import java.util.HashMap;
@@ -8,9 +8,9 @@
import java.util.Set;
public final class WordBoggle {
+
private WordBoggle() {
}
-
/**
* O(nm * 8^s + ws) time where n = width of boggle board, m = height of
* boggle board, s = length of longest word in string array, w = length of
diff --git a/src/main/java/com/thealgorithms/randomized/KargerMinCut.java b/src/main/java/com/thealgorithms/randomized/KargerMinCut.java
new file mode 100644
index 000000000000..14f1f97450a0
--- /dev/null
+++ b/src/main/java/com/thealgorithms/randomized/KargerMinCut.java
@@ -0,0 +1,195 @@
+package com.thealgorithms.randomized;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+/**
+ * Implementation of Karger's Minimum Cut algorithm.
+ *
+ *
Karger's algorithm is a randomized algorithm to compute the minimum cut of a connected graph.
+ * A minimum cut is the smallest set of edges that, if removed, would split the graph into two
+ * disconnected components.
+ *
+ *
The algorithm works by repeatedly contracting random edges in the graph until only two
+ * nodes remain. The edges between these two nodes represent a cut. By running the algorithm
+ * multiple times and keeping track of the smallest cut found, the probability of finding the
+ * true minimum cut increases.
+ *
+ *
Key steps of the algorithm:
+ *
+ *
Randomly select an edge and contract it, merging the two nodes into one.
+ *
Repeat the contraction process until only two nodes remain.
+ *
Count the edges between the two remaining nodes to determine the cut size.
+ *
Repeat the process multiple times to improve the likelihood of finding the true minimum cut.
+ *
+ *
+ * See more: Karger's algorithm
+ *
+ * @author MuhammadEzzatHBK
+ */
+public final class KargerMinCut {
+
+ /**
+ * Output of the Karger algorithm.
+ *
+ * @param first The first set of nodes in the cut.
+ * @param second The second set of nodes in the cut.
+ * @param minCut The size of the minimum cut.
+ */
+ public record KargerOutput(Set first, Set second, int minCut) {
+ }
+
+ private KargerMinCut() {
+ }
+
+ public static KargerOutput findMinCut(Collection nodeSet, List edges) {
+ return findMinCut(nodeSet, edges, 100);
+ }
+
+ /**
+ * Finds the minimum cut of a graph using Karger's algorithm.
+ *
+ * @param nodeSet: Input graph nodes
+ * @param edges: Input graph edges
+ * @param iterations: Iterations to run the algorithms for, more iterations = more accuracy
+ * @return A KargerOutput object containing the two sets of nodes and the size of the minimum cut.
+ */
+ public static KargerOutput findMinCut(Collection nodeSet, List edges, int iterations) {
+ Graph graph = new Graph(nodeSet, edges);
+ KargerOutput minCut = new KargerOutput(new HashSet<>(), new HashSet<>(), Integer.MAX_VALUE);
+ KargerOutput output;
+
+ // Run the algorithm multiple times to increase the probability of finding
+ for (int i = 0; i < iterations; i++) {
+ Graph clone = graph.copy();
+ output = clone.findMinCut();
+ if (output.minCut < minCut.minCut) {
+ minCut = output;
+ }
+ }
+ return minCut;
+ }
+
+ private static class DisjointSetUnion {
+ private final int[] parent;
+ int setCount;
+
+ DisjointSetUnion(int size) {
+ parent = new int[size];
+ for (int i = 0; i < size; i++) {
+ parent[i] = i;
+ }
+ setCount = size;
+ }
+
+ int find(int i) {
+ // If it's not its own parent, then it's not the root of its set
+ if (parent[i] != i) {
+ // Recursively find the root of its parent
+ // and update i's parent to point directly to the root (path compression)
+ parent[i] = find(parent[i]);
+ }
+
+ // Return the root (representative) of the set
+ return parent[i];
+ }
+
+ void union(int u, int v) {
+ // Find the root of each node
+ int rootU = find(u);
+ int rootV = find(v);
+
+ // If they belong to different sets, merge them
+ if (rootU != rootV) {
+ // Make rootV point to rootU — merge the two sets
+ parent[rootV] = rootU;
+
+ // Reduce the count of disjoint sets by 1
+ setCount--;
+ }
+ }
+
+ boolean inSameSet(int u, int v) {
+ return find(u) == find(v);
+ }
+
+ /*
+ This is a verbosity method, it's not a part of the core algorithm,
+ But it helps us provide more useful output.
+ */
+ Set getAnySet() {
+ int aRoot = find(0); // Get one of the two roots
+
+ Set set = new HashSet<>();
+ for (int i = 0; i < parent.length; i++) {
+ if (find(i) == aRoot) {
+ set.add(i);
+ }
+ }
+
+ return set;
+ }
+ }
+
+ private static class Graph {
+ private final List nodes;
+ private final List edges;
+
+ Graph(Collection nodeSet, List edges) {
+ this.nodes = new ArrayList<>(nodeSet);
+ this.edges = new ArrayList<>();
+ for (int[] e : edges) {
+ this.edges.add(new int[] {e[0], e[1]});
+ }
+ }
+
+ Graph copy() {
+ return new Graph(this.nodes, this.edges);
+ }
+
+ KargerOutput findMinCut() {
+ DisjointSetUnion dsu = new DisjointSetUnion(nodes.size());
+ List workingEdges = new ArrayList<>(edges);
+
+ Random rand = new Random();
+
+ while (dsu.setCount > 2) {
+ int[] e = workingEdges.get(rand.nextInt(workingEdges.size()));
+ if (!dsu.inSameSet(e[0], e[1])) {
+ dsu.union(e[0], e[1]);
+ }
+ }
+
+ int cutEdges = 0;
+ for (int[] e : edges) {
+ if (!dsu.inSameSet(e[0], e[1])) {
+ cutEdges++;
+ }
+ }
+
+ return collectResult(dsu, cutEdges);
+ }
+
+ /*
+ This is a verbosity method, it's not a part of the core algorithm,
+ But it helps us provide more useful output.
+ */
+ private KargerOutput collectResult(DisjointSetUnion dsu, int cutEdges) {
+ Set firstIndices = dsu.getAnySet();
+ Set firstSet = new HashSet<>();
+ Set secondSet = new HashSet<>();
+ for (int i = 0; i < nodes.size(); i++) {
+ if (firstIndices.contains(i)) {
+ firstSet.add(nodes.get(i));
+ } else {
+ secondSet.add(nodes.get(i));
+ }
+ }
+ return new KargerOutput(firstSet, secondSet, cutEdges);
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/randomized/ReservoirSampling.java b/src/main/java/com/thealgorithms/randomized/ReservoirSampling.java
new file mode 100644
index 000000000000..05e70f635055
--- /dev/null
+++ b/src/main/java/com/thealgorithms/randomized/ReservoirSampling.java
@@ -0,0 +1,55 @@
+package com.thealgorithms.randomized;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Reservoir Sampling Algorithm
+ *
+ * Use Case:
+ * - Efficient for selecting k random items from a stream of unknown size
+ * - Used in streaming systems, big data, and memory-limited environments
+ *
+ * Time Complexity: O(n)
+ * Space Complexity: O(k)
+ *
+ * @author Michael Alexander Montoya (@cureprotocols)
+ * @see Reservoir Sampling - Wikipedia
+ */
+public final class ReservoirSampling {
+
+ // Prevent instantiation of utility class
+ private ReservoirSampling() {
+ throw new UnsupportedOperationException("Utility class");
+ }
+
+ /**
+ * Selects k random elements from a stream using reservoir sampling.
+ *
+ * @param stream The input stream as an array of integers.
+ * @param sampleSize The number of elements to sample.
+ * @return A list containing k randomly selected elements.
+ */
+ public static List sample(int[] stream, int sampleSize) {
+ if (sampleSize > stream.length) {
+ throw new IllegalArgumentException("Sample size cannot exceed stream size.");
+ }
+
+ List reservoir = new ArrayList<>(sampleSize);
+ Random rand = new Random();
+
+ for (int i = 0; i < stream.length; i++) {
+ if (i < sampleSize) {
+ reservoir.add(stream[i]);
+ } else {
+ int j = rand.nextInt(i + 1);
+ if (j < sampleSize) {
+ reservoir.set(j, stream[i]);
+ }
+ }
+ }
+
+ return reservoir;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/scheduling/SJFScheduling.java b/src/main/java/com/thealgorithms/scheduling/SJFScheduling.java
index 6d105003e68f..cbbc65a3afc5 100644
--- a/src/main/java/com/thealgorithms/scheduling/SJFScheduling.java
+++ b/src/main/java/com/thealgorithms/scheduling/SJFScheduling.java
@@ -14,6 +14,18 @@ public class SJFScheduling {
protected ArrayList processes;
protected ArrayList schedule;
+ private static void sortProcessesByArrivalTime(List processes) {
+ for (int i = 0; i < processes.size(); i++) {
+ for (int j = i + 1; j < processes.size() - 1; j++) {
+ if (processes.get(j).getArrivalTime() > processes.get(j + 1).getArrivalTime()) {
+ final var temp = processes.get(j);
+ processes.set(j, processes.get(j + 1));
+ processes.set(j + 1, temp);
+ }
+ }
+ }
+ }
+
/**
* a simple constructor
* @param processes a list of processes the user wants to schedule
@@ -22,22 +34,10 @@ public class SJFScheduling {
SJFScheduling(final ArrayList processes) {
this.processes = processes;
schedule = new ArrayList<>();
- sortByArrivalTime();
+ sortProcessesByArrivalTime(this.processes);
}
protected void sortByArrivalTime() {
- int size = processes.size();
- int i;
- int j;
- ProcessDetails temp;
- for (i = 0; i < size; i++) {
- for (j = i + 1; j < size - 1; j++) {
- if (processes.get(j).getArrivalTime() > processes.get(j + 1).getArrivalTime()) {
- temp = processes.get(j);
- processes.set(j, processes.get(j + 1));
- processes.set(j + 1, temp);
- }
- }
- }
+ sortProcessesByArrivalTime(processes);
}
/**
diff --git a/src/main/java/com/thealgorithms/searches/SearchInARowAndColWiseSortedMatrix.java b/src/main/java/com/thealgorithms/searches/SearchInARowAndColWiseSortedMatrix.java
index 91fda373dca7..b53c7e5256ca 100644
--- a/src/main/java/com/thealgorithms/searches/SearchInARowAndColWiseSortedMatrix.java
+++ b/src/main/java/com/thealgorithms/searches/SearchInARowAndColWiseSortedMatrix.java
@@ -15,7 +15,6 @@ public int[] search(int[][] matrix, int value) {
// This variable iterates over columns
int j = n - 1;
int[] result = {-1, -1};
-
while (i < n && j >= 0) {
if (matrix[i][j] == value) {
result[0] = i;
diff --git a/src/main/java/com/thealgorithms/sorts/DarkSort.java b/src/main/java/com/thealgorithms/sorts/DarkSort.java
new file mode 100644
index 000000000000..4887d7d124ba
--- /dev/null
+++ b/src/main/java/com/thealgorithms/sorts/DarkSort.java
@@ -0,0 +1,59 @@
+package com.thealgorithms.sorts;
+
+/**
+ * Dark Sort algorithm implementation.
+ *
+ * Dark Sort uses a temporary array to count occurrences of elements and
+ * reconstructs the sorted array based on the counts.
+ */
+class DarkSort {
+
+ /**
+ * Sorts the array using the Dark Sort algorithm.
+ *
+ * @param unsorted the array to be sorted
+ * @return sorted array
+ */
+ public Integer[] sort(Integer[] unsorted) {
+ if (unsorted == null || unsorted.length <= 1) {
+ return unsorted;
+ }
+
+ int max = findMax(unsorted); // Find the maximum value in the array
+
+ // Create a temporary array for counting occurrences
+ int[] temp = new int[max + 1];
+
+ // Count occurrences of each element
+ for (int value : unsorted) {
+ temp[value]++;
+ }
+
+ // Reconstruct the sorted array
+ int index = 0;
+ for (int i = 0; i < temp.length; i++) {
+ while (temp[i] > 0) {
+ unsorted[index++] = i;
+ temp[i]--;
+ }
+ }
+
+ return unsorted;
+ }
+
+ /**
+ * Helper method to find the maximum value in an array.
+ *
+ * @param arr the array
+ * @return the maximum value
+ */
+ private int findMax(Integer[] arr) {
+ int max = arr[0];
+ for (int value : arr) {
+ if (value > max) {
+ max = value;
+ }
+ }
+ return max;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/strings/ReverseString.java b/src/main/java/com/thealgorithms/strings/ReverseString.java
index 46a0494fcbb4..54a9b779e828 100644
--- a/src/main/java/com/thealgorithms/strings/ReverseString.java
+++ b/src/main/java/com/thealgorithms/strings/ReverseString.java
@@ -36,4 +36,25 @@ public static String reverse2(String str) {
}
return new String(value);
}
+
+ /**
+ * Reverse version 3 the given string using a StringBuilder.
+ * This method converts the string to a character array,
+ * iterates through it in reverse order, and appends each character
+ * to a StringBuilder.
+ *
+ * @param string The input string to be reversed.
+ * @return The reversed string.
+ */
+ public static String reverse3(String string) {
+ if (string.isEmpty()) {
+ return string;
+ }
+ char[] chars = string.toCharArray();
+ StringBuilder sb = new StringBuilder();
+ for (int i = string.length() - 1; i >= 0; i--) {
+ sb.append(chars[i]);
+ }
+ return sb.toString();
+ }
}
diff --git a/src/main/java/com/thealgorithms/strings/Upper.java b/src/main/java/com/thealgorithms/strings/Upper.java
index fa9a408416ea..5e248cb6ee39 100644
--- a/src/main/java/com/thealgorithms/strings/Upper.java
+++ b/src/main/java/com/thealgorithms/strings/Upper.java
@@ -21,15 +21,19 @@ public static void main(String[] args) {
* @return the {@code String}, converted to uppercase.
*/
public static String toUpperCase(String s) {
- if (s == null || s.isEmpty()) {
+ if (s == null) {
+ throw new IllegalArgumentException("Input string connot be null");
+ }
+ if (s.isEmpty()) {
return s;
}
- char[] values = s.toCharArray();
- for (int i = 0; i < values.length; ++i) {
- if (Character.isLetter(values[i]) && Character.isLowerCase(values[i])) {
- values[i] = Character.toUpperCase(values[i]);
+ StringBuilder result = new StringBuilder(s);
+ for (int i = 0; i < result.length(); ++i) {
+ char currentChar = result.charAt(i);
+ if (Character.isLetter(currentChar) && Character.isLowerCase(currentChar)) {
+ result.setCharAt(i, Character.toUpperCase(currentChar));
}
}
- return new String(values);
+ return result.toString();
}
}
diff --git a/src/main/java/com/thealgorithms/strings/zigZagPattern/ZigZagPattern.java b/src/main/java/com/thealgorithms/strings/zigZagPattern/ZigZagPattern.java
index 3f33fc17b9b0..ad7835bdbb97 100644
--- a/src/main/java/com/thealgorithms/strings/zigZagPattern/ZigZagPattern.java
+++ b/src/main/java/com/thealgorithms/strings/zigZagPattern/ZigZagPattern.java
@@ -1,41 +1,38 @@
package com.thealgorithms.strings.zigZagPattern;
final class ZigZagPattern {
+
private ZigZagPattern() {
}
+ /**
+ * Encodes a given string into a zig-zag pattern.
+ *
+ * @param s the input string to be encoded
+ * @param numRows the number of rows in the zigzag pattern
+ * @return the encoded string in zigzag pattern format
+ */
public static String encode(String s, int numRows) {
if (numRows < 2 || s.length() < numRows) {
return s;
}
- int start = 0;
- int index = 0;
- int height = 1;
- int depth = numRows;
- char[] zigZagedArray = new char[s.length()];
- while (depth != 0) {
- int pointer = start;
- int heightSpace = 2 + ((height - 2) * 2);
- int depthSpace = 2 + ((depth - 2) * 2);
- boolean bool = true;
- while (pointer < s.length()) {
- zigZagedArray[index++] = s.charAt(pointer);
- if (heightSpace == 0) {
- pointer += depthSpace;
- } else if (depthSpace == 0) {
- pointer += heightSpace;
- } else if (bool) {
- pointer += depthSpace;
- bool = false;
- } else {
- pointer += heightSpace;
- bool = true;
+
+ StringBuilder result = new StringBuilder(s.length());
+ int cycleLength = 2 * numRows - 2;
+
+ for (int row = 0; row < numRows; row++) {
+ for (int j = row; j < s.length(); j += cycleLength) {
+ result.append(s.charAt(j));
+
+ if (row > 0 && row < numRows - 1) {
+ int diagonal = j + cycleLength - 2 * row;
+ if (diagonal < s.length()) {
+ result.append(s.charAt(diagonal));
+ }
}
}
- height++;
- depth--;
- start++;
}
- return new String(zigZagedArray);
+
+ return result.toString();
}
}
diff --git a/src/main/java/com/thealgorithms/tree/HeavyLightDecomposition.java b/src/main/java/com/thealgorithms/tree/HeavyLightDecomposition.java
new file mode 100644
index 000000000000..236a23205180
--- /dev/null
+++ b/src/main/java/com/thealgorithms/tree/HeavyLightDecomposition.java
@@ -0,0 +1,157 @@
+package com.thealgorithms.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Heavy-Light Decomposition (HLD) implementation in Java.
+ * HLD is used to efficiently handle path queries on trees, such as maximum,
+ * sum, or updates. It decomposes the tree into heavy and light chains,
+ * enabling queries in O(log N) time.
+ * Wikipedia Reference: https://en.wikipedia.org/wiki/Heavy-light_decomposition
+ * Author: Nithin U.
+ * Github: https://github.com/NithinU2802
+ */
+
+public class HeavyLightDecomposition {
+ private List> tree;
+ private int[] parent;
+ private int[] depth;
+ private int[] subtreeSize;
+ private int[] chainHead;
+ private int[] position;
+ private int[] nodeValue;
+ private int[] segmentTree;
+ private int positionIndex;
+
+ public HeavyLightDecomposition(int n) {
+ tree = new ArrayList<>();
+ for (int i = 0; i <= n; i++) {
+ tree.add(new ArrayList<>());
+ }
+ parent = new int[n + 1];
+ depth = new int[n + 1];
+ subtreeSize = new int[n + 1];
+ chainHead = new int[n + 1];
+ position = new int[n + 1];
+ nodeValue = new int[n + 1];
+ segmentTree = new int[4 * (n + 1)];
+ for (int i = 0; i <= n; i++) {
+ chainHead[i] = -1;
+ }
+ positionIndex = 0;
+ }
+
+ public int getPosition(int index) {
+ return position[index];
+ }
+
+ public int getPositionIndex() {
+ return positionIndex;
+ }
+
+ public void addEdge(int u, int v) {
+ tree.get(u).add(v);
+ tree.get(v).add(u);
+ }
+
+ private void dfsSize(int node, int parentNode) {
+ parent[node] = parentNode;
+ subtreeSize[node] = 1;
+ for (int child : tree.get(node)) {
+ if (child != parentNode) {
+ depth[child] = depth[node] + 1;
+ dfsSize(child, node);
+ subtreeSize[node] += subtreeSize[child];
+ }
+ }
+ }
+
+ private void decompose(int node, int head) {
+ chainHead[node] = head;
+ position[node] = positionIndex++;
+ int heavyChild = -1;
+ int maxSubtreeSize = -1;
+ for (int child : tree.get(node)) {
+ if (child != parent[node] && subtreeSize[child] > maxSubtreeSize) {
+ heavyChild = child;
+ maxSubtreeSize = subtreeSize[child];
+ }
+ }
+ if (heavyChild != -1) {
+ decompose(heavyChild, head);
+ }
+ for (int child : tree.get(node)) {
+ if (child != parent[node] && child != heavyChild) {
+ decompose(child, child);
+ }
+ }
+ }
+
+ private void buildSegmentTree(int node, int start, int end) {
+ if (start == end) {
+ segmentTree[node] = nodeValue[start];
+ return;
+ }
+ int mid = (start + end) / 2;
+ buildSegmentTree(2 * node, start, mid);
+ buildSegmentTree(2 * node + 1, mid + 1, end);
+ segmentTree[node] = Math.max(segmentTree[2 * node], segmentTree[2 * node + 1]);
+ }
+
+ public void updateSegmentTree(int node, int start, int end, int index, int value) {
+ if (start == end) {
+ segmentTree[node] = value;
+ return;
+ }
+ int mid = (start + end) / 2;
+ if (index <= mid) {
+ updateSegmentTree(2 * node, start, mid, index, value);
+ } else {
+ updateSegmentTree(2 * node + 1, mid + 1, end, index, value);
+ }
+ segmentTree[node] = Math.max(segmentTree[2 * node], segmentTree[2 * node + 1]);
+ }
+
+ public int querySegmentTree(int node, int start, int end, int left, int right) {
+ if (left > end || right < start) {
+ return Integer.MIN_VALUE;
+ }
+ if (left <= start && end <= right) {
+ return segmentTree[node];
+ }
+ int mid = (start + end) / 2;
+ int leftQuery = querySegmentTree(2 * node, start, mid, left, right);
+ int rightQuery = querySegmentTree(2 * node + 1, mid + 1, end, left, right);
+ return Math.max(leftQuery, rightQuery);
+ }
+
+ public int queryMaxInPath(int u, int v) {
+ int result = Integer.MIN_VALUE;
+ while (chainHead[u] != chainHead[v]) {
+ if (depth[chainHead[u]] < depth[chainHead[v]]) {
+ int temp = u;
+ u = v;
+ v = temp;
+ }
+ result = Math.max(result, querySegmentTree(1, 0, positionIndex - 1, position[chainHead[u]], position[u]));
+ u = parent[chainHead[u]];
+ }
+ if (depth[u] > depth[v]) {
+ int temp = u;
+ u = v;
+ v = temp;
+ }
+ result = Math.max(result, querySegmentTree(1, 0, positionIndex - 1, position[u], position[v]));
+ return result;
+ }
+
+ public void initialize(int root, int[] values) {
+ dfsSize(root, -1);
+ decompose(root, root);
+ for (int i = 0; i < values.length; i++) {
+ nodeValue[position[i]] = values[i];
+ }
+ buildSegmentTree(1, 0, positionIndex - 1);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/conversions/NumberToWordsTest.java b/src/test/java/com/thealgorithms/conversions/NumberToWordsTest.java
new file mode 100644
index 000000000000..7b264678daa4
--- /dev/null
+++ b/src/test/java/com/thealgorithms/conversions/NumberToWordsTest.java
@@ -0,0 +1,60 @@
+package com.thealgorithms.conversions;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.math.BigDecimal;
+import org.junit.jupiter.api.Test;
+
+public class NumberToWordsTest {
+
+ @Test
+ void testNullInput() {
+ assertEquals("Invalid Input", NumberToWords.convert(null), "Null input should return 'Invalid Input'");
+ }
+
+ @Test
+ void testZeroInput() {
+ assertEquals("Zero", NumberToWords.convert(BigDecimal.ZERO), "Zero input should return 'Zero'");
+ }
+
+ @Test
+ void testPositiveWholeNumbers() {
+ assertEquals("One", NumberToWords.convert(BigDecimal.ONE), "1 should convert to 'One'");
+ assertEquals("One Thousand", NumberToWords.convert(new BigDecimal("1000")), "1000 should convert to 'One Thousand'");
+ assertEquals("One Million", NumberToWords.convert(new BigDecimal("1000000")), "1000000 should convert to 'One Million'");
+ }
+
+ @Test
+ void testNegativeWholeNumbers() {
+ assertEquals("Negative One", NumberToWords.convert(new BigDecimal("-1")), "-1 should convert to 'Negative One'");
+ assertEquals("Negative One Thousand", NumberToWords.convert(new BigDecimal("-1000")), "-1000 should convert to 'Negative One Thousand'");
+ }
+
+ @Test
+ void testFractionalNumbers() {
+ assertEquals("Zero Point One Two Three", NumberToWords.convert(new BigDecimal("0.123")), "0.123 should convert to 'Zero Point One Two Three'");
+ assertEquals("Negative Zero Point Four Five Six", NumberToWords.convert(new BigDecimal("-0.456")), "-0.456 should convert to 'Negative Zero Point Four Five Six'");
+ }
+
+ @Test
+ void testLargeNumbers() {
+ assertEquals("Nine Hundred Ninety Nine Million Nine Hundred Ninety Nine Thousand Nine Hundred Ninety Nine", NumberToWords.convert(new BigDecimal("999999999")), "999999999 should convert correctly");
+ assertEquals("One Trillion", NumberToWords.convert(new BigDecimal("1000000000000")), "1000000000000 should convert to 'One Trillion'");
+ }
+
+ @Test
+ void testNegativeLargeNumbers() {
+ assertEquals("Negative Nine Trillion Eight Hundred Seventy Six Billion Five Hundred Forty Three Million Two Hundred Ten Thousand Nine Hundred Eighty Seven", NumberToWords.convert(new BigDecimal("-9876543210987")), "-9876543210987 should convert correctly");
+ }
+
+ @Test
+ void testFloatingPointPrecision() {
+ assertEquals("One Million Point Zero Zero One", NumberToWords.convert(new BigDecimal("1000000.001")), "1000000.001 should convert to 'One Million Point Zero Zero One'");
+ }
+
+ @Test
+ void testEdgeCases() {
+ assertEquals("Zero", NumberToWords.convert(new BigDecimal("-0.0")), "-0.0 should convert to 'Zero'");
+ assertEquals("Zero Point Zero Zero Zero Zero Zero Zero One", NumberToWords.convert(new BigDecimal("1E-7")), "1E-7 should convert to 'Zero Point Zero Zero Zero Zero Zero Zero One'");
+ }
+}
diff --git a/src/test/java/com/thealgorithms/conversions/WordsToNumberTest.java b/src/test/java/com/thealgorithms/conversions/WordsToNumberTest.java
new file mode 100644
index 000000000000..fbf63e37946b
--- /dev/null
+++ b/src/test/java/com/thealgorithms/conversions/WordsToNumberTest.java
@@ -0,0 +1,114 @@
+package com.thealgorithms.conversions;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.math.BigDecimal;
+import org.junit.jupiter.api.Test;
+
+public class WordsToNumberTest {
+
+ @Test
+ void testNullInput() {
+ WordsToNumberException exception = assertThrows(WordsToNumberException.class, () -> WordsToNumber.convert(null));
+ assertEquals(WordsToNumberException.ErrorType.NULL_INPUT, exception.getErrorType(), "Exception should be of type NULL_INPUT");
+ }
+
+ @Test
+ void testStandardCases() {
+ assertEquals("0", WordsToNumber.convert("zero"), "'zero' should convert to '0'");
+ assertEquals("5", WordsToNumber.convert("five"), "'five' should convert to '5'");
+ assertEquals("21", WordsToNumber.convert("twenty one"), "'twenty one' should convert to '21'");
+ assertEquals("101", WordsToNumber.convert("one hundred one"), "'one hundred' should convert to '101'");
+ assertEquals("342", WordsToNumber.convert("three hundred and forty two"), "'three hundred and forty two' should convert to '342'");
+ }
+
+ @Test
+ void testLargeNumbers() {
+ assertEquals("1000000", WordsToNumber.convert("one million"), "'one million' should convert to '1000000'");
+ assertEquals("1000000000", WordsToNumber.convert("one billion"), "'one billion' should convert to '1000000000'");
+ assertEquals("1000000000000", WordsToNumber.convert("one trillion"), "'one trillion' should convert to '1000000000000'");
+ assertEquals("999000000900999", WordsToNumber.convert("nine hundred ninety nine trillion nine hundred thousand nine hundred and ninety nine"), "'nine hundred ninety nine trillion nine hundred thousand nine hundred and ninety nine' should convert to '999000000900999'");
+ }
+
+ @Test
+ void testNegativeNumbers() {
+ assertEquals("-5", WordsToNumber.convert("negative five"), "'negative five' should convert to '-5'");
+ assertEquals("-120", WordsToNumber.convert("negative one hundred and twenty"), "'negative one hundred and twenty' should convert correctly");
+ }
+
+ @Test
+ void testNegativeLargeNumbers() {
+ assertEquals("-1000000000000", WordsToNumber.convert("negative one trillion"), "'negative one trillion' should convert to '-1000000000000'");
+ assertEquals("-9876543210987", WordsToNumber.convert("Negative Nine Trillion Eight Hundred Seventy Six Billion Five Hundred Forty Three Million Two Hundred Ten Thousand Nine Hundred Eighty Seven"), "");
+ }
+
+ @Test
+ void testDecimalNumbers() {
+ assertEquals("3.1415", WordsToNumber.convert("three point one four one five"), "'three point one four one five' should convert to '3.1415'");
+ assertEquals("-2.718", WordsToNumber.convert("negative two point seven one eight"), "'negative two point seven one eight' should convert to '-2.718'");
+ assertEquals("-1E-7", WordsToNumber.convert("negative zero point zero zero zero zero zero zero one"), "'negative zero point zero zero zero zero zero zero one' should convert to '-1E-7'");
+ }
+
+ @Test
+ void testLargeDecimalNumbers() {
+ assertEquals("1000000000.0000000001", WordsToNumber.convert("one billion point zero zero zero zero zero zero zero zero zero one"), "Tests a large whole number with a tiny fractional part");
+ assertEquals("999999999999999.9999999999999",
+ WordsToNumber.convert("nine hundred ninety nine trillion nine hundred ninety nine billion nine hundred ninety nine million nine hundred ninety nine thousand nine hundred ninety nine point nine nine nine nine nine nine nine nine nine nine nine nine nine"),
+ "Tests maximum scale handling for large decimal numbers");
+ assertEquals("0.505", WordsToNumber.convert("zero point five zero five"), "Tests a decimal with an internal zero, ensuring correct parsing");
+ assertEquals("42.00000000000001", WordsToNumber.convert("forty two point zero zero zero zero zero zero zero zero zero zero zero zero zero one"), "Tests a decimal with leading zeros before a significant figure");
+ assertEquals("7.89E-7", WordsToNumber.convert("zero point zero zero zero zero zero zero seven eight nine"), "Tests scientific notation for a small decimal with multiple digits");
+ assertEquals("0.999999", WordsToNumber.convert("zero point nine nine nine nine nine nine"), "Tests a decimal close to one with multiple repeated digits");
+ }
+
+ @Test
+ void testCaseInsensitivity() {
+ assertEquals("21", WordsToNumber.convert("TWENTY-ONE"), "Uppercase should still convert correctly");
+ assertEquals("-100.0001", WordsToNumber.convert("negAtiVe OnE HuNdReD, point ZeRO Zero zERo ONE"), "Mixed case should still convert correctly");
+ assertEquals("-225647.00019", WordsToNumber.convert("nEgative twO HundRed, and twenty-Five thOusaNd, six huNdred Forty-Seven, Point zero zero zero One nInE"));
+ }
+
+ @Test
+ void testInvalidInputs() {
+ WordsToNumberException exception;
+
+ exception = assertThrows(WordsToNumberException.class, () -> WordsToNumber.convert("negative one hundred AlPha"));
+ assertEquals(WordsToNumberException.ErrorType.UNKNOWN_WORD, exception.getErrorType());
+
+ exception = assertThrows(WordsToNumberException.class, () -> WordsToNumber.convert("twenty thirteen"));
+ assertEquals(WordsToNumberException.ErrorType.UNEXPECTED_WORD, exception.getErrorType());
+
+ exception = assertThrows(WordsToNumberException.class, () -> WordsToNumber.convert("negative negative ten"));
+ assertEquals(WordsToNumberException.ErrorType.MULTIPLE_NEGATIVES, exception.getErrorType());
+
+ exception = assertThrows(WordsToNumberException.class, () -> WordsToNumber.convert("one hundred hundred"));
+ assertEquals(WordsToNumberException.ErrorType.UNEXPECTED_WORD, exception.getErrorType());
+
+ exception = assertThrows(WordsToNumberException.class, () -> WordsToNumber.convert("one thousand and hundred"));
+ assertEquals(WordsToNumberException.ErrorType.INVALID_CONJUNCTION, exception.getErrorType());
+
+ exception = assertThrows(WordsToNumberException.class, () -> WordsToNumber.convert("one thousand hundred"));
+ assertEquals(WordsToNumberException.ErrorType.UNEXPECTED_WORD, exception.getErrorType());
+
+ exception = assertThrows(WordsToNumberException.class, () -> WordsToNumber.convert("nine hundred and nine hundred"));
+ assertEquals(WordsToNumberException.ErrorType.INVALID_CONJUNCTION, exception.getErrorType());
+
+ exception = assertThrows(WordsToNumberException.class, () -> WordsToNumber.convert("forty two point"));
+ assertEquals(WordsToNumberException.ErrorType.MISSING_DECIMAL_NUMBERS, exception.getErrorType());
+
+ exception = assertThrows(WordsToNumberException.class, () -> WordsToNumber.convert("sixty seven point hello"));
+ assertEquals(WordsToNumberException.ErrorType.UNEXPECTED_WORD_AFTER_POINT, exception.getErrorType());
+
+ exception = assertThrows(WordsToNumberException.class, () -> WordsToNumber.convert("one negative"));
+ assertEquals(WordsToNumberException.ErrorType.INVALID_NEGATIVE, exception.getErrorType());
+ }
+
+ @Test
+ void testConvertToBigDecimal() {
+ assertEquals(new BigDecimal("-100000000000000.056"), WordsToNumber.convertToBigDecimal("negative one hundred trillion point zero five six"), "should convert to appropriate BigDecimal value");
+
+ WordsToNumberException exception = assertThrows(WordsToNumberException.class, () -> WordsToNumber.convertToBigDecimal(null));
+ assertEquals(WordsToNumberException.ErrorType.NULL_INPUT, exception.getErrorType(), "Exception should be of type NULL_INPUT");
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/crdt/LWWElementSetTest.java b/src/test/java/com/thealgorithms/datastructures/crdt/LWWElementSetTest.java
index 36593d6669f8..0356949a8f69 100644
--- a/src/test/java/com/thealgorithms/datastructures/crdt/LWWElementSetTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/crdt/LWWElementSetTest.java
@@ -3,106 +3,96 @@
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import org.junit.jupiter.api.BeforeEach;
+import java.time.Instant;
import org.junit.jupiter.api.Test;
class LWWElementSetTest {
- private LWWElementSet set;
- private final Bias bias = Bias.ADDS;
-
- @BeforeEach
- void setUp() {
- set = new LWWElementSet();
- }
-
@Test
- void testAdd() {
- Element element = new Element("key1", 1, bias);
- set.add(element);
-
- assertTrue(set.lookup(element));
+ void testAddElement() {
+ LWWElementSet set = new LWWElementSet<>();
+ set.add("A");
+ assertTrue(set.lookup("A"));
}
@Test
- void testRemove() {
- Element element = new Element("key1", 1, bias);
- set.add(element);
- set.remove(element);
-
- assertFalse(set.lookup(element));
+ void testRemoveElement() {
+ LWWElementSet set = new LWWElementSet<>();
+ set.add("A");
+ set.remove("A");
+ assertFalse(set.lookup("A"));
}
@Test
- void testRemoveNonexistentElement() {
- Element element = new Element("key1", 1, bias);
- set.remove(element);
-
- assertFalse(set.lookup(element));
+ void testLookupWithoutAdding() {
+ LWWElementSet set = new LWWElementSet<>();
+ assertFalse(set.lookup("A"));
}
@Test
- void testLookupNonexistentElement() {
- Element element = new Element("key1", 1, bias);
+ void testLookupLaterTimestampsFalse() {
+ LWWElementSet set = new LWWElementSet<>();
+
+ set.addSet.put("A", new Element<>("A", Instant.now()));
+ set.removeSet.put("A", new Element<>("A", Instant.now().plusSeconds(10)));
- assertFalse(set.lookup(element));
+ assertFalse(set.lookup("A"));
}
@Test
- void testCompareEqualSets() {
- LWWElementSet otherSet = new LWWElementSet();
+ void testLookupEarlierTimestampsTrue() {
+ LWWElementSet set = new LWWElementSet<>();
- Element element = new Element("key1", 1, bias);
- set.add(element);
- otherSet.add(element);
+ set.addSet.put("A", new Element<>("A", Instant.now()));
+ set.removeSet.put("A", new Element<>("A", Instant.now().minusSeconds(10)));
- assertTrue(set.compare(otherSet));
-
- otherSet.add(new Element("key2", 2, bias));
- assertTrue(set.compare(otherSet));
+ assertTrue(set.lookup("A"));
}
@Test
- void testCompareDifferentSets() {
- LWWElementSet otherSet = new LWWElementSet();
-
- Element element1 = new Element("key1", 1, bias);
- Element element2 = new Element("key2", 2, bias);
-
- set.add(element1);
- otherSet.add(element2);
-
- assertFalse(set.compare(otherSet));
+ void testLookupWithConcurrentTimestamps() {
+ LWWElementSet set = new LWWElementSet<>();
+ Instant now = Instant.now();
+ set.addSet.put("A", new Element<>("A", now));
+ set.removeSet.put("A", new Element<>("A", now));
+ assertFalse(set.lookup("A"));
}
@Test
- void testMerge() {
- LWWElementSet otherSet = new LWWElementSet();
+ void testMergeTwoSets() {
+ LWWElementSet set1 = new LWWElementSet<>();
+ LWWElementSet set2 = new LWWElementSet<>();
- Element element1 = new Element("key1", 1, bias);
- Element element2 = new Element("key2", 2, bias);
+ set1.add("A");
+ set2.add("B");
+ set2.remove("A");
- set.add(element1);
- otherSet.add(element2);
+ set1.merge(set2);
- set.merge(otherSet);
-
- assertTrue(set.lookup(element1));
- assertTrue(set.lookup(element2));
+ assertFalse(set1.lookup("A"));
+ assertTrue(set1.lookup("B"));
}
@Test
- void testCompareTimestampsEqualTimestamps() {
- LWWElementSet lwwElementSet = new LWWElementSet();
+ void testMergeWithConflictingTimestamps() {
+ LWWElementSet set1 = new LWWElementSet<>();
+ LWWElementSet set2 = new LWWElementSet<>();
- Element e1 = new Element("key1", 10, Bias.REMOVALS);
- Element e2 = new Element("key1", 10, Bias.REMOVALS);
+ Instant now = Instant.now();
+ set1.addSet.put("A", new Element<>("A", now.minusSeconds(10)));
+ set2.addSet.put("A", new Element<>("A", now));
- assertTrue(lwwElementSet.compareTimestamps(e1, e2));
+ set1.merge(set2);
- e1 = new Element("key1", 10, Bias.ADDS);
- e2 = new Element("key1", 10, Bias.ADDS);
+ assertTrue(set1.lookup("A"));
+ }
- assertFalse(lwwElementSet.compareTimestamps(e1, e2));
+ @Test
+ void testRemoveOlderThanAdd() {
+ LWWElementSet set = new LWWElementSet<>();
+ Instant now = Instant.now();
+ set.addSet.put("A", new Element<>("A", now));
+ set.removeSet.put("A", new Element<>("A", now.minusSeconds(10)));
+ assertTrue(set.lookup("A"));
}
}
diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithmTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithmTest.java
new file mode 100644
index 000000000000..bf4e2828e069
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/graphs/DijkstraOptimizedAlgorithmTest.java
@@ -0,0 +1,64 @@
+package com.thealgorithms.datastructures.graphs;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class DijkstraOptimizedAlgorithmTest {
+
+ private DijkstraOptimizedAlgorithm dijkstraOptimizedAlgorithm;
+ private int[][] graph;
+
+ @BeforeEach
+ void setUp() {
+ graph = new int[][] {
+ {0, 4, 0, 0, 0, 0, 0, 8, 0},
+ {4, 0, 8, 0, 0, 0, 0, 11, 0},
+ {0, 8, 0, 7, 0, 4, 0, 0, 2},
+ {0, 0, 7, 0, 9, 14, 0, 0, 0},
+ {0, 0, 0, 9, 0, 10, 0, 0, 0},
+ {0, 0, 4, 14, 10, 0, 2, 0, 0},
+ {0, 0, 0, 0, 0, 2, 0, 1, 6},
+ {8, 11, 0, 0, 0, 0, 1, 0, 7},
+ {0, 0, 2, 0, 0, 0, 6, 7, 0},
+ };
+
+ dijkstraOptimizedAlgorithm = new DijkstraOptimizedAlgorithm(graph.length);
+ }
+
+ @Test
+ void testRunAlgorithm() {
+ int[] expectedDistances = {0, 4, 12, 19, 21, 11, 9, 8, 14};
+ assertArrayEquals(expectedDistances, dijkstraOptimizedAlgorithm.run(graph, 0));
+ }
+
+ @Test
+ void testGraphWithDisconnectedNodes() {
+ int[][] disconnectedGraph = {
+ {0, 3, 0, 0}, {3, 0, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0} // Node 3 is disconnected
+ };
+
+ DijkstraOptimizedAlgorithm dijkstraDisconnected = new DijkstraOptimizedAlgorithm(disconnectedGraph.length);
+
+ // Testing from vertex 0
+ int[] expectedDistances = {0, 3, 4, Integer.MAX_VALUE}; // Node 3 is unreachable
+ assertArrayEquals(expectedDistances, dijkstraDisconnected.run(disconnectedGraph, 0));
+ }
+
+ @Test
+ void testSingleVertexGraph() {
+ int[][] singleVertexGraph = {{0}};
+ DijkstraOptimizedAlgorithm dijkstraSingleVertex = new DijkstraOptimizedAlgorithm(1);
+
+ int[] expectedDistances = {0}; // The only vertex's distance to itself is 0
+ assertArrayEquals(expectedDistances, dijkstraSingleVertex.run(singleVertexGraph, 0));
+ }
+
+ @Test
+ void testInvalidSourceVertex() {
+ assertThrows(IllegalArgumentException.class, () -> dijkstraOptimizedAlgorithm.run(graph, -1));
+ assertThrows(IllegalArgumentException.class, () -> dijkstraOptimizedAlgorithm.run(graph, graph.length));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/lists/ReverseKGroupTest.java b/src/test/java/com/thealgorithms/datastructures/lists/ReverseKGroupTest.java
index b2db478f692c..76b7ab063de4 100644
--- a/src/test/java/com/thealgorithms/datastructures/lists/ReverseKGroupTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/lists/ReverseKGroupTest.java
@@ -20,8 +20,8 @@ public void testReverseKGroupWithEmptyList() {
@Test
public void testReverseKGroupWithSingleNodeList() {
ReverseKGroup reverser = new ReverseKGroup();
- Node singleNode = new Node(5);
- Node result = reverser.reverseKGroup(singleNode, 2);
+ SinglyLinkedListNode singleNode = new SinglyLinkedListNode(5);
+ SinglyLinkedListNode result = reverser.reverseKGroup(singleNode, 2);
assertEquals(5, result.value);
assertNull(result.next);
}
@@ -31,15 +31,15 @@ public void testReverseKGroupWithKEqualTo2() {
ReverseKGroup reverser = new ReverseKGroup();
// Create a list with multiple elements (1 -> 2 -> 3 -> 4 -> 5)
- Node head;
- head = new Node(1);
- head.next = new Node(2);
- head.next.next = new Node(3);
- head.next.next.next = new Node(4);
- head.next.next.next.next = new Node(5);
+ SinglyLinkedListNode head;
+ head = new SinglyLinkedListNode(1);
+ head.next = new SinglyLinkedListNode(2);
+ head.next.next = new SinglyLinkedListNode(3);
+ head.next.next.next = new SinglyLinkedListNode(4);
+ head.next.next.next.next = new SinglyLinkedListNode(5);
// Test reverse with k=2
- Node result1 = reverser.reverseKGroup(head, 2);
+ SinglyLinkedListNode result1 = reverser.reverseKGroup(head, 2);
assertEquals(2, result1.value);
assertEquals(1, result1.next.value);
assertEquals(4, result1.next.next.value);
@@ -53,15 +53,15 @@ public void testReverseKGroupWithKEqualTo3() {
ReverseKGroup reverser = new ReverseKGroup();
// Create a list with multiple elements (1 -> 2 -> 3 -> 4 -> 5)
- Node head;
- head = new Node(1);
- head.next = new Node(2);
- head.next.next = new Node(3);
- head.next.next.next = new Node(4);
- head.next.next.next.next = new Node(5);
+ SinglyLinkedListNode head;
+ head = new SinglyLinkedListNode(1);
+ head.next = new SinglyLinkedListNode(2);
+ head.next.next = new SinglyLinkedListNode(3);
+ head.next.next.next = new SinglyLinkedListNode(4);
+ head.next.next.next.next = new SinglyLinkedListNode(5);
// Test reverse with k=3
- Node result = reverser.reverseKGroup(head, 3);
+ SinglyLinkedListNode result = reverser.reverseKGroup(head, 3);
assertEquals(3, result.value);
assertEquals(2, result.next.value);
assertEquals(1, result.next.next.value);
diff --git a/src/test/java/com/thealgorithms/datastructures/lists/RotateSinglyLinkedListsTest.java b/src/test/java/com/thealgorithms/datastructures/lists/RotateSinglyLinkedListsTest.java
index 70c0dfccafa4..c476ad1b0203 100644
--- a/src/test/java/com/thealgorithms/datastructures/lists/RotateSinglyLinkedListsTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/lists/RotateSinglyLinkedListsTest.java
@@ -14,24 +14,24 @@ public class RotateSinglyLinkedListsTest {
private final RotateSinglyLinkedLists rotator = new RotateSinglyLinkedLists();
// Helper method to create a linked list from an array of values
- private Node createLinkedList(int[] values) {
+ private SinglyLinkedListNode createLinkedList(int[] values) {
if (values.length == 0) {
return null;
}
- Node head = new Node(values[0]);
- Node current = head;
+ SinglyLinkedListNode head = new SinglyLinkedListNode(values[0]);
+ SinglyLinkedListNode current = head;
for (int i = 1; i < values.length; i++) {
- current.next = new Node(values[i]);
+ current.next = new SinglyLinkedListNode(values[i]);
current = current.next;
}
return head;
}
// Helper method to convert a linked list to a string for easy comparison
- private String linkedListToString(Node head) {
+ private String linkedListToString(SinglyLinkedListNode head) {
StringBuilder sb = new StringBuilder();
- Node current = head;
+ SinglyLinkedListNode current = head;
while (current != null) {
sb.append(current.value);
if (current.next != null) {
@@ -51,55 +51,55 @@ public void testRotateRightEmptyList() {
@Test
public void testRotateRightSingleNodeList() {
// Rotate a list with a single element
- Node singleNode = new Node(5);
- Node rotatedSingleNode = rotator.rotateRight(singleNode, 3);
+ SinglyLinkedListNode singleNode = new SinglyLinkedListNode(5);
+ SinglyLinkedListNode rotatedSingleNode = rotator.rotateRight(singleNode, 3);
assertEquals("5", linkedListToString(rotatedSingleNode));
}
@Test
public void testRotateRightMultipleElementsList() {
// Rotate a list with multiple elements (rotate by 2)
- Node head = createLinkedList(new int[] {1, 2, 3, 4, 5});
- Node rotated = rotator.rotateRight(head, 2);
+ SinglyLinkedListNode head = createLinkedList(new int[] {1, 2, 3, 4, 5});
+ SinglyLinkedListNode rotated = rotator.rotateRight(head, 2);
assertEquals("4 -> 5 -> 1 -> 2 -> 3", linkedListToString(rotated));
}
@Test
public void testRotateRightFullRotation() {
// Rotate by more than the length of the list
- Node head = createLinkedList(new int[] {1, 2, 3, 4, 5});
- Node rotated = rotator.rotateRight(head, 7);
+ SinglyLinkedListNode head = createLinkedList(new int[] {1, 2, 3, 4, 5});
+ SinglyLinkedListNode rotated = rotator.rotateRight(head, 7);
assertEquals("4 -> 5 -> 1 -> 2 -> 3", linkedListToString(rotated));
}
@Test
public void testRotateRightZeroRotation() {
// Rotate a list by k = 0 (no rotation)
- Node head = createLinkedList(new int[] {1, 2, 3, 4, 5});
- Node rotated = rotator.rotateRight(head, 0);
+ SinglyLinkedListNode head = createLinkedList(new int[] {1, 2, 3, 4, 5});
+ SinglyLinkedListNode rotated = rotator.rotateRight(head, 0);
assertEquals("1 -> 2 -> 3 -> 4 -> 5", linkedListToString(rotated));
}
@Test
public void testRotateRightByListLength() {
// Rotate a list by k equal to list length (no change)
- Node head = createLinkedList(new int[] {1, 2, 3, 4, 5});
- Node rotated = rotator.rotateRight(head, 5);
+ SinglyLinkedListNode head = createLinkedList(new int[] {1, 2, 3, 4, 5});
+ SinglyLinkedListNode rotated = rotator.rotateRight(head, 5);
assertEquals("1 -> 2 -> 3 -> 4 -> 5", linkedListToString(rotated));
}
@Test
public void testRotateRightByMultipleOfListLength() {
- Node head = createLinkedList(new int[] {1, 2, 3, 4, 5});
- Node rotated = rotator.rotateRight(head, 10); // k = 2 * list length
+ SinglyLinkedListNode head = createLinkedList(new int[] {1, 2, 3, 4, 5});
+ SinglyLinkedListNode rotated = rotator.rotateRight(head, 10); // k = 2 * list length
assertEquals("1 -> 2 -> 3 -> 4 -> 5", linkedListToString(rotated));
}
@Test
public void testRotateRightLongerList() {
// Rotate a longer list by a smaller k
- Node head = createLinkedList(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9});
- Node rotated = rotator.rotateRight(head, 4);
+ SinglyLinkedListNode head = createLinkedList(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9});
+ SinglyLinkedListNode rotated = rotator.rotateRight(head, 4);
assertEquals("6 -> 7 -> 8 -> 9 -> 1 -> 2 -> 3 -> 4 -> 5", linkedListToString(rotated));
}
}
diff --git a/src/test/java/com/thealgorithms/datastructures/lists/SinglyLinkedListTest.java b/src/test/java/com/thealgorithms/datastructures/lists/SinglyLinkedListTest.java
index a47434083cdb..f80c6b5055f0 100644
--- a/src/test/java/com/thealgorithms/datastructures/lists/SinglyLinkedListTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/lists/SinglyLinkedListTest.java
@@ -18,9 +18,9 @@ public class SinglyLinkedListTest {
* @return linked list with pre-defined number of nodes
*/
private SinglyLinkedList createSampleList(int length) {
- List nodeList = new ArrayList<>();
+ List nodeList = new ArrayList<>();
for (int i = 1; i <= length; i++) {
- Node node = new Node(i);
+ SinglyLinkedListNode node = new SinglyLinkedListNode(i);
nodeList.add(node);
}
@@ -34,10 +34,10 @@ private SinglyLinkedList createSampleList(int length) {
@Test
void detectLoop() {
// List has cycle
- Node firstNode = new Node(1);
- Node secondNode = new Node(2);
- Node thirdNode = new Node(3);
- Node fourthNode = new Node(4);
+ SinglyLinkedListNode firstNode = new SinglyLinkedListNode(1);
+ SinglyLinkedListNode secondNode = new SinglyLinkedListNode(2);
+ SinglyLinkedListNode thirdNode = new SinglyLinkedListNode(3);
+ SinglyLinkedListNode fourthNode = new SinglyLinkedListNode(4);
firstNode.next = secondNode;
secondNode.next = thirdNode;
@@ -112,13 +112,13 @@ void reverseList() {
// Reversing the LinkedList using reverseList() method and storing the head of the reversed
// linkedlist in a head node The reversed linkedlist will be 4->3->2->1->null
- Node head = list.reverseListIter(list.getHead());
+ SinglyLinkedListNode head = list.reverseListIter(list.getHead());
// Recording the Nodes after reversing the LinkedList
- Node firstNode = head; // 4
- Node secondNode = firstNode.next; // 3
- Node thirdNode = secondNode.next; // 2
- Node fourthNode = thirdNode.next; // 1
+ SinglyLinkedListNode firstNode = head; // 4
+ SinglyLinkedListNode secondNode = firstNode.next; // 3
+ SinglyLinkedListNode thirdNode = secondNode.next; // 2
+ SinglyLinkedListNode fourthNode = thirdNode.next; // 1
// Checking whether the LinkedList is reversed or not by comparing the original list and
// reversed list nodes
@@ -134,10 +134,10 @@ void reverseList() {
void reverseListNullPointer() {
// Creating a linkedlist with first node assigned to null
SinglyLinkedList list = new SinglyLinkedList();
- Node first = list.getHead();
+ SinglyLinkedListNode first = list.getHead();
// Reversing the linkedlist
- Node head = list.reverseListIter(first);
+ SinglyLinkedListNode head = list.reverseListIter(first);
// checking whether the method works fine if the input is null
assertEquals(head, first);
@@ -151,10 +151,10 @@ void reverseListTest() {
// Reversing the LinkedList using reverseList() method and storing the head of the reversed
// linkedlist in a head node
- Node head = list.reverseListIter(list.getHead());
+ SinglyLinkedListNode head = list.reverseListIter(list.getHead());
// Storing the head in a temp variable, so that we cannot loose the track of head
- Node temp = head;
+ SinglyLinkedListNode temp = head;
int i = 20; // This is for the comparison of values of nodes of the reversed linkedlist
// Checking whether the reverseList() method performed its task
@@ -171,7 +171,7 @@ void recursiveReverseList() {
SinglyLinkedList list = createSampleList(5);
// Reversing the linked list using reverseList() method
- Node head = list.reverseListRec(list.getHead());
+ SinglyLinkedListNode head = list.reverseListRec(list.getHead());
// Check if the reversed list is: 5 -> 4 -> 3 -> 2 -> 1
assertEquals(5, head.value);
@@ -185,10 +185,10 @@ void recursiveReverseList() {
void recursiveReverseListNullPointer() {
// Create an empty linked list
SinglyLinkedList list = new SinglyLinkedList();
- Node first = list.getHead();
+ SinglyLinkedListNode first = list.getHead();
// Reversing the empty linked list
- Node head = list.reverseListRec(first);
+ SinglyLinkedListNode head = list.reverseListRec(first);
// Check if the head remains the same (null)
assertNull(head);
@@ -200,11 +200,11 @@ void recursiveReverseListTest() {
SinglyLinkedList list = createSampleList(20);
// Reversing the linked list using reverseList() method
- Node head = list.reverseListRec(list.getHead());
+ SinglyLinkedListNode head = list.reverseListRec(list.getHead());
// Check if the reversed list has the correct values
int i = 20;
- Node temp = head;
+ SinglyLinkedListNode temp = head;
while (temp != null && i > 0) {
assertEquals(i, temp.value);
temp = temp.next;
diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/EditDistanceTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/EditDistanceTest.java
index 267be9b056de..737e8d1d0918 100644
--- a/src/test/java/com/thealgorithms/dynamicprogramming/EditDistanceTest.java
+++ b/src/test/java/com/thealgorithms/dynamicprogramming/EditDistanceTest.java
@@ -1,7 +1,9 @@
package com.thealgorithms.dynamicprogramming;
+import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
@@ -12,4 +14,91 @@ public class EditDistanceTest {
void testMinDistance(String str1, String str2, int expected) {
assertEquals(expected, EditDistance.minDistance(str1, str2));
}
+
+ @Test
+ public void testEditDistanceBothEmptyStrings() {
+ assertEquals(0, EditDistance.editDistance("", ""));
+ }
+
+ @Test
+ public void testEditDistanceOneEmptyString() {
+ assertEquals(5, EditDistance.editDistance("", "hello"));
+ assertEquals(7, EditDistance.editDistance("worldly", ""));
+ }
+
+ @Test
+ public void testEditDistanceOneEmptyStringMemoization() {
+ int[][] storage = new int[1][6];
+ assertAll("String assertions",
+ ()
+ -> assertEquals(5, EditDistance.editDistance("", "hello", storage)),
+ () -> assertEquals(0, storage[0][0]), () -> assertEquals(0, storage[0][1]), () -> assertEquals(0, storage[0][2]), () -> assertEquals(0, storage[0][3]), () -> assertEquals(0, storage[0][4]), () -> assertEquals(5, storage[0][5]));
+ }
+
+ @Test
+ public void testEditDistanceEqualStrings() {
+ assertEquals(0, EditDistance.editDistance("test", "test"));
+ assertEquals(0, EditDistance.editDistance("abc", "abc"));
+ }
+
+ @Test
+ public void testEditDistanceEqualStringsMemoization() {
+ int[][] storage = new int[4][4];
+ assertAll("String assertions",
+ ()
+ -> assertEquals(0, EditDistance.editDistance("abc", "abc", storage)),
+ ()
+ -> assertEquals(0, storage[0][0]),
+ ()
+ -> assertEquals(0, storage[0][1]),
+ ()
+ -> assertEquals(0, storage[0][2]),
+ ()
+ -> assertEquals(0, storage[0][3]),
+ ()
+ -> assertEquals(0, storage[1][0]),
+ ()
+ -> assertEquals(0, storage[1][1]),
+ ()
+ -> assertEquals(0, storage[1][2]),
+ ()
+ -> assertEquals(0, storage[1][3]),
+ ()
+ -> assertEquals(0, storage[2][0]),
+ () -> assertEquals(0, storage[2][1]), () -> assertEquals(0, storage[2][2]), () -> assertEquals(0, storage[2][3]), () -> assertEquals(0, storage[3][0]), () -> assertEquals(0, storage[3][1]), () -> assertEquals(0, storage[3][2]), () -> assertEquals(0, storage[3][3]));
+ }
+
+ @Test
+ public void testEditDistanceOneCharacterDifference() {
+ assertEquals(1, EditDistance.editDistance("cat", "bat"));
+ assertEquals(1, EditDistance.editDistance("cat", "cats"));
+ assertEquals(1, EditDistance.editDistance("cats", "cat"));
+ }
+
+ @Test
+ public void testEditDistanceOneCharacterDifferenceMemoization() {
+ int[][] storage = new int[3][3];
+ assertAll("All assertions",
+ ()
+ -> assertEquals(1, EditDistance.editDistance("at", "it", storage)),
+ ()
+ -> assertEquals(0, storage[0][0]),
+ ()
+ -> assertEquals(1, storage[0][1]),
+ () -> assertEquals(2, storage[0][2]), () -> assertEquals(1, storage[1][0]), () -> assertEquals(0, storage[1][1]), () -> assertEquals(1, storage[1][2]), () -> assertEquals(2, storage[2][0]), () -> assertEquals(1, storage[2][1]), () -> assertEquals(1, storage[2][2]));
+ }
+
+ @Test
+ public void testEditDistanceGeneralCases() {
+ assertEquals(3, EditDistance.editDistance("kitten", "sitting"));
+ assertEquals(2, EditDistance.editDistance("flaw", "lawn"));
+ assertEquals(5, EditDistance.editDistance("intention", "execution"));
+ }
+
+ @Test
+ public void testEditDistanceGeneralCasesMemoization() {
+ int[][] storage = new int[7][8];
+ assertEquals(3, EditDistance.editDistance("kitten", "sitting", storage));
+ assertAll("All assertions", () -> assertEquals(0, storage[0][0]), () -> assertEquals(3, storage[6][7]));
+ }
}
diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequenceNLogNTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequenceNLogNTest.java
new file mode 100644
index 000000000000..dc87d6751460
--- /dev/null
+++ b/src/test/java/com/thealgorithms/dynamicprogramming/LongestIncreasingSubsequenceNLogNTest.java
@@ -0,0 +1,22 @@
+package com.thealgorithms.dynamicprogramming;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public class LongestIncreasingSubsequenceNLogNTest {
+
+ private static Stream provideTestCases() {
+ return Stream.of(Arguments.of(new int[] {10, 9, 2, 5, 3, 7, 101, 18}, 4), Arguments.of(new int[] {0, 1, 0, 3, 2, 3}, 4), Arguments.of(new int[] {7, 7, 7, 7, 7}, 1), Arguments.of(new int[] {1, 3, 5, 4, 7}, 4), Arguments.of(new int[] {}, 0), Arguments.of(new int[] {10}, 1),
+ Arguments.of(new int[] {3, 10, 2, 1, 20}, 3), Arguments.of(new int[] {50, 3, 10, 7, 40, 80}, 4));
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideTestCases")
+ public void testLengthOfLIS(int[] input, int expected) {
+ assertEquals(expected, LongestIncreasingSubsequenceNLogN.lengthOfLIS(input));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/TreeMatchingTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/TreeMatchingTest.java
new file mode 100644
index 000000000000..d5418770a5d1
--- /dev/null
+++ b/src/test/java/com/thealgorithms/dynamicprogramming/TreeMatchingTest.java
@@ -0,0 +1,120 @@
+package com.thealgorithms.dynamicprogramming;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.thealgorithms.datastructures.graphs.UndirectedAdjacencyListGraph;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class TreeMatchingTest {
+ UndirectedAdjacencyListGraph graph;
+
+ @BeforeEach
+ void setUp() {
+ graph = new UndirectedAdjacencyListGraph();
+ for (int i = 0; i < 14; i++) {
+ graph.addNode();
+ }
+ }
+
+ @Test
+ void testMaxMatchingForGeneralTree() {
+ graph.addEdge(0, 1, 20);
+ graph.addEdge(0, 2, 30);
+ graph.addEdge(1, 3, 40);
+ graph.addEdge(1, 4, 10);
+ graph.addEdge(2, 5, 20);
+ graph.addEdge(3, 6, 30);
+ graph.addEdge(3, 7, 30);
+ graph.addEdge(5, 8, 40);
+ graph.addEdge(5, 9, 10);
+
+ TreeMatching treeMatching = new TreeMatching(graph);
+ assertEquals(110, treeMatching.getMaxMatching(0, -1));
+ }
+
+ @Test
+ void testMaxMatchingForBalancedTree() {
+ graph.addEdge(0, 1, 20);
+ graph.addEdge(0, 2, 30);
+ graph.addEdge(0, 3, 40);
+ graph.addEdge(1, 4, 10);
+ graph.addEdge(1, 5, 20);
+ graph.addEdge(2, 6, 20);
+ graph.addEdge(3, 7, 30);
+ graph.addEdge(5, 8, 10);
+ graph.addEdge(5, 9, 20);
+ graph.addEdge(7, 10, 10);
+ graph.addEdge(7, 11, 10);
+ graph.addEdge(7, 12, 5);
+ TreeMatching treeMatching = new TreeMatching(graph);
+ assertEquals(100, treeMatching.getMaxMatching(0, -1));
+ }
+
+ @Test
+ void testMaxMatchingForTreeWithVariedEdgeWeights() {
+ graph.addEdge(0, 1, 20);
+ graph.addEdge(0, 2, 30);
+ graph.addEdge(0, 3, 40);
+ graph.addEdge(0, 4, 50);
+ graph.addEdge(1, 5, 20);
+ graph.addEdge(2, 6, 20);
+ graph.addEdge(3, 7, 30);
+ graph.addEdge(5, 8, 10);
+ graph.addEdge(5, 9, 20);
+ graph.addEdge(7, 10, 10);
+ graph.addEdge(4, 11, 50);
+ graph.addEdge(4, 12, 20);
+ TreeMatching treeMatching = new TreeMatching(graph);
+ assertEquals(140, treeMatching.getMaxMatching(0, -1));
+ }
+
+ @Test
+ void emptyTree() {
+ TreeMatching treeMatching = new TreeMatching(graph);
+ assertEquals(0, treeMatching.getMaxMatching(0, -1));
+ }
+
+ @Test
+ void testSingleNodeTree() {
+ UndirectedAdjacencyListGraph singleNodeGraph = new UndirectedAdjacencyListGraph();
+ singleNodeGraph.addNode();
+
+ TreeMatching treeMatching = new TreeMatching(singleNodeGraph);
+ assertEquals(0, treeMatching.getMaxMatching(0, -1));
+ }
+
+ @Test
+ void testLinearTree() {
+ graph.addEdge(0, 1, 10);
+ graph.addEdge(1, 2, 20);
+ graph.addEdge(2, 3, 30);
+ graph.addEdge(3, 4, 40);
+
+ TreeMatching treeMatching = new TreeMatching(graph);
+ assertEquals(60, treeMatching.getMaxMatching(0, -1));
+ }
+
+ @Test
+ void testStarShapedTree() {
+ graph.addEdge(0, 1, 15);
+ graph.addEdge(0, 2, 25);
+ graph.addEdge(0, 3, 35);
+ graph.addEdge(0, 4, 45);
+
+ TreeMatching treeMatching = new TreeMatching(graph);
+ assertEquals(45, treeMatching.getMaxMatching(0, -1));
+ }
+
+ @Test
+ void testUnbalancedTree() {
+ graph.addEdge(0, 1, 10);
+ graph.addEdge(0, 2, 20);
+ graph.addEdge(1, 3, 30);
+ graph.addEdge(2, 4, 40);
+ graph.addEdge(4, 5, 50);
+
+ TreeMatching treeMatching = new TreeMatching(graph);
+ assertEquals(100, treeMatching.getMaxMatching(0, -1));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/graph/ConstrainedShortestPathTest.java b/src/test/java/com/thealgorithms/graph/ConstrainedShortestPathTest.java
new file mode 100644
index 000000000000..eccd359f2634
--- /dev/null
+++ b/src/test/java/com/thealgorithms/graph/ConstrainedShortestPathTest.java
@@ -0,0 +1,218 @@
+package com.thealgorithms.graph;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.thealgorithms.graph.ConstrainedShortestPath.Graph;
+import org.junit.jupiter.api.Test;
+
+public class ConstrainedShortestPathTest {
+
+ /**
+ * Tests a simple linear graph to verify if the solver calculates the shortest path correctly.
+ * Expected: The minimal path cost from node 0 to node 2 should be 5 while not exceeding the resource limit.
+ */
+ @Test
+ public void testSimpleGraph() {
+ Graph graph = new Graph(3);
+ graph.addEdge(0, 1, 2, 3);
+ graph.addEdge(1, 2, 3, 2);
+
+ int maxResource = 5;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(5, solver.solve(0, 2));
+ }
+
+ /**
+ * Tests a graph where no valid path exists due to resource constraints.
+ * Expected: The solver should return -1, indicating no path is feasible.
+ */
+ @Test
+ public void testNoPath() {
+ Graph graph = new Graph(3);
+ graph.addEdge(0, 1, 2, 6);
+ graph.addEdge(1, 2, 3, 6);
+
+ int maxResource = 5;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(-1, solver.solve(0, 2));
+ }
+
+ /**
+ * Tests a graph with multiple paths between source and destination.
+ * Expected: The solver should choose the path with the minimal cost of 5, considering the resource limit.
+ */
+ @Test
+ public void testMultiplePaths() {
+ Graph graph = new Graph(4);
+ graph.addEdge(0, 1, 1, 1);
+ graph.addEdge(1, 3, 5, 2);
+ graph.addEdge(0, 2, 2, 1);
+ graph.addEdge(2, 3, 3, 2);
+
+ int maxResource = 3;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(5, solver.solve(0, 3));
+ }
+
+ /**
+ * Verifies that the solver allows a path exactly matching the resource limit.
+ * Expected: The path is valid with a total cost of 5.
+ */
+ @Test
+ public void testExactResourceLimit() {
+ Graph graph = new Graph(3);
+ graph.addEdge(0, 1, 2, 3);
+ graph.addEdge(1, 2, 3, 2);
+
+ int maxResource = 5;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(5, solver.solve(0, 2));
+ }
+
+ /**
+ * Tests a disconnected graph where the destination node cannot be reached.
+ * Expected: The solver should return -1, as the destination is unreachable.
+ */
+ @Test
+ public void testDisconnectedGraph() {
+ Graph graph = new Graph(4);
+ graph.addEdge(0, 1, 2, 2);
+ graph.addEdge(2, 3, 3, 2);
+
+ int maxResource = 5;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(-1, solver.solve(0, 3));
+ }
+
+ /**
+ * Tests a graph with cycles to ensure the solver does not fall into infinite loops and correctly calculates costs.
+ * Expected: The solver should compute the minimal path cost of 6.
+ */
+ @Test
+ public void testGraphWithCycles() {
+ Graph graph = new Graph(4);
+ graph.addEdge(0, 1, 2, 1);
+ graph.addEdge(1, 2, 3, 1);
+ graph.addEdge(2, 0, 1, 1);
+ graph.addEdge(1, 3, 4, 2);
+
+ int maxResource = 3;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(6, solver.solve(0, 3));
+ }
+
+ /**
+ * Tests the solver's performance and correctness on a large linear graph with 1000 nodes.
+ * Expected: The solver should efficiently calculate the shortest path with a cost of 999.
+ */
+ @Test
+ public void testLargeGraphPerformance() {
+ int nodeCount = 1000;
+ Graph graph = new Graph(nodeCount);
+ for (int i = 0; i < nodeCount - 1; i++) {
+ graph.addEdge(i, i + 1, 1, 1);
+ }
+
+ int maxResource = 1000;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(999, solver.solve(0, nodeCount - 1));
+ }
+
+ /**
+ * Tests a graph with isolated nodes to ensure the solver recognizes unreachable destinations.
+ * Expected: The solver should return -1 for unreachable nodes.
+ */
+ @Test
+ public void testIsolatedNodes() {
+ Graph graph = new Graph(5);
+ graph.addEdge(0, 1, 2, 1);
+ graph.addEdge(1, 2, 3, 1);
+
+ int maxResource = 5;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(-1, solver.solve(0, 3));
+ }
+
+ /**
+ * Tests a cyclic large graph with multiple overlapping paths.
+ * Expected: The solver should calculate the shortest path cost of 5.
+ */
+ @Test
+ public void testCyclicLargeGraph() {
+ Graph graph = new Graph(10);
+ for (int i = 0; i < 9; i++) {
+ graph.addEdge(i, (i + 1) % 10, 1, 1);
+ }
+ graph.addEdge(0, 5, 5, 3);
+
+ int maxResource = 10;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(5, solver.solve(0, 5));
+ }
+
+ /**
+ * Tests a large complex graph with multiple paths and varying resource constraints.
+ * Expected: The solver should identify the optimal path with a cost of 19 within the resource limit.
+ */
+ @Test
+ public void testLargeComplexGraph() {
+ Graph graph = new Graph(10);
+ graph.addEdge(0, 1, 4, 2);
+ graph.addEdge(0, 2, 3, 3);
+ graph.addEdge(1, 3, 2, 1);
+ graph.addEdge(2, 3, 5, 2);
+ graph.addEdge(2, 4, 8, 4);
+ graph.addEdge(3, 5, 7, 3);
+ graph.addEdge(3, 6, 6, 2);
+ graph.addEdge(4, 6, 3, 2);
+ graph.addEdge(5, 7, 1, 1);
+ graph.addEdge(6, 7, 2, 2);
+ graph.addEdge(7, 8, 3, 1);
+ graph.addEdge(8, 9, 2, 1);
+
+ int maxResource = 10;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(19, solver.solve(0, 9));
+ }
+
+ /**
+ * Edge case test where the graph has only one node and no edges.
+ * Expected: The minimal path cost is 0, as the start and destination are the same.
+ */
+ @Test
+ public void testSingleNodeGraph() {
+ Graph graph = new Graph(1);
+
+ int maxResource = 0;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(0, solver.solve(0, 0));
+ }
+
+ /**
+ * Tests a graph with multiple paths but a tight resource constraint.
+ * Expected: The solver should return -1 if no path can be found within the resource limit.
+ */
+ @Test
+ public void testTightResourceConstraint() {
+ Graph graph = new Graph(4);
+ graph.addEdge(0, 1, 3, 4);
+ graph.addEdge(1, 2, 1, 2);
+ graph.addEdge(0, 2, 2, 2);
+
+ int maxResource = 3;
+ ConstrainedShortestPath solver = new ConstrainedShortestPath(graph, maxResource);
+
+ assertEquals(2, solver.solve(0, 2));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/graph/TravelingSalesmanTest.java b/src/test/java/com/thealgorithms/graph/TravelingSalesmanTest.java
new file mode 100644
index 000000000000..b93c9f89c944
--- /dev/null
+++ b/src/test/java/com/thealgorithms/graph/TravelingSalesmanTest.java
@@ -0,0 +1,127 @@
+package com.thealgorithms.graph;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class TravelingSalesmanTest {
+
+ // Test Case 1: A simple distance matrix with 4 cities
+ @Test
+ public void testBruteForceSimple() {
+ int[][] distanceMatrix = {{0, 10, 15, 20}, {10, 0, 35, 25}, {15, 35, 0, 30}, {20, 25, 30, 0}};
+ int expectedMinDistance = 80;
+ int result = TravelingSalesman.bruteForce(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+
+ @Test
+ public void testDynamicProgrammingSimple() {
+ int[][] distanceMatrix = {{0, 10, 15, 20}, {10, 0, 35, 25}, {15, 35, 0, 30}, {20, 25, 30, 0}};
+ int expectedMinDistance = 80;
+ int result = TravelingSalesman.dynamicProgramming(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+
+ // Test Case 2: A distance matrix with 3 cities
+ @Test
+ public void testBruteForceThreeCities() {
+ int[][] distanceMatrix = {{0, 10, 15}, {10, 0, 35}, {15, 35, 0}};
+ int expectedMinDistance = 60;
+ int result = TravelingSalesman.bruteForce(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+
+ @Test
+ public void testDynamicProgrammingThreeCities() {
+ int[][] distanceMatrix = {{0, 10, 15}, {10, 0, 35}, {15, 35, 0}};
+ int expectedMinDistance = 60;
+ int result = TravelingSalesman.dynamicProgramming(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+
+ // Test Case 3: A distance matrix with 5 cities (larger input)
+ @Test
+ public void testBruteForceFiveCities() {
+ int[][] distanceMatrix = {{0, 2, 9, 10, 1}, {2, 0, 6, 5, 8}, {9, 6, 0, 4, 3}, {10, 5, 4, 0, 7}, {1, 8, 3, 7, 0}};
+ int expectedMinDistance = 15;
+ int result = TravelingSalesman.bruteForce(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+
+ @Test
+ public void testDynamicProgrammingFiveCities() {
+ int[][] distanceMatrix = {{0, 2, 9, 10, 1}, {2, 0, 6, 5, 8}, {9, 6, 0, 4, 3}, {10, 5, 4, 0, 7}, {1, 8, 3, 7, 0}};
+ int expectedMinDistance = 15;
+ int result = TravelingSalesman.dynamicProgramming(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+
+ // Test Case 4: A distance matrix with 2 cities (simple case)
+ @Test
+ public void testBruteForceTwoCities() {
+ int[][] distanceMatrix = {{0, 1}, {1, 0}};
+ int expectedMinDistance = 2;
+ int result = TravelingSalesman.bruteForce(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+
+ @Test
+ public void testDynamicProgrammingTwoCities() {
+ int[][] distanceMatrix = {{0, 1}, {1, 0}};
+ int expectedMinDistance = 2;
+ int result = TravelingSalesman.dynamicProgramming(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+
+ // Test Case 5: A distance matrix with identical distances
+ @Test
+ public void testBruteForceEqualDistances() {
+ int[][] distanceMatrix = {{0, 10, 10, 10}, {10, 0, 10, 10}, {10, 10, 0, 10}, {10, 10, 10, 0}};
+ int expectedMinDistance = 40;
+ int result = TravelingSalesman.bruteForce(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+
+ @Test
+ public void testDynamicProgrammingEqualDistances() {
+ int[][] distanceMatrix = {{0, 10, 10, 10}, {10, 0, 10, 10}, {10, 10, 0, 10}, {10, 10, 10, 0}};
+ int expectedMinDistance = 40;
+ int result = TravelingSalesman.dynamicProgramming(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+
+ // Test Case 6: A distance matrix with only one city
+ @Test
+ public void testBruteForceOneCity() {
+ int[][] distanceMatrix = {{0}};
+ int expectedMinDistance = 0;
+ int result = TravelingSalesman.bruteForce(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+
+ @Test
+ public void testDynamicProgrammingOneCity() {
+ int[][] distanceMatrix = {{0}};
+ int expectedMinDistance = 0;
+ int result = TravelingSalesman.dynamicProgramming(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+
+ // Test Case 7: Distance matrix with large numbers
+ @Test
+ public void testBruteForceLargeNumbers() {
+ int[][] distanceMatrix = {{0, 1000000, 2000000}, {1000000, 0, 1500000}, {2000000, 1500000, 0}};
+ int expectedMinDistance = 4500000;
+ int result = TravelingSalesman.bruteForce(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+
+ @Test
+ public void testDynamicProgrammingLargeNumbers() {
+ int[][] distanceMatrix = {{0, 1000000, 2000000}, {1000000, 0, 1500000}, {2000000, 1500000, 0}};
+ int expectedMinDistance = 4500000;
+ int result = TravelingSalesman.dynamicProgramming(distanceMatrix);
+ assertEquals(expectedMinDistance, result);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/maths/AbsoluteMaxTest.java b/src/test/java/com/thealgorithms/maths/AbsoluteMaxTest.java
index 70d2f64bc541..33461fbbc088 100644
--- a/src/test/java/com/thealgorithms/maths/AbsoluteMaxTest.java
+++ b/src/test/java/com/thealgorithms/maths/AbsoluteMaxTest.java
@@ -19,4 +19,12 @@ void testGetMaxValue() {
void testGetMaxValueWithNoArguments() {
assertThrows(IllegalArgumentException.class, AbsoluteMax::getMaxValue);
}
+
+ @Test
+ void testGetMaxValueWithSameAbsoluteValues() {
+ assertEquals(5, AbsoluteMax.getMaxValue(-5, 5));
+ assertEquals(5, AbsoluteMax.getMaxValue(5, -5));
+ assertEquals(12, AbsoluteMax.getMaxValue(-12, 9, 3, 12, 1));
+ assertEquals(12, AbsoluteMax.getMaxValue(12, 9, 3, -12, 1));
+ }
}
diff --git a/src/test/java/com/thealgorithms/maths/AbsoluteMinTest.java b/src/test/java/com/thealgorithms/maths/AbsoluteMinTest.java
index 4b676ca634f7..dfca757fd877 100644
--- a/src/test/java/com/thealgorithms/maths/AbsoluteMinTest.java
+++ b/src/test/java/com/thealgorithms/maths/AbsoluteMinTest.java
@@ -15,7 +15,13 @@ void testGetMinValue() {
@Test
void testGetMinValueWithNoArguments() {
- Exception exception = assertThrows(IllegalArgumentException.class, () -> AbsoluteMin.getMinValue());
+ Exception exception = assertThrows(IllegalArgumentException.class, AbsoluteMin::getMinValue);
assertEquals("Numbers array cannot be empty", exception.getMessage());
}
+
+ @Test
+ void testGetMinValueWithSameAbsoluteValues() {
+ assertEquals(-5, AbsoluteMin.getMinValue(-5, 5));
+ assertEquals(-5, AbsoluteMin.getMinValue(5, -5));
+ }
}
diff --git a/src/test/java/com/thealgorithms/maths/GoldbachConjectureTest.java b/src/test/java/com/thealgorithms/maths/GoldbachConjectureTest.java
new file mode 100644
index 000000000000..84c5824d26ae
--- /dev/null
+++ b/src/test/java/com/thealgorithms/maths/GoldbachConjectureTest.java
@@ -0,0 +1,29 @@
+package com.thealgorithms.maths;
+
+import static com.thealgorithms.maths.GoldbachConjecture.getPrimeSum;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+public class GoldbachConjectureTest {
+ @Test
+ void testValidEvenNumbers() {
+ assertEquals(new GoldbachConjecture.Result(3, 7), getPrimeSum(10)); // 10 = 3 + 7
+ assertEquals(new GoldbachConjecture.Result(5, 7), getPrimeSum(12)); // 12 = 5 + 7
+ assertEquals(new GoldbachConjecture.Result(3, 11), getPrimeSum(14)); // 14 = 3 + 11
+ assertEquals(new GoldbachConjecture.Result(5, 13), getPrimeSum(18)); // 18 = 5 + 13
+ }
+ @Test
+ void testInvalidOddNumbers() {
+ assertThrows(IllegalArgumentException.class, () -> getPrimeSum(7));
+ assertThrows(IllegalArgumentException.class, () -> getPrimeSum(15));
+ }
+ @Test
+ void testLesserThanTwo() {
+ assertThrows(IllegalArgumentException.class, () -> getPrimeSum(1));
+ assertThrows(IllegalArgumentException.class, () -> getPrimeSum(2));
+ assertThrows(IllegalArgumentException.class, () -> getPrimeSum(-5));
+ assertThrows(IllegalArgumentException.class, () -> getPrimeSum(-26));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/maths/MathBuilderTest.java b/src/test/java/com/thealgorithms/maths/MathBuilderTest.java
new file mode 100644
index 000000000000..dc381bfca5d3
--- /dev/null
+++ b/src/test/java/com/thealgorithms/maths/MathBuilderTest.java
@@ -0,0 +1,52 @@
+package com.thealgorithms.maths;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+class MathBuilderTest {
+
+ @Test
+ void simpleMath() {
+ double result = new MathBuilder.Builder(100).add(200).multiply(10).print().divideIf(20, (a, b) -> a % 2 == 0).sqrt().print().ceil().build().get();
+ assertEquals(13, result);
+ }
+
+ @Test
+ void memoryTest() {
+ long result = new MathBuilder.Builder().set(100).sqrt().remember().add(21).recallIf(a -> a < 50, true).mod(2).build().toLong();
+ assertEquals(0, result);
+ }
+
+ @Test
+ void freeFallDistance() {
+ long distance = new MathBuilder.Builder(9.81).multiply(0.5).multiply(5 * 5).round().build().toLong();
+ assertEquals(123, distance); // Expected result: 0.5 * 9.81 * 25 = 122.625 ≈ 123
+ }
+
+ @Test
+ void batchSalaryProcessing() {
+ double[] salaries = {2000, 3000, 4000, 5000};
+ long[] processedSalaries = new long[salaries.length];
+ for (int i = 0; i < salaries.length; i++) {
+ processedSalaries[i] = new MathBuilder.Builder(salaries[i]).addIf(salaries[i] * 0.1, (sal, bonus) -> sal > 2500).multiply(0.92).round().build().toLong();
+ }
+ long[] expectedSalaries = {1840, 3036, 4048, 5060};
+ assertArrayEquals(expectedSalaries, processedSalaries);
+ }
+
+ @Test
+ void parenthesis() {
+ // 10 + (20*5) - 40 + (100 / 10) = 80
+ double result = new MathBuilder.Builder(10).openParenthesis(20).multiply(5).closeParenthesisAndPlus().minus(40).openParenthesis(100).divide(10).closeParenthesisAndPlus().build().get();
+ assertEquals(80, result);
+ }
+
+ @Test
+ void areaOfCircle() {
+ // Radius is 4
+ double area = new MathBuilder.Builder().pi().openParenthesis(4).multiply(4).closeParenthesisAndMultiply().build().get();
+ assertEquals(Math.PI * 4 * 4, area);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/maths/SquareFreeIntegerTest.java b/src/test/java/com/thealgorithms/maths/SquareFreeIntegerTest.java
index d7e16e02602b..5b35ee7bd9d0 100644
--- a/src/test/java/com/thealgorithms/maths/SquareFreeIntegerTest.java
+++ b/src/test/java/com/thealgorithms/maths/SquareFreeIntegerTest.java
@@ -3,6 +3,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import com.thealgorithms.maths.Prime.SquareFreeInteger;
import java.util.List;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/thealgorithms/maths/VampireNumberTest.java b/src/test/java/com/thealgorithms/maths/VampireNumberTest.java
new file mode 100644
index 000000000000..6f331f1252cd
--- /dev/null
+++ b/src/test/java/com/thealgorithms/maths/VampireNumberTest.java
@@ -0,0 +1,32 @@
+package com.thealgorithms.maths;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+class VampireNumberTest {
+ @Test
+ void areVampireNumbers() {
+ Assertions.assertTrue(VampireNumber.isVampireNumber(15, 93, true));
+ Assertions.assertTrue(VampireNumber.isVampireNumber(135, 801, true));
+ Assertions.assertTrue(VampireNumber.isVampireNumber(201, 600, true));
+ }
+
+ @Test
+ void arePseudoVampireNumbers() {
+ Assertions.assertTrue(VampireNumber.isVampireNumber(150, 93, false));
+ Assertions.assertTrue(VampireNumber.isVampireNumber(546, 84, false));
+ Assertions.assertTrue(VampireNumber.isVampireNumber(641, 65, false));
+ }
+
+ @Test
+ void areNotVampireNumbers() {
+ Assertions.assertFalse(VampireNumber.isVampireNumber(51, 39, false));
+ Assertions.assertFalse(VampireNumber.isVampireNumber(51, 39, true));
+ }
+
+ @Test
+ void testSplitIntoSortedDigits() {
+ Assertions.assertEquals("123", VampireNumber.splitIntoSortedDigits(321));
+ Assertions.assertEquals("02234", VampireNumber.splitIntoSortedDigits(20, 324));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/maths/LiouvilleLambdaFunctionTest.java b/src/test/java/com/thealgorithms/maths/prime/LiouvilleLambdaFunctionTest.java
similarity index 94%
rename from src/test/java/com/thealgorithms/maths/LiouvilleLambdaFunctionTest.java
rename to src/test/java/com/thealgorithms/maths/prime/LiouvilleLambdaFunctionTest.java
index a2763047acf0..d32815c0b8a9 100644
--- a/src/test/java/com/thealgorithms/maths/LiouvilleLambdaFunctionTest.java
+++ b/src/test/java/com/thealgorithms/maths/prime/LiouvilleLambdaFunctionTest.java
@@ -1,8 +1,9 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.maths.prime;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import com.thealgorithms.maths.Prime.LiouvilleLambdaFunction;
import org.junit.jupiter.api.Test;
class LiouvilleLambdaFunctionTest {
diff --git a/src/test/java/com/thealgorithms/maths/MillerRabinPrimalityCheckTest.java b/src/test/java/com/thealgorithms/maths/prime/MillerRabinPrimalityCheckTest.java
similarity index 92%
rename from src/test/java/com/thealgorithms/maths/MillerRabinPrimalityCheckTest.java
rename to src/test/java/com/thealgorithms/maths/prime/MillerRabinPrimalityCheckTest.java
index d547cecf24cd..4defcd587758 100644
--- a/src/test/java/com/thealgorithms/maths/MillerRabinPrimalityCheckTest.java
+++ b/src/test/java/com/thealgorithms/maths/prime/MillerRabinPrimalityCheckTest.java
@@ -1,8 +1,9 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.maths.prime;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import com.thealgorithms.maths.Prime.MillerRabinPrimalityCheck;
import org.junit.jupiter.api.Test;
class MillerRabinPrimalityCheckTest {
diff --git a/src/test/java/com/thealgorithms/maths/MobiusFunctionTest.java b/src/test/java/com/thealgorithms/maths/prime/MobiusFunctionTest.java
similarity index 96%
rename from src/test/java/com/thealgorithms/maths/MobiusFunctionTest.java
rename to src/test/java/com/thealgorithms/maths/prime/MobiusFunctionTest.java
index f3a6514ce633..734d02477ba2 100644
--- a/src/test/java/com/thealgorithms/maths/MobiusFunctionTest.java
+++ b/src/test/java/com/thealgorithms/maths/prime/MobiusFunctionTest.java
@@ -1,8 +1,9 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.maths.prime;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import com.thealgorithms.maths.Prime.MobiusFunction;
import org.junit.jupiter.api.Test;
class MobiusFunctionTest {
diff --git a/src/test/java/com/thealgorithms/maths/PrimeCheckTest.java b/src/test/java/com/thealgorithms/maths/prime/PrimeCheckTest.java
similarity index 89%
rename from src/test/java/com/thealgorithms/maths/PrimeCheckTest.java
rename to src/test/java/com/thealgorithms/maths/prime/PrimeCheckTest.java
index c3e1634c51fe..2182bcd9cb16 100644
--- a/src/test/java/com/thealgorithms/maths/PrimeCheckTest.java
+++ b/src/test/java/com/thealgorithms/maths/prime/PrimeCheckTest.java
@@ -1,5 +1,6 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.maths.prime;
+import com.thealgorithms.maths.Prime.PrimeCheck;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/thealgorithms/maths/PrimeFactorizationTest.java b/src/test/java/com/thealgorithms/maths/prime/PrimeFactorizationTest.java
similarity index 93%
rename from src/test/java/com/thealgorithms/maths/PrimeFactorizationTest.java
rename to src/test/java/com/thealgorithms/maths/prime/PrimeFactorizationTest.java
index 6994379d736a..79d685726261 100644
--- a/src/test/java/com/thealgorithms/maths/PrimeFactorizationTest.java
+++ b/src/test/java/com/thealgorithms/maths/prime/PrimeFactorizationTest.java
@@ -1,7 +1,8 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.maths.prime;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import com.thealgorithms.maths.Prime.PrimeFactorization;
import java.util.List;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
diff --git a/src/test/java/com/thealgorithms/misc/InverseOfMatrixTest.java b/src/test/java/com/thealgorithms/matrix/InverseOfMatrixTest.java
similarity index 96%
rename from src/test/java/com/thealgorithms/misc/InverseOfMatrixTest.java
rename to src/test/java/com/thealgorithms/matrix/InverseOfMatrixTest.java
index 2f20de444315..930fb377cd32 100644
--- a/src/test/java/com/thealgorithms/misc/InverseOfMatrixTest.java
+++ b/src/test/java/com/thealgorithms/matrix/InverseOfMatrixTest.java
@@ -1,5 +1,4 @@
-package com.thealgorithms.misc;
-
+package com.thealgorithms.matrix;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import java.util.stream.Stream;
diff --git a/src/test/java/com/thealgorithms/maths/MatrixRankTest.java b/src/test/java/com/thealgorithms/matrix/MatrixRankTest.java
similarity index 98%
rename from src/test/java/com/thealgorithms/maths/MatrixRankTest.java
rename to src/test/java/com/thealgorithms/matrix/MatrixRankTest.java
index 415b84ec43f8..33a0196b7bf7 100644
--- a/src/test/java/com/thealgorithms/maths/MatrixRankTest.java
+++ b/src/test/java/com/thealgorithms/matrix/MatrixRankTest.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.matrix;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
diff --git a/src/test/java/com/thealgorithms/misc/MatrixTransposeTest.java b/src/test/java/com/thealgorithms/matrix/MatrixTransposeTest.java
similarity index 98%
rename from src/test/java/com/thealgorithms/misc/MatrixTransposeTest.java
rename to src/test/java/com/thealgorithms/matrix/MatrixTransposeTest.java
index cf668807b819..0457f31418cf 100644
--- a/src/test/java/com/thealgorithms/misc/MatrixTransposeTest.java
+++ b/src/test/java/com/thealgorithms/matrix/MatrixTransposeTest.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.misc;
+package com.thealgorithms.matrix;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
diff --git a/src/test/java/com/thealgorithms/maths/MatrixUtilTest.java b/src/test/java/com/thealgorithms/matrix/MatrixUtilTest.java
similarity index 96%
rename from src/test/java/com/thealgorithms/maths/MatrixUtilTest.java
rename to src/test/java/com/thealgorithms/matrix/MatrixUtilTest.java
index b954e6ff7511..78947b1e70cb 100644
--- a/src/test/java/com/thealgorithms/maths/MatrixUtilTest.java
+++ b/src/test/java/com/thealgorithms/matrix/MatrixUtilTest.java
@@ -1,7 +1,8 @@
-package com.thealgorithms.maths;
+package com.thealgorithms.matrix;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import com.thealgorithms.matrix.utils.MatrixUtil;
import java.math.BigDecimal;
import java.util.Objects;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/com/thealgorithms/misc/MedianOfMatrixTest.java b/src/test/java/com/thealgorithms/matrix/MedianOfMatrixTest.java
similarity index 96%
rename from src/test/java/com/thealgorithms/misc/MedianOfMatrixTest.java
rename to src/test/java/com/thealgorithms/matrix/MedianOfMatrixTest.java
index 19bc66857ae6..db66bb2d187b 100644
--- a/src/test/java/com/thealgorithms/misc/MedianOfMatrixTest.java
+++ b/src/test/java/com/thealgorithms/matrix/MedianOfMatrixTest.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.misc;
+package com.thealgorithms.matrix;
import static org.junit.jupiter.api.Assertions.assertEquals;
diff --git a/src/test/java/com/thealgorithms/matrix/MirrorOfMatrixTest.java b/src/test/java/com/thealgorithms/matrix/MirrorOfMatrixTest.java
new file mode 100644
index 000000000000..2e4370922370
--- /dev/null
+++ b/src/test/java/com/thealgorithms/matrix/MirrorOfMatrixTest.java
@@ -0,0 +1,53 @@
+package com.thealgorithms.matrix;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+
+class MirrorOfMatrixTest {
+
+ @Test
+ void testMirrorMatrixRegularMatrix() {
+ double[][] originalMatrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
+ double[][] expectedMirrorMatrix = {{3, 2, 1}, {6, 5, 4}, {9, 8, 7}};
+ double[][] mirroredMatrix = MirrorOfMatrix.mirrorMatrix(originalMatrix);
+ assertArrayEquals(expectedMirrorMatrix, mirroredMatrix);
+ }
+
+ @Test
+ void testMirrorMatrixEmptyMatrix() {
+ double[][] originalMatrix = {};
+ Exception e = assertThrows(IllegalArgumentException.class, () -> MirrorOfMatrix.mirrorMatrix(originalMatrix));
+ assertEquals("The input matrix cannot be empty", e.getMessage());
+ }
+
+ @Test
+ void testMirrorMatrixSingleElementMatrix() {
+ double[][] originalMatrix = {{42}};
+ double[][] expectedMirrorMatrix = {{42}};
+ double[][] mirroredMatrix = MirrorOfMatrix.mirrorMatrix(originalMatrix);
+ assertArrayEquals(expectedMirrorMatrix, mirroredMatrix);
+ }
+
+ @Test
+ void testMirrorMatrixMultipleRowsOneColumnMatrix() {
+ double[][] originalMatrix = {{1}, {2}, {3}, {4}};
+ double[][] expectedMirrorMatrix = {{1}, {2}, {3}, {4}};
+ double[][] mirroredMatrix = MirrorOfMatrix.mirrorMatrix(originalMatrix);
+ assertArrayEquals(expectedMirrorMatrix, mirroredMatrix);
+ }
+
+ @Test
+ void testMirrorMatrixNullInput() {
+ double[][] originalMatrix = null;
+ Exception e = assertThrows(IllegalArgumentException.class, () -> MirrorOfMatrix.mirrorMatrix(originalMatrix));
+ assertEquals("The input matrix cannot be null", e.getMessage());
+ }
+
+ @Test
+ void testMirrorMatrixThrows() {
+ assertThrows(IllegalArgumentException.class, () -> MirrorOfMatrix.mirrorMatrix(new double[][] {{1}, {2, 3}}));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/matrix/SolveSystemTest.java b/src/test/java/com/thealgorithms/matrix/SolveSystemTest.java
new file mode 100644
index 000000000000..c8d289bd8339
--- /dev/null
+++ b/src/test/java/com/thealgorithms/matrix/SolveSystemTest.java
@@ -0,0 +1,21 @@
+package com.thealgorithms.matrix;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class SolveSystemTest {
+
+ @ParameterizedTest
+ @MethodSource({"matrixGenerator"})
+ void solveSystem(double[][] matrix, double[] constants, double[] solution) {
+ double[] expected = SolveSystem.solveSystem(matrix, constants);
+ assertArrayEquals(expected, solution, 1.0E-10, "Solution does not match expected");
+ }
+ private static Stream matrixGenerator() {
+ return Stream.of(Arguments.of(new double[][] {{-5, 8, -4}, {0, 6, 3}, {0, 0, -4}}, new double[] {38, -9, 20}, new double[] {-2, 1, -5}), Arguments.of(new double[][] {{-2, -1, -1}, {3, 4, 1}, {3, 6, 5}}, new double[] {-11, 19, 43}, new double[] {2, 2, 5}));
+ }
+}
diff --git a/src/test/java/com/thealgorithms/matrix/TestPrintMatrixInSpiralOrder.java b/src/test/java/com/thealgorithms/matrix/TestPrintMatrixInSpiralOrder.java
new file mode 100644
index 000000000000..bb415a5861a8
--- /dev/null
+++ b/src/test/java/com/thealgorithms/matrix/TestPrintMatrixInSpiralOrder.java
@@ -0,0 +1,26 @@
+package com.thealgorithms.matrix;
+
+import static org.junit.jupiter.api.Assertions.assertIterableEquals;
+
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+public class TestPrintMatrixInSpiralOrder {
+ @Test
+ public void testOne() {
+ int[][] matrix = {{3, 4, 5, 6, 7}, {8, 9, 10, 11, 12}, {14, 15, 16, 17, 18}, {23, 24, 25, 26, 27}, {30, 31, 32, 33, 34}};
+ var printClass = new PrintAMatrixInSpiralOrder();
+ List res = printClass.print(matrix, matrix.length, matrix[0].length);
+ List list = List.of(3, 4, 5, 6, 7, 12, 18, 27, 34, 33, 32, 31, 30, 23, 14, 8, 9, 10, 11, 17, 26, 25, 24, 15, 16);
+ assertIterableEquals(res, list);
+ }
+
+ @Test
+ public void testTwo() {
+ int[][] matrix = {{2, 2}};
+ var printClass = new PrintAMatrixInSpiralOrder();
+ List res = printClass.print(matrix, matrix.length, matrix[0].length);
+ List list = List.of(2, 2);
+ assertIterableEquals(res, list);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/misc/MirrorOfMatrixTest.java b/src/test/java/com/thealgorithms/misc/MirrorOfMatrixTest.java
deleted file mode 100644
index 0da0cf0f804a..000000000000
--- a/src/test/java/com/thealgorithms/misc/MirrorOfMatrixTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.thealgorithms.misc;
-
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-import org.junit.jupiter.api.Test;
-
-class MirrorOfMatrixTest {
-
- @Test
- void testMirrorMatrixRegularMatrix() {
- int[][] originalMatrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
- int[][] expectedMirrorMatrix = {{3, 2, 1}, {6, 5, 4}, {9, 8, 7}};
- int[][] mirroredMatrix = MirrorOfMatrix.mirrorMatrix(originalMatrix);
- assertArrayEquals(expectedMirrorMatrix, mirroredMatrix);
- }
-
- @Test
- void testMirrorMatrixEmptyMatrix() {
- int[][] originalMatrix = {};
- int[][] expectedMirrorMatrix = {};
- int[][] mirroredMatrix = MirrorOfMatrix.mirrorMatrix(originalMatrix);
- assertArrayEquals(expectedMirrorMatrix, mirroredMatrix);
- }
-
- @Test
- void testMirrorMatrixSingleElementMatrix() {
- int[][] originalMatrix = {{42}};
- int[][] expectedMirrorMatrix = {{42}};
- int[][] mirroredMatrix = MirrorOfMatrix.mirrorMatrix(originalMatrix);
- assertArrayEquals(expectedMirrorMatrix, mirroredMatrix);
- }
-
- @Test
- void testMirrorMatrixMultipleRowsOneColumnMatrix() {
- int[][] originalMatrix = {{1}, {2}, {3}, {4}};
- int[][] expectedMirrorMatrix = {{1}, {2}, {3}, {4}};
- int[][] mirroredMatrix = MirrorOfMatrix.mirrorMatrix(originalMatrix);
- assertArrayEquals(expectedMirrorMatrix, mirroredMatrix);
- }
-
- @Test
- void testMirrorMatrixNullInput() {
- int[][] originalMatrix = null;
- assertNull(MirrorOfMatrix.mirrorMatrix(originalMatrix));
- }
-
- @Test
- void testMirrotMarixThrows() {
- assertThrows(IllegalArgumentException.class, () -> MirrorOfMatrix.mirrorMatrix(new int[][] {{1}, {2, 3}}));
- }
-}
diff --git a/src/test/java/com/thealgorithms/others/TestPrintMatrixInSpiralOrder.java b/src/test/java/com/thealgorithms/others/TestPrintMatrixInSpiralOrder.java
index 986e72ea45b5..d35d4bb60c73 100644
--- a/src/test/java/com/thealgorithms/others/TestPrintMatrixInSpiralOrder.java
+++ b/src/test/java/com/thealgorithms/others/TestPrintMatrixInSpiralOrder.java
@@ -1,26 +1,26 @@
-package com.thealgorithms.others;
-
-import static org.junit.jupiter.api.Assertions.assertIterableEquals;
-
-import java.util.List;
-import org.junit.jupiter.api.Test;
-
-public class TestPrintMatrixInSpiralOrder {
- @Test
- public void testOne() {
- int[][] matrix = {{3, 4, 5, 6, 7}, {8, 9, 10, 11, 12}, {14, 15, 16, 17, 18}, {23, 24, 25, 26, 27}, {30, 31, 32, 33, 34}};
- var printClass = new PrintAMatrixInSpiralOrder();
- List res = printClass.print(matrix, matrix.length, matrix[0].length);
- List list = List.of(3, 4, 5, 6, 7, 12, 18, 27, 34, 33, 32, 31, 30, 23, 14, 8, 9, 10, 11, 17, 26, 25, 24, 15, 16);
- assertIterableEquals(res, list);
- }
-
- @Test
- public void testTwo() {
- int[][] matrix = {{2, 2}};
- var printClass = new PrintAMatrixInSpiralOrder();
- List res = printClass.print(matrix, matrix.length, matrix[0].length);
- List list = List.of(2, 2);
- assertIterableEquals(res, list);
- }
-}
+package com.thealgorithms.others;
+
+import static org.junit.jupiter.api.Assertions.assertIterableEquals;
+
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+public class TestPrintMatrixInSpiralOrder {
+ @Test
+ public void testOne() {
+ int[][] matrix = {{3, 4, 5, 6, 7}, {8, 9, 10, 11, 12}, {14, 15, 16, 17, 18}, {23, 24, 25, 26, 27}, {30, 31, 32, 33, 34}};
+ var printClass = new PrintAMatrixInSpiralOrder();
+ List res = printClass.print(matrix, matrix.length, matrix[0].length);
+ List list = List.of(3, 4, 5, 6, 7, 12, 18, 27, 34, 33, 32, 31, 30, 23, 14, 8, 9, 10, 11, 17, 26, 25, 24, 15, 16);
+ assertIterableEquals(res, list);
+ }
+
+ @Test
+ public void testTwo() {
+ int[][] matrix = {{2, 2}};
+ var printClass = new PrintAMatrixInSpiralOrder();
+ List res = printClass.print(matrix, matrix.length, matrix[0].length);
+ List list = List.of(2, 2);
+ assertIterableEquals(res, list);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/others/SudokuTest.java b/src/test/java/com/thealgorithms/puzzlesandgames/SudokuTest.java
similarity index 97%
rename from src/test/java/com/thealgorithms/others/SudokuTest.java
rename to src/test/java/com/thealgorithms/puzzlesandgames/SudokuTest.java
index 5018b2768302..7fb96dcf805f 100644
--- a/src/test/java/com/thealgorithms/others/SudokuTest.java
+++ b/src/test/java/com/thealgorithms/puzzlesandgames/SudokuTest.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.others;
+package com.thealgorithms.puzzlesandgames;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
diff --git a/src/test/java/com/thealgorithms/others/TowerOfHanoiTest.java b/src/test/java/com/thealgorithms/puzzlesandgames/TowerOfHanoiTest.java
similarity index 97%
rename from src/test/java/com/thealgorithms/others/TowerOfHanoiTest.java
rename to src/test/java/com/thealgorithms/puzzlesandgames/TowerOfHanoiTest.java
index ca9376dd48eb..42669eb03bb4 100644
--- a/src/test/java/com/thealgorithms/others/TowerOfHanoiTest.java
+++ b/src/test/java/com/thealgorithms/puzzlesandgames/TowerOfHanoiTest.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.others;
+package com.thealgorithms.puzzlesandgames;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
diff --git a/src/test/java/com/thealgorithms/misc/WordBoggleTest.java b/src/test/java/com/thealgorithms/puzzlesandgames/WordBoggleTest.java
similarity index 98%
rename from src/test/java/com/thealgorithms/misc/WordBoggleTest.java
rename to src/test/java/com/thealgorithms/puzzlesandgames/WordBoggleTest.java
index 1d4ed7c5e737..ef5d3c92eb5e 100644
--- a/src/test/java/com/thealgorithms/misc/WordBoggleTest.java
+++ b/src/test/java/com/thealgorithms/puzzlesandgames/WordBoggleTest.java
@@ -1,4 +1,4 @@
-package com.thealgorithms.misc;
+package com.thealgorithms.puzzlesandgames;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
diff --git a/src/test/java/com/thealgorithms/randomized/KargerMinCutTest.java b/src/test/java/com/thealgorithms/randomized/KargerMinCutTest.java
new file mode 100644
index 000000000000..876b6bf45eaf
--- /dev/null
+++ b/src/test/java/com/thealgorithms/randomized/KargerMinCutTest.java
@@ -0,0 +1,114 @@
+package com.thealgorithms.randomized;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+public class KargerMinCutTest {
+
+ @Test
+ public void testSimpleGraph() {
+ // Graph: 0 -- 1
+ Collection nodes = Arrays.asList(0, 1);
+ List edges = List.of(new int[] {0, 1});
+
+ KargerMinCut.KargerOutput result = KargerMinCut.findMinCut(nodes, edges);
+
+ assertEquals(1, result.minCut());
+ assertTrue(result.first().contains(0) || result.first().contains(1));
+ assertTrue(result.second().contains(0) || result.second().contains(1));
+ }
+
+ @Test
+ public void testTriangleGraph() {
+ // Graph: 0 -- 1 -- 2 -- 0
+ Collection nodes = Arrays.asList(0, 1, 2);
+ List edges = List.of(new int[] {0, 1}, new int[] {1, 2}, new int[] {2, 0});
+
+ KargerMinCut.KargerOutput result = KargerMinCut.findMinCut(nodes, edges);
+
+ assertEquals(2, result.minCut());
+ }
+
+ @Test
+ public void testSquareGraph() {
+ // Graph: 0 -- 1
+ // | |
+ // 3 -- 2
+ Collection nodes = Arrays.asList(0, 1, 2, 3);
+ List edges = List.of(new int[] {0, 1}, new int[] {1, 2}, new int[] {2, 3}, new int[] {3, 0});
+
+ KargerMinCut.KargerOutput result = KargerMinCut.findMinCut(nodes, edges);
+
+ assertEquals(2, result.minCut());
+ }
+
+ @Test
+ public void testDisconnectedGraph() {
+ // Graph: 0 -- 1 2 -- 3
+ Collection nodes = Arrays.asList(0, 1, 2, 3);
+ List edges = List.of(new int[] {0, 1}, new int[] {2, 3});
+
+ KargerMinCut.KargerOutput result = KargerMinCut.findMinCut(nodes, edges);
+
+ assertEquals(0, result.minCut());
+ }
+
+ @Test
+ public void testCompleteGraph() {
+ // Complete Graph: 0 -- 1 -- 2 -- 3 (all nodes connected to each other)
+ Collection nodes = Arrays.asList(0, 1, 2, 3);
+ List edges = List.of(new int[] {0, 1}, new int[] {0, 2}, new int[] {0, 3}, new int[] {1, 2}, new int[] {1, 3}, new int[] {2, 3});
+
+ KargerMinCut.KargerOutput result = KargerMinCut.findMinCut(nodes, edges);
+
+ assertEquals(3, result.minCut());
+ }
+
+ @Test
+ public void testSingleNodeGraph() {
+ // Graph: Single node with no edges
+ Collection nodes = List.of(0);
+ List edges = List.of();
+
+ KargerMinCut.KargerOutput result = KargerMinCut.findMinCut(nodes, edges);
+
+ assertEquals(0, result.minCut());
+ assertTrue(result.first().contains(0));
+ assertTrue(result.second().isEmpty());
+ }
+
+ @Test
+ public void testTwoNodesNoEdge() {
+ // Graph: 0 1 (no edges)
+ Collection nodes = Arrays.asList(0, 1);
+ List edges = List.of();
+
+ KargerMinCut.KargerOutput result = KargerMinCut.findMinCut(nodes, edges);
+
+ assertEquals(0, result.minCut());
+ assertTrue(result.first().contains(0) || result.first().contains(1));
+ assertTrue(result.second().contains(0) || result.second().contains(1));
+ }
+
+ @Test
+ public void testComplexGraph() {
+ // Nodes: 0, 1, 2, 3, 4, 5, 6, 7, 8
+ // Edges: Fully connected graph with additional edges for complexity
+ Collection nodes = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8);
+ List edges = List.of(new int[] {0, 1}, new int[] {0, 2}, new int[] {0, 3}, new int[] {0, 4}, new int[] {0, 5}, new int[] {1, 2}, new int[] {1, 3}, new int[] {1, 4}, new int[] {1, 5}, new int[] {1, 6}, new int[] {2, 3}, new int[] {2, 4}, new int[] {2, 5}, new int[] {2, 6},
+ new int[] {2, 7}, new int[] {3, 4}, new int[] {3, 5}, new int[] {3, 6}, new int[] {3, 7}, new int[] {3, 8}, new int[] {4, 5}, new int[] {4, 6}, new int[] {4, 7}, new int[] {4, 8}, new int[] {5, 6}, new int[] {5, 7}, new int[] {5, 8}, new int[] {6, 7}, new int[] {6, 8}, new int[] {7, 8},
+ new int[] {0, 6}, new int[] {1, 7}, new int[] {2, 8});
+
+ KargerMinCut.KargerOutput result = KargerMinCut.findMinCut(nodes, edges);
+
+ // The exact minimum cut value depends on the randomization, but it should be consistent
+ // for this graph structure. For a fully connected graph, the minimum cut is typically
+ // determined by the smallest number of edges connecting two partitions.
+ assertTrue(result.minCut() > 0);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/randomized/ReservoirSamplingTest.java b/src/test/java/com/thealgorithms/randomized/ReservoirSamplingTest.java
new file mode 100644
index 000000000000..0c6061fcde2a
--- /dev/null
+++ b/src/test/java/com/thealgorithms/randomized/ReservoirSamplingTest.java
@@ -0,0 +1,45 @@
+package com.thealgorithms.randomized;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+public class ReservoirSamplingTest {
+
+ @Test
+ public void testSampleSizeEqualsStreamLength() {
+ int[] stream = {1, 2, 3, 4, 5};
+ int sampleSize = 5;
+
+ List result = ReservoirSampling.sample(stream, sampleSize);
+
+ assertEquals(sampleSize, result.size());
+ assertTrue(Arrays.stream(stream).allMatch(result::contains));
+ }
+
+ @Test
+ public void testSampleSizeLessThanStreamLength() {
+ int[] stream = {10, 20, 30, 40, 50, 60};
+ int sampleSize = 3;
+
+ List result = ReservoirSampling.sample(stream, sampleSize);
+
+ assertEquals(sampleSize, result.size());
+ for (int value : result) {
+ assertTrue(Arrays.stream(stream).anyMatch(x -> x == value));
+ }
+ }
+
+ @Test
+ public void testSampleSizeGreaterThanStreamLengthThrowsException() {
+ int[] stream = {1, 2, 3};
+
+ Exception exception = assertThrows(IllegalArgumentException.class, () -> ReservoirSampling.sample(stream, 5));
+
+ assertEquals("Sample size cannot exceed stream size.", exception.getMessage());
+ }
+}
diff --git a/src/test/java/com/thealgorithms/searches/TestSearchInARowAndColWiseSortedMatrix.java b/src/test/java/com/thealgorithms/searches/TestSearchInARowAndColWiseSortedMatrix.java
index 014fb4bd24af..a56f79670cf3 100644
--- a/src/test/java/com/thealgorithms/searches/TestSearchInARowAndColWiseSortedMatrix.java
+++ b/src/test/java/com/thealgorithms/searches/TestSearchInARowAndColWiseSortedMatrix.java
@@ -1,27 +1,25 @@
-package com.thealgorithms.searches;
-
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-
-import org.junit.jupiter.api.Test;
-
-public class TestSearchInARowAndColWiseSortedMatrix {
- @Test
- public void searchItem() {
- int[][] matrix = {{3, 4, 5, 6, 7}, {8, 9, 10, 11, 12}, {14, 15, 16, 17, 18}, {23, 24, 25, 26, 27}, {30, 31, 32, 33, 34}};
-
- var test = new SearchInARowAndColWiseSortedMatrix();
- int[] res = test.search(matrix, 16);
- int[] expectedResult = {2, 2};
- assertArrayEquals(expectedResult, res);
- }
-
- @Test
- public void notFound() {
- int[][] matrix = {{3, 4, 5, 6, 7}, {8, 9, 10, 11, 12}, {14, 15, 16, 17, 18}, {23, 24, 25, 26, 27}, {30, 31, 32, 33, 34}};
-
- var test = new SearchInARowAndColWiseSortedMatrix();
- int[] res = test.search(matrix, 96);
- int[] expectedResult = {-1, -1};
- assertArrayEquals(expectedResult, res);
- }
-}
+package com.thealgorithms.searches;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class TestSearchInARowAndColWiseSortedMatrix {
+ @Test
+ public void searchItem() {
+ int[][] matrix = {{3, 4, 5, 6, 7}, {8, 9, 10, 11, 12}, {14, 15, 16, 17, 18}, {23, 24, 25, 26, 27}, {30, 31, 32, 33, 34}};
+ var test = new SearchInARowAndColWiseSortedMatrix();
+ int[] res = test.search(matrix, 16);
+ int[] expectedResult = {2, 2};
+ assertArrayEquals(expectedResult, res);
+ }
+
+ @Test
+ public void notFound() {
+ int[][] matrix = {{3, 4, 5, 6, 7}, {8, 9, 10, 11, 12}, {14, 15, 16, 17, 18}, {23, 24, 25, 26, 27}, {30, 31, 32, 33, 34}};
+ var test = new SearchInARowAndColWiseSortedMatrix();
+ int[] res = test.search(matrix, 96);
+ int[] expectedResult = {-1, -1};
+ assertArrayEquals(expectedResult, res);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/sorts/DarkSortTest.java b/src/test/java/com/thealgorithms/sorts/DarkSortTest.java
new file mode 100644
index 000000000000..1df077e2ad74
--- /dev/null
+++ b/src/test/java/com/thealgorithms/sorts/DarkSortTest.java
@@ -0,0 +1,74 @@
+package com.thealgorithms.sorts;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.junit.jupiter.api.Test;
+
+class DarkSortTest {
+
+ @Test
+ void testSortWithIntegers() {
+ Integer[] unsorted = {5, 3, 8, 6, 2, 7, 4, 1};
+ Integer[] expected = {1, 2, 3, 4, 5, 6, 7, 8};
+
+ DarkSort darkSort = new DarkSort();
+ Integer[] sorted = darkSort.sort(unsorted);
+
+ assertArrayEquals(expected, sorted);
+ }
+
+ @Test
+ void testEmptyArray() {
+ Integer[] unsorted = {};
+ Integer[] expected = {};
+
+ DarkSort darkSort = new DarkSort();
+ Integer[] sorted = darkSort.sort(unsorted);
+
+ assertArrayEquals(expected, sorted);
+ }
+
+ @Test
+ void testSingleElementArray() {
+ Integer[] unsorted = {42};
+ Integer[] expected = {42};
+
+ DarkSort darkSort = new DarkSort();
+ Integer[] sorted = darkSort.sort(unsorted);
+
+ assertArrayEquals(expected, sorted);
+ }
+
+ @Test
+ void testAlreadySortedArray() {
+ Integer[] unsorted = {1, 2, 3, 4, 5};
+ Integer[] expected = {1, 2, 3, 4, 5};
+
+ DarkSort darkSort = new DarkSort();
+ Integer[] sorted = darkSort.sort(unsorted);
+
+ assertArrayEquals(expected, sorted);
+ }
+
+ @Test
+ void testDuplicateElementsArray() {
+ Integer[] unsorted = {4, 2, 7, 2, 1, 4};
+ Integer[] expected = {1, 2, 2, 4, 4, 7};
+
+ DarkSort darkSort = new DarkSort();
+ Integer[] sorted = darkSort.sort(unsorted);
+
+ assertArrayEquals(expected, sorted);
+ }
+
+ @Test
+ void testNullArray() {
+ Integer[] unsorted = null;
+
+ DarkSort darkSort = new DarkSort();
+ Integer[] sorted = darkSort.sort(unsorted);
+
+ assertNull(sorted, "Sorting a null array should return null");
+ }
+}
diff --git a/src/test/java/com/thealgorithms/strings/ReverseStringTest.java b/src/test/java/com/thealgorithms/strings/ReverseStringTest.java
index 501f702976ec..08f5fb586d82 100644
--- a/src/test/java/com/thealgorithms/strings/ReverseStringTest.java
+++ b/src/test/java/com/thealgorithms/strings/ReverseStringTest.java
@@ -25,4 +25,10 @@ public void testReverseString(String input, String expectedOutput) {
public void testReverseString2(String input, String expectedOutput) {
assertEquals(expectedOutput, ReverseString.reverse2(input));
}
+
+ @ParameterizedTest
+ @MethodSource("testCases")
+ public void testReverseString3(String input, String expectedOutput) {
+ assertEquals(expectedOutput, ReverseString.reverse3(input));
+ }
}
diff --git a/src/test/java/com/thealgorithms/strings/zigZagPattern/ZigZagPatternTest.java b/src/test/java/com/thealgorithms/strings/zigZagPattern/ZigZagPatternTest.java
index 518bfab80f08..2cbbfe3d2dd8 100644
--- a/src/test/java/com/thealgorithms/strings/zigZagPattern/ZigZagPatternTest.java
+++ b/src/test/java/com/thealgorithms/strings/zigZagPattern/ZigZagPatternTest.java
@@ -6,10 +6,14 @@
public class ZigZagPatternTest {
@Test
- public void palindrome() {
+ public void testZigZagPattern() {
String input1 = "HelloWorldFromJava";
String input2 = "javaIsAProgrammingLanguage";
Assertions.assertEquals(ZigZagPattern.encode(input1, 4), "HooeWrrmalolFJvlda");
Assertions.assertEquals(ZigZagPattern.encode(input2, 4), "jAaLgasPrmgaaevIrgmnnuaoig");
+ // Edge cases
+ Assertions.assertEquals("ABC", ZigZagPattern.encode("ABC", 1)); // Single row
+ Assertions.assertEquals("A", ZigZagPattern.encode("A", 2)); // numRows > length of string
+ Assertions.assertEquals("", ZigZagPattern.encode("", 3)); // Empty string
}
}
diff --git a/src/test/java/com/thealgorithms/tree/HeavyLightDecompositionTest.java b/src/test/java/com/thealgorithms/tree/HeavyLightDecompositionTest.java
new file mode 100644
index 000000000000..29189290e1d4
--- /dev/null
+++ b/src/test/java/com/thealgorithms/tree/HeavyLightDecompositionTest.java
@@ -0,0 +1,69 @@
+package com.thealgorithms.tree;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class HeavyLightDecompositionTest {
+
+ private HeavyLightDecomposition hld;
+ private final int[] values = {0, 10, 20, 30, 40, 50};
+
+ /**
+ * Initializes the test environment with a predefined tree structure and values.
+ */
+ @BeforeEach
+ void setUp() {
+ hld = new HeavyLightDecomposition(5);
+ hld.addEdge(1, 2);
+ hld.addEdge(1, 3);
+ hld.addEdge(2, 4);
+ hld.addEdge(2, 5);
+ hld.initialize(1, values);
+ }
+
+ /**
+ * Verifies that the tree initializes successfully without errors.
+ */
+ @Test
+ void testBasicTreeInitialization() {
+ assertTrue(true, "Basic tree structure initialized successfully");
+ }
+
+ /**
+ * Tests the maximum value query in the path between nodes.
+ */
+ @Test
+ void testQueryMaxInPath() {
+ assertEquals(50, hld.queryMaxInPath(4, 5), "Max value in path (4,5) should be 50");
+ assertEquals(30, hld.queryMaxInPath(3, 2), "Max value in path (3,2) should be 30");
+ }
+
+ /**
+ * Tests updating a node's value and ensuring it is reflected in queries.
+ */
+ @Test
+ void testUpdateNodeValue() {
+ hld.updateSegmentTree(1, 0, hld.getPositionIndex() - 1, hld.getPosition(4), 100);
+ assertEquals(100, hld.queryMaxInPath(4, 5), "Updated value should be reflected in query");
+ }
+
+ /**
+ * Tests the maximum value query in a skewed tree structure.
+ */
+ @Test
+ void testSkewedTreeMaxQuery() {
+ assertEquals(40, hld.queryMaxInPath(1, 4), "Max value in skewed tree (1,4) should be 40");
+ }
+
+ /**
+ * Ensures query handles cases where u is a deeper node correctly.
+ */
+ @Test
+ void testDepthSwapInPathQuery() {
+ assertEquals(50, hld.queryMaxInPath(5, 2), "Query should handle depth swap correctly");
+ assertEquals(40, hld.queryMaxInPath(4, 1), "Query should handle swapped nodes correctly and return max value");
+ }
+}