Date: Fri, 13 Oct 2023 01:43:32 +0530
Subject: [PATCH 0047/1338] Update BinarySearch (#4747)
---
.../searches/PerfectBinarySearch.java | 62 +++++++++++++------
.../searches/PerfectBinarySearchTest.java | 43 +++++++++++++
2 files changed, 87 insertions(+), 18 deletions(-)
create mode 100644 src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java
diff --git a/src/main/java/com/thealgorithms/searches/PerfectBinarySearch.java b/src/main/java/com/thealgorithms/searches/PerfectBinarySearch.java
index bfeb5efc3a62..495e2e41bc5b 100644
--- a/src/main/java/com/thealgorithms/searches/PerfectBinarySearch.java
+++ b/src/main/java/com/thealgorithms/searches/PerfectBinarySearch.java
@@ -1,28 +1,54 @@
package com.thealgorithms.searches;
-class PerfectBinarySearch {
+import com.thealgorithms.devutils.searches.SearchAlgorithm;
- static int binarySearch(int[] arr, int target) {
- int low = 0;
- int high = arr.length - 1;
+/**
+ * Binary search is one of the most popular algorithms The algorithm finds the
+ * position of a target value within a sorted array
+ *
+ *
+ * Worst-case performance O(log n) Best-case performance O(1) Average
+ * performance O(log n) Worst-case space complexity O(1)
+ *
+ * @author D Sunil (https://github.com/sunilnitdgp)
+ * @see SearchAlgorithm
+ */
- while (low <= high) {
- int mid = (low + high) / 2;
+public class PerfectBinarySearch implements SearchAlgorithm {
- if (arr[mid] == target) {
- return mid;
- } else if (arr[mid] > target) {
- high = mid - 1;
+ /**
+ * @param array is an array where the element should be found
+ * @param key is an element which should be found
+ * @param is any comparable type
+ * @return index of the element
+ */
+ @Override
+ public > int find(T[] array, T key) {
+ return search(array, key, 0, array.length - 1);
+ }
+
+ /**
+ * This method implements the Generic Binary Search iteratively.
+ *
+ * @param array The array to make the binary search
+ * @param key The number you are looking for
+ * @return the location of the key, or -1 if not found
+ */
+ private static > int search(T[] array, T key, int left, int right) {
+ while (left <= right) {
+ int median = (left + right) >>> 1;
+ int comp = key.compareTo(array[median]);
+
+ if (comp == 0) {
+ return median; // Key found
+ }
+
+ if (comp < 0) {
+ right = median - 1; // Adjust the right bound
} else {
- low = mid + 1;
+ left = median + 1; // Adjust the left bound
}
}
- return -1;
- }
-
- public static void main(String[] args) {
- int[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
- assert PerfectBinarySearch.binarySearch(array, -1) == -1;
- assert PerfectBinarySearch.binarySearch(array, 11) == -1;
+ return -1; // Key not found
}
}
diff --git a/src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java b/src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java
new file mode 100644
index 000000000000..0ba0b03b33b4
--- /dev/null
+++ b/src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java
@@ -0,0 +1,43 @@
+import static org.junit.jupiter.api.Assertions.*;
+
+import com.thealgorithms.searches.PerfectBinarySearch;
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author D Sunil (https://github.com/sunilnitdgp)
+ * @see PerfectBinarySearch
+ */
+public class PerfectBinarySearchTest {
+
+ @Test
+ public void testIntegerBinarySearch() {
+ Integer[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+ PerfectBinarySearch binarySearch = new PerfectBinarySearch<>();
+
+ // Test cases for elements present in the array
+ assertEquals(0, binarySearch.find(array, 1)); // First element
+ assertEquals(4, binarySearch.find(array, 5)); // Middle element
+ assertEquals(9, binarySearch.find(array, 10)); // Last element
+ assertEquals(6, binarySearch.find(array, 7)); // Element in the middle
+
+ // Test cases for elements not in the array
+ assertEquals(-1, binarySearch.find(array, 0)); // Element before the array
+ assertEquals(-1, binarySearch.find(array, 11)); // Element after the array
+ assertEquals(-1, binarySearch.find(array, 100)); // Element not in the array
+ }
+
+ @Test
+ public void testStringBinarySearch() {
+ String[] array = {"apple", "banana", "cherry", "date", "fig"};
+ PerfectBinarySearch binarySearch = new PerfectBinarySearch<>();
+
+ // Test cases for elements not in the array
+ assertEquals(-1, binarySearch.find(array, "apricot")); // Element not in the array
+ assertEquals(-1, binarySearch.find(array, "bananaa")); // Element not in the array
+
+ // Test cases for elements present in the array
+ assertEquals(0, binarySearch.find(array, "apple")); // First element
+ assertEquals(2, binarySearch.find(array, "cherry")); // Middle element
+ assertEquals(4, binarySearch.find(array, "fig")); // Last element
+ }
+}
From 24a82230626e986392bcba7dc86b80118aefcdc3 Mon Sep 17 00:00:00 2001
From: Pronay Debnath
Date: Sat, 14 Oct 2023 00:53:30 +0530
Subject: [PATCH 0048/1338] Added [FEATURE REQUEST] Golden Ration formula to
find Nth Fibonacci number #4505 (#4513)
* Create FibonacciNumber.java
* Update FibonacciNumber.java
* Update FibonacciNumber.java
* Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update FibonacciNumber.java
* Update FibonacciNumber.java
* Update FibonacciNumber.java
* Update FibonacciNumber.java
* Create FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumber.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update FibonacciNumber.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumber.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Delete src/main/java/com/thealgorithms/maths/FibonacciNumberTest.java
* Create FibonacciNumberTest.java
* Update FibonacciNumber.java
* Update FibonacciNumberTest.java
* Update FibonacciNumber.java
* Update FibonacciNumber.java
* Update FibonacciNumber.java
* Update FibonacciNumber.java
* Update FibonacciNumberTest.java
* Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Create FibonacciCalculator.java
* Update FibonacciNumberTest.java
* Update and rename FibonacciCalculator.java to FibCalc.java
* Update FibonacciNumberTest.java
* Update FibCalc.java
* Update FibonacciNumber.java
* Delete src/test/java/com/thealgorithms/maths/FibCalc.java
* Create FibCalc.java
* Update FibonacciNumberTest.java
* Update FibCalc.java
* Update FibonacciNumberTest.java
* Update FibonacciNumber.java
* Update FibonacciNumberTest.java
* Update FibonacciNumber.java
* Update FibonacciNumber.java
* Update FibonacciNumber.java
* Update FibonacciNumber.java
* Update FibonacciNumberTest.java
* Update FibonacciNumber.java
* fix: use proper name
* fix: use proper class name
* tests: add `returnsCorrectValues`
* Update and rename FibCalc.java to Fibonacci.java
* Update Fibonacci.java
* Update FibonacciNumber.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update Fibonacci.java
* Update FibonacciNumber.java
* Update and rename FibCalcTest.java to FibonacciTest.java
* Update FibonacciNumber.java
* Update Fibonacci.java
* Update Fibonacci.java
* Update Fibonacci.java
* Update FibonacciTest.java
* Update Fibonacci.java
* Update src/main/java/com/thealgorithms/maths/Fibonacci.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update FibonacciTest.java
* Update FibonacciNumberTest.java
* Update FibonacciNumberTest.java
* Update FibonacciTest.java
* Update src/main/java/com/thealgorithms/maths/Fibonacci.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/test/java/com/thealgorithms/maths/FibonacciTest.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/main/java/com/thealgorithms/maths/Fibonacci.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/main/java/com/thealgorithms/maths/FibonacciNumber.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/test/java/com/thealgorithms/maths/FibonacciNumberTest.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update FibonacciNumber.java
* Update FibonacciNumber.java
* Update Fibonacci.java
* Update FibonacciNumber.java
* Update and rename FibonacciNumber.java to FibonacciNumberGoldenRation.java
* Update and rename FibonacciNumberTest.java to FibonacciNumberGoldenRationTest.java
* Update Fibonacci.java
* Update FibonacciNumberGoldenRation.java
* Update FibonacciNumberGoldenRationTest.java
* Update FibonacciTest.java
* Update Fibonacci.java
* Update FibonacciNumberGoldenRationTest.java
* Update FibonacciNumberGoldenRationTest.java
* Update FibonacciNumberGoldenRation.java
* Update FibonacciNumberGoldenRation.java
* Update FibonacciNumberGoldenRationTest.java
* Update FibonacciNumberGoldenRationTest.java
* Update src/main/java/com/thealgorithms/maths/FibonacciNumberGoldenRation.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update and rename Fibonacci.java to FibonacciLoop.java
* Update FibonacciNumberGoldenRation.java
* Update FibonacciNumberGoldenRationTest.java
* Update and rename FibonacciTest.java to FibonacciLoopTest.java
* Update FibonacciLoop.java
* Update FibonacciLoop.java
* Update FibonacciNumberGoldenRation.java
* docs: add missing dot
---------
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Co-authored-by: vil02
---
.../thealgorithms/maths/FibonacciLoop.java | 41 +++++++++++++++
.../maths/FibonacciNumberGoldenRation.java | 50 +++++++++++++++++++
.../maths/FibonacciLoopTest.java | 36 +++++++++++++
.../FibonacciNumberGoldenRationTest.java | 29 +++++++++++
4 files changed, 156 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/maths/FibonacciLoop.java
create mode 100644 src/main/java/com/thealgorithms/maths/FibonacciNumberGoldenRation.java
create mode 100644 src/test/java/com/thealgorithms/maths/FibonacciLoopTest.java
create mode 100644 src/test/java/com/thealgorithms/maths/FibonacciNumberGoldenRationTest.java
diff --git a/src/main/java/com/thealgorithms/maths/FibonacciLoop.java b/src/main/java/com/thealgorithms/maths/FibonacciLoop.java
new file mode 100644
index 000000000000..de23a4305c3f
--- /dev/null
+++ b/src/main/java/com/thealgorithms/maths/FibonacciLoop.java
@@ -0,0 +1,41 @@
+package com.thealgorithms.maths;
+
+import java.math.BigInteger;
+
+/**
+ * This class provides methods for calculating Fibonacci numbers using BigInteger for large values of 'n'.
+ */
+public final class FibonacciLoop {
+
+ private FibonacciLoop() {
+ // Private constructor to prevent instantiation of this utility class.
+ }
+
+ /**
+ * Calculates the nth Fibonacci number.
+ *
+ * @param n The index of the Fibonacci number to calculate.
+ * @return The nth Fibonacci number as a BigInteger.
+ * @throws IllegalArgumentException if the input 'n' is a negative integer.
+ */
+ public static BigInteger compute(final int n) {
+ if (n < 0) {
+ throw new IllegalArgumentException("Input 'n' must be a non-negative integer.");
+ }
+
+ if (n <= 1) {
+ return BigInteger.valueOf(n);
+ }
+
+ BigInteger prev = BigInteger.ZERO;
+ BigInteger current = BigInteger.ONE;
+
+ for (int i = 2; i <= n; i++) {
+ BigInteger next = prev.add(current);
+ prev = current;
+ current = next;
+ }
+
+ return current;
+ }
+}
diff --git a/src/main/java/com/thealgorithms/maths/FibonacciNumberGoldenRation.java b/src/main/java/com/thealgorithms/maths/FibonacciNumberGoldenRation.java
new file mode 100644
index 000000000000..4df37a40f541
--- /dev/null
+++ b/src/main/java/com/thealgorithms/maths/FibonacciNumberGoldenRation.java
@@ -0,0 +1,50 @@
+package com.thealgorithms.maths;
+
+/**
+ * This class provides methods for calculating Fibonacci numbers using Binet's formula.
+ * Binet's formula is based on the golden ratio and allows computing Fibonacci numbers efficiently.
+ *
+ * @see Binet's formula on Wikipedia
+ */
+public final class FibonacciNumberGoldenRation {
+ private FibonacciNumberGoldenRation() {
+ // Private constructor to prevent instantiation of this utility class.
+ }
+
+ /**
+ * Compute the limit for 'n' that fits in a long data type.
+ * Reducing the limit to 70 due to potential floating-point arithmetic errors
+ * that may result in incorrect results for larger inputs.
+ */
+ public static final int MAX_ARG = 70;
+
+ /**
+ * Calculates the nth Fibonacci number using Binet's formula.
+ *
+ * @param n The index of the Fibonacci number to calculate.
+ * @return The nth Fibonacci number as a long.
+ * @throws IllegalArgumentException if the input 'n' is negative or exceeds the range of a long data type.
+ */
+ public static long compute(int n) {
+ if (n < 0) {
+ throw new IllegalArgumentException("Input 'n' must be a non-negative integer.");
+ }
+
+ if (n > MAX_ARG) {
+ throw new IllegalArgumentException("Input 'n' is too big to give accurate result.");
+ }
+
+ if (n <= 1) {
+ return n;
+ }
+
+ // Calculate the nth Fibonacci number using the golden ratio formula
+ final double sqrt5 = Math.sqrt(5);
+ final double phi = (1 + sqrt5) / 2;
+ final double psi = (1 - sqrt5) / 2;
+ final double result = (Math.pow(phi, n) - Math.pow(psi, n)) / sqrt5;
+
+ // Round to the nearest integer and return as a long
+ return Math.round(result);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/maths/FibonacciLoopTest.java b/src/test/java/com/thealgorithms/maths/FibonacciLoopTest.java
new file mode 100644
index 000000000000..93aec39765d4
--- /dev/null
+++ b/src/test/java/com/thealgorithms/maths/FibonacciLoopTest.java
@@ -0,0 +1,36 @@
+package com.thealgorithms.maths;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.math.BigInteger;
+import org.junit.jupiter.api.Test;
+
+public class FibonacciLoopTest {
+ @Test
+ public void checkValueAtZero() {
+ assertEquals(BigInteger.ZERO, FibonacciLoop.compute(0));
+ }
+
+ @Test
+ public void checkValueAtOne() {
+ assertEquals(BigInteger.ONE, FibonacciLoop.compute(1));
+ }
+
+ @Test
+ public void checkValueAtTwo() {
+ assertEquals(BigInteger.ONE, FibonacciLoop.compute(2));
+ }
+
+ @Test
+ public void checkRecurrenceRelation() {
+ for (int i = 0; i < 100; ++i) {
+ assertEquals(FibonacciLoop.compute(i + 2), FibonacciLoop.compute(i + 1).add(FibonacciLoop.compute(i)));
+ }
+ }
+
+ @Test
+ public void checkNegativeInput() {
+ assertThrows(IllegalArgumentException.class, () -> { FibonacciLoop.compute(-1); });
+ }
+}
diff --git a/src/test/java/com/thealgorithms/maths/FibonacciNumberGoldenRationTest.java b/src/test/java/com/thealgorithms/maths/FibonacciNumberGoldenRationTest.java
new file mode 100644
index 000000000000..e3f7bf3e0fed
--- /dev/null
+++ b/src/test/java/com/thealgorithms/maths/FibonacciNumberGoldenRationTest.java
@@ -0,0 +1,29 @@
+package com.thealgorithms.maths;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.math.BigInteger;
+import org.junit.jupiter.api.Test;
+
+public class FibonacciNumberGoldenRationTest {
+
+ @Test
+ public void returnsCorrectValues() {
+ for (int n = 0; n <= FibonacciNumberGoldenRation.MAX_ARG; ++n) {
+ final var actual = FibonacciNumberGoldenRation.compute(n);
+ final var expected = FibonacciLoop.compute(n);
+ assertEquals(expected, BigInteger.valueOf(actual));
+ }
+ }
+
+ @Test
+ public void throwsIllegalArgumentExceptionForNegativeInput() {
+ assertThrows(IllegalArgumentException.class, () -> { FibonacciNumberGoldenRation.compute(-1); });
+ }
+
+ @Test
+ public void throwsIllegalArgumentExceptionForLargeInput() {
+ assertThrows(IllegalArgumentException.class, () -> { FibonacciNumberGoldenRation.compute(FibonacciNumberGoldenRation.MAX_ARG + 1); });
+ }
+}
From 48ae88f09d595bf6bdd3440b003e08419c885126 Mon Sep 17 00:00:00 2001
From: Lukas <142339568+lukasb1b@users.noreply.github.com>
Date: Sun, 15 Oct 2023 09:03:25 +0200
Subject: [PATCH 0049/1338] Bit swap (#4770)
* Create BitSwap.java
* Create BitSwapTest.java
* Update BitSwap.java
* Update BitSwap.java
* Update BitSwapTest.java
* Update BitSwap.java
* Update BitSwap.java
* Update BitSwapTest.java
* Update BitSwapTest.java
* Update src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/test/java/com/thealgorithms/bitmanipulation/BitSwapTest.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update BitSwap.java
* Update BitSwap.java
* Update BitSwap.java
* Update src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* Update src/test/java/com/thealgorithms/bitmanipulation/BitSwapTest.java
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* style: remove redundant blank line
---------
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
---
.../thealgorithms/bitmanipulation/BitSwap.java | 15 +++++++++++++++
.../bitmanipulation/BitSwapTest.java | 13 +++++++++++++
2 files changed, 28 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java
create mode 100644 src/test/java/com/thealgorithms/bitmanipulation/BitSwapTest.java
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java b/src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java
new file mode 100644
index 000000000000..40b3097b1276
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java
@@ -0,0 +1,15 @@
+package com.thealgorithms.bitmanipulation;
+
+public final class BitSwap {
+ private BitSwap() {
+ }
+ /*
+ * @brief Swaps the bits at the position posA and posB from data
+ */
+ public static int bitSwap(int data, final int posA, final int posB) {
+ if (SingleBitOperations.getBit(data, posA) != SingleBitOperations.getBit(data, posB)) {
+ data ^= (1 << posA) ^ (1 << posB);
+ }
+ return data;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/bitmanipulation/BitSwapTest.java b/src/test/java/com/thealgorithms/bitmanipulation/BitSwapTest.java
new file mode 100644
index 000000000000..40de770e0c66
--- /dev/null
+++ b/src/test/java/com/thealgorithms/bitmanipulation/BitSwapTest.java
@@ -0,0 +1,13 @@
+package com.thealgorithms.bitmanipulation;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+public class BitSwapTest {
+ @Test
+ void testHighestSetBit() {
+ assertEquals(3, BitSwap.bitSwap(3, 0, 1));
+ assertEquals(5, BitSwap.bitSwap(6, 0, 1));
+ assertEquals(7, BitSwap.bitSwap(7, 1, 1));
+ }
+}
From 8002137b764de30918bfc1375fd816034edc3f16 Mon Sep 17 00:00:00 2001
From: Ayoub Chegraoui
Date: Sun, 15 Oct 2023 15:02:24 +0100
Subject: [PATCH 0050/1338] Fixed some typos and links for javadoc, and some
refactoring (#4755)
---
.../com/thealgorithms/ciphers/AESEncryption.java | 2 +-
.../thealgorithms/conversions/AnyBaseToDecimal.java | 2 +-
.../thealgorithms/conversions/DecimalToAnyBase.java | 2 +-
.../thealgorithms/conversions/RgbHsvConversion.java | 4 ++--
.../java/com/thealgorithms/geometry/GrahamScan.java | 12 +++++-------
5 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/src/main/java/com/thealgorithms/ciphers/AESEncryption.java b/src/main/java/com/thealgorithms/ciphers/AESEncryption.java
index 2b12aeaa0466..169fc10e5269 100644
--- a/src/main/java/com/thealgorithms/ciphers/AESEncryption.java
+++ b/src/main/java/com/thealgorithms/ciphers/AESEncryption.java
@@ -19,7 +19,7 @@ public class AESEncryption {
/**
* 1. Generate a plain text for encryption 2. Get a secret key (printed in
- * hexadecimal form). In actual use this must by encrypted and kept safe.
+ * hexadecimal form). In actual use this must be encrypted and kept safe.
* The same key is required for decryption.
*/
public static void main(String[] args) throws Exception {
diff --git a/src/main/java/com/thealgorithms/conversions/AnyBaseToDecimal.java b/src/main/java/com/thealgorithms/conversions/AnyBaseToDecimal.java
index 837b35305c80..20f15bc2ff39 100644
--- a/src/main/java/com/thealgorithms/conversions/AnyBaseToDecimal.java
+++ b/src/main/java/com/thealgorithms/conversions/AnyBaseToDecimal.java
@@ -1,7 +1,7 @@
package com.thealgorithms.conversions;
/**
- * @author Varun Upadhyay (https://github.com/varunu28)
+ * @author Varun Upadhyay (...)
*/
// Driver program
public class AnyBaseToDecimal {
diff --git a/src/main/java/com/thealgorithms/conversions/DecimalToAnyBase.java b/src/main/java/com/thealgorithms/conversions/DecimalToAnyBase.java
index 31ef2bffb708..2d0223a4c448 100644
--- a/src/main/java/com/thealgorithms/conversions/DecimalToAnyBase.java
+++ b/src/main/java/com/thealgorithms/conversions/DecimalToAnyBase.java
@@ -5,7 +5,7 @@
import java.util.ArrayList;
/**
- * @author Varun Upadhyay (https://github.com/varunu28)
+ * @author Varun Upadhyay (...)
*/
// Driver Program
public class DecimalToAnyBase {
diff --git a/src/main/java/com/thealgorithms/conversions/RgbHsvConversion.java b/src/main/java/com/thealgorithms/conversions/RgbHsvConversion.java
index ca64c3ffd7a6..65cb00fc0ad0 100644
--- a/src/main/java/com/thealgorithms/conversions/RgbHsvConversion.java
+++ b/src/main/java/com/thealgorithms/conversions/RgbHsvConversion.java
@@ -10,8 +10,8 @@
* models how colors appear under light. In it, colors are represented using
* three components: hue, saturation and (brightness-)value. This class provides
* methods for converting colors from one representation to the other.
- * (description adapted from https://en.wikipedia.org/wiki/RGB_color_model and
- * https://en.wikipedia.org/wiki/HSL_and_HSV).
+ * (description adapted from [1] and
+ * [2]).
*/
public class RgbHsvConversion {
diff --git a/src/main/java/com/thealgorithms/geometry/GrahamScan.java b/src/main/java/com/thealgorithms/geometry/GrahamScan.java
index 3325a65829e0..9122c6f6f3cc 100644
--- a/src/main/java/com/thealgorithms/geometry/GrahamScan.java
+++ b/src/main/java/com/thealgorithms/geometry/GrahamScan.java
@@ -6,7 +6,7 @@
/*
* A Java program that computes the convex hull using the Graham Scan algorithm
- * In the best case, time complexity is O(n), while in the worst case, it is log(n).
+ * In the best case, time complexity is O(n), while in the worst case, it is O(nlog(n)).
* O(n) space complexity
*
* This algorithm is only applicable to integral coordinates.
@@ -106,16 +106,14 @@ public static int orientation(Point a, Point b, Point c) {
/**
* @param p2 Co-ordinate of point to compare to.
- * This function will compare the points and will return a positive integer it the
+ * This function will compare the points and will return a positive integer if the
* point is greater than the argument point and a negative integer if the point is
* less than the argument point.
*/
public int compareTo(Point p2) {
- if (this.y < p2.y) return -1;
- if (this.y > p2.y) return +1;
- if (this.x < p2.x) return -1;
- if (this.x > p2.x) return +1;
- return 0;
+ int res = Integer.compare(this.y, p2.y);
+ if (res == 0) res = Integer.compare(this.x, p2.x);
+ return res;
}
/**
From f3345d9e06dd39c730ad960ef6f4f8dbf73041b3 Mon Sep 17 00:00:00 2001
From: ironspec07 <127649008+ironspec07@users.noreply.github.com>
Date: Fri, 20 Oct 2023 00:32:27 +0530
Subject: [PATCH 0051/1338] Fixed typo error for better readability (#4835)
---
src/main/java/com/thealgorithms/misc/ColorContrastRatio.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/com/thealgorithms/misc/ColorContrastRatio.java b/src/main/java/com/thealgorithms/misc/ColorContrastRatio.java
index f7767d54a0aa..2d8371a9a53d 100644
--- a/src/main/java/com/thealgorithms/misc/ColorContrastRatio.java
+++ b/src/main/java/com/thealgorithms/misc/ColorContrastRatio.java
@@ -3,7 +3,7 @@
import java.awt.Color;
/**
- * @brief A Java implementation of the offcial W3 documented procedure to
+ * @brief A Java implementation of the official W3 documented procedure to
* calculate contrast ratio between colors on the web. This is used to calculate
* the readability of a foreground color on top of a background color.
* @since 2020-10-15
From e87036d886f2a3e477053bde76d5567f21615dd7 Mon Sep 17 00:00:00 2001
From: Aditi Bansal <142652964+Aditi22Bansal@users.noreply.github.com>
Date: Fri, 20 Oct 2023 01:07:29 +0530
Subject: [PATCH 0052/1338] Correct documentation of `IsEven` (#4845)
* Update IsEven.java
* Update IsEven.java
* Update IsEven.java
---------
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
---
src/main/java/com/thealgorithms/bitmanipulation/IsEven.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/IsEven.java b/src/main/java/com/thealgorithms/bitmanipulation/IsEven.java
index ec30eb09168b..b6bdc25fcc2b 100644
--- a/src/main/java/com/thealgorithms/bitmanipulation/IsEven.java
+++ b/src/main/java/com/thealgorithms/bitmanipulation/IsEven.java
@@ -1,7 +1,7 @@
package com.thealgorithms.bitmanipulation;
/**
- * Converts any Octal Number to a Binary Number
+ * Checks whether a number is even
* @author Bama Charan Chhandogi (https://github.com/BamaCharanChhandogi)
*/
From 9dae389faa03b8400b6f0796383f47495887151a Mon Sep 17 00:00:00 2001
From: Appari Satya Barghav <36763910+satyabarghav@users.noreply.github.com>
Date: Tue, 24 Oct 2023 02:39:42 +0530
Subject: [PATCH 0053/1338] Herons : Changed the signature of the function
(#4686)
* Made changes to the code to correct the Logic of Armstrong Number
* Resolved the issues
* Trying to resolve the Linter error by changing Variable name
* Changed Variable Names : trying to resolve Clang error
* Chnged the signature of the function
* Added the Function documentation
* Added exception for parameters
* Resolved with suggested changes
* Resolved with Suggested changes
* fix: use proper logic
---------
Co-authored-by: vil02
---
.../thealgorithms/maths/HeronsFormula.java | 35 ++++++++++++++-----
.../maths/HeronsFormulaTest.java | 20 ++++++++---
2 files changed, 42 insertions(+), 13 deletions(-)
diff --git a/src/main/java/com/thealgorithms/maths/HeronsFormula.java b/src/main/java/com/thealgorithms/maths/HeronsFormula.java
index 72052a1b8d45..5baee715d1ec 100644
--- a/src/main/java/com/thealgorithms/maths/HeronsFormula.java
+++ b/src/main/java/com/thealgorithms/maths/HeronsFormula.java
@@ -1,18 +1,35 @@
package com.thealgorithms.maths;
/**
+ * Wikipedia for HeronsFormula => https://en.wikipedia.org/wiki/Heron%27s_formula
* Find the area of a triangle using only side lengths
*/
-public class HeronsFormula {
+public final class HeronsFormula {
- public static double Herons(int s1, int s2, int s3) {
- double a = s1;
- double b = s2;
- double c = s3;
- double s = (a + b + c) / 2.0;
- double area = 0;
- area = Math.sqrt((s) * (s - a) * (s - b) * (s - c));
- return area;
+ /*
+ * A function to get the Area of a Triangle using Heron's Formula
+ * @param s1,s2,s3 => the three sides of the Triangle
+ * @return area using the formula (√(s(s – s1)(s – s2)(s – s3)))
+ * here s is called semi-perimeter and it is the half of the perimeter (i.e; s = (s1+s2+s3)/2)
+ * @author satyabarghav
+ */
+ private HeronsFormula() {
+ }
+
+ private static boolean areAllSidesPositive(final double a, final double b, final double c) {
+ return a > 0 && b > 0 && c > 0;
+ }
+
+ private static boolean canFormTriangle(final double a, final double b, final double c) {
+ return a + b > c && b + c > a && c + a > b;
+ }
+
+ public static double herons(final double a, final double b, final double c) {
+ if (!areAllSidesPositive(a, b, c) || !canFormTriangle(a, b, c)) {
+ throw new IllegalArgumentException("Triangle can't be formed with the given side lengths");
+ }
+ final double s = (a + b + c) / 2.0;
+ return Math.sqrt((s) * (s - a) * (s - b) * (s - c));
}
}
diff --git a/src/test/java/com/thealgorithms/maths/HeronsFormulaTest.java b/src/test/java/com/thealgorithms/maths/HeronsFormulaTest.java
index 32feeacdb916..22cecf4dc960 100644
--- a/src/test/java/com/thealgorithms/maths/HeronsFormulaTest.java
+++ b/src/test/java/com/thealgorithms/maths/HeronsFormulaTest.java
@@ -7,21 +7,33 @@ public class HeronsFormulaTest {
@Test
void test1() {
- Assertions.assertEquals(HeronsFormula.Herons(3, 4, 5), 6.0);
+ Assertions.assertEquals(HeronsFormula.herons(3, 4, 5), 6.0);
}
@Test
void test2() {
- Assertions.assertEquals(HeronsFormula.Herons(24, 30, 18), 216.0);
+ Assertions.assertEquals(HeronsFormula.herons(24, 30, 18), 216.0);
}
@Test
void test3() {
- Assertions.assertEquals(HeronsFormula.Herons(1, 1, 1), 0.4330127018922193);
+ Assertions.assertEquals(HeronsFormula.herons(1, 1, 1), 0.4330127018922193);
}
@Test
void test4() {
- Assertions.assertEquals(HeronsFormula.Herons(4, 5, 8), 8.181534085976786);
+ Assertions.assertEquals(HeronsFormula.herons(4, 5, 8), 8.181534085976786);
+ }
+
+ @Test
+ public void testCalculateAreaWithInvalidInput() {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> { HeronsFormula.herons(1, 2, 3); });
+ Assertions.assertThrows(IllegalArgumentException.class, () -> { HeronsFormula.herons(2, 1, 3); });
+ Assertions.assertThrows(IllegalArgumentException.class, () -> { HeronsFormula.herons(3, 2, 1); });
+ Assertions.assertThrows(IllegalArgumentException.class, () -> { HeronsFormula.herons(1, 3, 2); });
+
+ Assertions.assertThrows(IllegalArgumentException.class, () -> { HeronsFormula.herons(1, 1, 0); });
+ Assertions.assertThrows(IllegalArgumentException.class, () -> { HeronsFormula.herons(1, 0, 1); });
+ Assertions.assertThrows(IllegalArgumentException.class, () -> { HeronsFormula.herons(0, 1, 1); });
}
}
From a4711d61d87cf75bf68f1f0b25345b1439220acf Mon Sep 17 00:00:00 2001
From: Aakil Iqbal <62759233+aakiliqbal@users.noreply.github.com>
Date: Wed, 25 Oct 2023 09:30:18 +0530
Subject: [PATCH 0054/1338] Added MapReduce Algorithm in Misc Folder. (#4828)
* Added MapReduce Algorithm in Misc Folder.
* Did formatting correctly
* Removed main function and added MapReduceTest
* format the code
---
.../com/thealgorithms/misc/MapReduce.java | 39 +++++++++++++++++++
.../com/thealgorithms/misc/MapReduceTest.java | 23 +++++++++++
2 files changed, 62 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/misc/MapReduce.java
create mode 100644 src/test/java/com/thealgorithms/misc/MapReduceTest.java
diff --git a/src/main/java/com/thealgorithms/misc/MapReduce.java b/src/main/java/com/thealgorithms/misc/MapReduce.java
new file mode 100644
index 000000000000..baf960f8ecef
--- /dev/null
+++ b/src/main/java/com/thealgorithms/misc/MapReduce.java
@@ -0,0 +1,39 @@
+package com.thealgorithms.misc;
+
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/*
+* MapReduce is a programming model for processing and generating large data sets with a parallel,
+distributed algorithm on a cluster.
+* It has two main steps: the Map step, where the data is divided into smaller chunks and processed in parallel,
+and the Reduce step, where the results from the Map step are combined to produce the final output.
+* Wikipedia link : https://en.wikipedia.org/wiki/MapReduce
+*/
+
+public class MapReduce {
+ /*
+ *Counting all the words frequency within a sentence.
+ */
+ public static String mapreduce(String sentence) {
+ List wordList = Arrays.stream(sentence.split(" ")).toList();
+
+ // Map step
+ Map wordCounts = wordList.stream().collect(Collectors.groupingBy(Function.identity(), LinkedHashMap::new, Collectors.counting()));
+
+ // Reduce step
+ StringBuilder result = new StringBuilder();
+ wordCounts.forEach((word, count) -> result.append(word).append(": ").append(count).append(","));
+
+ // Removing the last ',' if it exists
+ if (!result.isEmpty()) {
+ result.setLength(result.length() - 1);
+ }
+
+ return result.toString();
+ }
+}
diff --git a/src/test/java/com/thealgorithms/misc/MapReduceTest.java b/src/test/java/com/thealgorithms/misc/MapReduceTest.java
new file mode 100644
index 000000000000..213acad9743b
--- /dev/null
+++ b/src/test/java/com/thealgorithms/misc/MapReduceTest.java
@@ -0,0 +1,23 @@
+package com.thealgorithms.misc;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+public class MapReduceTest {
+ @Test
+ public void testMapReduceWithSingleWordSentence() {
+ String oneWordSentence = "Hactober";
+ String result = MapReduce.mapreduce(oneWordSentence);
+
+ assertEquals("Hactober: 1", result);
+ }
+
+ @Test
+ public void testMapReduceWithMultipleWordSentence() {
+ String multipleWordSentence = "I Love Love HactoberFest";
+ String result = MapReduce.mapreduce(multipleWordSentence);
+
+ assertEquals("I: 1,Love: 2,HactoberFest: 1", result);
+ }
+}
From 9dde8a780832a29c508deb3382410e36f127fdf1 Mon Sep 17 00:00:00 2001
From: Anup Omkar <57665180+anupomkar@users.noreply.github.com>
Date: Wed, 25 Oct 2023 19:04:05 +0530
Subject: [PATCH 0055/1338] Add `MatrixRank` (#4571)
* feat: adding matrix rank algorithm
* fix: formatting
* fix: adding comments, refactor and handling edge cases
* refactor: minor refactor
* enhancement: check matrix validity
* refactor: minor refactor and fixes
* Update src/main/java/com/thealgorithms/maths/MatrixRank.java
* feat: add unit test to check if input matrix is not modified while calculating the rank
---------
Co-authored-by: Anup Omkar
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Co-authored-by: Andrii Siriak
---
.../com/thealgorithms/maths/MatrixRank.java | 164 ++++++++++++++++++
.../thealgorithms/maths/MatrixRankTest.java | 45 +++++
2 files changed, 209 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/maths/MatrixRank.java
create mode 100644 src/test/java/com/thealgorithms/maths/MatrixRankTest.java
diff --git a/src/main/java/com/thealgorithms/maths/MatrixRank.java b/src/main/java/com/thealgorithms/maths/MatrixRank.java
new file mode 100644
index 000000000000..7a628b92dccb
--- /dev/null
+++ b/src/main/java/com/thealgorithms/maths/MatrixRank.java
@@ -0,0 +1,164 @@
+package com.thealgorithms.maths;
+
+/**
+ * This class provides a method to compute the rank of a matrix.
+ * In linear algebra, the rank of a matrix is the maximum number of linearly independent rows or columns in the matrix.
+ * For example, consider the following 3x3 matrix:
+ * 1 2 3
+ * 2 4 6
+ * 3 6 9
+ * Despite having 3 rows and 3 columns, this matrix only has a rank of 1 because all rows (and columns) are multiples of each other.
+ * It's a fundamental concept that gives key insights into the structure of the matrix.
+ * It's important to note that the rank is not only defined for square matrices but for any m x n matrix.
+ *
+ * @author Anup Omkar
+ */
+public final class MatrixRank {
+
+ private MatrixRank() {
+ }
+
+ private static final double EPSILON = 1e-10;
+
+ /**
+ * @brief Computes the rank of the input matrix
+ *
+ * @param matrix The input matrix
+ * @return The rank of the input matrix
+ */
+ public static int computeRank(double[][] matrix) {
+ validateInputMatrix(matrix);
+
+ int numRows = matrix.length;
+ int numColumns = matrix[0].length;
+ int rank = 0;
+
+ boolean[] rowMarked = new boolean[numRows];
+
+ double[][] matrixCopy = deepCopy(matrix);
+
+ for (int colIndex = 0; colIndex < numColumns; ++colIndex) {
+ int pivotRow = findPivotRow(matrixCopy, rowMarked, colIndex);
+ if (pivotRow != numRows) {
+ ++rank;
+ rowMarked[pivotRow] = true;
+ normalizePivotRow(matrixCopy, pivotRow, colIndex);
+ eliminateRows(matrixCopy, pivotRow, colIndex);
+ }
+ }
+ return rank;
+ }
+
+ private static boolean isZero(double value) {
+ return Math.abs(value) < EPSILON;
+ }
+
+ private static double[][] deepCopy(double[][] matrix) {
+ int numRows = matrix.length;
+ int numColumns = matrix[0].length;
+ double[][] matrixCopy = new double[numRows][numColumns];
+ for (int rowIndex = 0; rowIndex < numRows; ++rowIndex) {
+ System.arraycopy(matrix[rowIndex], 0, matrixCopy[rowIndex], 0, numColumns);
+ }
+ 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.
+ * This row is then used to "eliminate" other rows, by subtracting multiples of the pivot row from them, so that all other entries in the pivot column become zero.
+ * This process is repeated for each column, each time selecting a new pivot row, until the matrix is in row echelon form.
+ * The number of pivot rows (rows with a leading entry, or pivot) then gives the rank of the matrix.
+ *
+ * @param matrix The input matrix
+ * @param rowMarked An array indicating which rows have been marked
+ * @param colIndex The column index
+ * @return The pivot row index, or the number of rows if no suitable pivot row was found
+ */
+ private static int findPivotRow(double[][] matrix, boolean[] rowMarked, int colIndex) {
+ int numRows = matrix.length;
+ for (int pivotRow = 0; pivotRow < numRows; ++pivotRow) {
+ if (!rowMarked[pivotRow] && !isZero(matrix[pivotRow][colIndex])) {
+ return pivotRow;
+ }
+ }
+ return numRows;
+ }
+
+ /**
+ * @brief This method divides all values in the pivot row by the value in the given column.
+ * This ensures that the pivot value itself will be 1, which simplifies further calculations.
+ *
+ * @param matrix The input matrix
+ * @param pivotRow The pivot row index
+ * @param colIndex The column index
+ */
+ private static void normalizePivotRow(double[][] matrix, int pivotRow, int colIndex) {
+ int numColumns = matrix[0].length;
+ for (int nextCol = colIndex + 1; nextCol < numColumns; ++nextCol) {
+ matrix[pivotRow][nextCol] /= matrix[pivotRow][colIndex];
+ }
+ }
+
+ /**
+ * @brief This method subtracts multiples of the pivot row from all other rows,
+ * so that all values in the given column of other rows will be zero.
+ * This is a key step in reducing the matrix to row echelon form.
+ *
+ * @param matrix The input matrix
+ * @param pivotRow The pivot row index
+ * @param colIndex The column index
+ */
+ private static void eliminateRows(double[][] matrix, int pivotRow, int colIndex) {
+ int numRows = matrix.length;
+ int numColumns = matrix[0].length;
+ for (int otherRow = 0; otherRow < numRows; ++otherRow) {
+ if (otherRow != pivotRow && !isZero(matrix[otherRow][colIndex])) {
+ for (int col2 = colIndex + 1; col2 < numColumns; ++col2) {
+ matrix[otherRow][col2] -= matrix[pivotRow][col2] * matrix[otherRow][colIndex];
+ }
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/thealgorithms/maths/MatrixRankTest.java b/src/test/java/com/thealgorithms/maths/MatrixRankTest.java
new file mode 100644
index 000000000000..415b84ec43f8
--- /dev/null
+++ b/src/test/java/com/thealgorithms/maths/MatrixRankTest.java
@@ -0,0 +1,45 @@
+package com.thealgorithms.maths;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.Arrays;
+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 MatrixRankTest {
+
+ private static Stream validInputStream() {
+ return Stream.of(Arguments.of(3, new double[][] {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}), Arguments.of(0, new double[][] {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}), Arguments.of(1, new double[][] {{1}}), Arguments.of(2, new double[][] {{1, 2}, {3, 4}}),
+ Arguments.of(2, new double[][] {{3, -1, 2}, {-3, 1, 2}, {-6, 2, 4}}), Arguments.of(3, new double[][] {{2, 3, 0, 1}, {1, 0, 1, 2}, {-1, 1, 1, -2}, {1, 5, 3, -1}}), Arguments.of(1, new double[][] {{1, 2, 3}, {3, 6, 9}}),
+ Arguments.of(2, new double[][] {{0.25, 0.5, 0.75, 2}, {1.5, 3, 4.5, 6}, {1, 2, 3, 4}}));
+ }
+
+ private static Stream invalidInputStream() {
+ return Stream.of(Arguments.of((Object) new double[][] {{1, 2}, {10}, {100, 200, 300}}), // jagged array
+ Arguments.of((Object) new double[][] {}), // empty matrix
+ Arguments.of((Object) new double[][] {{}, {}}), // empty row
+ Arguments.of((Object) null), // null matrix
+ Arguments.of((Object) new double[][] {{1, 2}, null}) // null row
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("validInputStream")
+ void computeRankTests(int expectedRank, double[][] matrix) {
+ int originalHashCode = Arrays.deepHashCode(matrix);
+ int rank = MatrixRank.computeRank(matrix);
+ int newHashCode = Arrays.deepHashCode(matrix);
+
+ assertEquals(expectedRank, rank);
+ assertEquals(originalHashCode, newHashCode);
+ }
+
+ @ParameterizedTest
+ @MethodSource("invalidInputStream")
+ void computeRankWithInvalidMatrix(double[][] matrix) {
+ assertThrows(IllegalArgumentException.class, () -> MatrixRank.computeRank(matrix));
+ }
+}
From 945e7b56bb186c3be908e02720e932b5ce834e01 Mon Sep 17 00:00:00 2001
From: Satvik Singh Sengar
Date: Mon, 30 Oct 2023 22:54:23 +0530
Subject: [PATCH 0056/1338] Fix:/Number of count of major element in Boyer
Moore algorithm (#4728)
* Number of count of major element in Boyer Moore algorithm
* test: add `BoyerMooreTest`
* style: basic linting
* tests: add test case from the issue
---------
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Co-authored-by: vil02
---
.../com/thealgorithms/others/BoyerMoore.java | 30 +++++++------------
.../thealgorithms/others/BoyerMooreTest.java | 22 ++++++++++++++
2 files changed, 32 insertions(+), 20 deletions(-)
create mode 100644 src/test/java/com/thealgorithms/others/BoyerMooreTest.java
diff --git a/src/main/java/com/thealgorithms/others/BoyerMoore.java b/src/main/java/com/thealgorithms/others/BoyerMoore.java
index 09235b521b44..d9d5b5d028ef 100644
--- a/src/main/java/com/thealgorithms/others/BoyerMoore.java
+++ b/src/main/java/com/thealgorithms/others/BoyerMoore.java
@@ -6,27 +6,28 @@
*/
package com.thealgorithms.others;
-import java.util.*;
-
-public class BoyerMoore {
+public final class BoyerMoore {
+ private BoyerMoore() {
+ }
- public static int findmajor(int[] a) {
+ public static int findmajor(final int[] a) {
int count = 0;
int cand = -1;
- for (int i = 0; i < a.length; i++) {
+ for (final var k : a) {
if (count == 0) {
- cand = a[i];
+ cand = k;
count = 1;
} else {
- if (a[i] == cand) {
+ if (k == cand) {
count++;
} else {
count--;
}
}
}
- for (int i = 0; i < a.length; i++) {
- if (a[i] == cand) {
+ count = 0;
+ for (final var j : a) {
+ if (j == cand) {
count++;
}
}
@@ -35,15 +36,4 @@ public static int findmajor(int[] a) {
}
return -1;
}
-
- public static void main(String[] args) {
- Scanner input = new Scanner(System.in);
- int n = input.nextInt();
- int[] a = new int[n];
- for (int i = 0; i < n; i++) {
- a[i] = input.nextInt();
- }
- System.out.println("the majority element is " + findmajor(a));
- input.close();
- }
}
diff --git a/src/test/java/com/thealgorithms/others/BoyerMooreTest.java b/src/test/java/com/thealgorithms/others/BoyerMooreTest.java
new file mode 100644
index 000000000000..b614c14070bd
--- /dev/null
+++ b/src/test/java/com/thealgorithms/others/BoyerMooreTest.java
@@ -0,0 +1,22 @@
+package com.thealgorithms.others;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public class BoyerMooreTest {
+
+ @ParameterizedTest
+ @MethodSource("inputStream")
+ void numberTests(int expected, int[] input) {
+ Assertions.assertEquals(expected, BoyerMoore.findmajor(input));
+ }
+
+ private static Stream inputStream() {
+ return Stream.of(Arguments.of(5, new int[] {5, 5, 5, 2}), Arguments.of(10, new int[] {10, 10, 20}), Arguments.of(10, new int[] {10, 20, 10}), Arguments.of(10, new int[] {20, 10, 10}), Arguments.of(-1, new int[] {10, 10, 20, 20, 30, 30}), Arguments.of(4, new int[] {1, 4, 2, 4, 4, 5, 4}));
+ }
+}
From e5f3d232c9fb97ed350a57708fc29d30fa0b28ae Mon Sep 17 00:00:00 2001
From: Phuong Nguyen
Date: Tue, 31 Oct 2023 05:09:43 +0700
Subject: [PATCH 0057/1338] refactor: use method `SortUtils.swap` (#4946)
* refactor: use method SortUtils.swap
* fix: clang format
* style: explicitly import `swap`
---------
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
---
src/main/java/com/thealgorithms/sorts/SelectionSort.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/main/java/com/thealgorithms/sorts/SelectionSort.java b/src/main/java/com/thealgorithms/sorts/SelectionSort.java
index 555b4b6037dc..e43df7fe622e 100644
--- a/src/main/java/com/thealgorithms/sorts/SelectionSort.java
+++ b/src/main/java/com/thealgorithms/sorts/SelectionSort.java
@@ -1,5 +1,7 @@
package com.thealgorithms.sorts;
+import static com.thealgorithms.sorts.SortUtils.swap;
+
public class SelectionSort implements SortAlgorithm {
/**
@@ -20,9 +22,7 @@ public > T[] sort(T[] arr) {
}
}
if (minIndex != i) {
- T temp = arr[i];
- arr[i] = arr[minIndex];
- arr[minIndex] = temp;
+ swap(arr, i, minIndex);
}
}
return arr;
From d086afce09a7de8d64332cc41015d3cf00e90cee Mon Sep 17 00:00:00 2001
From: Hardik Pawar <97388607+Hardvan@users.noreply.github.com>
Date: Tue, 31 Oct 2023 03:48:05 +0530
Subject: [PATCH 0058/1338] Enhance code density and readability (#4914)
* Enhance code density and readability
* Add wiki link
---------
Co-authored-by: vil02 <65706193+vil02@users.noreply.github.com>
---
.../divideandconquer/BinaryExponentiation.java | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/main/java/com/thealgorithms/divideandconquer/BinaryExponentiation.java b/src/main/java/com/thealgorithms/divideandconquer/BinaryExponentiation.java
index da45d5b90cae..a70b16b0d069 100644
--- a/src/main/java/com/thealgorithms/divideandconquer/BinaryExponentiation.java
+++ b/src/main/java/com/thealgorithms/divideandconquer/BinaryExponentiation.java
@@ -2,6 +2,8 @@
// Java Program to Implement Binary Exponentiation (power in log n)
+// Reference Link: https://en.wikipedia.org/wiki/Exponentiation_by_squaring
+
/*
* Binary Exponentiation is a method to calculate a to the power of b.
* It is used to calculate a^n in O(log n) time.
@@ -14,14 +16,14 @@ public class BinaryExponentiation {
// recursive function to calculate a to the power of b
public static long calculatePower(long x, long y) {
+ // Base Case
if (y == 0) {
return 1;
}
- long val = calculatePower(x, y / 2);
- if (y % 2 == 0) {
- return val * val;
+ if (y % 2 == 1) { // odd power
+ return x * calculatePower(x, y - 1);
}
- return val * val * x;
+ return calculatePower(x * x, y / 2); // even power
}
// iterative function to calculate a to the power of b
From 574138c7a35351a0837bb4bd56e2eb295064b690 Mon Sep 17 00:00:00 2001
From: Prathamesh Powar
Date: Tue, 31 Oct 2023 13:37:59 +0530
Subject: [PATCH 0059/1338] Cleanup `BoyerMoore` (#4951)
* modify code to make use of java Optional class
* revert changes
* add java.util.Optional
* add java.util.Optional
* refactors: make `findmajor` return `optional`
* refactors: make method name findMajor and split it
* refactors: change method name in tests
* Apply suggestions from code review
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
* change back to int
* fix: swap arguments
* tests: add some test cases
* refactor: add `isMajority` and avoid rounding
* style: use `var`
* style: swap arguments of `countOccurrences`
---------
Co-authored-by: vil02
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
---
.../com/thealgorithms/others/BoyerMoore.java | 35 +++++++++++++------
.../thealgorithms/others/BoyerMooreTest.java | 20 ++++++++---
2 files changed, 40 insertions(+), 15 deletions(-)
diff --git a/src/main/java/com/thealgorithms/others/BoyerMoore.java b/src/main/java/com/thealgorithms/others/BoyerMoore.java
index d9d5b5d028ef..e67427deda79 100644
--- a/src/main/java/com/thealgorithms/others/BoyerMoore.java
+++ b/src/main/java/com/thealgorithms/others/BoyerMoore.java
@@ -5,35 +5,50 @@
https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_majority_vote_algorithm
*/
package com.thealgorithms.others;
+import java.util.Optional;
public final class BoyerMoore {
private BoyerMoore() {
}
- public static int findmajor(final int[] a) {
+ public static Optional findMajor(final int[] a) {
+ final var candidate = findCandidate(a);
+ final var count = countOccurrences(candidate, a);
+ if (isMajority(count, a.length)) {
+ return Optional.of(candidate);
+ }
+ return Optional.empty();
+ }
+
+ private static int findCandidate(final int[] a) {
int count = 0;
- int cand = -1;
+ int candidate = -1;
for (final var k : a) {
if (count == 0) {
- cand = k;
+ candidate = k;
count = 1;
} else {
- if (k == cand) {
+ if (k == candidate) {
count++;
} else {
count--;
}
}
}
- count = 0;
+ return candidate;
+ }
+
+ private static int countOccurrences(final int candidate, final int[] a) {
+ int count = 0;
for (final var j : a) {
- if (j == cand) {
+ if (j == candidate) {
count++;
}
}
- if (count > (a.length / 2)) {
- return cand;
- }
- return -1;
+ return count;
+ }
+
+ private static boolean isMajority(final int count, final int totalCount) {
+ return 2 * count > totalCount;
}
}
diff --git a/src/test/java/com/thealgorithms/others/BoyerMooreTest.java b/src/test/java/com/thealgorithms/others/BoyerMooreTest.java
index b614c14070bd..b1497f7bc525 100644
--- a/src/test/java/com/thealgorithms/others/BoyerMooreTest.java
+++ b/src/test/java/com/thealgorithms/others/BoyerMooreTest.java
@@ -11,12 +11,22 @@
public class BoyerMooreTest {
@ParameterizedTest
- @MethodSource("inputStream")
- void numberTests(int expected, int[] input) {
- Assertions.assertEquals(expected, BoyerMoore.findmajor(input));
+ @MethodSource("inputStreamWithExistingMajority")
+ void checkWhenMajorityExists(int expected, int[] input) {
+ Assertions.assertEquals(expected, BoyerMoore.findMajor(input).get());
}
- private static Stream inputStream() {
- return Stream.of(Arguments.of(5, new int[] {5, 5, 5, 2}), Arguments.of(10, new int[] {10, 10, 20}), Arguments.of(10, new int[] {10, 20, 10}), Arguments.of(10, new int[] {20, 10, 10}), Arguments.of(-1, new int[] {10, 10, 20, 20, 30, 30}), Arguments.of(4, new int[] {1, 4, 2, 4, 4, 5, 4}));
+ private static Stream inputStreamWithExistingMajority() {
+ return Stream.of(Arguments.of(5, new int[] {5, 5, 5, 2}), Arguments.of(10, new int[] {10, 10, 20}), Arguments.of(10, new int[] {10, 20, 10}), Arguments.of(10, new int[] {20, 10, 10}), Arguments.of(4, new int[] {1, 4, 2, 4, 4, 5, 4}), Arguments.of(-1, new int[] {-1}));
+ }
+
+ @ParameterizedTest
+ @MethodSource("inputStreamWithoutMajority")
+ void checkWhenMajorityExists(int[] input) {
+ Assertions.assertFalse(BoyerMoore.findMajor(input).isPresent());
+ }
+
+ private static Stream inputStreamWithoutMajority() {
+ return Stream.of(Arguments.of(new int[] {10, 10, 20, 20, 30, 30}), Arguments.of(new int[] {10, 20, 30, 40, 50}), Arguments.of(new int[] {1, 2}), Arguments.of(new int[] {}));
}
}
From c527dff92da2046b850ffe9a3b8d0c2aae15d588 Mon Sep 17 00:00:00 2001
From: "D.Sunil"
Date: Sun, 12 Nov 2023 02:25:48 +0530
Subject: [PATCH 0060/1338] Add Javadoc comments (#4745)
---
.../dynamicprogramming/RodCutting.java | 37 +++++++++++--------
1 file changed, 21 insertions(+), 16 deletions(-)
diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/RodCutting.java b/src/main/java/com/thealgorithms/dynamicprogramming/RodCutting.java
index 28ff41d1a2d1..4583aec2e1b4 100644
--- a/src/main/java/com/thealgorithms/dynamicprogramming/RodCutting.java
+++ b/src/main/java/com/thealgorithms/dynamicprogramming/RodCutting.java
@@ -1,32 +1,37 @@
package com.thealgorithms.dynamicprogramming;
/**
- * A DynamicProgramming solution for Rod cutting problem Returns the best
- * obtainable price for a rod of length n and price[] as prices of different
- * pieces
+ * A Dynamic Programming solution for the Rod cutting problem.
+ * Returns the best obtainable price for a rod of length n and price[] as prices of different pieces.
*/
public class RodCutting {
- private static int cutRod(int[] price, int n) {
+ /**
+ * This method calculates the maximum obtainable value for cutting a rod of length n
+ * into different pieces, given the prices for each possible piece length.
+ *
+ * @param price An array representing the prices of different pieces, where price[i-1]
+ * represents the price of a piece of length i.
+ * @param n The length of the rod to be cut.
+ * @return The maximum obtainable value.
+ */
+ public static int cutRod(int[] price, int n) {
+ // Create an array to store the maximum obtainable values for each rod length.
int[] val = new int[n + 1];
val[0] = 0;
+ // Calculate the maximum value for each rod length from 1 to n.
for (int i = 1; i <= n; i++) {
- int max_val = Integer.MIN_VALUE;
- for (int j = 0; j < i; j++) {
- max_val = Math.max(max_val, price[j] + val[i - j - 1]);
+ int maxVal = Integer.MIN_VALUE;
+ // Try all possible ways to cut the rod and find the maximum value.
+ for (int j = 1; j <= i; j++) {
+ maxVal = Math.max(maxVal, price[j - 1] + val[i - j]);
}
-
- val[i] = max_val;
+ // Store the maximum value for the current rod length.
+ val[i] = maxVal;
}
+ // The final element of 'val' contains the maximum obtainable value for a rod of length 'n'.
return val[n];
}
-
- // main function to test
- public static void main(String[] args) {
- int[] arr = new int[] {2, 5, 13, 19, 20};
- int result = cutRod(arr, arr.length);
- System.out.println("Maximum Obtainable Value is " + result);
- }
}
From b1efd4e34bb18a618ab205c9c2a62802f151c70d Mon Sep 17 00:00:00 2001
From: Niklas Hoefflin <122729995+itakurah@users.noreply.github.com>
Date: Fri, 24 Nov 2023 18:13:44 +0100
Subject: [PATCH 0061/1338] Add G-Counter (Grow-only Counter) (#4965)
---
.../datastructures/crdt/GCounter.java | 84 +++++++++++++++++++
.../datastructures/crdt/GCounterTest.java | 54 ++++++++++++
2 files changed, 138 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/crdt/GCounterTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java b/src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java
new file mode 100644
index 000000000000..63364f858ec5
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java
@@ -0,0 +1,84 @@
+package com.thealgorithms.datastructures.crdt;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * G-Counter (Grow-only Counter) is a state-based CRDT (Conflict-free Replicated Data Type)
+ * designed for tracking counts in a distributed and concurrent environment.
+ * Each process maintains its own counter, allowing only increments. The total count
+ * is obtained by summing individual process counts.
+ * This implementation supports incrementing, querying the total count,
+ * comparing with other G-Counters, and merging with another G-Counter
+ * to compute the element-wise maximum.
+ * (https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type)
+ *
+ * @author itakurah (https://github.com/itakurah)
+ */
+
+class GCounter {
+ private final Map P;
+ private final int myId;
+ private final int n;
+
+ /**
+ * Constructs a G-Counter for a cluster of n nodes.
+ *
+ * @param n The number of nodes in the cluster.
+ */
+ public GCounter(int myId, int n) {
+ this.myId = myId;
+ this.n = n;
+ this.P = new HashMap<>();
+
+ for (int i = 0; i < n; i++) {
+ P.put(i, 0);
+ }
+ }
+
+ /**
+ * Increments the counter for the current node.
+ */
+ public void increment() {
+ P.put(myId, P.get(myId) + 1);
+ }
+
+ /**
+ * Gets the total value of the counter by summing up values from all nodes.
+ *
+ * @return The total value of the counter.
+ */
+ public int value() {
+ int sum = 0;
+ for (int v : P.values()) {
+ sum += v;
+ }
+ return sum;
+ }
+
+ /**
+ * Compares the state of this G-Counter with another G-Counter.
+ *
+ * @param other The other G-Counter to compare with.
+ * @return True if the state of this G-Counter is less than or equal to the state of the other G-Counter.
+ */
+ public boolean compare(GCounter other) {
+ for (int i = 0; i < n; i++) {
+ if (this.P.get(i) > other.P.get(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Merges the state of this G-Counter with another G-Counter.
+ *
+ * @param other The other G-Counter to merge with.
+ */
+ public void merge(GCounter other) {
+ for (int i = 0; i < n; i++) {
+ this.P.put(i, Math.max(this.P.get(i), other.P.get(i)));
+ }
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/crdt/GCounterTest.java b/src/test/java/com/thealgorithms/datastructures/crdt/GCounterTest.java
new file mode 100644
index 000000000000..f931e602383c
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/crdt/GCounterTest.java
@@ -0,0 +1,54 @@
+package com.thealgorithms.datastructures.crdt;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+public class GCounterTest {
+ @Test
+ void increment() {
+ GCounter counter = new GCounter(0, 3);
+ counter.increment();
+ counter.increment();
+ counter.increment();
+ assertEquals(3, counter.value());
+ }
+
+ @Test
+ void merge() {
+ GCounter counter1 = new GCounter(0, 3);
+ counter1.increment();
+ GCounter counter2 = new GCounter(1, 3);
+ counter2.increment();
+ counter2.increment();
+ GCounter counter3 = new GCounter(2, 3);
+ counter3.increment();
+ counter3.increment();
+ counter3.increment();
+ counter1.merge(counter2);
+ counter1.merge(counter3);
+ counter2.merge(counter1);
+ counter3.merge(counter2);
+ assertEquals(6, counter1.value());
+ assertEquals(6, counter2.value());
+ assertEquals(6, counter3.value());
+ }
+
+ @Test
+ void compare() {
+ GCounter counter1 = new GCounter(0, 5);
+ GCounter counter2 = new GCounter(3, 5);
+ counter1.increment();
+ counter1.increment();
+ counter2.merge(counter1);
+ counter2.increment();
+ counter2.increment();
+ assertTrue(counter1.compare(counter2));
+ counter1.increment();
+ counter2.increment();
+ counter2.merge(counter1);
+ assertTrue(counter1.compare(counter2));
+ counter1.increment();
+ assertFalse(counter1.compare(counter2));
+ }
+}
From 1518e84fb961f988b35ef402ec25a6576879c7ff Mon Sep 17 00:00:00 2001
From: Doksanbir
Date: Sun, 26 Nov 2023 14:34:13 +0300
Subject: [PATCH 0062/1338] Add Tribonacci Numbers (fixes #4646) (#4959)
---
.../dynamicprogramming/Tribonacci.java | 30 +++++++++++++++++++
.../dynamicprogramming/TribonacciTest.java | 24 +++++++++++++++
2 files changed, 54 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/dynamicprogramming/Tribonacci.java
create mode 100644 src/test/java/com/thealgorithms/dynamicprogramming/TribonacciTest.java
diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/Tribonacci.java b/src/main/java/com/thealgorithms/dynamicprogramming/Tribonacci.java
new file mode 100644
index 000000000000..99f9029009ab
--- /dev/null
+++ b/src/main/java/com/thealgorithms/dynamicprogramming/Tribonacci.java
@@ -0,0 +1,30 @@
+package com.thealgorithms.dynamicprogramming;
+
+/**
+ * The {@code Tribonacci} class provides a method to compute the n-th number in the Tribonacci sequence.
+ * N-th Tribonacci Number - https://leetcode.com/problems/n-th-tribonacci-number/description/
+ */
+public class Tribonacci {
+
+ /**
+ * Computes the n-th Tribonacci number.
+ *
+ * @param n the index of the Tribonacci number to compute
+ * @return the n-th Tribonacci number
+ */
+ public static int compute(int n) {
+ if (n == 0) return 0;
+ if (n == 1 || n == 2) return 1;
+
+ int first = 0, second = 1, third = 1;
+
+ for (int i = 3; i <= n; i++) {
+ int next = first + second + third;
+ first = second;
+ second = third;
+ third = next;
+ }
+
+ return third;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/TribonacciTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/TribonacciTest.java
new file mode 100644
index 000000000000..434a1825dfec
--- /dev/null
+++ b/src/test/java/com/thealgorithms/dynamicprogramming/TribonacciTest.java
@@ -0,0 +1,24 @@
+package com.thealgorithms.dynamicprogramming;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+/**
+ * Test class for {@code Tribonacci}.
+ */
+public class TribonacciTest {
+
+ /**
+ * Tests the Tribonacci computation for a set of known values.
+ */
+ @Test
+ public void testKnownValues() {
+ assertEquals(0, Tribonacci.compute(0), "The 0th Tribonacci should be 0.");
+ assertEquals(1, Tribonacci.compute(1), "The 1st Tribonacci should be 1.");
+ assertEquals(1, Tribonacci.compute(2), "The 2nd Tribonacci should be 1.");
+ assertEquals(2, Tribonacci.compute(3), "The 3rd Tribonacci should be 2.");
+ assertEquals(4, Tribonacci.compute(4), "The 4th Tribonacci should be 4.");
+ assertEquals(7, Tribonacci.compute(5), "The 5th Tribonacci should be 7.");
+ }
+}
From 3392b5116dc79f876a275539ec099b3d3a6894c6 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Tue, 28 Nov 2023 21:40:51 +0100
Subject: [PATCH 0063/1338] Add `codeql.yml` (#4966)
---
.github/workflows/codeql.yml | 47 ++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
create mode 100644 .github/workflows/codeql.yml
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 000000000000..482c8bc60527
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,47 @@
+---
+name: "CodeQL"
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - master
+ pull_request:
+ schedule:
+ - cron: '53 3 * * 0'
+
+env:
+ LANGUAGE: 'java-kotlin'
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: 'ubuntu-latest'
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ - name: Set up JDK 17
+ uses: actions/setup-java@v3
+ with:
+ java-version: 17
+ distribution: 'adopt'
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: ${{ env.LANGUAGE }}
+
+ - name: Build
+ run: mvn --batch-mode --update-snapshots verify
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
+ with:
+ category: "/language:${{env.LANGUAGE}}"
+...
From 361b4108ee0ae7f5e5fde95121d4d5d91eae5c6a Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Wed, 29 Nov 2023 22:21:25 +0100
Subject: [PATCH 0064/1338] Use explicit cast to `int` in `FractionalKnapsack`
(#4971)
---
.../com/thealgorithms/greedyalgorithms/FractionalKnapsack.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/com/thealgorithms/greedyalgorithms/FractionalKnapsack.java b/src/main/java/com/thealgorithms/greedyalgorithms/FractionalKnapsack.java
index c5570f35c004..f46364fc704b 100644
--- a/src/main/java/com/thealgorithms/greedyalgorithms/FractionalKnapsack.java
+++ b/src/main/java/com/thealgorithms/greedyalgorithms/FractionalKnapsack.java
@@ -32,7 +32,7 @@ public static int fractionalKnapsack(int weight[], int value[], int capacity) {
current -= weight[index];
} else {
// If only a fraction of the item can fit, add a proportionate value.
- finalValue += ratio[i][1] * current;
+ finalValue += (int) (ratio[i][1] * current);
break; // Stop adding items to the knapsack since it's full.
}
}
From f8de2901887a360ac3d2901b523f6b7e4df65e54 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Wed, 29 Nov 2023 22:30:59 +0100
Subject: [PATCH 0065/1338] Explicitly cast result of `Math.pow` to `int` in
`BinaryToHexadecimal` (#4970)
---
.../java/com/thealgorithms/conversions/BinaryToHexadecimal.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/com/thealgorithms/conversions/BinaryToHexadecimal.java b/src/main/java/com/thealgorithms/conversions/BinaryToHexadecimal.java
index c942cbb7d843..011b60a952b8 100644
--- a/src/main/java/com/thealgorithms/conversions/BinaryToHexadecimal.java
+++ b/src/main/java/com/thealgorithms/conversions/BinaryToHexadecimal.java
@@ -34,7 +34,7 @@ static String binToHex(int binary) {
for (i = 0; i < 4; i++) {
currbit = binary % 10;
binary = binary / 10;
- code4 += currbit * Math.pow(2, i);
+ code4 += currbit * (int) Math.pow(2, i);
}
hex = hm.get(code4) + hex;
}
From fc21a8bffe4398ba059c76f7968f43d150985103 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Thu, 30 Nov 2023 09:50:09 +0100
Subject: [PATCH 0066/1338] Explicitly cast result of `Math.pow` to `long` in
`Armstrong` (#4972)
---
src/main/java/com/thealgorithms/maths/Armstrong.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/com/thealgorithms/maths/Armstrong.java b/src/main/java/com/thealgorithms/maths/Armstrong.java
index 526b31c3891f..ff4ae027a0b7 100644
--- a/src/main/java/com/thealgorithms/maths/Armstrong.java
+++ b/src/main/java/com/thealgorithms/maths/Armstrong.java
@@ -27,7 +27,7 @@ public boolean isArmstrong(int number) {
while (originalNumber > 0) {
long digit = originalNumber % 10;
- sum += 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, power); // The digit raised to the power of the number of digits and added to the sum.
originalNumber /= 10;
}
From 9bebcee5c795dfc675196803b7d987ca3e4f9025 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Thu, 30 Nov 2023 17:36:31 +0100
Subject: [PATCH 0067/1338] Make `sumOfDigits` `long` in
`HarshadNumber.isHarshad` (#4973)
fix: make `sumOfDigits` `long` in `HarshadNumber.isHarshad`
---
src/main/java/com/thealgorithms/maths/HarshadNumber.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/main/java/com/thealgorithms/maths/HarshadNumber.java b/src/main/java/com/thealgorithms/maths/HarshadNumber.java
index 854e4d555b40..4778dc81b664 100644
--- a/src/main/java/com/thealgorithms/maths/HarshadNumber.java
+++ b/src/main/java/com/thealgorithms/maths/HarshadNumber.java
@@ -15,7 +15,7 @@ public static boolean isHarshad(long n) {
if (n <= 0) return false;
long t = n;
- int sumOfDigits = 0;
+ long sumOfDigits = 0;
while (t > 0) {
sumOfDigits += t % 10;
t /= 10;
From e759544c333de9b98ff51458e1d71c69006f976b Mon Sep 17 00:00:00 2001
From: Niklas Hoefflin <122729995+itakurah@users.noreply.github.com>
Date: Sat, 2 Dec 2023 18:53:17 +0100
Subject: [PATCH 0068/1338] Add Boruvka's algorithm to find Minimum Spanning
Tree (#4964)
---
DIRECTORY.md | 20 ++
.../graphs/BoruvkaAlgorithm.java | 217 ++++++++++++++++++
.../graphs/BoruvkaAlgorithmTest.java | 191 +++++++++++++++
3 files changed, 428 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithm.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithmTest.java
diff --git a/DIRECTORY.md b/DIRECTORY.md
index 6de516618484..89f08c27248b 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -19,6 +19,7 @@
* [PowerSum](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/backtracking/PowerSum.java)
* [WordSearch](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/backtracking/WordSearch.java)
* bitmanipulation
+ * [BitSwap](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/BitSwap.java)
* [HighestSetBit](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/HighestSetBit.java)
* [IndexOfRightMostSetBit](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/IndexOfRightMostSetBit.java)
* [IsEven](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/IsEven.java)
@@ -81,6 +82,8 @@
* [LFUCache](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/caches/LFUCache.java)
* [LRUCache](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/caches/LRUCache.java)
* [MRUCache](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/caches/MRUCache.java)
+ * crdt
+ * [GCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java)
* disjointsetunion
* [DisjointSetUnion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnion.java)
* [Node](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/disjointsetunion/Node.java)
@@ -90,6 +93,7 @@
* [A Star](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/A_Star.java)
* [BellmanFord](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/BellmanFord.java)
* [BipartiteGrapfDFS](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/BipartiteGrapfDFS.java)
+ * [BoruvkaAlgorithm](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithm.java)
* [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)
* [DIJSKSTRAS ALGORITHM](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/graphs/DIJSKSTRAS_ALGORITHM.java)
@@ -239,6 +243,7 @@
* [SubsetCount](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/SubsetCount.java)
* [SubsetSum](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/SubsetSum.java)
* [Sum Of Subset](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/Sum_Of_Subset.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)
* [WildcardMatching](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/WildcardMatching.java)
* [WineProblem](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/dynamicprogramming/WineProblem.java)
@@ -281,7 +286,9 @@
* [FFT](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/FFT.java)
* [FFTBluestein](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/FFTBluestein.java)
* [FibonacciJavaStreams](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/FibonacciJavaStreams.java)
+ * [FibonacciLoop](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/FibonacciLoop.java)
* [FibonacciNumberCheck](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/FibonacciNumberCheck.java)
+ * [FibonacciNumberGoldenRation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/FibonacciNumberGoldenRation.java)
* [FindKthNumber](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/FindKthNumber.java)
* [FindMax](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/FindMax.java)
* [FindMaxRecursion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/FindMaxRecursion.java)
@@ -307,6 +314,7 @@
* [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)
* [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)
@@ -359,6 +367,7 @@
* 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)
@@ -564,6 +573,7 @@
* [PowerSumTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/backtracking/PowerSumTest.java)
* [WordSearchTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/backtracking/WordSearchTest.java)
* bitmanipulation
+ * [BitSwapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/BitSwapTest.java)
* [HighestSetBitTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/HighestSetBitTest.java)
* [IndexOfRightMostSetBitTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/IndexOfRightMostSetBitTest.java)
* [IsEvenTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/IsEvenTest.java)
@@ -605,9 +615,12 @@
* [LFUCacheTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/caches/LFUCacheTest.java)
* [LRUCacheTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/caches/LRUCacheTest.java)
* [MRUCacheTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/caches/MRUCacheTest.java)
+ * crdt
+ * [GCounterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/GCounterTest.java)
* disjointsetunion
* [DisjointSetUnionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionTest.java)
* graphs
+ * [BoruvkaAlgorithmTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithmTest.java)
* [HamiltonianCycleTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/HamiltonianCycleTest.java)
* [KosarajuTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/KosarajuTest.java)
* [TarjansAlgorithmTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/graphs/TarjansAlgorithmTest.java)
@@ -666,6 +679,7 @@
* [OptimalJobSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/OptimalJobSchedulingTest.java)
* [PartitionProblemTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/PartitionProblemTest.java)
* [SubsetCountTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/SubsetCountTest.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)
* [WildcardMatchingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/dynamicprogramming/WildcardMatchingTest.java)
* geometry
@@ -700,7 +714,9 @@
* [FastInverseSqrtTests](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/FastInverseSqrtTests.java)
* [FFTTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/FFTTest.java)
* [FibonacciJavaStreamsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/FibonacciJavaStreamsTest.java)
+ * [FibonacciLoopTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/FibonacciLoopTest.java)
* [FibonacciNumberCheckTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/FibonacciNumberCheckTest.java)
+ * [FibonacciNumberGoldenRationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/FibonacciNumberGoldenRationTest.java)
* [FindMaxRecursionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/FindMaxRecursionTest.java)
* [FindMaxTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/FindMaxTest.java)
* [FindMinRecursionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/FindMinRecursionTest.java)
@@ -719,6 +735,7 @@
* [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)
* [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)
@@ -755,6 +772,7 @@
* [TwinPrimeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/TwinPrimeTest.java)
* [VolumeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/VolumeTest.java)
* misc
+ * [MapReduceTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/misc/MapReduceTest.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)
@@ -763,6 +781,7 @@
* others
* [ArrayLeftRotationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/ArrayLeftRotationTest.java)
* [BestFitCPUTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/BestFitCPUTest.java)
+ * [BoyerMooreTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/BoyerMooreTest.java)
* cn
* [HammingDistanceTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/cn/HammingDistanceTest.java)
* [ConwayTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/ConwayTest.java)
@@ -798,6 +817,7 @@
* [HowManyTimesRotatedTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/HowManyTimesRotatedTest.java)
* [KMPSearchTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/KMPSearchTest.java)
* [OrderAgnosticBinarySearchTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/OrderAgnosticBinarySearchTest.java)
+ * [PerfectBinarySearchTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java)
* [QuickSelectTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/QuickSelectTest.java)
* [RabinKarpAlgorithmTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/RabinKarpAlgorithmTest.java)
* [RecursiveBinarySearchTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/searches/RecursiveBinarySearchTest.java)
diff --git a/src/main/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithm.java b/src/main/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithm.java
new file mode 100644
index 000000000000..dcdb08ad133e
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithm.java
@@ -0,0 +1,217 @@
+package com.thealgorithms.datastructures.graphs;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Boruvka's algorithm to find Minimum Spanning Tree
+ * (https://en.wikipedia.org/wiki/Bor%C5%AFvka%27s_algorithm)
+ *
+ * @author itakurah (https://github.com/itakurah)
+ */
+
+final class BoruvkaAlgorithm {
+ private BoruvkaAlgorithm() {
+ }
+
+ /**
+ * Represents an edge in the graph
+ */
+ static class Edge {
+ final int src;
+ final int dest;
+ final int weight;
+
+ Edge(final int src, final int dest, final int weight) {
+ this.src = src;
+ this.dest = dest;
+ this.weight = weight;
+ }
+ }
+
+ /**
+ * Represents the graph
+ */
+ static class Graph {
+ final int vertex;
+ final List edges;
+
+ /**
+ * Constructor for the graph
+ *
+ * @param vertex number of vertices
+ * @param edges list of edges
+ */
+ Graph(final int vertex, final List edges) {
+ if (vertex < 0) {
+ throw new IllegalArgumentException("Number of vertices must be positive");
+ }
+ if (edges == null || edges.isEmpty()) {
+ throw new IllegalArgumentException("Edges list must not be null or empty");
+ }
+ for (final var edge : edges) {
+ checkEdgeVertices(edge.src, vertex);
+ checkEdgeVertices(edge.dest, vertex);
+ }
+
+ this.vertex = vertex;
+ this.edges = edges;
+ }
+ }
+
+ /**
+ * Represents a subset for Union-Find operations
+ */
+ private static class Component {
+ int parent;
+ int rank;
+
+ Component(final int parent, final int rank) {
+ this.parent = parent;
+ this.rank = rank;
+ }
+ }
+
+ /**
+ * Represents the state of Union-Find components and the result list
+ */
+ private static class BoruvkaState {
+ List result;
+ Component[] components;
+ final Graph graph;
+
+ BoruvkaState(final Graph graph) {
+ this.result = new ArrayList<>();
+ this.components = initializeComponents(graph);
+ this.graph = graph;
+ }
+
+ /**
+ * Adds the cheapest edges to the result list and performs Union operation on the subsets.
+ *
+ * @param cheapest Array containing the cheapest edge for each subset.
+ */
+ void merge(final Edge[] cheapest) {
+ for (int i = 0; i < graph.vertex; ++i) {
+ if (cheapest[i] != null) {
+ final var component1 = find(components, cheapest[i].src);
+ final var component2 = find(components, cheapest[i].dest);
+
+ if (component1 != component2) {
+ result.add(cheapest[i]);
+ union(components, component1, component2);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks if there are more edges to add to the result list
+ *
+ * @return true if there are more edges to add, false otherwise
+ */
+ boolean hasMoreEdgesToAdd() {
+ return result.size() < graph.vertex - 1;
+ }
+
+ /**
+ * Computes the cheapest edges for each subset in the Union-Find structure.
+ *
+ * @return an array containing the cheapest edge for each subset.
+ */
+ private Edge[] computeCheapestEdges() {
+ Edge[] cheapest = new Edge[graph.vertex];
+ for (final var edge : graph.edges) {
+ final var set1 = find(components, edge.src);
+ final var set2 = find(components, edge.dest);
+
+ if (set1 != set2) {
+ if (cheapest[set1] == null || edge.weight < cheapest[set1].weight) {
+ cheapest[set1] = edge;
+ }
+ if (cheapest[set2] == null || edge.weight < cheapest[set2].weight) {
+ cheapest[set2] = edge;
+ }
+ }
+ }
+ return cheapest;
+ }
+
+ /**
+ * Initializes subsets for Union-Find
+ *
+ * @param graph the graph
+ * @return the initialized subsets
+ */
+ private static Component[] initializeComponents(final Graph graph) {
+ Component[] components = new Component[graph.vertex];
+ for (int v = 0; v < graph.vertex; ++v) {
+ components[v] = new Component(v, 0);
+ }
+ return components;
+ }
+ }
+
+ /**
+ * Finds the parent of the subset using path compression
+ *
+ * @param components array of subsets
+ * @param i index of the subset
+ * @return the parent of the subset
+ */
+ static int find(final Component[] components, final int i) {
+ if (components[i].parent != i) {
+ components[i].parent = find(components, components[i].parent);
+ }
+ return components[i].parent;
+ }
+
+ /**
+ * Performs the Union operation for Union-Find
+ *
+ * @param components array of subsets
+ * @param x index of the first subset
+ * @param y index of the second subset
+ */
+ static void union(Component[] components, final int x, final int y) {
+ final int xroot = find(components, x);
+ final int yroot = find(components, y);
+
+ if (components[xroot].rank < components[yroot].rank) {
+ components[xroot].parent = yroot;
+ } else if (components[xroot].rank > components[yroot].rank) {
+ components[yroot].parent = xroot;
+ } else {
+ components[yroot].parent = xroot;
+ components[xroot].rank++;
+ }
+ }
+
+ /**
+ * Boruvka's algorithm to find the Minimum Spanning Tree
+ *
+ * @param graph the graph
+ * @return list of edges in the Minimum Spanning Tree
+ */
+ static List boruvkaMST(final Graph graph) {
+ var boruvkaState = new BoruvkaState(graph);
+
+ while (boruvkaState.hasMoreEdgesToAdd()) {
+ final var cheapest = boruvkaState.computeCheapestEdges();
+ boruvkaState.merge(cheapest);
+ }
+ return boruvkaState.result;
+ }
+
+ /**
+ * Checks if the edge vertices are in a valid range
+ *
+ * @param vertex the vertex to check
+ * @param upperBound the upper bound for the vertex range
+ */
+ private static void checkEdgeVertices(final int vertex, final int upperBound) {
+ if (vertex < 0 || vertex >= upperBound) {
+ throw new IllegalArgumentException("Edge vertex out of range");
+ }
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithmTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithmTest.java
new file mode 100644
index 000000000000..b5f75f5e831e
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/graphs/BoruvkaAlgorithmTest.java
@@ -0,0 +1,191 @@
+package com.thealgorithms.datastructures.graphs;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import com.thealgorithms.datastructures.graphs.BoruvkaAlgorithm.Graph;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+public class BoruvkaAlgorithmTest {
+ @Test
+ public void testBoruvkaMSTV9E14() {
+ List edges = new ArrayList<>();
+
+ edges.add(new BoruvkaAlgorithm.Edge(0, 1, 10));
+ edges.add(new BoruvkaAlgorithm.Edge(0, 2, 12));
+ edges.add(new BoruvkaAlgorithm.Edge(1, 2, 9));
+ edges.add(new BoruvkaAlgorithm.Edge(1, 3, 8));
+ edges.add(new BoruvkaAlgorithm.Edge(2, 4, 3));
+ edges.add(new BoruvkaAlgorithm.Edge(2, 5, 1));
+ edges.add(new BoruvkaAlgorithm.Edge(4, 5, 3));
+ edges.add(new BoruvkaAlgorithm.Edge(4, 3, 7));
+ edges.add(new BoruvkaAlgorithm.Edge(3, 6, 8));
+ edges.add(new BoruvkaAlgorithm.Edge(3, 7, 5));
+ edges.add(new BoruvkaAlgorithm.Edge(5, 7, 6));
+ edges.add(new BoruvkaAlgorithm.Edge(6, 7, 9));
+ edges.add(new BoruvkaAlgorithm.Edge(6, 8, 2));
+ edges.add(new BoruvkaAlgorithm.Edge(7, 8, 11));
+
+ final var graph = new Graph(9, edges);
+ /**
+ * Adjacency matrix
+ * 0 1 2 3 4 5 6 7 8
+ * 0 0 10 12 0 0 0 0 0 0
+ * 1 10 0 9 8 0 0 0 0 0
+ * 2 12 9 0 0 3 1 0 0 0
+ * 3 0 8 0 0 7 0 8 5 0
+ * 4 0 0 3 7 0 3 0 0 0
+ * 5 0 0 1 0 3 0 0 6 0
+ * 6 0 0 0 8 0 0 0 9 2
+ * 7 0 0 0 5 0 6 9 0 11
+ * 8 0 0 0 0 0 0 2 11 0
+ */
+ final var result = BoruvkaAlgorithm.boruvkaMST(graph);
+ assertEquals(8, result.size());
+ assertEquals(43, computeTotalWeight(result));
+ }
+
+ @Test
+ void testBoruvkaMSTV2E1() {
+ List edges = new ArrayList<>();
+
+ edges.add(new BoruvkaAlgorithm.Edge(0, 1, 10));
+
+ final var graph = new Graph(2, edges);
+
+ /**
+ * Adjacency matrix
+ * 0 1
+ * 0 0 10
+ * 1 10 0
+ */
+ final var result = BoruvkaAlgorithm.boruvkaMST(graph);
+ assertEquals(1, result.size());
+ assertEquals(10, computeTotalWeight(result));
+ }
+
+ @Test
+ void testCompleteGraphK4() {
+ List edges = new ArrayList<>();
+ edges.add(new BoruvkaAlgorithm.Edge(0, 1, 7));
+ edges.add(new BoruvkaAlgorithm.Edge(0, 2, 2));
+ edges.add(new BoruvkaAlgorithm.Edge(0, 3, 5));
+ edges.add(new BoruvkaAlgorithm.Edge(1, 2, 3));
+ edges.add(new BoruvkaAlgorithm.Edge(1, 3, 4));
+ edges.add(new BoruvkaAlgorithm.Edge(2, 3, 1));
+
+ final var graph = new Graph(4, edges);
+
+ /**
+ * Adjacency matrix
+ * 0 1 2 3
+ * 0 0 7 2 5
+ * 1 7 0 3 4
+ * 2 2 3 0 1
+ * 3 5 4 1 0
+ */
+ final var result = BoruvkaAlgorithm.boruvkaMST(graph);
+ assertEquals(3, result.size());
+ assertEquals(6, computeTotalWeight(result));
+ }
+
+ @Test
+ void testNegativeVertices() {
+ Exception exception1 = assertThrows(IllegalArgumentException.class, () -> new Graph(-1, null));
+ String expectedMessage = "Number of vertices must be positive";
+ String actualMessage = exception1.getMessage();
+
+ assertTrue(actualMessage.contains(expectedMessage));
+ }
+
+ @Test
+ void testEdgesNull() {
+ Exception exception = assertThrows(IllegalArgumentException.class, () -> new Graph(0, null));
+ String expectedMessage = "Edges list must not be null or empty";
+ String actualMessage = exception.getMessage();
+
+ assertTrue(actualMessage.contains(expectedMessage));
+ }
+
+ @Test
+ void testEdgesEmpty() {
+ Exception exception = assertThrows(IllegalArgumentException.class, () -> new Graph(0, new ArrayList<>()));
+ String expectedMessage = "Edges list must not be null or empty";
+ String actualMessage = exception.getMessage();
+
+ assertTrue(actualMessage.contains(expectedMessage));
+ }
+
+ @Test
+ void testEdgesRange() {
+ // Valid input
+ List validEdges = new ArrayList<>();
+ validEdges.add(new BoruvkaAlgorithm.Edge(0, 1, 2));
+ validEdges.add(new BoruvkaAlgorithm.Edge(1, 2, 3));
+ final var validGraph = new BoruvkaAlgorithm.Graph(3, validEdges);
+ assertEquals(validEdges, validGraph.edges);
+
+ // Edge source out of range
+ Exception exception1 = assertThrows(IllegalArgumentException.class, () -> {
+ List invalidEdges = new ArrayList<>();
+ invalidEdges.add(new BoruvkaAlgorithm.Edge(-1, 1, 2));
+ final var invalidGraph = new BoruvkaAlgorithm.Graph(1, invalidEdges);
+ assertEquals(invalidEdges, invalidGraph.edges);
+ });
+ String expectedMessage1 = "Edge vertex out of range";
+ String actualMessage1 = exception1.getMessage();
+
+ assertTrue(actualMessage1.contains(expectedMessage1));
+
+ // Edge source out of range
+ Exception exception2 = assertThrows(IllegalArgumentException.class, () -> {
+ List invalidEdges = new ArrayList<>();
+ invalidEdges.add(new BoruvkaAlgorithm.Edge(1, 0, 2));
+ final var invalidGraph = new BoruvkaAlgorithm.Graph(1, invalidEdges);
+ assertEquals(invalidEdges, invalidGraph.edges);
+ });
+ String expectedMessage2 = "Edge vertex out of range";
+ String actualMessage2 = exception2.getMessage();
+
+ assertTrue(actualMessage2.contains(expectedMessage2));
+
+ // Edge destination out of range
+ Exception exception3 = assertThrows(IllegalArgumentException.class, () -> {
+ List invalidEdges = new ArrayList<>();
+ invalidEdges.add(new BoruvkaAlgorithm.Edge(0, -1, 2));
+ final var invalidGraph = new BoruvkaAlgorithm.Graph(1, invalidEdges);
+ assertEquals(invalidEdges, invalidGraph.edges);
+ });
+ String expectedMessage3 = "Edge vertex out of range";
+ String actualMessage3 = exception3.getMessage();
+
+ assertTrue(actualMessage3.contains(expectedMessage3));
+
+ // Edge destination out of range
+ Exception exception4 = assertThrows(IllegalArgumentException.class, () -> {
+ List invalidEdges = new ArrayList<>();
+ invalidEdges.add(new BoruvkaAlgorithm.Edge(0, 1, 2));
+ final var invalidGraph = new BoruvkaAlgorithm.Graph(1, invalidEdges);
+ assertEquals(invalidEdges, invalidGraph.edges);
+ });
+ String expectedMessage4 = "Edge vertex out of range";
+ String actualMessage4 = exception4.getMessage();
+
+ assertTrue(actualMessage4.contains(expectedMessage4));
+ }
+
+ /**
+ * Computes the total weight of the Minimum Spanning Tree
+ *
+ * @param result list of edges in the Minimum Spanning Tree
+ * @return the total weight of the Minimum Spanning Tree
+ */
+ int computeTotalWeight(final List result) {
+ int totalWeight = 0;
+ for (final var edge : result) {
+ totalWeight += edge.weight;
+ }
+ return totalWeight;
+ }
+}
From 3001620c1eef3246f666c459f096ba390afce06b Mon Sep 17 00:00:00 2001
From: Niklas Hoefflin <122729995+itakurah@users.noreply.github.com>
Date: Mon, 4 Dec 2023 17:22:02 +0100
Subject: [PATCH 0069/1338] Add PN-Counter (#4974)
---
DIRECTORY.md | 2 +
.../datastructures/crdt/PNCounter.java | 100 ++++++++++++++++++
.../datastructures/crdt/PNCounterTest.java | 54 ++++++++++
3 files changed, 156 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/crdt/PNCounterTest.java
diff --git a/DIRECTORY.md b/DIRECTORY.md
index 89f08c27248b..0548d3455581 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -84,6 +84,7 @@
* [MRUCache](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/caches/MRUCache.java)
* crdt
* [GCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java)
+ * [PNCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java)
* disjointsetunion
* [DisjointSetUnion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnion.java)
* [Node](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/disjointsetunion/Node.java)
@@ -617,6 +618,7 @@
* [MRUCacheTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/caches/MRUCacheTest.java)
* crdt
* [GCounterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/GCounterTest.java)
+ * [PNCounterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/PNCounterTest.java)
* disjointsetunion
* [DisjointSetUnionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionTest.java)
* graphs
diff --git a/src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java b/src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java
new file mode 100644
index 000000000000..828e0b0804b3
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java
@@ -0,0 +1,100 @@
+package com.thealgorithms.datastructures.crdt;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * PN-Counter (Positive-Negative Counter) is a state-based CRDT (Conflict-free Replicated Data Type)
+ * designed for tracking counts with both increments and decrements in a distributed and concurrent environment.
+ * It combines two G-Counters, one for increments (P) and one for decrements (N).
+ * The total count is obtained by subtracting the value of the decrement counter from the increment counter.
+ * This implementation supports incrementing, decrementing, querying the total count,
+ * comparing with other PN-Counters, and merging with another PN-Counter
+ * to compute the element-wise maximum for both increment and decrement counters.
+ * (https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type)
+ *
+ * @author itakurah (Niklas Hoefflin) (https://github.com/itakurah)
+ */
+
+class PNCounter {
+ private final Map P;
+ private final Map N;
+ private final int myId;
+ private final int n;
+
+ /**
+ * Constructs a PN-Counter for a cluster of n nodes.
+ *
+ * @param myId The identifier of the current node.
+ * @param n The number of nodes in the cluster.
+ */
+ public PNCounter(int myId, int n) {
+ this.myId = myId;
+ this.n = n;
+ this.P = new HashMap<>();
+ this.N = new HashMap<>();
+
+ for (int i = 0; i < n; i++) {
+ P.put(i, 0);
+ N.put(i, 0);
+ }
+ }
+
+ /**
+ * Increments the increment counter for the current node.
+ */
+ public void increment() {
+ P.put(myId, P.get(myId) + 1);
+ }
+
+ /**
+ * Increments the decrement counter for the current node.
+ */
+ public void decrement() {
+ N.put(myId, N.get(myId) + 1);
+ }
+
+ /**
+ * Gets the total value of the counter by subtracting the decrement counter from the increment counter.
+ *
+ * @return The total value of the counter.
+ */
+ public int value() {
+ int sumP = P.values().stream().mapToInt(Integer::intValue).sum();
+ int sumN = N.values().stream().mapToInt(Integer::intValue).sum();
+ return sumP - sumN;
+ }
+
+ /**
+ * Compares the state of this PN-Counter with another PN-Counter.
+ *
+ * @param other The other PN-Counter to compare with.
+ * @return True if the state of this PN-Counter is less than or equal to the state of the other PN-Counter.
+ */
+ public boolean compare(PNCounter other) {
+ if (this.n != other.n) {
+ throw new IllegalArgumentException("Cannot compare PN-Counters with different number of nodes");
+ }
+ for (int i = 0; i < n; i++) {
+ if (this.P.get(i) > other.P.get(i) && this.N.get(i) > other.N.get(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Merges the state of this PN-Counter with another PN-Counter.
+ *
+ * @param other The other PN-Counter to merge with.
+ */
+ public void merge(PNCounter other) {
+ if (this.n != other.n) {
+ throw new IllegalArgumentException("Cannot merge PN-Counters with different number of nodes");
+ }
+ for (int i = 0; i < n; i++) {
+ this.P.put(i, Math.max(this.P.get(i), other.P.get(i)));
+ this.N.put(i, Math.max(this.N.get(i), other.N.get(i)));
+ }
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/crdt/PNCounterTest.java b/src/test/java/com/thealgorithms/datastructures/crdt/PNCounterTest.java
new file mode 100644
index 000000000000..46c22a6edcb7
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/crdt/PNCounterTest.java
@@ -0,0 +1,54 @@
+package com.thealgorithms.datastructures.crdt;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+public class PNCounterTest {
+
+ @Test
+ public void testIncrement() {
+ PNCounter counter = new PNCounter(0, 3);
+ counter.increment();
+ assertEquals(1, counter.value());
+ }
+
+ @Test
+ public void testDecrement() {
+ PNCounter counter = new PNCounter(0, 3);
+ counter.decrement();
+ assertEquals(-1, counter.value());
+ }
+
+ @Test
+ public void testIncrementAndDecrement() {
+ PNCounter counter = new PNCounter(0, 3);
+ counter.increment();
+ counter.increment();
+ counter.decrement();
+ assertEquals(1, counter.value());
+ }
+
+ @Test
+ public void testCompare() {
+ PNCounter counter1 = new PNCounter(0, 3);
+ counter1.increment();
+ PNCounter counter2 = new PNCounter(1, 3);
+ assertTrue(counter1.compare(counter2));
+ counter2.increment();
+ assertTrue(counter2.compare(counter1));
+ counter1.decrement();
+ assertFalse(counter1.compare(counter2));
+ }
+
+ @Test
+ public void testMerge() {
+ PNCounter counter1 = new PNCounter(0, 3);
+ counter1.increment();
+ counter1.increment();
+ PNCounter counter2 = new PNCounter(1, 3);
+ counter2.increment();
+ counter1.merge(counter2);
+ assertEquals(3, counter1.value());
+ }
+}
From e59a3b1ebba0b484fad64adb06aedc06eb366825 Mon Sep 17 00:00:00 2001
From: Niklas Hoefflin <122729995+itakurah@users.noreply.github.com>
Date: Tue, 5 Dec 2023 19:39:18 +0100
Subject: [PATCH 0070/1338] Add G-Set (Grow-only Set) (#4975)
---
DIRECTORY.md | 2 +
.../datastructures/crdt/GSet.java | 65 +++++++++++++++++
.../datastructures/crdt/GSetTest.java | 71 +++++++++++++++++++
3 files changed, 138 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/crdt/GSet.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java
diff --git a/DIRECTORY.md b/DIRECTORY.md
index 0548d3455581..4a94809560a1 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -84,6 +84,7 @@
* [MRUCache](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/caches/MRUCache.java)
* crdt
* [GCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java)
+ * [GSet](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java)
* [PNCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java)
* disjointsetunion
* [DisjointSetUnion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnion.java)
@@ -618,6 +619,7 @@
* [MRUCacheTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/caches/MRUCacheTest.java)
* crdt
* [GCounterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/GCounterTest.java)
+ * [GSetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java)
* [PNCounterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/PNCounterTest.java)
* disjointsetunion
* [DisjointSetUnionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionTest.java)
diff --git a/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java b/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java
new file mode 100644
index 000000000000..37873adc2573
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java
@@ -0,0 +1,65 @@
+package com.thealgorithms.datastructures.crdt;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * GSet (Grow-only Set) is a state-based CRDT (Conflict-free Replicated Data Type)
+ * that allows only the addition of elements and ensures that once an element is added,
+ * it cannot be removed. The merge operation of two G-Sets is their union.
+ * This implementation supports adding elements, looking up elements, comparing with other G-Sets,
+ * and merging with another G-Set to create a new G-Set containing all unique elements from both sets.
+ * (https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type)
+ *
+ * @author itakurah (Niklas Hoefflin) (https://github.com/itakurah)
+ */
+
+public class GSet {
+ private final Set elements;
+
+ /**
+ * Constructs an empty G-Set.
+ */
+ public GSet() {
+ this.elements = new HashSet<>();
+ }
+
+ /**
+ * Adds an element to the G-Set.
+ *
+ * @param e the element to be added
+ */
+ public void addElement(T e) {
+ elements.add(e);
+ }
+
+ /**
+ * Checks if the given element is present in the G-Set.
+ *
+ * @param e the element to be checked
+ * @return true if the element is present, false otherwise
+ */
+ public boolean lookup(T e) {
+ return elements.contains(e);
+ }
+
+ /**
+ * Compares the G-Set with another G-Set to check if it is a subset.
+ *
+ * @param other the other G-Set to compare with
+ * @return true if the current G-Set is a subset of the other, false otherwise
+ */
+ public boolean compare(GSet other) {
+ return elements.containsAll(other.elements);
+ }
+
+ /**
+ * Merges the current G-Set with another G-Set, creating a new G-Set
+ * containing all unique elements from both sets.
+ *
+ * @param other the G-Set to merge with
+ */
+ public void merge(GSet other) {
+ elements.addAll(other.elements);
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java b/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java
new file mode 100644
index 000000000000..99588259006f
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java
@@ -0,0 +1,71 @@
+package com.thealgorithms.datastructures.crdt;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+class GSetTest {
+
+ @Test
+ void testAddElement() {
+ GSet gSet = new GSet<>();
+ gSet.addElement("apple");
+ gSet.addElement("orange");
+
+ assertTrue(gSet.lookup("apple"));
+ assertTrue(gSet.lookup("orange"));
+ assertFalse(gSet.lookup("banana"));
+ }
+
+ @Test
+ void testLookup() {
+ GSet gSet = new GSet<>();
+ gSet.addElement(1);
+ gSet.addElement(2);
+
+ assertTrue(gSet.lookup(1));
+ assertTrue(gSet.lookup(2));
+ assertFalse(gSet.lookup(3));
+ }
+
+ @Test
+ void testCompare() {
+ GSet gSet1 = new GSet<>();
+ GSet gSet2 = new GSet<>();
+
+ gSet1.addElement("apple");
+ gSet1.addElement("orange");
+
+ gSet2.addElement("orange");
+ gSet2.addElement("banana");
+
+ assertFalse(gSet1.compare(gSet2));
+
+ GSet gSet3 = new GSet<>();
+ gSet3.addElement("apple");
+ gSet3.addElement("orange");
+
+ assertTrue(gSet1.compare(gSet3));
+ }
+
+ @Test
+ void testMerge() {
+ GSet gSet1 = new GSet<>();
+ GSet gSet2 = new GSet<>();
+
+ gSet1.addElement("apple");
+ gSet1.addElement("orange");
+
+ gSet2.addElement("orange");
+ gSet2.addElement("banana");
+
+ GSet mergedSet = new GSet<>();
+ mergedSet.merge(gSet1);
+ mergedSet.merge(gSet2);
+
+ assertTrue(mergedSet.lookup("apple"));
+ assertTrue(mergedSet.lookup("orange"));
+ assertTrue(mergedSet.lookup("banana"));
+ assertFalse(mergedSet.lookup("grape"));
+ }
+}
From 36580bac1e1901486950a2df27e534665f47e6b7 Mon Sep 17 00:00:00 2001
From: Nassor Shabataka <86209375+ImmaculateShaba@users.noreply.github.com>
Date: Wed, 6 Dec 2023 02:37:58 -0500
Subject: [PATCH 0071/1338] Fix typo in NextGraterElement (#4976)
---
...erElement.java => NextGreaterElement.java} | 24 +++++++++----------
1 file changed, 12 insertions(+), 12 deletions(-)
rename src/main/java/com/thealgorithms/stacks/{NextGraterElement.java => NextGreaterElement.java} (69%)
diff --git a/src/main/java/com/thealgorithms/stacks/NextGraterElement.java b/src/main/java/com/thealgorithms/stacks/NextGreaterElement.java
similarity index 69%
rename from src/main/java/com/thealgorithms/stacks/NextGraterElement.java
rename to src/main/java/com/thealgorithms/stacks/NextGreaterElement.java
index 0cf56349c662..d681e41fbfc3 100644
--- a/src/main/java/com/thealgorithms/stacks/NextGraterElement.java
+++ b/src/main/java/com/thealgorithms/stacks/NextGreaterElement.java
@@ -4,26 +4,26 @@
import java.util.Stack;
/*
- Given an array "input" you need to print the first grater element for each element.
- For a given element x of an array, the Next Grater element of that element is the
- first grater element to the right side of it. If no such element is present print -1.
+ Given an array "input" you need to print the first greater element for each element.
+ For a given element x of an array, the Next greater element of that element is the
+ first greater element to the right side of it. If no such element is present print -1.
Example
input = { 2, 7, 3, 5, 4, 6, 8 };
At i = 0
- Next Grater element between (1 to n) is 7
+ Next greater element between (1 to n) is 7
At i = 1
- Next Grater element between (2 to n) is 8
+ Next greater element between (2 to n) is 8
At i = 2
- Next Grater element between (3 to n) is 5
+ Next greater element between (3 to n) is 5
At i = 3
- Next Grater element between (4 to n) is 6
+ Next greater element between (4 to n) is 6
At i = 4
- Next Grater element between (5 to n) is 6
+ Next greater element between (5 to n) is 6
At i = 5
- Next Grater element between (6 to n) is 8
+ Next greater element between (6 to n) is 8
At i = 6
- Next Grater element between (6 to n) is -1
+ Next greater element between (6 to n) is -1
result : [7, 8, 5, 6, 6, 8, -1]
@@ -37,11 +37,11 @@ Next Grater element between (6 to n) is -1
popped elements.
d. Finally, push the next in the stack.
- 3. If elements are left in stack after completing while loop then their Next Grater element is
+ 3. If elements are left in stack after completing while loop then their Next greater element is
-1.
*/
-public class NextGraterElement {
+public class NextGreaterElement {
public static int[] findNextGreaterElements(int[] array) {
if (array == null) {
From 249ee1dc994735a6cf02a6048ab8bedd2e91ce4a Mon Sep 17 00:00:00 2001
From: Niklas Hoefflin <122729995+itakurah@users.noreply.github.com>
Date: Thu, 7 Dec 2023 16:23:22 +0100
Subject: [PATCH 0072/1338] Add 2P-Set (Two-Phase Set) for both addition and
removal operations in distributed systems (#4977)
---
DIRECTORY.md | 4 +-
.../datastructures/crdt/TwoPSet.java | 84 +++++++++++++++++++
.../datastructures/crdt/TwoPSetTest.java | 68 +++++++++++++++
3 files changed, 155 insertions(+), 1 deletion(-)
create mode 100644 src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java
diff --git a/DIRECTORY.md b/DIRECTORY.md
index 4a94809560a1..703642a0d28e 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -86,6 +86,7 @@
* [GCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java)
* [GSet](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java)
* [PNCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java)
+ * [TwoPSet](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java)
* disjointsetunion
* [DisjointSetUnion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnion.java)
* [Node](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/disjointsetunion/Node.java)
@@ -528,7 +529,7 @@
* [InfixToPostfix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/InfixToPostfix.java)
* [LargestRectangle](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/LargestRectangle.java)
* [MaximumMinimumWindow](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/MaximumMinimumWindow.java)
- * [NextGraterElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/NextGraterElement.java)
+ * [NextGreaterElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/NextGreaterElement.java)
* [NextSmallerElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/NextSmallerElement.java)
* [PostfixToInfix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/PostfixToInfix.java)
* [StackPostfixNotation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/StackPostfixNotation.java)
@@ -621,6 +622,7 @@
* [GCounterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/GCounterTest.java)
* [GSetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java)
* [PNCounterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/PNCounterTest.java)
+ * [TwoPSetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java)
* disjointsetunion
* [DisjointSetUnionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/disjointsetunion/DisjointSetUnionTest.java)
* graphs
diff --git a/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java b/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java
new file mode 100644
index 000000000000..f5e155c28d8d
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java
@@ -0,0 +1,84 @@
+package com.thealgorithms.datastructures.crdt;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * TwoPhaseSet (2P-Set) is a state-based CRDT (Conflict-free Replicated Data Type) designed for managing sets
+ * with support for both addition and removal operations in a distributed and concurrent environment.
+ * It combines two G-Sets (grow-only sets) - one set for additions and another set (tombstone set) for removals.
+ * Once an element is removed and placed in the tombstone set, it cannot be re-added, adhering to "remove-wins" semantics.
+ * This implementation supports querying the presence of elements, adding elements, removing elements,
+ * comparing with other 2P-Sets, and merging two 2P-Sets while preserving the remove-wins semantics.
+ * (https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type)
+ *
+ * @author itakurah (Niklas Hoefflin) (https://github.com/itakurah)
+ */
+
+public class TwoPSet {
+ private Set setA;
+ private Set setR;
+
+ /**
+ * Constructs an empty Two-Phase Set.
+ */
+ public TwoPSet() {
+ this.setA = new HashSet<>();
+ this.setR = new HashSet<>();
+ }
+
+ /**
+ * Checks if an element is in the set and has not been removed.
+ *
+ * @param element The element to be checked.
+ * @return True if the element is in the set and has not been removed, otherwise false.
+ */
+ public boolean lookup(String element) {
+ return setA.contains(element) && !setR.contains(element);
+ }
+
+ /**
+ * Adds an element to the set.
+ *
+ * @param element The element to be added.
+ */
+ public void add(String element) {
+ setA.add(element);
+ }
+
+ /**
+ * Removes an element from the set. The element will be placed in the tombstone set.
+ *
+ * @param element The element to be removed.
+ */
+ public void remove(String element) {
+ if (lookup(element)) {
+ setR.add(element);
+ }
+ }
+
+ /**
+ * Compares the current 2P-Set with another 2P-Set.
+ *
+ * @param otherSet The other 2P-Set to compare with.
+ * @return True if both SetA and SetR are subset, otherwise false.
+ */
+ public boolean compare(TwoPSet otherSet) {
+ return otherSet.setA.containsAll(setA) && otherSet.setR.containsAll(setR);
+ }
+
+ /**
+ * Merges the current 2P-Set with another 2P-Set.
+ *
+ * @param otherSet The other 2P-Set to merge with.
+ * @return A new 2P-Set containing the merged elements.
+ */
+ public TwoPSet merge(TwoPSet otherSet) {
+ TwoPSet mergedSet = new TwoPSet();
+ mergedSet.setA.addAll(this.setA);
+ mergedSet.setA.addAll(otherSet.setA);
+ mergedSet.setR.addAll(this.setR);
+ mergedSet.setR.addAll(otherSet.setR);
+ return mergedSet;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java b/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java
new file mode 100644
index 000000000000..18ab5c169e5c
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java
@@ -0,0 +1,68 @@
+package com.thealgorithms.datastructures.crdt;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class TwoPSetTest {
+
+ private TwoPSet set;
+
+ @BeforeEach
+ void setUp() {
+ set = new TwoPSet();
+ }
+
+ @Test
+ void testLookup() {
+ set.add("A");
+ assertTrue(set.lookup("A"));
+ assertFalse(set.lookup("B"));
+ set.remove("A");
+ assertFalse(set.lookup("A"));
+ }
+
+ @Test
+ void testAdd() {
+ set.add("A");
+ assertTrue(set.lookup("A"));
+ }
+
+ @Test
+ void testRemove() {
+ set.add("A");
+ set.remove("A");
+ assertFalse(set.lookup("A"));
+ }
+
+ @Test
+ void testCompare() {
+ TwoPSet set1 = new TwoPSet();
+ set1.add("A");
+ set1.add("B");
+ TwoPSet set2 = new TwoPSet();
+ set2.add("A");
+ assertFalse(set1.compare(set2));
+ set2.add("B");
+ assertTrue(set1.compare(set2));
+ set1.remove("A");
+ assertFalse(set1.compare(set2));
+ set2.remove("A");
+ assertTrue(set1.compare(set2));
+ }
+
+ @Test
+ void testMerge() {
+ TwoPSet set1 = new TwoPSet();
+ set1.add("A");
+ set1.add("B");
+ TwoPSet set2 = new TwoPSet();
+ set2.add("B");
+ set2.add("C");
+ TwoPSet mergedSet = set1.merge(set2);
+ assertTrue(mergedSet.lookup("A"));
+ assertTrue(mergedSet.lookup("B"));
+ assertTrue(mergedSet.lookup("C"));
+ }
+}
From 92131de3774d6dc7be7662bd0a8a9c02704255d5 Mon Sep 17 00:00:00 2001
From: Niklas Hoefflin <122729995+itakurah@users.noreply.github.com>
Date: Thu, 7 Dec 2023 17:06:56 +0100
Subject: [PATCH 0073/1338] =?UTF-8?q?Fix=20compare()=20for=20subset=20chec?=
=?UTF-8?q?k=20(S.A=20=E2=8A=86=20T.A)=20(#4978)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../thealgorithms/datastructures/crdt/GSet.java | 2 +-
.../datastructures/crdt/GSetTest.java | 14 ++++----------
2 files changed, 5 insertions(+), 11 deletions(-)
diff --git a/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java b/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java
index 37873adc2573..2b8959ed0136 100644
--- a/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java
+++ b/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java
@@ -50,7 +50,7 @@ public boolean lookup(T e) {
* @return true if the current G-Set is a subset of the other, false otherwise
*/
public boolean compare(GSet other) {
- return elements.containsAll(other.elements);
+ return other.elements.containsAll(elements);
}
/**
diff --git a/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java b/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java
index 99588259006f..74250ede1f23 100644
--- a/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java
@@ -32,20 +32,14 @@ void testLookup() {
void testCompare() {
GSet gSet1 = new GSet<>();
GSet gSet2 = new GSet<>();
-
gSet1.addElement("apple");
gSet1.addElement("orange");
-
gSet2.addElement("orange");
- gSet2.addElement("banana");
-
assertFalse(gSet1.compare(gSet2));
-
- GSet gSet3 = new GSet<>();
- gSet3.addElement("apple");
- gSet3.addElement("orange");
-
- assertTrue(gSet1.compare(gSet3));
+ gSet2.addElement("apple");
+ assertTrue(gSet1.compare(gSet2));
+ gSet2.addElement("banana");
+ assertTrue(gSet1.compare(gSet2));
}
@Test
From b8b1dea38de84d7647921cd1859b7d58303e9b86 Mon Sep 17 00:00:00 2001
From: Niklas Hoefflin <122729995+itakurah@users.noreply.github.com>
Date: Fri, 8 Dec 2023 19:57:07 +0100
Subject: [PATCH 0074/1338] Add LWW Element Set (Last Write Wins Element Set)
(#4979)
---
DIRECTORY.md | 2 +
.../datastructures/crdt/LWWElementSet.java | 138 ++++++++++++++++++
.../crdt/LWWElementSetTest.java | 107 ++++++++++++++
3 files changed, 247 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/crdt/LWWElementSet.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/crdt/LWWElementSetTest.java
diff --git a/DIRECTORY.md b/DIRECTORY.md
index 703642a0d28e..f033416dc38a 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -85,6 +85,7 @@
* crdt
* [GCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java)
* [GSet](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java)
+ * [LWWElementSet](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/LWWElementSet.java)
* [PNCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java)
* [TwoPSet](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java)
* disjointsetunion
@@ -621,6 +622,7 @@
* crdt
* [GCounterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/GCounterTest.java)
* [GSetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java)
+ * [LWWElementSetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/LWWElementSetTest.java)
* [PNCounterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/PNCounterTest.java)
* [TwoPSetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java)
* disjointsetunion
diff --git a/src/main/java/com/thealgorithms/datastructures/crdt/LWWElementSet.java b/src/main/java/com/thealgorithms/datastructures/crdt/LWWElementSet.java
new file mode 100644
index 000000000000..722c916ab0ce
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/crdt/LWWElementSet.java
@@ -0,0 +1,138 @@
+package com.thealgorithms.datastructures.crdt;
+
+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.
+ *
+ * @author itakurah (Niklas Hoefflin) (https://github.com/itakurah)
+ * @see Conflict-free_replicated_data_type
+ * @see itakurah (Niklas Hoefflin)
+ */
+
+class Element {
+ String key;
+ int timestamp;
+ Bias bias;
+
+ /**
+ * 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).
+ */
+ public 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.
+ */
+ public LWWElementSet() {
+ this.addSet = new HashMap<>();
+ this.removeSet = new HashMap<>();
+ }
+
+ /**
+ * Adds an element to the addSet.
+ *
+ * @param e The element to be added.
+ */
+ public void add(Element e) {
+ addSet.put(e.key, e);
+ }
+
+ /**
+ * Removes an element from the removeSet.
+ *
+ * @param e The element to be removed.
+ */
+ public void remove(Element e) {
+ if (lookup(e)) {
+ removeSet.put(e.key, e);
+ }
+ }
+
+ /**
+ * Checks if an element is in the LWWElementSet by comparing timestamps in the addSet and removeSet.
+ *
+ * @param e The element to be checked.
+ * @return True if the element is present, false otherwise.
+ */
+ public boolean lookup(Element e) {
+ Element inAddSet = addSet.get(e.key);
+ Element inRemoveSet = removeSet.get(e.key);
+
+ return (inAddSet != null && (inRemoveSet == null || inAddSet.timestamp > inRemoveSet.timestamp));
+ }
+
+ /**
+ * Compares the LWWElementSet with another LWWElementSet to check if addSet and removeSet are a subset.
+ *
+ * @param other The LWWElementSet to compare.
+ * @return True if the set is subset, false otherwise.
+ */
+ public boolean compare(LWWElementSet other) {
+ return other.addSet.keySet().containsAll(addSet.keySet()) && other.removeSet.keySet().containsAll(removeSet.keySet());
+ }
+
+ /**
+ * Merges another LWWElementSet into this set by resolving conflicts based on timestamps.
+ *
+ * @param other The LWWElementSet to merge.
+ */
+ 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);
+ }
+ }
+ }
+
+ /**
+ * Compares timestamps of two elements based on their bias (ADDS or REMOVALS).
+ *
+ * @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.
+ */
+ public boolean compareTimestamps(Element e, Element other) {
+ if (!e.bias.equals(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.equals(Bias.ADDS);
+ }
+ return timestampComparison < 0;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/crdt/LWWElementSetTest.java b/src/test/java/com/thealgorithms/datastructures/crdt/LWWElementSetTest.java
new file mode 100644
index 000000000000..6fb227bd80c5
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/crdt/LWWElementSetTest.java
@@ -0,0 +1,107 @@
+package com.thealgorithms.datastructures.crdt;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.BeforeEach;
+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));
+ }
+
+ @Test
+ void testRemove() {
+ Element element = new Element("key1", 1, bias);
+ set.add(element);
+ set.remove(element);
+
+ assertFalse(set.lookup(element));
+ }
+
+ @Test
+ void testRemoveNonexistentElement() {
+ Element element = new Element("key1", 1, bias);
+ set.remove(element);
+
+ assertFalse(set.lookup(element));
+ }
+
+ @Test
+ void testLookupNonexistentElement() {
+ Element element = new Element("key1", 1, bias);
+
+ assertFalse(set.lookup(element));
+ }
+
+ @Test
+ void testCompareEqualSets() {
+ LWWElementSet otherSet = new LWWElementSet();
+
+ Element element = new Element("key1", 1, bias);
+ set.add(element);
+ otherSet.add(element);
+
+ assertTrue(set.compare(otherSet));
+
+ otherSet.add(new Element("key2", 2, bias));
+ assertTrue(set.compare(otherSet));
+ }
+
+ @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));
+ }
+
+ @Test
+ void testMerge() {
+ LWWElementSet otherSet = new LWWElementSet();
+
+ Element element1 = new Element("key1", 1, bias);
+ Element element2 = new Element("key2", 2, bias);
+
+ set.add(element1);
+ otherSet.add(element2);
+
+ set.merge(otherSet);
+
+ assertTrue(set.lookup(element1));
+ assertTrue(set.lookup(element2));
+ }
+
+ @Test
+ void testCompareTimestampsEqualTimestamps() {
+ LWWElementSet lwwElementSet = new LWWElementSet();
+
+ Element e1 = new Element("key1", 10, Bias.REMOVALS);
+ Element e2 = new Element("key1", 10, Bias.REMOVALS);
+
+ assertTrue(lwwElementSet.compareTimestamps(e1, e2));
+
+ e1 = new Element("key1", 10, Bias.ADDS);
+ e2 = new Element("key1", 10, Bias.ADDS);
+
+ assertFalse(lwwElementSet.compareTimestamps(e1, e2));
+ }
+}
From 4aa8e6a0eb65e8edb9b716851ee4dd8881c434af Mon Sep 17 00:00:00 2001
From: Niklas Hoefflin <122729995+itakurah@users.noreply.github.com>
Date: Mon, 11 Dec 2023 19:58:56 +0100
Subject: [PATCH 0075/1338] Updated TwoPSet to use Generics instead of Strings
(#4981)
---
.../datastructures/crdt/TwoPSet.java | 18 +++++++++---------
.../datastructures/crdt/TwoPSetTest.java | 14 +++++++-------
2 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java b/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java
index f5e155c28d8d..c0ce17b2802b 100644
--- a/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java
+++ b/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java
@@ -15,9 +15,9 @@
* @author itakurah (Niklas Hoefflin) (https://github.com/itakurah)
*/
-public class TwoPSet {
- private Set setA;
- private Set setR;
+public class TwoPSet {
+ private final Set setA;
+ private final Set setR;
/**
* Constructs an empty Two-Phase Set.
@@ -33,7 +33,7 @@ public TwoPSet() {
* @param element The element to be checked.
* @return True if the element is in the set and has not been removed, otherwise false.
*/
- public boolean lookup(String element) {
+ public boolean lookup(T element) {
return setA.contains(element) && !setR.contains(element);
}
@@ -42,7 +42,7 @@ public boolean lookup(String element) {
*
* @param element The element to be added.
*/
- public void add(String element) {
+ public void add(T element) {
setA.add(element);
}
@@ -51,7 +51,7 @@ public void add(String element) {
*
* @param element The element to be removed.
*/
- public void remove(String element) {
+ public void remove(T element) {
if (lookup(element)) {
setR.add(element);
}
@@ -63,7 +63,7 @@ public void remove(String element) {
* @param otherSet The other 2P-Set to compare with.
* @return True if both SetA and SetR are subset, otherwise false.
*/
- public boolean compare(TwoPSet otherSet) {
+ public boolean compare(TwoPSet otherSet) {
return otherSet.setA.containsAll(setA) && otherSet.setR.containsAll(setR);
}
@@ -73,8 +73,8 @@ public boolean compare(TwoPSet otherSet) {
* @param otherSet The other 2P-Set to merge with.
* @return A new 2P-Set containing the merged elements.
*/
- public TwoPSet merge(TwoPSet otherSet) {
- TwoPSet mergedSet = new TwoPSet();
+ public TwoPSet merge(TwoPSet otherSet) {
+ TwoPSet mergedSet = new TwoPSet<>();
mergedSet.setA.addAll(this.setA);
mergedSet.setA.addAll(otherSet.setA);
mergedSet.setR.addAll(this.setR);
diff --git a/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java b/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java
index 18ab5c169e5c..d81362e854d0 100644
--- a/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java
+++ b/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java
@@ -7,11 +7,11 @@
class TwoPSetTest {
- private TwoPSet set;
+ private TwoPSet set;
@BeforeEach
void setUp() {
- set = new TwoPSet();
+ set = new TwoPSet<>();
}
@Test
@@ -38,10 +38,10 @@ void testRemove() {
@Test
void testCompare() {
- TwoPSet set1 = new TwoPSet();
+ TwoPSet set1 = new TwoPSet<>();
set1.add("A");
set1.add("B");
- TwoPSet set2 = new TwoPSet();
+ TwoPSet set2 = new TwoPSet<>();
set2.add("A");
assertFalse(set1.compare(set2));
set2.add("B");
@@ -54,13 +54,13 @@ void testCompare() {
@Test
void testMerge() {
- TwoPSet set1 = new TwoPSet();
+ TwoPSet set1 = new TwoPSet<>();
set1.add("A");
set1.add("B");
- TwoPSet set2 = new TwoPSet();
+ TwoPSet set2 = new TwoPSet<>();
set2.add("B");
set2.add("C");
- TwoPSet mergedSet = set1.merge(set2);
+ TwoPSet mergedSet = set1.merge(set2);
assertTrue(mergedSet.lookup("A"));
assertTrue(mergedSet.lookup("B"));
assertTrue(mergedSet.lookup("C"));
From e26fd9da71130837d327d747f6bc87688322eee5 Mon Sep 17 00:00:00 2001
From: Niklas Hoefflin <122729995+itakurah@users.noreply.github.com>
Date: Mon, 11 Dec 2023 22:05:43 +0100
Subject: [PATCH 0076/1338] Add OR-Set (Observed-Remove Set) (#4980)
---
DIRECTORY.md | 2 +
.../datastructures/crdt/ORSet.java | 191 ++++++++++++++++++
.../datastructures/crdt/ORSetTest.java | 86 ++++++++
3 files changed, 279 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/crdt/ORSet.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/crdt/ORSetTest.java
diff --git a/DIRECTORY.md b/DIRECTORY.md
index f033416dc38a..b769250e4749 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -86,6 +86,7 @@
* [GCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/GCounter.java)
* [GSet](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/GSet.java)
* [LWWElementSet](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/LWWElementSet.java)
+ * [ORSet](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/ORSet.java)
* [PNCounter](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/PNCounter.java)
* [TwoPSet](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/crdt/TwoPSet.java)
* disjointsetunion
@@ -623,6 +624,7 @@
* [GCounterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/GCounterTest.java)
* [GSetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/GSetTest.java)
* [LWWElementSetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/LWWElementSetTest.java)
+ * [ORSetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/ORSetTest.java)
* [PNCounterTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/PNCounterTest.java)
* [TwoPSetTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/crdt/TwoPSetTest.java)
* disjointsetunion
diff --git a/src/main/java/com/thealgorithms/datastructures/crdt/ORSet.java b/src/main/java/com/thealgorithms/datastructures/crdt/ORSet.java
new file mode 100644
index 000000000000..a4cc2ffdd4a6
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/crdt/ORSet.java
@@ -0,0 +1,191 @@
+package com.thealgorithms.datastructures.crdt;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * ORSet (Observed-Removed Set) is a state-based CRDT (Conflict-free Replicated Data Type)
+ * that supports both addition and removal of elements. This particular implementation follows
+ * the Add-Wins strategy, meaning that in case of conflicting add and remove operations,
+ * the add operation takes precedence. The merge operation of two OR-Sets ensures that
+ * elements added at any replica are eventually observed at all replicas. Removed elements,
+ * once observed, are never reintroduced.
+ * This OR-Set implementation provides methods for adding elements, removing elements,
+ * checking for element existence, retrieving the set of elements, comparing with other OR-Sets,
+ * and merging with another OR-Set to create a new OR-Set containing all unique elements
+ * from both sets.
+ *
+ * @author itakurah (Niklas Hoefflin) (https://github.com/itakurah)
+ * @see Conflict-free_replicated_data_type
+ * @see itakurah (Niklas Hoefflin)
+ */
+
+public class ORSet {
+
+ private final Set> elements;
+ private final Set> tombstones;
+
+ /**
+ * Constructs an empty OR-Set.
+ */
+ public ORSet() {
+ this.elements = new HashSet<>();
+ this.tombstones = new HashSet<>();
+ }
+
+ /**
+ * Checks if the set contains the specified element.
+ *
+ * @param element the element to check for
+ * @return true if the set contains the element, false otherwise
+ */
+ public boolean contains(T element) {
+ return elements.stream().anyMatch(pair -> pair.getElement().equals(element));
+ }
+
+ /**
+ * Retrieves the elements in the set.
+ *
+ * @return a set containing the elements
+ */
+ public Set elements() {
+ Set result = new HashSet<>();
+ elements.forEach(pair -> result.add(pair.getElement()));
+ return result;
+ }
+
+ /**
+ * Adds the specified element to the set.
+ *
+ * @param element the element to add
+ */
+ public void add(T element) {
+ String n = prepare();
+ effect(element, n);
+ }
+
+ /**
+ * Removes the specified element from the set.
+ *
+ * @param element the element to remove
+ */
+ public void remove(T element) {
+ Set> pairsToRemove = prepare(element);
+ effect(pairsToRemove);
+ }
+
+ /**
+ * Collect all pairs with the specified element.
+ *
+ * @param element the element to collect pairs for
+ * @return a set of pairs with the specified element to be removed
+ */
+ private Set> prepare(T element) {
+ Set> pairsToRemove = new HashSet<>();
+ for (Pair pair : elements) {
+ if (pair.getElement().equals(element)) {
+ pairsToRemove.add(pair);
+ }
+ }
+ return pairsToRemove;
+ }
+
+ /**
+ * Generates a unique tag for the element.
+ *
+ * @return the unique tag
+ */
+ private String prepare() {
+ return generateUniqueTag();
+ }
+
+ /**
+ * Adds the element with the specified unique tag to the set.
+ *
+ * @param element the element to add
+ * @param n the unique tag associated with the element
+ */
+ private void effect(T element, String n) {
+ Pair pair = new Pair<>(element, n);
+ elements.add(pair);
+ elements.removeAll(tombstones);
+ }
+
+ /**
+ * Removes the specified pairs from the set.
+ *
+ * @param pairsToRemove the pairs to remove
+ */
+ private void effect(Set> pairsToRemove) {
+ elements.removeAll(pairsToRemove);
+ tombstones.addAll(pairsToRemove);
+ }
+
+ /**
+ * Generates a unique tag.
+ *
+ * @return the unique tag
+ */
+ private String generateUniqueTag() {
+ return UUID.randomUUID().toString();
+ }
+
+ /**
+ * Compares this Add-Wins OR-Set with another OR-Set to check if elements and tombstones are a subset.
+ *
+ * @param other the other OR-Set to compare
+ * @return true if the sets are subset, false otherwise
+ */
+ public boolean compare(ORSet other) {
+ Set> union = new HashSet<>(elements);
+ union.addAll(tombstones);
+
+ Set> otherUnion = new HashSet<>(other.elements);
+ otherUnion.addAll(other.tombstones);
+
+ return otherUnion.containsAll(union) && other.tombstones.containsAll(tombstones);
+ }
+
+ /**
+ * Merges this Add-Wins OR-Set with another OR-Set.
+ *
+ * @param other the other OR-Set to merge
+ */
+ public void merge(ORSet other) {
+ elements.removeAll(other.tombstones);
+ other.elements.removeAll(tombstones);
+ elements.addAll(other.elements);
+ tombstones.addAll(other.tombstones);
+ }
+
+ /**
+ * Represents a pair containing an element and a unique tag.
+ *
+ * @param the type of the element in the pair
+ */
+ public static class Pair {
+ private final T element;
+ private final String uniqueTag;
+
+ /**
+ * Constructs a pair with the specified element and unique tag.
+ *
+ * @param element the element in the pair
+ * @param uniqueTag the unique tag associated with the element
+ */
+ public Pair(T element, String uniqueTag) {
+ this.element = element;
+ this.uniqueTag = uniqueTag;
+ }
+
+ /**
+ * Gets the element from the pair.
+ *
+ * @return the element
+ */
+ public T getElement() {
+ return element;
+ }
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/crdt/ORSetTest.java b/src/test/java/com/thealgorithms/datastructures/crdt/ORSetTest.java
new file mode 100644
index 000000000000..f12c38f174dc
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/crdt/ORSetTest.java
@@ -0,0 +1,86 @@
+package com.thealgorithms.datastructures.crdt;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.Set;
+import org.junit.jupiter.api.Test;
+
+class ORSetTest {
+
+ @Test
+ void testContains() {
+ ORSet orSet = new ORSet<>();
+ orSet.add("A");
+ assertTrue(orSet.contains("A"));
+ }
+
+ @Test
+ void testAdd() {
+ ORSet orSet = new ORSet<>();
+ orSet.add("A");
+ assertTrue(orSet.contains("A"));
+ }
+
+ @Test
+ void testRemove() {
+ ORSet orSet = new ORSet<>();
+ orSet.add("A");
+ orSet.add("A");
+ orSet.remove("A");
+ assertFalse(orSet.contains("A"));
+ }
+
+ @Test
+ void testElements() {
+ ORSet orSet = new ORSet<>();
+ orSet.add("A");
+ orSet.add("B");
+ assertEquals(Set.of("A", "B"), orSet.elements());
+ }
+
+ @Test
+ void testCompareEqualSets() {
+ ORSet orSet1 = new ORSet<>();
+ ORSet orSet2 = new ORSet<>();
+
+ orSet1.add("A");
+ orSet2.add("A");
+ orSet2.add("B");
+ orSet2.add("C");
+ orSet2.remove("C");
+ orSet1.merge(orSet2);
+ orSet2.merge(orSet1);
+ orSet2.remove("B");
+
+ assertTrue(orSet1.compare(orSet2));
+ }
+
+ @Test
+ void testCompareDifferentSets() {
+ ORSet orSet1 = new ORSet<>();
+ ORSet orSet2 = new ORSet<>();
+
+ orSet1.add("A");
+ orSet2.add("B");
+
+ assertFalse(orSet1.compare(orSet2));
+ }
+
+ @Test
+ void testMerge() {
+ ORSet orSet1 = new ORSet<>();
+ ORSet orSet2 = new ORSet<>();
+
+ orSet1.add("A");
+ orSet1.add("A");
+ orSet1.add("B");
+ orSet1.remove("B");
+ orSet2.add("B");
+ orSet2.add("C");
+ orSet2.remove("C");
+ orSet1.merge(orSet2);
+
+ assertTrue(orSet1.contains("A"));
+ assertTrue(orSet1.contains("B"));
+ }
+}
From 7ece806cf5cae7c3531f2eb54c56cf33fed2e579 Mon Sep 17 00:00:00 2001
From: aryan1165 <111041731+aryan1165@users.noreply.github.com>
Date: Tue, 26 Dec 2023 03:54:28 +0530
Subject: [PATCH 0077/1338] Remove duplicate file of Simple Substitution Cipher
(fixes #4494) (#4495)
---
DIRECTORY.md | 2 -
.../ciphers/SimpleSubstitutionCipher.java | 83 -------------------
.../ciphers/SimpleSubstitutionCipherTest.java | 48 -----------
3 files changed, 133 deletions(-)
delete mode 100644 src/main/java/com/thealgorithms/ciphers/SimpleSubstitutionCipher.java
delete mode 100644 src/test/java/com/thealgorithms/ciphers/SimpleSubstitutionCipherTest.java
diff --git a/DIRECTORY.md b/DIRECTORY.md
index b769250e4749..fd50b2914cff 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -48,7 +48,6 @@
* [ProductCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/ProductCipher.java)
* [RSA](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/RSA.java)
* [SimpleSubCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/SimpleSubCipher.java)
- * [SimpleSubstitutionCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/SimpleSubstitutionCipher.java)
* [Vigenere](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/Vigenere.java)
* conversions
* [AnyBaseToAnyBase](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/conversions/AnyBaseToAnyBase.java)
@@ -596,7 +595,6 @@
* [PolybiusTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/PolybiusTest.java)
* [RSATest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/RSATest.java)
* [SimpleSubCipherTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/SimpleSubCipherTest.java)
- * [SimpleSubstitutionCipherTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/SimpleSubstitutionCipherTest.java)
* [VigenereTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/VigenereTest.java)
* conversions
* [BinaryToDecimalTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/conversions/BinaryToDecimalTest.java)
diff --git a/src/main/java/com/thealgorithms/ciphers/SimpleSubstitutionCipher.java b/src/main/java/com/thealgorithms/ciphers/SimpleSubstitutionCipher.java
deleted file mode 100644
index 6ce3c564abc7..000000000000
--- a/src/main/java/com/thealgorithms/ciphers/SimpleSubstitutionCipher.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.thealgorithms.ciphers;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * The simple substitution cipher is a cipher that has been in use for many
- * hundreds of years (an excellent history is given in Simon Singhs 'the Code
- * Book'). It basically consists of substituting every plaintext character for a
- * different ciphertext character. It differs from the Caesar cipher in that the
- * cipher alphabet is not simply the alphabet shifted, it is completely jumbled.
- *
- * @author Hassan Elseoudy
- */
-public class SimpleSubstitutionCipher {
-
- /**
- * Encrypt text by replacing each element with its opposite character.
- *
- * @return Encrypted message
- */
- public static String encode(String message, String cipherSmall) {
- StringBuilder encoded = new StringBuilder();
-
- // This map is used to encode
- Map cipherMap = new HashMap<>();
-
- char beginSmallLetter = 'a';
- char beginCapitalLetter = 'A';
-
- cipherSmall = cipherSmall.toLowerCase();
- String cipherCapital = cipherSmall.toUpperCase();
-
- // To handle Small and Capital letters
- for (int i = 0; i < cipherSmall.length(); i++) {
- cipherMap.put(beginSmallLetter++, cipherSmall.charAt(i));
- cipherMap.put(beginCapitalLetter++, cipherCapital.charAt(i));
- }
-
- for (int i = 0; i < message.length(); i++) {
- if (Character.isAlphabetic(message.charAt(i))) {
- encoded.append(cipherMap.get(message.charAt(i)));
- } else {
- encoded.append(message.charAt(i));
- }
- }
-
- return encoded.toString();
- }
-
- /**
- * Decrypt message by replacing each element with its opposite character in
- * cipher.
- *
- * @return message
- */
- public static String decode(String encryptedMessage, String cipherSmall) {
- StringBuilder decoded = new StringBuilder();
-
- Map cipherMap = new HashMap<>();
-
- char beginSmallLetter = 'a';
- char beginCapitalLetter = 'A';
-
- cipherSmall = cipherSmall.toLowerCase();
- String cipherCapital = cipherSmall.toUpperCase();
-
- for (int i = 0; i < cipherSmall.length(); i++) {
- cipherMap.put(cipherSmall.charAt(i), beginSmallLetter++);
- cipherMap.put(cipherCapital.charAt(i), beginCapitalLetter++);
- }
-
- for (int i = 0; i < encryptedMessage.length(); i++) {
- if (Character.isAlphabetic(encryptedMessage.charAt(i))) {
- decoded.append(cipherMap.get(encryptedMessage.charAt(i)));
- } else {
- decoded.append(encryptedMessage.charAt(i));
- }
- }
-
- return decoded.toString();
- }
-}
diff --git a/src/test/java/com/thealgorithms/ciphers/SimpleSubstitutionCipherTest.java b/src/test/java/com/thealgorithms/ciphers/SimpleSubstitutionCipherTest.java
deleted file mode 100644
index f7cace2e08aa..000000000000
--- a/src/test/java/com/thealgorithms/ciphers/SimpleSubstitutionCipherTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.thealgorithms.ciphers;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import org.junit.jupiter.api.Test;
-
-public class SimpleSubstitutionCipherTest {
-
- @Test
- void testEncode() {
- // Given
- String message = "HELLOWORLD";
- String key = "phqgiumeaylnofdxjkrcvstzwb";
-
- // When
- String actual = SimpleSubstitutionCipher.encode(message, key);
-
- // Then
- assertEquals("EINNDTDKNG", actual);
- }
-
- @Test
- void testDecode() {
- // Given
- String message = "EINNDTDKNG";
- String key = "phqgiumeaylnofdxjkrcvstzwb";
-
- // When
- String actual = SimpleSubstitutionCipher.decode(message, key);
-
- // Then
- assertEquals("HELLOWORLD", actual);
- }
-
- @Test
- void testIsTextTheSameAfterEncodeAndDecode() {
- // Given
- String text = "HELLOWORLD";
- String key = "phqgiumeaylnofdxjkrcvstzwb";
-
- // When
- String encodedText = SimpleSubstitutionCipher.encode(text, key);
- String decodedText = SimpleSubstitutionCipher.decode(encodedText, key);
-
- // Then
- assertEquals(text, decodedText);
- }
-}
From a7d140a43e03821728f919f2402b006ae985cfa5 Mon Sep 17 00:00:00 2001
From: Nishant Jain <121454072+inishantjain@users.noreply.github.com>
Date: Tue, 2 Jan 2024 23:48:01 +0530
Subject: [PATCH 0078/1338] Add Set Kth Bit (#4990)
---
.../bitmanipulation/SetKthBit.java | 22 ++++++++++++++++++
.../bitmanipulation/SetKthBitTest.java | 23 +++++++++++++++++++
2 files changed, 45 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/bitmanipulation/SetKthBit.java
create mode 100644 src/test/java/com/thealgorithms/bitmanipulation/SetKthBitTest.java
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/SetKthBit.java b/src/main/java/com/thealgorithms/bitmanipulation/SetKthBit.java
new file mode 100644
index 000000000000..3c4e50d1d38d
--- /dev/null
+++ b/src/main/java/com/thealgorithms/bitmanipulation/SetKthBit.java
@@ -0,0 +1,22 @@
+package com.thealgorithms.bitmanipulation;
+
+/***
+ * Sets the kth bit of a given integer to 1
+ * e.g. setting 3rd bit in binary of 17 (binary 10001) gives 25 (binary 11001)
+ * @author inishantjain
+ */
+
+public class SetKthBit {
+ /**
+ * Sets the kth bit of a given integer.
+ *
+ * @param num The original integer.
+ * @param k The position of the bit to set (0-based index).
+ * @return The integer with the kth bit set.
+ */
+ public static int setKthBit(int num, int k) {
+ int mask = 1 << k;
+ num = num | mask;
+ return num;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/bitmanipulation/SetKthBitTest.java b/src/test/java/com/thealgorithms/bitmanipulation/SetKthBitTest.java
new file mode 100644
index 000000000000..35d5fa35da54
--- /dev/null
+++ b/src/test/java/com/thealgorithms/bitmanipulation/SetKthBitTest.java
@@ -0,0 +1,23 @@
+package com.thealgorithms.bitmanipulation;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+class SetKthBitTest {
+
+ @Test
+ void testSetKthBit() {
+ // Test case: Setting the 0th bit in 5 (binary 101)
+ assertEquals(5, SetKthBit.setKthBit(5, 0));
+
+ // Test case: Setting the 2nd bit in 10 (binary 1010)
+ assertEquals(14, SetKthBit.setKthBit(10, 2));
+
+ // Test case: Setting the 3rd bit in 15 (binary 1111)
+ assertEquals(15, SetKthBit.setKthBit(15, 3));
+
+ // Test case: Setting the 1st bit in 0 (binary 0)
+ assertEquals(2, SetKthBit.setKthBit(0, 1));
+ }
+}
From 9bef5a169c2295eee0c377db1f5afa0141bceb79 Mon Sep 17 00:00:00 2001
From: Govind Gupta <102366719+Govind516@users.noreply.github.com>
Date: Wed, 3 Jan 2024 18:44:38 +0530
Subject: [PATCH 0079/1338] Add Playfair Cipher (#4988)
---
DIRECTORY.md | 4 +
.../thealgorithms/ciphers/PlayfairCipher.java | 128 ++++++++++++++++++
.../thealgorithms/ciphers/PlayfairTest.java | 37 +++++
3 files changed, 169 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/ciphers/PlayfairCipher.java
create mode 100644 src/test/java/com/thealgorithms/ciphers/PlayfairTest.java
diff --git a/DIRECTORY.md b/DIRECTORY.md
index fd50b2914cff..b621216da7f1 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -27,6 +27,7 @@
* [NonRepeatingNumberFinder](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinder.java)
* [NumbersDifferentSigns](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/NumbersDifferentSigns.java)
* [ReverseBits](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/ReverseBits.java)
+ * [SetKthBit](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/SetKthBit.java)
* [SingleBitOperations](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/SingleBitOperations.java)
* ciphers
* a5
@@ -44,6 +45,7 @@
* [ColumnarTranspositionCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java)
* [DES](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/DES.java)
* [HillCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/HillCipher.java)
+ * [PlayfairCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/PlayfairCipher.java)
* [Polybius](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/Polybius.java)
* [ProductCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/ProductCipher.java)
* [RSA](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/RSA.java)
@@ -585,6 +587,7 @@
* [NonRepeatingNumberFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/NonRepeatingNumberFinderTest.java)
* [NumbersDifferentSignsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/NumbersDifferentSignsTest.java)
* [ReverseBitsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/ReverseBitsTest.java)
+ * [SetKthBitTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/SetKthBitTest.java)
* [SingleBitOperationsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/SingleBitOperationsTest.java)
* ciphers
* a5
@@ -592,6 +595,7 @@
* [BlowfishTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/BlowfishTest.java)
* [CaesarTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/CaesarTest.java)
* [DESTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/DESTest.java)
+ * [PlayfairTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/PlayfairTest.java)
* [PolybiusTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/PolybiusTest.java)
* [RSATest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/RSATest.java)
* [SimpleSubCipherTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/SimpleSubCipherTest.java)
diff --git a/src/main/java/com/thealgorithms/ciphers/PlayfairCipher.java b/src/main/java/com/thealgorithms/ciphers/PlayfairCipher.java
new file mode 100644
index 000000000000..76ceb6dbce31
--- /dev/null
+++ b/src/main/java/com/thealgorithms/ciphers/PlayfairCipher.java
@@ -0,0 +1,128 @@
+package com.thealgorithms.ciphers;
+
+public class PlayfairCipher {
+
+ private char[][] matrix;
+ private String key;
+
+ public PlayfairCipher(String key) {
+ this.key = key;
+ generateMatrix();
+ }
+
+ public String encrypt(String plaintext) {
+ plaintext = prepareText(plaintext.replace("J", "I"));
+ StringBuilder ciphertext = new StringBuilder();
+ for (int i = 0; i < plaintext.length(); i += 2) {
+ char char1 = plaintext.charAt(i);
+ char char2 = plaintext.charAt(i + 1);
+ int[] pos1 = findPosition(char1);
+ int[] pos2 = findPosition(char2);
+ int row1 = pos1[0];
+ int col1 = pos1[1];
+ int row2 = pos2[0];
+ int col2 = pos2[1];
+ if (row1 == row2) {
+ ciphertext.append(matrix[row1][(col1 + 1) % 5]);
+ ciphertext.append(matrix[row2][(col2 + 1) % 5]);
+ } else if (col1 == col2) {
+ ciphertext.append(matrix[(row1 + 1) % 5][col1]);
+ ciphertext.append(matrix[(row2 + 1) % 5][col2]);
+ } else {
+ ciphertext.append(matrix[row1][col2]);
+ ciphertext.append(matrix[row2][col1]);
+ }
+ }
+ return ciphertext.toString();
+ }
+
+ public String decrypt(String ciphertext) {
+ StringBuilder plaintext = new StringBuilder();
+ for (int i = 0; i < ciphertext.length(); i += 2) {
+ char char1 = ciphertext.charAt(i);
+ char char2 = ciphertext.charAt(i + 1);
+ int[] pos1 = findPosition(char1);
+ int[] pos2 = findPosition(char2);
+ int row1 = pos1[0];
+ int col1 = pos1[1];
+ int row2 = pos2[0];
+ int col2 = pos2[1];
+ if (row1 == row2) {
+ plaintext.append(matrix[row1][(col1 + 4) % 5]);
+ plaintext.append(matrix[row2][(col2 + 4) % 5]);
+ } else if (col1 == col2) {
+ plaintext.append(matrix[(row1 + 4) % 5][col1]);
+ plaintext.append(matrix[(row2 + 4) % 5][col2]);
+ } else {
+ plaintext.append(matrix[row1][col2]);
+ plaintext.append(matrix[row2][col1]);
+ }
+ }
+ return plaintext.toString();
+ }
+
+ private void generateMatrix() {
+ String keyWithoutDuplicates = removeDuplicateChars(key + "ABCDEFGHIKLMNOPQRSTUVWXYZ");
+ matrix = new char[5][5];
+ int index = 0;
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < 5; j++) {
+ matrix[i][j] = keyWithoutDuplicates.charAt(index);
+ index++;
+ }
+ }
+ }
+
+ private String removeDuplicateChars(String str) {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < str.length(); i++) {
+ if (result.indexOf(String.valueOf(str.charAt(i))) == -1) {
+ result.append(str.charAt(i));
+ }
+ }
+ return result.toString();
+ }
+
+ private String prepareText(String text) {
+ text = text.toUpperCase().replaceAll("[^A-Z]", "");
+ StringBuilder preparedText = new StringBuilder();
+ char prevChar = '\0';
+ for (char c : text.toCharArray()) {
+ if (c != prevChar) {
+ preparedText.append(c);
+ prevChar = c;
+ } else {
+ preparedText.append('X').append(c);
+ prevChar = '\0';
+ }
+ }
+ if (preparedText.length() % 2 != 0) {
+ preparedText.append('X');
+ }
+ return preparedText.toString();
+ }
+
+ private int[] findPosition(char c) {
+ int[] pos = new int[2];
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < 5; j++) {
+ if (matrix[i][j] == c) {
+ pos[0] = i;
+ pos[1] = j;
+ return pos;
+ }
+ }
+ }
+ return pos;
+ }
+
+ public void printMatrix() {
+ System.out.println("\nPlayfair Cipher Matrix:");
+ for (int i = 0; i < 5; i++) {
+ for (int j = 0; j < 5; j++) {
+ System.out.print(matrix[i][j] + " ");
+ }
+ System.out.println();
+ }
+ }
+}
diff --git a/src/test/java/com/thealgorithms/ciphers/PlayfairTest.java b/src/test/java/com/thealgorithms/ciphers/PlayfairTest.java
new file mode 100644
index 000000000000..5562241b48db
--- /dev/null
+++ b/src/test/java/com/thealgorithms/ciphers/PlayfairTest.java
@@ -0,0 +1,37 @@
+package com.thealgorithms.ciphers;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.junit.jupiter.api.Test;
+
+public class PlayfairTest {
+
+ @Test
+ public void testEncryption() {
+ PlayfairCipher playfairCipher = new PlayfairCipher("KEYWORD");
+
+ String plaintext = "HELLO";
+ String encryptedText = playfairCipher.encrypt(plaintext);
+ assertEquals("GYIZSC", encryptedText);
+ }
+
+ @Test
+ public void testDecryption() {
+ PlayfairCipher playfairCipher = new PlayfairCipher("KEYWORD");
+
+ String encryptedText = "UDRIYP";
+ String decryptedText = playfairCipher.decrypt(encryptedText);
+ assertEquals("NEBFVH", decryptedText);
+ }
+
+ @Test
+ public void testEncryptionAndDecryption() {
+ PlayfairCipher playfairCipher = new PlayfairCipher("KEYWORD");
+
+ String plaintext = "PLAYFAIR";
+ String encryptedText = playfairCipher.encrypt(plaintext);
+ String decryptedText = playfairCipher.decrypt(encryptedText);
+
+ assertEquals(plaintext, decryptedText);
+ }
+}
From 6a0c0585e4530f0c9cfd207ffe825c5acc3f022f Mon Sep 17 00:00:00 2001
From: AthinaSw <152101068+AthinaSw@users.noreply.github.com>
Date: Wed, 3 Jan 2024 20:11:07 +0200
Subject: [PATCH 0080/1338] Add cross-correlation and auto-correlation (#4984)
---
.../thealgorithms/maths/AutoCorrelation.java | 55 ++++++++++++
.../thealgorithms/maths/CrossCorrelation.java | 87 +++++++++++++++++++
.../maths/AutoCorrelationTest.java | 37 ++++++++
.../maths/CrossCorrelationTest.java | 37 ++++++++
4 files changed, 216 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/maths/AutoCorrelation.java
create mode 100644 src/main/java/com/thealgorithms/maths/CrossCorrelation.java
create mode 100644 src/test/java/com/thealgorithms/maths/AutoCorrelationTest.java
create mode 100644 src/test/java/com/thealgorithms/maths/CrossCorrelationTest.java
diff --git a/src/main/java/com/thealgorithms/maths/AutoCorrelation.java b/src/main/java/com/thealgorithms/maths/AutoCorrelation.java
new file mode 100644
index 000000000000..5b38235bcd01
--- /dev/null
+++ b/src/main/java/com/thealgorithms/maths/AutoCorrelation.java
@@ -0,0 +1,55 @@
+package com.thealgorithms.maths;
+
+/**
+ * Class for linear auto-correlation of a discrete signal
+ *
+ * @author Athina-Frederiki Swinkels
+ * @version 2.0
+ */
+
+public class AutoCorrelation {
+
+ /**
+ * Discrete linear auto-correlation function.
+ * Input and output signals have starting index 0.
+ *
+ * @param x The discrete signal
+ * @return The result of the auto-correlation of signals x. The result is also a signal.
+ */
+ public static double[] autoCorrelation(double[] x) {
+
+ /*
+ To find the auto-correlation of a discrete signal x, we perform cross-correlation between x signal and itself.
+ Here's an example:
+ x=[1,2,1,1]
+ y=[1,2,1,1]
+
+ i=0: [1,2,1,1]
+ [1,2,1,1] result[0]=1*1=1
+
+ i=1: [1,2,1,1]
+ [1,2,1,1] result[1]=1*1+2*1=3
+
+ i=2: [1,2,1,1]
+ [1,2,1,1] result[2]=1*2+2*1+1*1=5
+
+ i=3: [1,2,1,1]
+ [1,2,1,1] result[3]=1*1+2*2+1*1+1*1=7
+
+ i=4: [1,2,1,1]
+ [1,2,1,1] result[4]=2*1+1*2+1*1=5
+
+ i=5: [1,2,1,1]
+ [1,2,1,1] result[5]=1*1+1*2=3
+
+ i=1: [1,2,1,1]
+ [1,2,1,1] result[6]=1*1=1
+
+ result=[1,3,5,7,5,3,1]
+
+
+ */
+
+ return CrossCorrelation.crossCorrelation(x, x);
+ }
+}
diff --git a/src/main/java/com/thealgorithms/maths/CrossCorrelation.java b/src/main/java/com/thealgorithms/maths/CrossCorrelation.java
new file mode 100644
index 000000000000..080e4ab7e74b
--- /dev/null
+++ b/src/main/java/com/thealgorithms/maths/CrossCorrelation.java
@@ -0,0 +1,87 @@
+package com.thealgorithms.maths;
+
+/**
+ * Class for linear cross-correlation of two discrete signals
+ *
+ * @author Athina-Frederiki Swinkels
+ * @version 1.0
+ */
+
+public class CrossCorrelation {
+
+ /**
+ * Discrete linear cross-correlation function.
+ * Input and output signals have starting index 0.
+ *
+ * @param x The first discrete signal
+ * @param y The second discrete signal
+ * @return The result of the cross-correlation of signals x,y. The result is also a signal.
+ */
+ public static double[] crossCorrelation(double[] x, double[] y) {
+ // The result signal's length is the sum of the input signals' lengths minus 1
+ double[] result = new double[x.length + y.length - 1];
+ int N = result.length;
+
+ /*
+ To find the cross-correlation between 2 discrete signals x & y, we start by "placing" the second signal
+ y under the first signal x, shifted to the left so that the last value of y meets the first value of x
+ and for every new position (i++) of the result signal, we shift y signal one position to the right, until
+ the first y-value meets the last x-value. The result-value for each position is the sum of all x*y meeting
+ values.
+ Here's an example:
+ x=[1,2,1,1]
+ y=[1,1,2,1]
+
+ i=0: [1,2,1,1]
+ [1,1,2,1] result[0]=1*1=1
+
+ i=1: [1,2,1,1]
+ [1,1,2,1] result[1]=1*2+2*1=4
+
+ i=2: [1,2,1,1]
+ [1,1,2,1] result[2]=1*1+2*2+1*1=6
+
+ i=3: [1,2,1,1]
+ [1,1,2,1] result[3]=1*1+2*1+1*2+1*1=6
+
+ i=4: [1,2,1,1]
+ [1,1,2,1] result[4]=2*1+1*1+1*2=5
+
+ i=5: [1,2,1,1]
+ [1,1,2,1] result[5]=1*1+1*1=2
+
+ i=1: [1,2,1,1]
+ [1,1,2,1] result[6]=1*1=1
+
+ result=[1,4,6,6,5,2,1]
+
+
+
+
+ To find the result[i] value for each i:0->N-1, the positions of x-signal in which the 2 signals meet
+ are calculated: kMin<=k<=kMax.
+ The variable 'yStart' indicates the starting index of y in each sum calculation.
+ The variable 'count' increases the index of y-signal by 1, to move to the next value.
+ */
+ int yStart = y.length;
+ for (int i = 0; i < N; i++) {
+ result[i] = 0;
+
+ int kMin = Math.max(i - (y.length - 1), 0);
+ int kMax = Math.min(i, x.length - 1);
+
+ if (i < y.length) {
+ yStart--;
+ }
+
+ int count = 0;
+ for (int k = kMin; k <= kMax; k++) {
+ result[i] += x[k] * y[yStart + count];
+ count++;
+ }
+ }
+
+ // The calculated cross-correlation of x & y signals is returned here.
+ return result;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/maths/AutoCorrelationTest.java b/src/test/java/com/thealgorithms/maths/AutoCorrelationTest.java
new file mode 100644
index 000000000000..cacfe5904faa
--- /dev/null
+++ b/src/test/java/com/thealgorithms/maths/AutoCorrelationTest.java
@@ -0,0 +1,37 @@
+package com.thealgorithms.maths;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+/**
+ * Test class for AutoCorrelation class
+ *
+ * @author Athina-Frederiki Swinkels
+ * @version 2.0
+ */
+
+public class AutoCorrelationTest {
+
+ @ParameterizedTest
+ @CsvSource({"1;2;1;1, 1;3;5;7;5;3;1", "1;2;3, 3;8;14;8;3", "1.5;2.3;3.1;4.2, 6.3;14.31;23.6;34.79;23.6;14.31;6.3"})
+
+ public void testAutoCorrelationParameterized(String input, String expected) {
+ double[] array = convertStringToArray(input);
+ double[] expectedResult = convertStringToArray(expected);
+
+ double[] result = AutoCorrelation.autoCorrelation(array);
+
+ assertArrayEquals(expectedResult, result, 0.0001);
+ }
+
+ private double[] convertStringToArray(String input) {
+ String[] elements = input.split(";");
+ double[] result = new double[elements.length];
+ for (int i = 0; i < elements.length; i++) {
+ result[i] = Double.parseDouble(elements[i]);
+ }
+ return result;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/maths/CrossCorrelationTest.java b/src/test/java/com/thealgorithms/maths/CrossCorrelationTest.java
new file mode 100644
index 000000000000..a7e4f14fb3af
--- /dev/null
+++ b/src/test/java/com/thealgorithms/maths/CrossCorrelationTest.java
@@ -0,0 +1,37 @@
+package com.thealgorithms.maths;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+/**
+ * Test class for CrossCorrelation class
+ *
+ * @author Athina-Frederiki Swinkels
+ * @version 2.0
+ */
+public class CrossCorrelationTest {
+
+ @ParameterizedTest
+ @CsvSource({"1;2;1;1, 1;1;2;1, 1;4;6;6;5;2;1", "1;2;3, 1;2;3;4;5, 5;14;26;20;14;8;3", "1;2;3;4;5, 1;2;3, 3;8;14;20;26;14;5", "1.5;2.3;3.1;4.2, 1.1;2.2;3.3, 4.95;10.89;16.94;23.21;12.65;4.62"})
+
+ public void testCrossCorrelationParameterized(String input1, String input2, String expected) {
+ double[] array1 = convertStringToArray(input1);
+ double[] array2 = convertStringToArray(input2);
+ double[] expectedResult = convertStringToArray(expected);
+
+ double[] result = CrossCorrelation.crossCorrelation(array1, array2);
+
+ assertArrayEquals(expectedResult, result, 0.0001);
+ }
+
+ private double[] convertStringToArray(String input) {
+ String[] elements = input.split(";");
+ double[] result = new double[elements.length];
+ for (int i = 0; i < elements.length; i++) {
+ result[i] = Double.parseDouble(elements[i]);
+ }
+ return result;
+ }
+}
From 092ac5795bc2004c04032fc2b79ee892e2ffcb05 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Wed, 3 Jan 2024 23:28:59 +0100
Subject: [PATCH 0081/1338] Remove `SetKthBit` in favor of
`SingleBitOperations.setBit` (#4991)
---
.../bitmanipulation/SetKthBit.java | 22 ------
.../bitmanipulation/SetKthBitTest.java | 23 -------
.../SingleBitOperationsTest.java | 68 ++++++++++---------
3 files changed, 36 insertions(+), 77 deletions(-)
delete mode 100644 src/main/java/com/thealgorithms/bitmanipulation/SetKthBit.java
delete mode 100644 src/test/java/com/thealgorithms/bitmanipulation/SetKthBitTest.java
diff --git a/src/main/java/com/thealgorithms/bitmanipulation/SetKthBit.java b/src/main/java/com/thealgorithms/bitmanipulation/SetKthBit.java
deleted file mode 100644
index 3c4e50d1d38d..000000000000
--- a/src/main/java/com/thealgorithms/bitmanipulation/SetKthBit.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.thealgorithms.bitmanipulation;
-
-/***
- * Sets the kth bit of a given integer to 1
- * e.g. setting 3rd bit in binary of 17 (binary 10001) gives 25 (binary 11001)
- * @author inishantjain
- */
-
-public class SetKthBit {
- /**
- * Sets the kth bit of a given integer.
- *
- * @param num The original integer.
- * @param k The position of the bit to set (0-based index).
- * @return The integer with the kth bit set.
- */
- public static int setKthBit(int num, int k) {
- int mask = 1 << k;
- num = num | mask;
- return num;
- }
-}
diff --git a/src/test/java/com/thealgorithms/bitmanipulation/SetKthBitTest.java b/src/test/java/com/thealgorithms/bitmanipulation/SetKthBitTest.java
deleted file mode 100644
index 35d5fa35da54..000000000000
--- a/src/test/java/com/thealgorithms/bitmanipulation/SetKthBitTest.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.thealgorithms.bitmanipulation;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import org.junit.jupiter.api.Test;
-
-class SetKthBitTest {
-
- @Test
- void testSetKthBit() {
- // Test case: Setting the 0th bit in 5 (binary 101)
- assertEquals(5, SetKthBit.setKthBit(5, 0));
-
- // Test case: Setting the 2nd bit in 10 (binary 1010)
- assertEquals(14, SetKthBit.setKthBit(10, 2));
-
- // Test case: Setting the 3rd bit in 15 (binary 1111)
- assertEquals(15, SetKthBit.setKthBit(15, 3));
-
- // Test case: Setting the 1st bit in 0 (binary 0)
- assertEquals(2, SetKthBit.setKthBit(0, 1));
- }
-}
diff --git a/src/test/java/com/thealgorithms/bitmanipulation/SingleBitOperationsTest.java b/src/test/java/com/thealgorithms/bitmanipulation/SingleBitOperationsTest.java
index a6bb76689ec8..9cac8d670a4a 100644
--- a/src/test/java/com/thealgorithms/bitmanipulation/SingleBitOperationsTest.java
+++ b/src/test/java/com/thealgorithms/bitmanipulation/SingleBitOperationsTest.java
@@ -1,32 +1,36 @@
-package com.thealgorithms.bitmanipulation;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import org.junit.jupiter.api.Test;
-
-public class SingleBitOperationsTest {
-
- @Test
- public void flipBitTest() {
- assertEquals(1, SingleBitOperations.flipBit(3, 1));
- assertEquals(11, SingleBitOperations.flipBit(3, 3));
- }
-
- @Test
- public void setBitTest() {
- assertEquals(5, SingleBitOperations.setBit(4, 0));
- assertEquals(4, SingleBitOperations.setBit(4, 2));
- }
-
- @Test
- public void clearBitTest() {
- assertEquals(5, SingleBitOperations.clearBit(7, 1));
- assertEquals(5, SingleBitOperations.clearBit(5, 1));
- }
-
- @Test
- public void getBitTest() {
- assertEquals(0, SingleBitOperations.getBit(6, 0));
- assertEquals(1, SingleBitOperations.getBit(7, 1));
- }
-}
+package com.thealgorithms.bitmanipulation;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class SingleBitOperationsTest {
+
+ @Test
+ public void flipBitTest() {
+ assertEquals(1, SingleBitOperations.flipBit(3, 1));
+ assertEquals(11, SingleBitOperations.flipBit(3, 3));
+ }
+
+ @Test
+ public void setBitTest() {
+ assertEquals(5, SingleBitOperations.setBit(4, 0));
+ assertEquals(4, SingleBitOperations.setBit(4, 2));
+ assertEquals(5, SingleBitOperations.setBit(5, 0));
+ assertEquals(14, SingleBitOperations.setBit(10, 2));
+ assertEquals(15, SingleBitOperations.setBit(15, 3));
+ assertEquals(2, SingleBitOperations.setBit(0, 1));
+ }
+
+ @Test
+ public void clearBitTest() {
+ assertEquals(5, SingleBitOperations.clearBit(7, 1));
+ assertEquals(5, SingleBitOperations.clearBit(5, 1));
+ }
+
+ @Test
+ public void getBitTest() {
+ assertEquals(0, SingleBitOperations.getBit(6, 0));
+ assertEquals(1, SingleBitOperations.getBit(7, 1));
+ }
+}
From 1ea95ffa928e42bda532380233a9667764dafdf5 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Thu, 4 Jan 2024 11:56:48 +0100
Subject: [PATCH 0082/1338] Cleanup `PerfectSquare` and its tests (#4992)
---
.../thealgorithms/maths/PerfectSquare.java | 14 ++-----
.../maths/PerfectSquareTest.java | 41 ++++++-------------
2 files changed, 16 insertions(+), 39 deletions(-)
diff --git a/src/main/java/com/thealgorithms/maths/PerfectSquare.java b/src/main/java/com/thealgorithms/maths/PerfectSquare.java
index 702e62943d88..fbc7a6f19bd0 100644
--- a/src/main/java/com/thealgorithms/maths/PerfectSquare.java
+++ b/src/main/java/com/thealgorithms/maths/PerfectSquare.java
@@ -3,14 +3,8 @@
/**
* https://en.wikipedia.org/wiki/Perfect_square
*/
-public class PerfectSquare {
-
- public static void main(String[] args) {
- assert !isPerfectSquare(-1);
- assert !isPerfectSquare(3);
- assert !isPerfectSquare(5);
- assert isPerfectSquare(9);
- assert isPerfectSquare(100);
+public final class PerfectSquare {
+ private PerfectSquare() {
}
/**
@@ -20,8 +14,8 @@ public static void main(String[] args) {
* @return true if {@code number} is perfect square, otherwise
* false
*/
- public static boolean isPerfectSquare(int number) {
- int sqrt = (int) Math.sqrt(number);
+ public static boolean isPerfectSquare(final int number) {
+ final int sqrt = (int) Math.sqrt(number);
return sqrt * sqrt == number;
}
}
diff --git a/src/test/java/com/thealgorithms/maths/PerfectSquareTest.java b/src/test/java/com/thealgorithms/maths/PerfectSquareTest.java
index 487b477816fd..450ba972debe 100644
--- a/src/test/java/com/thealgorithms/maths/PerfectSquareTest.java
+++ b/src/test/java/com/thealgorithms/maths/PerfectSquareTest.java
@@ -1,38 +1,21 @@
package com.thealgorithms.maths;
-import static org.junit.jupiter.api.Assertions.*;
-
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
public class PerfectSquareTest {
-
- @Test
- public void TestPerfectSquareifiscorrect() {
- // Valid Partition
- int number = 9;
-
- boolean result = PerfectSquare.isPerfectSquare(number);
-
- assertTrue(result);
- }
-
- @Test
- public void TestPerfectSquareifisnotcorrect() {
- // Invalid Partition 1
- int number = 3;
-
- boolean result = PerfectSquare.isPerfectSquare(number);
-
- assertFalse(result);
+ @ParameterizedTest
+ @ValueSource(ints = {0, 1, 2 * 2, 3 * 3, 4 * 4, 5 * 5, 6 * 6, 7 * 7, 8 * 8, 9 * 9, 10 * 10, 11 * 11, 123 * 123})
+ void positiveTest(final int number) {
+ Assertions.assertTrue(PerfectSquare.isPerfectSquare(number));
}
- @Test
- public void TestPerfectSquareifisNegativeNumber() {
- // Invalid Partition 2
- int number = -10;
-
- boolean result = PerfectSquare.isPerfectSquare(number);
-
- assertFalse(result);
+ @ParameterizedTest
+ @ValueSource(ints = {-1, -2, -3, -4, -5, -100, 2, 3, 5, 6, 7, 8, 10, 11, 12, 13, 15, 17, 99, 101, 257, 999, 1001})
+ void negativeTest(final int number) {
+ Assertions.assertFalse(PerfectSquare.isPerfectSquare(number));
}
}
From 8930ab5b16ad3ab062c22004dbfc3da701bb85ef Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Fri, 5 Jan 2024 22:05:52 +0100
Subject: [PATCH 0083/1338] Cleanup `SumOfDigits` and its tests (#4994)
---
.../com/thealgorithms/maths/SumOfDigits.java | 35 +++++-----------
.../thealgorithms/maths/SumOfDigitsTest.java | 40 +++++++++----------
2 files changed, 31 insertions(+), 44 deletions(-)
diff --git a/src/main/java/com/thealgorithms/maths/SumOfDigits.java b/src/main/java/com/thealgorithms/maths/SumOfDigits.java
index 09b690facdb9..e5ec8a02025d 100644
--- a/src/main/java/com/thealgorithms/maths/SumOfDigits.java
+++ b/src/main/java/com/thealgorithms/maths/SumOfDigits.java
@@ -1,13 +1,7 @@
package com.thealgorithms.maths;
-public class SumOfDigits {
-
- public static void main(String[] args) {
- assert sumOfDigits(-123) == 6 && sumOfDigitsRecursion(-123) == 6 && sumOfDigitsFast(-123) == 6;
-
- assert sumOfDigits(0) == 0 && sumOfDigitsRecursion(0) == 0 && sumOfDigitsFast(0) == 0;
-
- assert sumOfDigits(12345) == 15 && sumOfDigitsRecursion(12345) == 15 && sumOfDigitsFast(12345) == 15;
+public final class SumOfDigits {
+ private SumOfDigits() {
}
/**
@@ -17,12 +11,12 @@ public static void main(String[] args) {
* @return sum of digits of given {@code number}
*/
public static int sumOfDigits(int number) {
- number = number < 0 ? -number : number;
- /* calculate abs value */
+ final int base = 10;
+ number = Math.abs(number);
int sum = 0;
while (number != 0) {
- sum += number % 10;
- number /= 10;
+ sum += number % base;
+ number /= base;
}
return sum;
}
@@ -34,9 +28,9 @@ public static int sumOfDigits(int number) {
* @return sum of digits of given {@code number}
*/
public static int sumOfDigitsRecursion(int number) {
- number = number < 0 ? -number : number;
- /* calculate abs value */
- return number < 10 ? number : number % 10 + sumOfDigitsRecursion(number / 10);
+ final int base = 10;
+ number = Math.abs(number);
+ return number < base ? number : number % base + sumOfDigitsRecursion(number / base);
}
/**
@@ -45,14 +39,7 @@ public static int sumOfDigitsRecursion(int number) {
* @param number the number contains digits
* @return sum of digits of given {@code number}
*/
- public static int sumOfDigitsFast(int number) {
- number = number < 0 ? -number : number;
- /* calculate abs value */
- char[] digits = (number + "").toCharArray();
- int sum = 0;
- for (int i = 0; i < digits.length; ++i) {
- sum += digits[i] - '0';
- }
- return sum;
+ public static int sumOfDigitsFast(final int number) {
+ return String.valueOf(Math.abs(number)).chars().map(c -> c - '0').reduce(0, Integer::sum);
}
}
diff --git a/src/test/java/com/thealgorithms/maths/SumOfDigitsTest.java b/src/test/java/com/thealgorithms/maths/SumOfDigitsTest.java
index 1c3b56b7ee5e..76aca44a2220 100644
--- a/src/test/java/com/thealgorithms/maths/SumOfDigitsTest.java
+++ b/src/test/java/com/thealgorithms/maths/SumOfDigitsTest.java
@@ -1,31 +1,31 @@
package com.thealgorithms.maths;
-import static org.junit.jupiter.api.Assertions.*;
-
-import org.junit.jupiter.api.Test;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
class SumOfDigitsTest {
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void sumOfDigitsTest(final int expected, final int input) {
+ Assertions.assertEquals(expected, SumOfDigits.sumOfDigits(input));
+ }
- SumOfDigits SoD = new SumOfDigits();
-
- @Test
- void testZero() {
- assertEquals(0, SumOfDigits.sumOfDigits(0));
- assertEquals(0, SumOfDigits.sumOfDigitsRecursion(0));
- assertEquals(0, SumOfDigits.sumOfDigitsFast(0));
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void sumOfDigitsRecursionTest(final int expected, final int input) {
+ Assertions.assertEquals(expected, SumOfDigits.sumOfDigitsRecursion(input));
}
- @Test
- void testPositive() {
- assertEquals(15, SumOfDigits.sumOfDigits(12345));
- assertEquals(15, SumOfDigits.sumOfDigitsRecursion(12345));
- assertEquals(15, SumOfDigits.sumOfDigitsFast(12345));
+ @ParameterizedTest
+ @MethodSource("testCases")
+ void sumOfDigitsFastTest(final int expected, final int input) {
+ Assertions.assertEquals(expected, SumOfDigits.sumOfDigitsFast(input));
}
- @Test
- void testNegative() {
- assertEquals(6, SumOfDigits.sumOfDigits(-123));
- assertEquals(6, SumOfDigits.sumOfDigitsRecursion(-123));
- assertEquals(6, SumOfDigits.sumOfDigitsFast(-123));
+ private static Stream testCases() {
+ return Stream.of(Arguments.of(0, 0), Arguments.of(1, 1), Arguments.of(15, 12345), Arguments.of(6, -123), Arguments.of(1, -100000), Arguments.of(8, 512));
}
}
From 704b5878b660535477370a8f2d8c9d5175169302 Mon Sep 17 00:00:00 2001
From: "Tung Bui (Leo)"
Date: Sun, 7 Jan 2024 19:20:43 +0700
Subject: [PATCH 0084/1338] Use Discord channel in stale issue/PR message
(#5004)
---
.github/workflows/stale.yml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index 8fbb262b9e36..ee14629b2e41 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -8,10 +8,10 @@ jobs:
steps:
- uses: actions/stale@v4
with:
- stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
- close-issue-message: 'Please reopen this issue once you add more information and updates here. If this is not the case and you need some help, feel free to seek help from our [Gitter](https://gitter.im/TheAlgorithms) or ping one of the reviewers. Thank you for your contributions!'
- stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
- close-pr-message: 'Please reopen this pull request once you commit the changes requested or make improvements on the code. If this is not the case and you need some help, feel free to seek help from our [Gitter](https://gitter.im/TheAlgorithms) or ping one of the reviewers. Thank you for your contributions!'
+ stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution!'
+ close-issue-message: 'Please reopen this issue once you have made the required changes. If you need help, feel free to ask in our [Discord](https://the-algorithms.com/discord) server or ping one of the maintainers here. Thank you for your contribution!'
+ stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contribution!'
+ close-pr-message: 'Please reopen this pull request once you have made the required changes. If you need help, feel free to ask in our [Discord](https://the-algorithms.com/discord) server or ping one of the maintainers here. Thank you for your contribution!'
exempt-issue-labels: 'dont-close'
exempt-pr-labels: 'dont-close'
days-before-stale: 30
From 0c881e39f24152a47ba03d4580a5cc8a6d6a69bc Mon Sep 17 00:00:00 2001
From: Nishant Jain <121454072+inishantjain@users.noreply.github.com>
Date: Mon, 8 Jan 2024 19:04:36 +0530
Subject: [PATCH 0085/1338] Simplify minimizing lateness (#4999)
---
.../greedyalgorithms/MinimizingLateness.java | 43 +++++++++++++++
.../MinimizingLateness.java | 55 -------------------
.../minimizinglateness/lateness_data.txt | 7 ---
.../MinimizingLatenessTest.java | 43 +++++++++++++++
4 files changed, 86 insertions(+), 62 deletions(-)
create mode 100644 src/main/java/com/thealgorithms/greedyalgorithms/MinimizingLateness.java
delete mode 100644 src/main/java/com/thealgorithms/minimizinglateness/MinimizingLateness.java
delete mode 100644 src/main/java/com/thealgorithms/minimizinglateness/lateness_data.txt
create mode 100644 src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessTest.java
diff --git a/src/main/java/com/thealgorithms/greedyalgorithms/MinimizingLateness.java b/src/main/java/com/thealgorithms/greedyalgorithms/MinimizingLateness.java
new file mode 100644
index 000000000000..938ae79bb625
--- /dev/null
+++ b/src/main/java/com/thealgorithms/greedyalgorithms/MinimizingLateness.java
@@ -0,0 +1,43 @@
+package com.thealgorithms.greedyalgorithms;
+
+import java.util.Arrays;
+
+public class MinimizingLateness {
+
+ public static class Job {
+ String jobName;
+ int startTime = 0;
+ int lateness = 0;
+ int processingTime;
+ int deadline;
+
+ public Job(String jobName, int processingTime, int deadline) {
+ this.jobName = jobName;
+ this.processingTime = processingTime;
+ this.deadline = deadline;
+ }
+
+ public static Job of(String jobName, int processingTime, int deadline) {
+ return new Job(jobName, processingTime, deadline);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s, startTime: %d, endTime: %d, lateness: %d", jobName, startTime, processingTime + startTime, lateness);
+ }
+ }
+
+ static void calculateLateness(Job... jobs) {
+
+ // sort the jobs based on their deadline
+ Arrays.sort(jobs, (a, b) -> a.deadline - b.deadline);
+
+ int startTime = 0;
+
+ for (Job job : jobs) {
+ job.startTime = startTime;
+ startTime += job.processingTime;
+ job.lateness = Math.max(0, startTime - job.deadline); // if the job finishes before deadline the lateness is 0
+ }
+ }
+}
diff --git a/src/main/java/com/thealgorithms/minimizinglateness/MinimizingLateness.java b/src/main/java/com/thealgorithms/minimizinglateness/MinimizingLateness.java
deleted file mode 100644
index fc7eae6ae9fc..000000000000
--- a/src/main/java/com/thealgorithms/minimizinglateness/MinimizingLateness.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.thealgorithms.minimizinglateness;
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.StringTokenizer;
-
-public class MinimizingLateness {
-
- private static class Schedule { // Schedule class
-
- int t = 0; // Time required for the operation to be performed
- int d = 0; // Time the job should be completed
- public Schedule(int t, int d) {
- this.t = t;
- this.d = d;
- }
- }
-
- public static void main(String[] args) throws IOException {
- StringTokenizer token;
-
- BufferedReader in = new BufferedReader(new FileReader("MinimizingLateness/lateness_data.txt"));
- String ch = in.readLine();
- if (ch == null || ch.isEmpty()) {
- in.close();
- return;
- }
- int indexCount = Integer.parseInt(ch);
- System.out.println("Input Data : ");
- System.out.println(indexCount); // number of operations
- Schedule[] array = new Schedule[indexCount]; // Create an array to hold the operation
- int i = 0;
- while ((ch = in.readLine()) != null) {
- token = new StringTokenizer(ch, " ");
- // Include the time required for the operation to be performed in the array and the time
- // it should be completed.
- array[i] = new Schedule(Integer.parseInt(token.nextToken()), Integer.parseInt(token.nextToken()));
- i++;
- System.out.println(array[i - 1].t + " " + array[i - 1].d);
- }
-
- int tryTime = 0; // Total time worked
- int lateness = 0; // Lateness
- for (int j = 0; j < indexCount - 1; j++) {
- tryTime = tryTime + array[j].t; // Add total work time
- // Lateness
- lateness = lateness + Math.max(0, tryTime - array[j].d);
- }
- System.out.println();
- System.out.println("Output Data : ");
- System.out.println(lateness);
- in.close();
- }
-}
diff --git a/src/main/java/com/thealgorithms/minimizinglateness/lateness_data.txt b/src/main/java/com/thealgorithms/minimizinglateness/lateness_data.txt
deleted file mode 100644
index e2bac0d1cbd0..000000000000
--- a/src/main/java/com/thealgorithms/minimizinglateness/lateness_data.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-6
-3 6
-2 8
-1 9
-4 9
-3 14
-2 15
\ No newline at end of file
diff --git a/src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessTest.java b/src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessTest.java
new file mode 100644
index 000000000000..04f6900d14db
--- /dev/null
+++ b/src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessTest.java
@@ -0,0 +1,43 @@
+package com.thealgorithms.greedyalgorithms;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.thealgorithms.greedyalgorithms.MinimizingLateness.Job;
+import org.junit.jupiter.api.Test;
+
+public class MinimizingLatenessTest {
+
+ @Test
+ void testCalculateLateness() {
+ // Test case with three jobs
+ Job job1 = new Job("Job1", 4, 6);
+ Job job2 = new Job("Job2", 2, 8);
+ Job job3 = new Job("Job3", 1, 9);
+ Job job4 = new Job("Job4", 5, 9);
+ Job job5 = new Job("Job5", 4, 10);
+ Job job6 = new Job("Job6", 3, 5);
+
+ MinimizingLateness.calculateLateness(job1, job2, job3, job4, job5, job6);
+
+ // Check lateness for each job
+ assertEquals(6, job4.lateness);
+ assertEquals(0, job6.lateness);
+ assertEquals(1, job2.lateness);
+ }
+
+ @Test
+ void testCheckStartTime() {
+
+ Job job1 = new Job("Job1", 2, 5);
+ Job job2 = new Job("Job2", 1, 7);
+ Job job3 = new Job("Job3", 3, 8);
+ Job job4 = new Job("Job4", 2, 4);
+ Job job5 = new Job("Job5", 4, 10);
+
+ MinimizingLateness.calculateLateness(job1, job2, job3, job4, job5);
+
+ assertEquals(2, job1.startTime);
+ assertEquals(5, job3.startTime);
+ assertEquals(8, job5.startTime);
+ }
+}
From bb2fff0cbb73f91d2b7d43741add059cd219e0a2 Mon Sep 17 00:00:00 2001
From: Nishant Jain <121454072+inishantjain@users.noreply.github.com>
Date: Mon, 8 Jan 2024 19:11:14 +0530
Subject: [PATCH 0086/1338] Add package name (#5007)
---
.../com/thealgorithms/searches/PerfectBinarySearchTest.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java b/src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java
index 0ba0b03b33b4..ca5829c54495 100644
--- a/src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java
+++ b/src/test/java/com/thealgorithms/searches/PerfectBinarySearchTest.java
@@ -1,6 +1,7 @@
+package com.thealgorithms.searches;
+
import static org.junit.jupiter.api.Assertions.*;
-import com.thealgorithms.searches.PerfectBinarySearch;
import org.junit.jupiter.api.Test;
/**
From c403e0033198adb2b023d01296ea1e3fc7fc2620 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Mon, 8 Jan 2024 22:32:18 +0100
Subject: [PATCH 0087/1338] Use `GITHUB_ACTOR` in `git config` (#5009)
---
.github/workflows/update_directory.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/update_directory.yml b/.github/workflows/update_directory.yml
index 0530a0c267a9..3638e3529e0b 100644
--- a/.github/workflows/update_directory.yml
+++ b/.github/workflows/update_directory.yml
@@ -84,8 +84,8 @@ jobs:
- name: Update DIRECTORY.md
run: |
cat DIRECTORY.md
- git config --global user.name github-actions
- git config --global user.email '${GITHUB_ACTOR}@users.noreply.github.com'
+ git config --global user.name "$GITHUB_ACTOR"
+ git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com"
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY
git add DIRECTORY.md
git commit -am "Update directory" || true
From 570f7e7ef6876a6a5b6a7caf63056680969e3c18 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Mon, 8 Jan 2024 22:44:32 +0100
Subject: [PATCH 0088/1338] Remove unused import (#5010)
---
.../java/com/thealgorithms/strings/ReverseWordsInStringTest.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/test/java/com/thealgorithms/strings/ReverseWordsInStringTest.java b/src/test/java/com/thealgorithms/strings/ReverseWordsInStringTest.java
index 44e397459349..7cab6aa7c698 100644
--- a/src/test/java/com/thealgorithms/strings/ReverseWordsInStringTest.java
+++ b/src/test/java/com/thealgorithms/strings/ReverseWordsInStringTest.java
@@ -2,7 +2,6 @@
import java.util.stream.Stream;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
From fd84b0b10e2e6d17b161e53586164948b69d3b75 Mon Sep 17 00:00:00 2001
From: mpousmali <115431039+mpousmali@users.noreply.github.com>
Date: Mon, 8 Jan 2024 23:48:11 +0200
Subject: [PATCH 0089/1338] Add SRTF Algorithm (#5011)
---
.gitpod.yml | 1 +
.../scheduling/SRTFScheduling.java | 69 +++++++++++++++++++
.../scheduling/SRTFSchedulingTest.java | 61 ++++++++++++++++
3 files changed, 131 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/scheduling/SRTFScheduling.java
create mode 100644 src/test/java/com/thealgorithms/scheduling/SRTFSchedulingTest.java
diff --git a/.gitpod.yml b/.gitpod.yml
index 4a3944d0023d..21d69f6e2122 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -10,3 +10,4 @@ tasks:
vscode:
extensions:
- xaver.clang-format
+
diff --git a/src/main/java/com/thealgorithms/scheduling/SRTFScheduling.java b/src/main/java/com/thealgorithms/scheduling/SRTFScheduling.java
new file mode 100644
index 000000000000..ad8aeabacad8
--- /dev/null
+++ b/src/main/java/com/thealgorithms/scheduling/SRTFScheduling.java
@@ -0,0 +1,69 @@
+package com.thealgorithms.scheduling;
+
+import com.thealgorithms.devutils.entities.ProcessDetails;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implementation of Shortest Remaining Time First Scheduling Algorithm.
+ * In the SRTF scheduling algorithm, the process with the smallest amount of time remaining until completion is selected to execute.
+ * Example:
+ * Consider the processes p1, p2 and the following table with info about their arrival and burst time:
+ * Process | Burst Time | Arrival Time
+ * P1 | 6 ms | 0 ms
+ * P2 | 2 ms | 1 ms
+ * In this example, P1 will be executed at time = 0 until time = 1 when P2 arrives. At time = 2, P2 will be executed until time = 4. At time 4, P2 is done, and P1 is executed again to be done.
+ * That's a simple example of how the algorithm works.
+ * More information you can find here -> https://en.wikipedia.org/wiki/Shortest_remaining_time
+ */
+public class SRTFScheduling {
+ protected List processes;
+ protected List ready;
+
+ /**
+ * Constructor
+ * @param processes ArrayList of ProcessDetails given as input
+ */
+ public SRTFScheduling(ArrayList processes) {
+ this.processes = new ArrayList<>();
+ ready = new ArrayList<>();
+ this.processes = processes;
+ }
+
+ public void evaluateScheduling() {
+ int time = 0, cr = 0; // cr=current running process, time= units of time
+ int n = processes.size();
+ int[] remainingTime = new int[n];
+
+ /* calculating remaining time of every process and total units of time */
+ for (int i = 0; i < n; i++) {
+ remainingTime[i] = processes.get(i).getBurstTime();
+ time += processes.get(i).getBurstTime();
+ }
+
+ /* if the first process doesn't arrive at 0, we have more units of time */
+ if (processes.get(0).getArrivalTime() != 0) {
+ time += processes.get(0).getArrivalTime();
+ }
+
+ /* printing id of the process which is executed at every unit of time */
+ // if the first process doesn't arrive at 0, we print only \n until it arrives
+ if (processes.get(0).getArrivalTime() != 0) {
+ for (int i = 0; i < processes.get(0).getArrivalTime(); i++) {
+ ready.add(null);
+ }
+ }
+
+ for (int i = processes.get(0).getArrivalTime(); i < time; i++) {
+ /* checking if there's a process with remaining time less than current running process.
+ If we find it, then it executes. */
+ for (int j = 0; j < n; j++) {
+ if (processes.get(j).getArrivalTime() <= i && (remainingTime[j] < remainingTime[cr] && remainingTime[j] > 0 || remainingTime[cr] == 0)) {
+ cr = j;
+ }
+ }
+ ready.add(processes.get(cr).getProcessId());
+ remainingTime[cr]--;
+ }
+ }
+}
diff --git a/src/test/java/com/thealgorithms/scheduling/SRTFSchedulingTest.java b/src/test/java/com/thealgorithms/scheduling/SRTFSchedulingTest.java
new file mode 100644
index 000000000000..0cfe3d34f0ec
--- /dev/null
+++ b/src/test/java/com/thealgorithms/scheduling/SRTFSchedulingTest.java
@@ -0,0 +1,61 @@
+package com.thealgorithms.scheduling;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.thealgorithms.devutils.entities.ProcessDetails;
+import java.util.ArrayList;
+import org.junit.jupiter.api.Test;
+
+class SRTFSchedulingTest {
+ ArrayList processes;
+
+ public void initialization() {
+ processes = new ArrayList<>();
+ processes.add(new ProcessDetails("4", 0, 3));
+ processes.add(new ProcessDetails("3", 1, 8));
+ processes.add(new ProcessDetails("1", 2, 6));
+ processes.add(new ProcessDetails("5", 4, 4));
+ processes.add(new ProcessDetails("2", 5, 2));
+ }
+
+ @Test
+ public void Constructor() {
+ initialization();
+ SRTFScheduling s = new SRTFScheduling(processes);
+ assertEquals(3, s.processes.get(0).getBurstTime());
+ assertEquals(8, s.processes.get(1).getBurstTime());
+ assertEquals(6, s.processes.get(2).getBurstTime());
+ assertEquals(4, s.processes.get(3).getBurstTime());
+ assertEquals(2, s.processes.get(4).getBurstTime());
+ }
+
+ @Test
+ void evaluateScheduling() {
+ initialization();
+ SRTFScheduling s = new SRTFScheduling(processes);
+ s.evaluateScheduling();
+ assertEquals("4", s.ready.get(0));
+ assertEquals("4", s.ready.get(1));
+ assertEquals("4", s.ready.get(2));
+ assertEquals("1", s.ready.get(3));
+ assertEquals("5", s.ready.get(4));
+ assertEquals("2", s.ready.get(5));
+ assertEquals("2", s.ready.get(6));
+ assertEquals("5", s.ready.get(7));
+ assertEquals("5", s.ready.get(8));
+ assertEquals("5", s.ready.get(9));
+ assertEquals("1", s.ready.get(10));
+ assertEquals("1", s.ready.get(11));
+ assertEquals("1", s.ready.get(12));
+ assertEquals("1", s.ready.get(13));
+ assertEquals("1", s.ready.get(14));
+ assertEquals("3", s.ready.get(15));
+ assertEquals("3", s.ready.get(16));
+ assertEquals("3", s.ready.get(17));
+ assertEquals("3", s.ready.get(18));
+ assertEquals("3", s.ready.get(19));
+ assertEquals("3", s.ready.get(20));
+ assertEquals("3", s.ready.get(21));
+ assertEquals("3", s.ready.get(22));
+ }
+}
From 19b7a22ec94987f9d6a0df2079249c11deb9b337 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Wed, 10 Jan 2024 19:31:38 +0100
Subject: [PATCH 0090/1338] Remove unused imports from `BoyerMooreTest` (#5012)
---
src/test/java/com/thealgorithms/others/BoyerMooreTest.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/test/java/com/thealgorithms/others/BoyerMooreTest.java b/src/test/java/com/thealgorithms/others/BoyerMooreTest.java
index b1497f7bc525..b6620793d267 100644
--- a/src/test/java/com/thealgorithms/others/BoyerMooreTest.java
+++ b/src/test/java/com/thealgorithms/others/BoyerMooreTest.java
@@ -1,9 +1,7 @@
package com.thealgorithms.others;
-import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.stream.Stream;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
From 8804cec9574badcdc1e690c6db1314a463c10458 Mon Sep 17 00:00:00 2001
From: Sarthak Chaudhary <86872379+SarthakChaudhary46@users.noreply.github.com>
Date: Sat, 13 Jan 2024 13:59:30 +0530
Subject: [PATCH 0091/1338] Feature/4638 array right rotation (#5014)
* Create ArrayRightRotationTest.java
* Create ArrayRightRotation.java
* The updated one
* The updated one
* Added the test cases
* Added new test cases!
* Update ArrayRightRotation.java
* Update ArrayRightRotationTest.java
---
.../others/ArrayRightRotation.java | 28 ++++++++++
.../others/ArrayRightRotationTest.java | 53 +++++++++++++++++++
2 files changed, 81 insertions(+)
create mode 100644 src/test/java/com/thealgorithms/others/ArrayRightRotation.java
create mode 100644 src/test/java/com/thealgorithms/others/ArrayRightRotationTest.java
diff --git a/src/test/java/com/thealgorithms/others/ArrayRightRotation.java b/src/test/java/com/thealgorithms/others/ArrayRightRotation.java
new file mode 100644
index 000000000000..a78ef81f32a4
--- /dev/null
+++ b/src/test/java/com/thealgorithms/others/ArrayRightRotation.java
@@ -0,0 +1,28 @@
+package com.thealgorithms.others;
+
+public class ArrayRightRotation {
+ public static int[] rotateRight(int[] arr, int k) {
+ if (arr == null || arr.length == 0 || k < 0) {
+ throw new IllegalArgumentException("Invalid input");
+ }
+
+ int n = arr.length;
+ k = k % n; // Handle cases where k is larger than the array length
+
+ reverseArray(arr, 0, n - 1);
+ reverseArray(arr, 0, k - 1);
+ reverseArray(arr, k, n - 1);
+
+ return arr;
+ }
+
+ private static void reverseArray(int[] arr, int start, int end) {
+ while (start < end) {
+ int temp = arr[start];
+ arr[start] = arr[end];
+ arr[end] = temp;
+ start++;
+ end--;
+ }
+ }
+}
diff --git a/src/test/java/com/thealgorithms/others/ArrayRightRotationTest.java b/src/test/java/com/thealgorithms/others/ArrayRightRotationTest.java
new file mode 100644
index 000000000000..f132d56dd9cd
--- /dev/null
+++ b/src/test/java/com/thealgorithms/others/ArrayRightRotationTest.java
@@ -0,0 +1,53 @@
+package com.thealgorithms.others;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+
+import org.junit.jupiter.api.Test;
+
+class ArrayRightRotationTest {
+
+ @Test
+ void testArrayRightRotation() {
+ int[] arr = {1, 2, 3, 4, 5, 6, 7};
+ int k = 3;
+ int[] expected = {5, 6, 7, 1, 2, 3, 4};
+ int[] result = ArrayRightRotation.rotateRight(arr, k);
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ void testArrayRightRotationWithZeroSteps() {
+ int[] arr = {1, 2, 3, 4, 5, 6, 7};
+ int k = 0;
+ int[] expected = {1, 2, 3, 4, 5, 6, 7};
+ int[] result = ArrayRightRotation.rotateRight(arr, k);
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ void testArrayRightRotationWithEqualSizeSteps() {
+ int[] arr = {1, 2, 3, 4, 5, 6, 7};
+ int k = arr.length;
+ int[] expected = {1, 2, 3, 4, 5, 6, 7};
+ int[] result = ArrayRightRotation.rotateRight(arr, k);
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ void testArrayRightRotationWithLowerSizeSteps() {
+ int[] arr = {1, 2, 3, 4, 5, 6, 7};
+ int k = 2;
+ int[] expected = {6, 7, 1, 2, 3, 4, 5};
+ int[] result = ArrayRightRotation.rotateRight(arr, k);
+ assertArrayEquals(expected, result);
+ }
+
+ @Test
+ void testArrayRightRotationWithHigherSizeSteps() {
+ int[] arr = {1, 2, 3, 4, 5, 6, 7};
+ int k = 10;
+ int[] expected = {5, 6, 7, 1, 2, 3, 4};
+ int[] result = ArrayRightRotation.rotateRight(arr, k);
+ assertArrayEquals(expected, result);
+ }
+}
From 9426053f73d55efde9c3c601f9cf4f30a33ec673 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sat, 13 Jan 2024 10:04:32 +0100
Subject: [PATCH 0092/1338] Remove unused import from `PowerOfTwoOrNotTest`
(#5015)
style: remove unused import from `PowerOfTwoOrNotTest.java`
---
src/test/java/com/thealgorithms/maths/PowerOfTwoOrNotTest.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/test/java/com/thealgorithms/maths/PowerOfTwoOrNotTest.java b/src/test/java/com/thealgorithms/maths/PowerOfTwoOrNotTest.java
index df01d481ccd8..ac8d2be17d7c 100644
--- a/src/test/java/com/thealgorithms/maths/PowerOfTwoOrNotTest.java
+++ b/src/test/java/com/thealgorithms/maths/PowerOfTwoOrNotTest.java
@@ -3,7 +3,6 @@
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import java.util.Map;
import org.junit.jupiter.api.Test;
public class PowerOfTwoOrNotTest {
From ac7152d757096d5a30e68b3864108e2843d0c2ed Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sat, 13 Jan 2024 10:21:57 +0100
Subject: [PATCH 0093/1338] Remove unused imports from `PerfectSquareTest`
(#5016)
style: remove unused imports from `PerfectSquareTest`
---
src/test/java/com/thealgorithms/maths/PerfectSquareTest.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/test/java/com/thealgorithms/maths/PerfectSquareTest.java b/src/test/java/com/thealgorithms/maths/PerfectSquareTest.java
index 450ba972debe..08c96bc71f9b 100644
--- a/src/test/java/com/thealgorithms/maths/PerfectSquareTest.java
+++ b/src/test/java/com/thealgorithms/maths/PerfectSquareTest.java
@@ -1,8 +1,6 @@
package com.thealgorithms.maths;
-import java.util.stream.Stream;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
From 3528399b2e385bffcfe0a2fff27d2a866d04a77a Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sat, 13 Jan 2024 10:26:44 +0100
Subject: [PATCH 0094/1338] Remove unused import from `JobSequencing` (#5017)
style: remove unused import from `JobSequencing`
---
.../java/com/thealgorithms/greedyalgorithms/JobSequencing.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/main/java/com/thealgorithms/greedyalgorithms/JobSequencing.java b/src/main/java/com/thealgorithms/greedyalgorithms/JobSequencing.java
index bf81e067bac1..4d2cf7c95a03 100644
--- a/src/main/java/com/thealgorithms/greedyalgorithms/JobSequencing.java
+++ b/src/main/java/com/thealgorithms/greedyalgorithms/JobSequencing.java
@@ -2,7 +2,6 @@
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
// Problem Link: https://en.wikipedia.org/wiki/Job-shop_scheduling
From a216cb8a59ad04b3cadcc156e69dea41f3d1b465 Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sat, 13 Jan 2024 10:28:50 +0100
Subject: [PATCH 0095/1338] Remove unused import from `HashMapCuckooHashing`
(#5018)
style: remove unused import from `HashMapCuckooHashing`
---
.../datastructures/hashmap/hashing/HashMapCuckooHashing.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapCuckooHashing.java b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapCuckooHashing.java
index 74b2527f925c..053751ebbc51 100644
--- a/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapCuckooHashing.java
+++ b/src/main/java/com/thealgorithms/datastructures/hashmap/hashing/HashMapCuckooHashing.java
@@ -1,6 +1,5 @@
package com.thealgorithms.datastructures.hashmap.hashing;
-import java.lang.Math;
import java.util.Objects;
/**
From 55f08cc0139579760964e786364e2239cc65a8d9 Mon Sep 17 00:00:00 2001
From: Bhishmadev Ghosh <111000117+bhishma620@users.noreply.github.com>
Date: Sat, 27 Jan 2024 00:00:26 +0530
Subject: [PATCH 0096/1338] Add tests `SumOfSubset` (#5021)
* Updated main and test
* removed
* style: reorder test cases
---------
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
---
.../{Sum_Of_Subset.java => SumOfSubset.java} | 13 +------------
.../dynamicprogramming/SumOfSubsetTest.java | 17 +++++++++++++++++
2 files changed, 18 insertions(+), 12 deletions(-)
rename src/main/java/com/thealgorithms/dynamicprogramming/{Sum_Of_Subset.java => SumOfSubset.java} (54%)
create mode 100644 src/test/java/com/thealgorithms/dynamicprogramming/SumOfSubsetTest.java
diff --git a/src/main/java/com/thealgorithms/dynamicprogramming/Sum_Of_Subset.java b/src/main/java/com/thealgorithms/dynamicprogramming/SumOfSubset.java
similarity index 54%
rename from src/main/java/com/thealgorithms/dynamicprogramming/Sum_Of_Subset.java
rename to src/main/java/com/thealgorithms/dynamicprogramming/SumOfSubset.java
index 90c07889a57f..622f8b146d96 100644
--- a/src/main/java/com/thealgorithms/dynamicprogramming/Sum_Of_Subset.java
+++ b/src/main/java/com/thealgorithms/dynamicprogramming/SumOfSubset.java
@@ -1,17 +1,6 @@
package com.thealgorithms.dynamicprogramming;
-public class Sum_Of_Subset {
-
- public static void main(String[] args) {
- int[] arr = {7, 3, 2, 5, 8};
- int Key = 14;
-
- if (subsetSum(arr, arr.length - 1, Key)) {
- System.out.print("Yes, that sum exists");
- } else {
- System.out.print("Nope, that number does not exist");
- }
- }
+public class SumOfSubset {
public static boolean subsetSum(int[] arr, int num, int Key) {
if (Key == 0) {
diff --git a/src/test/java/com/thealgorithms/dynamicprogramming/SumOfSubsetTest.java b/src/test/java/com/thealgorithms/dynamicprogramming/SumOfSubsetTest.java
new file mode 100644
index 000000000000..53c34937cbab
--- /dev/null
+++ b/src/test/java/com/thealgorithms/dynamicprogramming/SumOfSubsetTest.java
@@ -0,0 +1,17 @@
+package com.thealgorithms.dynamicprogramming;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+class SumOfSubsetTest {
+
+ @Test
+ void basicCheck() {
+ assertEquals(false, SumOfSubset.subsetSum(new int[] {1, 2, 7, 10, 9}, 4, 14));
+ assertEquals(false, SumOfSubset.subsetSum(new int[] {2, 15, 1, 6, 7}, 4, 4));
+ assertEquals(true, SumOfSubset.subsetSum(new int[] {7, 3, 2, 5, 8}, 4, 14));
+ assertEquals(true, SumOfSubset.subsetSum(new int[] {4, 3, 2, 1}, 3, 5));
+ assertEquals(true, SumOfSubset.subsetSum(new int[] {1, 7, 2, 9, 10}, 4, 13));
+ }
+}
From b99aeef6743fc718c53c5aa29141d4f9e9f01460 Mon Sep 17 00:00:00 2001
From: Debasish Biswas
Date: Mon, 29 Jan 2024 01:18:40 +0530
Subject: [PATCH 0097/1338] Remove debasishbsws from CODEOWNERS (#5033)
As I am not very active in this repository, I should step down from being a CodeOwner /cc @BamaCharanChhandogi @yanglbme
---
.github/CODEOWNERS | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 0706d623599a..a84f13be1047 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1 +1 @@
-* @yanglbme @debasishbsws @vil02 @BamaCharanChhandogi
+* @yanglbme @vil02 @BamaCharanChhandogi
From 14b3f45f9f32df108de5d0eace624f23d6bbe1bf Mon Sep 17 00:00:00 2001
From: VedantK <145242784+555vedant@users.noreply.github.com>
Date: Thu, 1 Feb 2024 13:55:31 +0530
Subject: [PATCH 0098/1338] Add `ExchangeSort` (#5029)
* added ExchangeSort and its testcases
---------
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
---
.../com/thealgorithms/sorts/ExchangeSort.java | 47 +++++++++++++++++++
.../thealgorithms/sorts/ExchangeSortTest.java | 8 ++++
2 files changed, 55 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/sorts/ExchangeSort.java
create mode 100644 src/test/java/com/thealgorithms/sorts/ExchangeSortTest.java
diff --git a/src/main/java/com/thealgorithms/sorts/ExchangeSort.java b/src/main/java/com/thealgorithms/sorts/ExchangeSort.java
new file mode 100644
index 000000000000..28303430950c
--- /dev/null
+++ b/src/main/java/com/thealgorithms/sorts/ExchangeSort.java
@@ -0,0 +1,47 @@
+package com.thealgorithms.sorts;
+
+/**
+ * ExchangeSort is an implementation of the Exchange Sort algorithm.
+ *
+ *
+ * Exchange sort works by comparing each element with all subsequent elements,
+ * swapping where needed, to ensure the correct placement of each element
+ * in the final sorted order. It iteratively performs this process for each
+ * element in the array. While it lacks the advantage of bubble sort in
+ * detecting sorted lists in one pass, it can be more efficient than bubble sort
+ * due to a constant factor (one less pass over the data to be sorted; half as
+ * many total comparisons) in worst-case scenarios.
+ *
+ *
+ *
+ * Reference: https://en.wikipedia.org/wiki/Sorting_algorithm#Exchange_sort
+ *
+ *
+ * @author 555vedant (Vedant Kasar)
+ */
+class ExchangeSort implements SortAlgorithm {
+ /**
+ * Implementation of Exchange Sort Algorithm
+ *
+ * @param array the array to be sorted.
+ * @param the type of elements in the array.
+ * @return the sorted array.
+ */
+ @Override
+ public > T[] sort(T[] array) {
+ for (int i = 0; i < array.length - 1; i++) {
+ for (int j = i + 1; j < array.length; j++) {
+ if (array[i].compareTo(array[j]) > 0) {
+ swap(array, i, j);
+ }
+ }
+ }
+ return array;
+ }
+
+ private void swap(T[] array, int i, int j) {
+ T temp = array[i];
+ array[i] = array[j];
+ array[j] = temp;
+ }
+}
diff --git a/src/test/java/com/thealgorithms/sorts/ExchangeSortTest.java b/src/test/java/com/thealgorithms/sorts/ExchangeSortTest.java
new file mode 100644
index 000000000000..6c4271fa9e19
--- /dev/null
+++ b/src/test/java/com/thealgorithms/sorts/ExchangeSortTest.java
@@ -0,0 +1,8 @@
+package com.thealgorithms.sorts;
+
+public class ExchangeSortTest extends SortingAlgorithmTest {
+ @Override
+ SortAlgorithm getSortAlgorithm() {
+ return new ExchangeSort();
+ }
+}
From 55cc562d64a0e7caa622d18a67f51cf79970f48e Mon Sep 17 00:00:00 2001
From: Piotr Idzik <65706193+vil02@users.noreply.github.com>
Date: Sun, 11 Feb 2024 22:21:08 +0100
Subject: [PATCH 0099/1338] chore: update `actions/checkout` to `v4` (#5036)
---
.github/workflows/codeql.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 482c8bc60527..cea50a26c19a 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -24,7 +24,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v3
From 47a9b1b647d890d3cce50cd21774f5c78c350782 Mon Sep 17 00:00:00 2001
From: straf10 <115450409+straf10@users.noreply.github.com>
Date: Mon, 12 Feb 2024 21:48:07 +0200
Subject: [PATCH 0100/1338] Add `WelshPowell` (Graph Colouring) (#5034)
* Welsh Powell Algorithm + Test
---------
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
---
.../datastructures/graphs/WelshPowell.java | 113 ++++++++++++++++
.../graphs/WelshPowellTest.java | 124 ++++++++++++++++++
2 files changed, 237 insertions(+)
create mode 100644 src/main/java/com/thealgorithms/datastructures/graphs/WelshPowell.java
create mode 100644 src/test/java/com/thealgorithms/datastructures/graphs/WelshPowellTest.java
diff --git a/src/main/java/com/thealgorithms/datastructures/graphs/WelshPowell.java b/src/main/java/com/thealgorithms/datastructures/graphs/WelshPowell.java
new file mode 100644
index 000000000000..3b823f02388d
--- /dev/null
+++ b/src/main/java/com/thealgorithms/datastructures/graphs/WelshPowell.java
@@ -0,0 +1,113 @@
+package com.thealgorithms.datastructures.graphs;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.stream.IntStream;
+
+/*
+ * The Welsh-Powell algorithm is a graph coloring algorithm
+ * used for coloring a graph with the minimum number of colors.
+ * https://en.wikipedia.org/wiki/Graph_coloring
+ */
+
+public final class WelshPowell {
+ private static final int BLANK_COLOR = -1; // Representing uncolored state
+
+ private WelshPowell() {
+ }
+
+ static class Graph {
+ private HashSet[] adjacencyLists;
+
+ private Graph(int vertices) {
+ if (vertices < 0) {
+ throw new IllegalArgumentException("Number of vertices cannot be negative");
+ }
+
+ adjacencyLists = new HashSet[vertices];
+ Arrays.setAll(adjacencyLists, i -> new HashSet<>());
+ }
+
+ private void addEdge(int nodeA, int nodeB) {
+ validateVertex(nodeA);
+ validateVertex(nodeB);
+ if (nodeA == nodeB) {
+ throw new IllegalArgumentException("Self-loops are not allowed");
+ }
+ adjacencyLists[nodeA].add(nodeB);
+ adjacencyLists[nodeB].add(nodeA);
+ }
+
+ private void validateVertex(int vertex) {
+ if (vertex < 0 || vertex >= getNumVertices()) {
+ throw new IllegalArgumentException("Vertex " + vertex + " is out of bounds");
+ }
+ }
+
+ HashSet getAdjacencyList(int vertex) {
+ return adjacencyLists[vertex];
+ }
+
+ int getNumVertices() {
+ return adjacencyLists.length;
+ }
+ }
+
+ public static Graph makeGraph(int numberOfVertices, int[][] listOfEdges) {
+ Graph graph = new Graph(numberOfVertices);
+ for (int[] edge : listOfEdges) {
+ if (edge.length != 2) {
+ throw new IllegalArgumentException("Edge array must have exactly two elements");
+ }
+ graph.addEdge(edge[0], edge[1]);
+ }
+ return graph;
+ }
+
+ public static int[] findColoring(Graph graph) {
+ int[] colors = initializeColors(graph.getNumVertices());
+ Integer[] sortedVertices = getSortedNodes(graph);
+ for (int vertex : sortedVertices) {
+ if (isBlank(colors[vertex])) {
+ boolean[] usedColors = computeUsedColors(graph, vertex, colors);
+ final var newColor = firstUnusedColor(usedColors);
+ colors[vertex] = newColor;
+ Arrays.stream(sortedVertices).forEach(otherVertex -> {
+ if (isBlank(colors[otherVertex]) && !isAdjacentToColored(graph, otherVertex, colors)) {
+ colors[otherVertex] = newColor;
+ }
+ });
+ }
+ }
+ return colors;
+ }
+
+ private static boolean isBlank(int color) {
+ return color == BLANK_COLOR;
+ }
+
+ private static boolean isAdjacentToColored(Graph graph, int vertex, int[] colors) {
+ return graph.getAdjacencyList(vertex).stream().anyMatch(otherVertex -> !isBlank(colors[otherVertex]));
+ }
+
+ private static int[] initializeColors(int numberOfVertices) {
+ int[] colors = new int[numberOfVertices];
+ Arrays.fill(colors, BLANK_COLOR);
+ return colors;
+ }
+
+ private static Integer[] getSortedNodes(final Graph graph) {
+ return IntStream.range(0, graph.getNumVertices()).boxed().sorted(Comparator.comparingInt(v -> - graph.getAdjacencyList(v).size())).toArray(Integer[] ::new);
+ }
+
+ private static boolean[] computeUsedColors(final Graph graph, final int vertex, final int[] colors) {
+ boolean[] usedColors = new boolean[graph.getNumVertices()];
+ graph.getAdjacencyList(vertex).stream().map(neighbor -> colors[neighbor]).filter(color -> !isBlank(color)).forEach(color -> usedColors[color] = true);
+ return usedColors;
+ }
+
+ private static int firstUnusedColor(boolean[] usedColors) {
+ return IntStream.range(0, usedColors.length).filter(color -> !usedColors[color]).findFirst().getAsInt();
+ }
+}
diff --git a/src/test/java/com/thealgorithms/datastructures/graphs/WelshPowellTest.java b/src/test/java/com/thealgorithms/datastructures/graphs/WelshPowellTest.java
new file mode 100644
index 000000000000..b37657db5c05
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/graphs/WelshPowellTest.java
@@ -0,0 +1,124 @@
+package com.thealgorithms.datastructures.graphs;
+
+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 com.thealgorithms.datastructures.graphs.WelshPowell.Graph;
+import java.util.Arrays;
+import org.junit.jupiter.api.Test;
+
+class WelshPowellTest {
+
+ @Test
+ void testSimpleGraph() {
+ final var graph = WelshPowell.makeGraph(4, new int[][] {{0, 1}, {1, 2}, {2, 3}});
+ int[] colors = WelshPowell.findColoring(graph);
+ assertTrue(isColoringValid(graph, colors));
+ assertEquals(2, countDistinctColors(colors));
+ }
+
+ @Test
+ void testDisconnectedGraph() {
+ final var graph = WelshPowell.makeGraph(3, new int[][] {}); // No edges
+ int[] colors = WelshPowell.findColoring(graph);
+ assertTrue(isColoringValid(graph, colors));
+ assertEquals(1, countDistinctColors(colors));
+ }
+
+ @Test
+ void testCompleteGraph() {
+ final var graph = WelshPowell.makeGraph(3, new int[][] {{0, 1}, {1, 2}, {2, 0}});
+ int[] colors = WelshPowell.findColoring(graph);
+ assertTrue(isColoringValid(graph, colors));
+ assertEquals(3, countDistinctColors(colors));
+ }
+
+ // The following test originates from the following website : https://www.geeksforgeeks.org/welsh-powell-graph-colouring-algorithm/
+ @Test
+ void testComplexGraph() {
+ int[][] edges = {
+ {0, 7}, // A-H
+ {0, 1}, // A-B
+ {1, 3}, // B-D
+ {2, 3}, // C-D
+ {3, 8}, // D-I
+ {3, 10}, // D-K
+ {4, 10}, // E-K
+ {4, 5}, // E-F
+ {5, 6}, // F-G
+ {6, 10}, // G-K
+ {6, 7}, // G-H
+ {7, 8}, // H-I
+ {7, 9}, // H-J
+ {7, 10}, // H-K
+ {8, 9}, // I-J
+ {9, 10}, // J-K
+ };
+
+ final var graph = WelshPowell.makeGraph(11, edges); // 11 vertices from A (0) to K (10)
+ int[] colors = WelshPowell.findColoring(graph);
+
+ assertTrue(isColoringValid(graph, colors), "The coloring should be valid with no adjacent vertices sharing the same color.");
+ assertEquals(3, countDistinctColors(colors), "The chromatic number of the graph should be 3.");
+ }
+
+ @Test
+ void testNegativeVertices() {
+ assertThrows(IllegalArgumentException.class, () -> { WelshPowell.makeGraph(-1, new int[][] {}); }, "Number of vertices cannot be negative");
+ }
+
+ @Test
+ void testSelfLoop() {
+ assertThrows(IllegalArgumentException.class, () -> { WelshPowell.makeGraph(3, new int[][] {{0, 0}}); }, "Self-loops are not allowed");
+ }
+
+ @Test
+ void testInvalidVertex() {
+ assertThrows(IllegalArgumentException.class, () -> { WelshPowell.makeGraph(3, new int[][] {{0, 3}}); }, "Vertex out of bounds");
+ assertThrows(IllegalArgumentException.class, () -> { WelshPowell.makeGraph(3, new int[][] {{0, -1}}); }, "Vertex out of bounds");
+ }
+
+ @Test
+ void testInvalidEdgeArray() {
+ assertThrows(IllegalArgumentException.class, () -> { WelshPowell.makeGraph(3, new int[][] {{0}}); }, "Edge array must have exactly two elements");
+ }
+
+ @Test
+ void testWithPreColoredVertex() {
+ // Create a linear graph with 4 vertices and edges connecting them in sequence
+ final var graph = WelshPowell.makeGraph(4, new int[][] {{0, 1}, {1, 2}, {2, 3}});
+
+ // Apply the Welsh-Powell coloring algorithm to the graph
+ int[] colors = WelshPowell.findColoring(graph);
+
+ // Validate that the coloring is correct (no two adjacent vertices have the same color)
+ assertTrue(isColoringValid(graph, colors));
+
+ // Check if the algorithm has used at least 2 colors (expected for a linear graph)
+ assertTrue(countDistinctColors(colors) >= 2);
+
+ // Verify that all vertices have been assigned a color
+ for (int color : colors) {
+ assertTrue(color >= 0);
+ }
+ }
+
+ private boolean isColoringValid(Graph graph, int[] colors) {
+ if (Arrays.stream(colors).anyMatch(n -> n < 0)) {
+ return false;
+ }
+ for (int i = 0; i < graph.getNumVertices(); i++) {
+ for (int neighbor : graph.getAdjacencyList(i)) {
+ if (i != neighbor && colors[i] == colors[neighbor]) {
+ return false; // Adjacent vertices have the same color
+ }
+ }
+ }
+ return true; // No adjacent vertices share the same color
+ }
+
+ private int countDistinctColors(int[] colors) {
+ return (int) Arrays.stream(colors).distinct().count();
+ }
+}
From ab371843aca53ab802e21427d28de5a65577a694 Mon Sep 17 00:00:00 2001
From: SOZEL <80200848+TruongNhanNguyen@users.noreply.github.com>
Date: Wed, 13 Mar 2024 01:49:58 +0700
Subject: [PATCH 0101/1338] Close `Scanner` to avoid resource leak (#5077)
---
.../thealgorithms/ciphers/ProductCipher.java | 107 ++++++++---------
.../datastructures/graphs/BellmanFord.java | 109 +++++++++---------
.../datastructures/stacks/ReverseStack.java | 40 +++----
.../maths/NonRepeatingElement.java | 103 +++++++++--------
.../others/InsertDeleteInArray.java | 73 ++++++------
.../searches/RecursiveBinarySearch.java | 36 +++---
6 files changed, 243 insertions(+), 225 deletions(-)
diff --git a/src/main/java/com/thealgorithms/ciphers/ProductCipher.java b/src/main/java/com/thealgorithms/ciphers/ProductCipher.java
index c5ce8a9b157c..5b1d46fe9a9a 100644
--- a/src/main/java/com/thealgorithms/ciphers/ProductCipher.java
+++ b/src/main/java/com/thealgorithms/ciphers/ProductCipher.java
@@ -5,67 +5,68 @@
class ProductCipher {
public static void main(String[] args) {
- Scanner sc = new Scanner(System.in);
- System.out.println("Enter the input to be encrypted: ");
- String substitutionInput = sc.nextLine();
- System.out.println(" ");
- System.out.println("Enter a number: ");
- int n = sc.nextInt();
+ try (Scanner sc = new Scanner(System.in)) {
+ System.out.println("Enter the input to be encrypted: ");
+ String substitutionInput = sc.nextLine();
+ System.out.println(" ");
+ System.out.println("Enter a number: ");
+ int n = sc.nextInt();
- // Substitution encryption
- StringBuffer substitutionOutput = new StringBuffer();
- for (int i = 0; i < substitutionInput.length(); i++) {
- char c = substitutionInput.charAt(i);
- substitutionOutput.append((char) (c + 5));
- }
- System.out.println(" ");
- System.out.println("Substituted text: ");
- System.out.println(substitutionOutput);
+ // Substitution encryption
+ StringBuffer substitutionOutput = new StringBuffer();
+ for (int i = 0; i < substitutionInput.length(); i++) {
+ char c = substitutionInput.charAt(i);
+ substitutionOutput.append((char) (c + 5));
+ }
+ System.out.println(" ");
+ System.out.println("Substituted text: ");
+ System.out.println(substitutionOutput);
- // Transposition encryption
- String transpositionInput = substitutionOutput.toString();
- int modulus;
- if ((modulus = transpositionInput.length() % n) != 0) {
- modulus = n - modulus;
+ // Transposition encryption
+ String transpositionInput = substitutionOutput.toString();
+ int modulus;
+ if ((modulus = transpositionInput.length() % n) != 0) {
+ modulus = n - modulus;
- for (; modulus != 0; modulus--) {
- transpositionInput += "/";
+ for (; modulus != 0; modulus--) {
+ transpositionInput += "/";
+ }
}
- }
- StringBuffer transpositionOutput = new StringBuffer();
- System.out.println(" ");
- System.out.println("Transposition Matrix: ");
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < transpositionInput.length() / n; j++) {
- char c = transpositionInput.charAt(i + (j * n));
- System.out.print(c);
- transpositionOutput.append(c);
+ StringBuffer transpositionOutput = new StringBuffer();
+ System.out.println(" ");
+ System.out.println("Transposition Matrix: ");
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < transpositionInput.length() / n; j++) {
+ char c = transpositionInput.charAt(i + (j * n));
+ System.out.print(c);
+ transpositionOutput.append(c);
+ }
+ System.out.println();
}
- System.out.println();
- }
- System.out.println(" ");
- System.out.println("Final encrypted text: ");
- System.out.println(transpositionOutput);
+ System.out.println(" ");
+ System.out.println("Final encrypted text: ");
+ System.out.println(transpositionOutput);
- // Transposition decryption
- n = transpositionOutput.length() / n;
- StringBuffer transpositionPlaintext = new StringBuffer();
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < transpositionOutput.length() / n; j++) {
- char c = transpositionOutput.charAt(i + (j * n));
- transpositionPlaintext.append(c);
+ // Transposition decryption
+ n = transpositionOutput.length() / n;
+ StringBuffer transpositionPlaintext = new StringBuffer();
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < transpositionOutput.length() / n; j++) {
+ char c = transpositionOutput.charAt(i + (j * n));
+ transpositionPlaintext.append(c);
+ }
}
- }
- // Substitution decryption
- StringBuffer plaintext = new StringBuffer();
- for (int i = 0; i < transpositionPlaintext.length(); i++) {
- char c = transpositionPlaintext.charAt(i);
- plaintext.append((char) (c - 5));
- }
+ // Substitution decryption
+ StringBuffer plaintext = new StringBuffer();
+ for (int i = 0; i < transpositionPlaintext.length(); i++) {
+ char c = transpositionPlaintext.charAt(i);
+ plaintext.append((char) (c - 5));
+ }
- System.out.println("Plaintext: ");
- System.out.println(plaintext);
- sc.close();
+ System.out.println("Plaintext: ");
+ System.out.println(plaintext);
+ sc.close();
+ }
}
}
diff --git a/src/main/java/com/thealgorithms/datastructures/graphs/BellmanFord.java b/src/main/java/com/thealgorithms/datastructures/graphs/BellmanFord.java
index 8229c1fa947d..9f5022b44465 100644
--- a/src/main/java/com/thealgorithms/datastructures/graphs/BellmanFord.java
+++ b/src/main/java/com/thealgorithms/datastructures/graphs/BellmanFord.java
@@ -2,9 +2,13 @@
import java.util.*;
-class BellmanFord /*Implementation of Bellman ford to detect negative cycles. Graph accepts inputs
-in form of edges which have start vertex, end vertex and weights. Vertices should be labelled with a
-number between 0 and total number of vertices-1,both inclusive*/
+class BellmanFord /*
+ * Implementation of Bellman ford to detect negative cycles. Graph accepts
+ * inputs
+ * in form of edges which have start vertex, end vertex and weights. Vertices
+ * should be labelled with a
+ * number between 0 and total number of vertices-1,both inclusive
+ */
{
int vertex, edge;
@@ -36,7 +40,7 @@ public Edge(int a, int b, int c) {
/**
* @param p[] Parent array which shows updates in edges
- * @param i Current vertex under consideration
+ * @param i Current vertex under consideration
*/
void printPath(int[] p, int i) {
if (p[i] == -1) { // Found the path back to parent
@@ -52,64 +56,65 @@ public static void main(String[] args) {
}
public void go() { // shows distance to all vertices // Interactive run for understanding the
- // class first time. Assumes source vertex is 0 and
- Scanner sc = new Scanner(System.in); // Grab scanner object for user input
- int i, v, e, u, ve, w, j, neg = 0;
- System.out.println("Enter no. of vertices and edges please");
- v = sc.nextInt();
- e = sc.nextInt();
- Edge[] arr = new Edge[e]; // Array of edges
- System.out.println("Input edges");
- for (i = 0; i < e; i++) {
- u = sc.nextInt();
- ve = sc.nextInt();
- w = sc.nextInt();
- arr[i] = new Edge(u, ve, w);
- }
- int[] dist = new int[v]; // Distance array for holding the finalized shortest path distance
- // between source
- // and all vertices
- int[] p = new int[v]; // Parent array for holding the paths
- for (i = 0; i < v; i++) {
- dist[i] = Integer.MAX_VALUE; // Initializing distance values
- }
- dist[0] = 0;
- p[0] = -1;
- for (i = 0; i < v - 1; i++) {
+ try ( // class first time. Assumes source vertex is 0 and
+ Scanner sc = new Scanner(System.in)) {
+ int i, v, e, u, ve, w, j, neg = 0;
+ System.out.println("Enter no. of vertices and edges please");
+ v = sc.nextInt();
+ e = sc.nextInt();
+ Edge[] arr = new Edge[e]; // Array of edges
+ System.out.println("Input edges");
+ for (i = 0; i < e; i++) {
+ u = sc.nextInt();
+ ve = sc.nextInt();
+ w = sc.nextInt();
+ arr[i] = new Edge(u, ve, w);
+ }
+ int[] dist = new int[v]; // Distance array for holding the finalized shortest path distance
+ // between source
+ // and all vertices
+ int[] p = new int[v]; // Parent array for holding the paths
+ for (i = 0; i < v; i++) {
+ dist[i] = Integer.MAX_VALUE; // Initializing distance values
+ }
+ dist[0] = 0;
+ p[0] = -1;
+ for (i = 0; i < v - 1; i++) {
+ for (j = 0; j < e; j++) {
+ if (dist[arr[j].u] != Integer.MAX_VALUE && dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
+ dist[arr[j].v] = dist[arr[j].u] + arr[j].w; // Update
+ p[arr[j].v] = arr[j].u;
+ }
+ }
+ }
+ // Final cycle for negative checking
for (j = 0; j < e; j++) {
if (dist[arr[j].u] != Integer.MAX_VALUE && dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
- dist[arr[j].v] = dist[arr[j].u] + arr[j].w; // Update
- p[arr[j].v] = arr[j].u;
+ neg = 1;
+ System.out.println("Negative cycle");
+ break;
}
}
- }
- // Final cycle for negative checking
- for (j = 0; j < e; j++) {
- if (dist[arr[j].u] != Integer.MAX_VALUE && dist[arr[j].v] > dist[arr[j].u] + arr[j].w) {
- neg = 1;
- System.out.println("Negative cycle");
- break;
- }
- }
- if (neg == 0) { // Go ahead and show results of computation
- System.out.println("Distances are: ");
- for (i = 0; i < v; i++) {
- System.out.println(i + " " + dist[i]);
- }
- System.out.println("Path followed:");
- for (i = 0; i < v; i++) {
- System.out.print("0 ");
- printPath(p, i);
- System.out.println();
+ if (neg == 0) { // Go ahead and show results of computation
+ System.out.println("Distances are: ");
+ for (i = 0; i < v; i++) {
+ System.out.println(i + " " + dist[i]);
+ }
+ System.out.println("Path followed:");
+ for (i = 0; i < v; i++) {
+ System.out.print("0 ");
+ printPath(p, i);
+ System.out.println();
+ }
}
+ sc.close();
}
- sc.close();
}
/**
* @param source Starting vertex
- * @param end Ending vertex
- * @param Edge Array of edges
+ * @param end Ending vertex
+ * @param Edge Array of edges
*/
public void show(int source, int end,
Edge[] arr) { // be created by using addEdge() method and passed by calling getEdgeArray()
diff --git a/src/main/java/com/thealgorithms/datastructures/stacks/ReverseStack.java b/src/main/java/com/thealgorithms/datastructures/stacks/ReverseStack.java
index f269d08b5678..c9d2ea05778b 100644
--- a/src/main/java/com/thealgorithms/datastructures/stacks/ReverseStack.java
+++ b/src/main/java/com/thealgorithms/datastructures/stacks/ReverseStack.java
@@ -11,21 +11,22 @@
public class ReverseStack {
public static void main(String[] args) {
- Scanner sc = new Scanner(System.in);
- System.out.println("Enter the number of elements you wish to insert in the stack");
- int n = sc.nextInt();
- int i;
- Stack stack = new Stack();
- System.out.println("Enter the stack elements");
- for (i = 0; i < n; i++) {
- stack.push(sc.nextInt());
- }
- sc.close();
- reverseStack(stack);
- System.out.println("The reversed stack is:");
- while (!stack.isEmpty()) {
- System.out.print(stack.peek() + ",");
- stack.pop();
+ try (Scanner sc = new Scanner(System.in)) {
+ System.out.println("Enter the number of elements you wish to insert in the stack");
+ int n = sc.nextInt();
+ int i;
+ Stack stack = new Stack();
+ System.out.println("Enter the stack elements");
+ for (i = 0; i < n; i++) {
+ stack.push(sc.nextInt());
+ }
+ sc.close();
+ reverseStack(stack);
+ System.out.println("The reversed stack is:");
+ while (!stack.isEmpty()) {
+ System.out.print(stack.peek() + ",");
+ stack.pop();
+ }
}
}
@@ -48,16 +49,15 @@ private static void reverseStack(Stack stack) {
private static void insertAtBottom(Stack stack, int element) {
if (stack.isEmpty()) {
- // When stack is empty, insert the element so it will be present at the bottom of the
- // stack
+ // When stack is empty, insert the element so it will be present at
+ // the bottom of the stack
stack.push(element);
return;
}
int ele = stack.peek();
- /*Keep popping elements till stack becomes empty. Push the elements once the topmost element
- has moved to the bottom of the stack.
- */
+ // Keep popping elements till stack becomes empty. Push the elements
+ // once the topmost element has moved to the bottom of the stack.
stack.pop();
insertAtBottom(stack, element);
diff --git a/src/main/java/com/thealgorithms/maths/NonRepeatingElement.java b/src/main/java/com/thealgorithms/maths/NonRepeatingElement.java
index 86dce42f1564..01fdd5a6a5a5 100644
--- a/src/main/java/com/thealgorithms/maths/NonRepeatingElement.java
+++ b/src/main/java/com/thealgorithms/maths/NonRepeatingElement.java
@@ -10,61 +10,70 @@
public class NonRepeatingElement {
public static void main(String[] args) {
- Scanner sc = new Scanner(System.in);
- int i, res = 0;
- System.out.println("Enter the number of elements in the array");
- int n = sc.nextInt();
- if ((n & 1) == 1) {
- // Not allowing odd number of elements as we are expecting 2 non repeating numbers
- System.out.println("Array should contain even number of elements");
- return;
- }
- int[] arr = new int[n];
+ try (Scanner sc = new Scanner(System.in)) {
+ int i, res = 0;
+ System.out.println("Enter the number of elements in the array");
+ int n = sc.nextInt();
+ if ((n & 1) == 1) {
+ // Not allowing odd number of elements as we are expecting 2 non repeating
+ // numbers
+ System.out.println("Array should contain even number of elements");
+ return;
+ }
+ int[] arr = new int[n];
- System.out.println("Enter " + n + " elements in the array. NOTE: Only 2 elements should not repeat");
- for (i = 0; i < n; i++) {
- arr[i] = sc.nextInt();
- }
+ System.out.println("Enter " + n + " elements in the array. NOTE: Only 2 elements should not repeat");
+ for (i = 0; i < n; i++) {
+ arr[i] = sc.nextInt();
+ }
- try {
- sc.close();
- } catch (Exception e) {
- System.out.println("Unable to close scanner" + e);
- }
+ try {
+ sc.close();
+ } catch (Exception e) {
+ System.out.println("Unable to close scanner" + e);
+ }
- // Find XOR of the 2 non repeating elements
- for (i = 0; i < n; i++) {
- res ^= arr[i];
- }
+ // Find XOR of the 2 non repeating elements
+ for (i = 0; i < n; i++) {
+ res ^= arr[i];
+ }
- // Finding the rightmost set bit
- res = res & (-res);
- int num1 = 0, num2 = 0;
+ // Finding the rightmost set bit
+ res = res & (-res);
+ int num1 = 0, num2 = 0;
- for (i = 0; i < n; i++) {
- if ((res & arr[i]) > 0) { // Case 1 explained below
- num1 ^= arr[i];
- } else {
- num2 ^= arr[i]; // Case 2 explained below
+ for (i = 0; i < n; i++) {
+ if ((res & arr[i]) > 0) { // Case 1 explained below
+ num1 ^= arr[i];
+ } else {
+ num2 ^= arr[i]; // Case 2 explained below
+ }
}
- }
- System.out.println("The two non repeating elements are " + num1 + " and " + num2);
- sc.close();
+ System.out.println("The two non repeating elements are " + num1 + " and " + num2);
+ sc.close();
+ }
}
/*
- Explanation of the code:
- let us assume we have an array [1,2,1,2,3,4]
- Property of XOR: num ^ num = 0.
- If we XOR all the elemnets of the array we will be left with 3 ^ 4 as 1 ^ 1 and 2 ^ 2 would give
- 0. Our task is to find num1 and num2 from the result of 3 ^ 4 = 7. We need to find two's
- complement of 7 and find the rightmost set bit. i.e. (num & (-num)) Two's complement of 7 is 001
- and hence res = 1. There can be 2 options when we Bitise AND this res with all the elements in our
- array
- 1. Result will come non zero number
- 2. Result will be 0.
- In the first case we will XOR our element with the first number (which is initially 0)
- In the second case we will XOR our element with the second number(which is initially 0)
- This is how we will get non repeating elements with the help of bitwise operators.
+ * Explanation of the code:
+ * let us assume we have an array [1,2,1,2,3,4]
+ * Property of XOR: num ^ num = 0.
+ * If we XOR all the elemnets of the array we will be left with 3 ^ 4 as 1 ^ 1
+ * and 2 ^ 2 would give
+ * 0. Our task is to find num1 and num2 from the result of 3 ^ 4 = 7. We need to
+ * find two's
+ * complement of 7 and find the rightmost set bit. i.e. (num & (-num)) Two's
+ * complement of 7 is 001
+ * and hence res = 1. There can be 2 options when we Bitise AND this res with
+ * all the elements in our
+ * array
+ * 1. Result will come non zero number
+ * 2. Result will be 0.
+ * In the first case we will XOR our element with the first number (which is
+ * initially 0)
+ * In the second case we will XOR our element with the second number(which is
+ * initially 0)
+ * This is how we will get non repeating elements with the help of bitwise
+ * operators.
*/
}
diff --git a/src/main/java/com/thealgorithms/others/InsertDeleteInArray.java b/src/main/java/com/thealgorithms/others/InsertDeleteInArray.java
index c90cfea1fcb1..201c0ad2dd80 100644
--- a/src/main/java/com/thealgorithms/others/InsertDeleteInArray.java
+++ b/src/main/java/com/thealgorithms/others/InsertDeleteInArray.java
@@ -5,46 +5,47 @@
public class InsertDeleteInArray {
public static void main(String[] args) {
- Scanner s = new Scanner(System.in); // Input statement
- System.out.println("Enter the size of the array");
- int size = s.nextInt();
- int[] a = new int[size];
- int i;
+ try (Scanner s = new Scanner(System.in)) {
+ System.out.println("Enter the size of the array");
+ int size = s.nextInt();
+ int[] a = new int[size];
+ int i;
- // To enter the initial elements
- for (i = 0; i < size; i++) {
- System.out.println("Enter the element");
- a[i] = s.nextInt();
- }
+ // To enter the initial elements
+ for (i = 0; i < size; i++) {
+ System.out.println("Enter the element");
+ a[i] = s.nextInt();
+ }
- // To insert a new element(we are creating a new array)
- System.out.println("Enter the index at which the element should be inserted");
- int insert_pos = s.nextInt();
- System.out.println("Enter the element to be inserted");
- int ins = s.nextInt();
- int size2 = size + 1;
- int[] b = new int[size2];
- for (i = 0; i < size2; i++) {
- if (i <= insert_pos) {
- b[i] = a[i];
- } else {
- b[i] = a[i - 1];
+ // To insert a new element(we are creating a new array)
+ System.out.println("Enter the index at which the element should be inserted");
+ int insert_pos = s.nextInt();
+ System.out.println("Enter the element to be inserted");
+ int ins = s.nextInt();
+ int size2 = size + 1;
+ int[] b = new int[size2];
+ for (i = 0; i < size2; i++) {
+ if (i <= insert_pos) {
+ b[i] = a[i];
+ } else {
+ b[i] = a[i - 1];
+ }
+ }
+ b[insert_pos] = ins;
+ for (i = 0; i < size2; i++) {
+ System.out.println(b[i]);
}
- }
- b[insert_pos] = ins;
- for (i = 0; i < size2; i++) {
- System.out.println(b[i]);
- }
- // To delete an element given the index
- System.out.println("Enter the index at which element is to be deleted");
- int del_pos = s.nextInt();
- for (i = del_pos; i < size2 - 1; i++) {
- b[i] = b[i + 1];
- }
- for (i = 0; i < size2 - 1; i++) {
- System.out.println(b[i]);
+ // To delete an element given the index
+ System.out.println("Enter the index at which element is to be deleted");
+ int del_pos = s.nextInt();
+ for (i = del_pos; i < size2 - 1; i++) {
+ b[i] = b[i + 1];
+ }
+ for (i = 0; i < size2 - 1; i++) {
+ System.out.println(b[i]);
+ }
+ s.close();
}
- s.close();
}
}
diff --git a/src/main/java/com/thealgorithms/searches/RecursiveBinarySearch.java b/src/main/java/com/thealgorithms/searches/RecursiveBinarySearch.java
index 0a84aa1d64ce..8860f3380e31 100644
--- a/src/main/java/com/thealgorithms/searches/RecursiveBinarySearch.java
+++ b/src/main/java/com/thealgorithms/searches/RecursiveBinarySearch.java
@@ -3,6 +3,7 @@
// File Name should be RecursiveBinarySearch.java
// Explanation:- https://www.tutorialspoint.com/java-program-for-binary-search-recursive
package com.thealgorithms.searches;
+
import java.util.*;
// Create a SearchAlgorithm class with a generic type
@@ -47,28 +48,29 @@ public int binsear(T[] arr, int left, int right, T target) {
}
public static void main(String[] args) {
- Scanner sc = new Scanner(System.in);
- // User inputs
- System.out.print("Enter the number of elements in the array: ");
- int n = sc.nextInt();
+ try (Scanner sc = new Scanner(System.in)) {
+ // User inputs
+ System.out.print("Enter the number of elements in the array: ");
+ int n = sc.nextInt();
- Integer[] a = new Integer[n]; // You can change the array type as needed
+ Integer[] a = new Integer[n]; // You can change the array type as needed
- System.out.println("Enter the elements in sorted order:");
+ System.out.println("Enter the elements in sorted order:");
- for (int i = 0; i < n; i++) {
- a[i] = sc.nextInt();
- }
+ for (int i = 0; i < n; i++) {
+ a[i] = sc.nextInt();
+ }
- System.out.print("Enter the target element to search for: ");
- int t = sc.nextInt();
+ System.out.print("Enter the target element to search for: ");
+ int t = sc.nextInt();
- RecursiveBinarySearch searcher = new RecursiveBinarySearch<>();
- int res = searcher.find(a, t);
+ RecursiveBinarySearch searcher = new RecursiveBinarySearch<>();
+ int res = searcher.find(a, t);
- if (res == -1)
- System.out.println("Element not found in the array.");
- else
- System.out.println("Element found at index " + res);
+ if (res == -1)
+ System.out.println("Element not found in the array.");
+ else
+ System.out.println("Element found at index " + res);
+ }
}
}
From 192427a5d288b3b7d4eca28056ded28cac513b61 Mon Sep 17 00:00:00 2001
From: SOZEL <80200848+TruongNhanNguyen@users.noreply.github.com>
Date: Sat, 16 Mar 2024 01:03:27 +0700
Subject: [PATCH 0102/1338] Parameterize references to generic types. (#5078)
* chore: remove unused imports
* fix: parameterize references to generic types
---------
Co-authored-by: vil02 <65706193+vil02@users.noreply.github.com>
---
src/main/java/com/thealgorithms/backtracking/MColoring.java | 1 -
.../datastructures/dynamicarray/DynamicArray.java | 2 +-
.../thealgorithms/datastructures/lists/CircleLinkedList.java | 4 ++--
.../thealgorithms/datastructures/lists/CursorLinkedList.java | 2 +-
src/main/java/com/thealgorithms/misc/ThreeSumProblem.java | 4 ++--
src/main/java/com/thealgorithms/searches/UnionFind.java | 2 +-
src/main/java/com/thealgorithms/strings/WordLadder.java | 4 ++--
7 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/src/main/java/com/thealgorithms/backtracking/MColoring.java b/src/main/java/com/thealgorithms/backtracking/MColoring.java
index c9bc02008058..93b17941566a 100644
--- a/src/main/java/com/thealgorithms/backtracking/MColoring.java
+++ b/src/main/java/com/thealgorithms/backtracking/MColoring.java
@@ -1,6 +1,5 @@
package com.thealgorithms.backtracking;
-import java.io.*;
import java.util.*;
/**
diff --git a/src/main/java/com/thealgorithms/datastructures/dynamicarray/DynamicArray.java b/src/main/java/com/thealgorithms/datastructures/dynamicarray/DynamicArray.java
index fb7783575e57..f6f0276e0c35 100644
--- a/src/main/java/com/thealgorithms/datastructures/dynamicarray/DynamicArray.java
+++ b/src/main/java/com/thealgorithms/datastructures/dynamicarray/DynamicArray.java
@@ -145,7 +145,7 @@ public String toString() {
* @return Iterator a Dynamic Array Iterator
*/
@Override
- public Iterator iterator() {
+ public Iterator