Skip to content

Commit 90cf74a

Browse files
authored
Merge branch 'master' into kruskal-mst
2 parents aa5a1e5 + 48e02b3 commit 90cf74a

File tree

6 files changed

+231
-21
lines changed

6 files changed

+231
-21
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.thealgorithms.maths;
2+
3+
/**
4+
* In mathematics, the extended Euclidean algorithm is an extension to the
5+
* Euclidean algorithm, and computes, in addition to the greatest common divisor
6+
* (gcd) of integers a and b, also the coefficients of Bézout's identity, which
7+
* are integers x and y such that ax + by = gcd(a, b).
8+
*
9+
* <p>
10+
* For more details, see
11+
* https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
12+
*/
13+
public final class ExtendedEuclideanAlgorithm {
14+
15+
private ExtendedEuclideanAlgorithm() {
16+
}
17+
18+
/**
19+
* This method implements the extended Euclidean algorithm.
20+
*
21+
* @param a The first number.
22+
* @param b The second number.
23+
* @return An array of three integers:
24+
* <ul>
25+
* <li>Index 0: The greatest common divisor (gcd) of a and b.</li>
26+
* <li>Index 1: The value of x in the equation ax + by = gcd(a, b).</li>
27+
* <li>Index 2: The value of y in the equation ax + by = gcd(a, b).</li>
28+
* </ul>
29+
*/
30+
public static long[] extendedGCD(long a, long b) {
31+
if (b == 0) {
32+
// Base case: gcd(a, 0) = a. The equation is a*1 + 0*0 = a.
33+
return new long[] {a, 1, 0};
34+
}
35+
36+
// Recursive call
37+
long[] result = extendedGCD(b, a % b);
38+
long gcd = result[0];
39+
long x1 = result[1];
40+
long y1 = result[2];
41+
42+
// Update coefficients using the results from the recursive call
43+
long x = y1;
44+
long y = x1 - a / b * y1;
45+
46+
return new long[] {gcd, x, y};
47+
}
48+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.thealgorithms.physics;
2+
3+
/**
4+
* Implements the Thin Lens Formula used in ray optics:
5+
*
6+
* <pre>
7+
* 1/f = 1/v + 1/u
8+
* </pre>
9+
*
10+
* where:
11+
* <ul>
12+
* <li>f = focal length</li>
13+
* <li>u = object distance</li>
14+
* <li>v = image distance</li>
15+
* </ul>
16+
*
17+
* Uses the Cartesian sign convention.
18+
*
19+
* @see <a href="https://en.wikipedia.org/wiki/Thin_lens">Thin Lens</a>
20+
*/
21+
public final class ThinLens {
22+
23+
private ThinLens() {
24+
throw new AssertionError("No instances.");
25+
}
26+
27+
/**
28+
* Computes the image distance using the thin lens formula.
29+
*
30+
* @param focalLength focal length of the lens (f)
31+
* @param objectDistance object distance (u)
32+
* @return image distance (v)
33+
* @throws IllegalArgumentException if focal length or object distance is zero
34+
*/
35+
public static double imageDistance(double focalLength, double objectDistance) {
36+
37+
if (focalLength == 0 || objectDistance == 0) {
38+
throw new IllegalArgumentException("Focal length and object distance must be non-zero.");
39+
}
40+
41+
return 1.0 / ((1.0 / focalLength) - (1.0 / objectDistance));
42+
}
43+
44+
/**
45+
* Computes magnification of the image.
46+
*
47+
* <pre>
48+
* m = v / u
49+
* </pre>
50+
*
51+
* @param imageDistance image distance (v)
52+
* @param objectDistance object distance (u)
53+
* @return magnification
54+
* @throws IllegalArgumentException if object distance is zero
55+
*/
56+
public static double magnification(double imageDistance, double objectDistance) {
57+
58+
if (objectDistance == 0) {
59+
throw new IllegalArgumentException("Object distance must be non-zero.");
60+
}
61+
62+
return imageDistance / objectDistance;
63+
}
64+
65+
/**
66+
* Determines whether the image formed is real or virtual.
67+
*
68+
* @param imageDistance image distance (v)
69+
* @return {@code true} if image is real, {@code false} if virtual
70+
*/
71+
public static boolean isRealImage(double imageDistance) {
72+
return imageDistance > 0;
73+
}
74+
}

src/main/java/com/thealgorithms/recursion/FibonacciSeries.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ private FibonacciSeries() {
1212
throw new UnsupportedOperationException("Utility class");
1313
}
1414
public static int fibonacci(int n) {
15+
if (n < 0) {
16+
throw new IllegalArgumentException("n must be a non-negative integer");
17+
}
1518
if (n <= 1) {
1619
return n;
17-
} else {
18-
return fibonacci(n - 1) + fibonacci(n - 2);
1920
}
21+
return fibonacci(n - 1) + fibonacci(n - 2);
2022
}
2123
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.thealgorithms.maths;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import org.junit.jupiter.api.Test;
6+
7+
public class ExtendedEuclideanAlgorithmTest {
8+
9+
/**
10+
* Verifies that the returned values satisfy Bézout's identity: a*x + b*y =
11+
* gcd(a, b)
12+
*/
13+
private void verifyBezoutIdentity(long a, long b, long[] result) {
14+
long gcd = result[0];
15+
long x = result[1];
16+
long y = result[2];
17+
assertEquals(a * x + b * y, gcd, "Bézout's identity failed for gcd(" + a + ", " + b + ")");
18+
}
19+
20+
@Test
21+
public void testExtendedGCD() {
22+
// Test case 1: General case gcd(30, 50) = 10
23+
long[] result1 = ExtendedEuclideanAlgorithm.extendedGCD(30, 50);
24+
assertEquals(10, result1[0], "Test Case 1 Failed: gcd(30, 50) should be 10");
25+
verifyBezoutIdentity(30, 50, result1);
26+
27+
// Test case 2: Another general case gcd(240, 46) = 2
28+
long[] result2 = ExtendedEuclideanAlgorithm.extendedGCD(240, 46);
29+
assertEquals(2, result2[0], "Test Case 2 Failed: gcd(240, 46) should be 2");
30+
verifyBezoutIdentity(240, 46, result2);
31+
32+
// Test case 3: Base case where b is 0, gcd(10, 0) = 10
33+
long[] result3 = ExtendedEuclideanAlgorithm.extendedGCD(10, 0);
34+
assertEquals(10, result3[0], "Test Case 3 Failed: gcd(10, 0) should be 10");
35+
verifyBezoutIdentity(10, 0, result3);
36+
37+
// Test case 4: Numbers are co-prime gcd(17, 13) = 1
38+
long[] result4 = ExtendedEuclideanAlgorithm.extendedGCD(17, 13);
39+
assertEquals(1, result4[0], "Test Case 4 Failed: gcd(17, 13) should be 1");
40+
verifyBezoutIdentity(17, 13, result4);
41+
42+
// Test case 5: One number is a multiple of the other gcd(100, 20) = 20
43+
long[] result5 = ExtendedEuclideanAlgorithm.extendedGCD(100, 20);
44+
assertEquals(20, result5[0], "Test Case 5 Failed: gcd(100, 20) should be 20");
45+
verifyBezoutIdentity(100, 20, result5);
46+
}
47+
}

src/test/java/com/thealgorithms/maths/GCDTest.java

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,57 +6,77 @@
66
public class GCDTest {
77

88
@Test
9-
void test1() {
9+
void testNegativeAndZeroThrowsException() {
1010
Assertions.assertThrows(ArithmeticException.class, () -> GCD.gcd(-1, 0));
1111
}
1212

1313
@Test
14-
void test2() {
14+
void testPositiveAndNegativeThrowsException() {
1515
Assertions.assertThrows(ArithmeticException.class, () -> GCD.gcd(10, -2));
1616
}
1717

1818
@Test
19-
void test3() {
19+
void testBothNegativeThrowsException() {
2020
Assertions.assertThrows(ArithmeticException.class, () -> GCD.gcd(-5, -3));
2121
}
2222

2323
@Test
24-
void test4() {
25-
Assertions.assertEquals(GCD.gcd(0, 2), 2);
24+
void testZeroAndPositiveReturnsPositive() {
25+
Assertions.assertEquals(2, GCD.gcd(0, 2));
2626
}
2727

2828
@Test
29-
void test5() {
30-
Assertions.assertEquals(GCD.gcd(10, 0), 10);
29+
void testPositiveAndZeroReturnsPositive() {
30+
Assertions.assertEquals(10, GCD.gcd(10, 0));
3131
}
3232

3333
@Test
34-
void test6() {
35-
Assertions.assertEquals(GCD.gcd(1, 0), 1);
34+
void testOneAndZeroReturnsOne() {
35+
Assertions.assertEquals(1, GCD.gcd(1, 0));
3636
}
3737

3838
@Test
39-
void test7() {
40-
Assertions.assertEquals(GCD.gcd(9, 6), 3);
39+
void testTwoPositiveNumbers() {
40+
Assertions.assertEquals(3, GCD.gcd(9, 6));
4141
}
4242

4343
@Test
44-
void test8() {
45-
Assertions.assertEquals(GCD.gcd(48, 18, 30, 12), 6);
44+
void testMultipleArgumentsGcd() {
45+
Assertions.assertEquals(6, GCD.gcd(48, 18, 30, 12));
4646
}
4747

4848
@Test
49-
void testArrayGcd1() {
50-
Assertions.assertEquals(GCD.gcd(new int[] {9, 6}), 3);
49+
void testArrayInputGcd() {
50+
Assertions.assertEquals(3, GCD.gcd(new int[] {9, 6}));
5151
}
5252

5353
@Test
54-
void testArrayGcd2() {
55-
Assertions.assertEquals(GCD.gcd(new int[] {2 * 3 * 5 * 7, 2 * 5 * 5 * 5, 2 * 5 * 11, 5 * 5 * 5 * 13}), 5);
54+
void testArrayWithCommonFactor() {
55+
Assertions.assertEquals(5, GCD.gcd(new int[] {2 * 3 * 5 * 7, 2 * 5 * 5 * 5, 2 * 5 * 11, 5 * 5 * 5 * 13}));
5656
}
5757

5858
@Test
59-
void testArrayGcdForEmptyInput() {
60-
Assertions.assertEquals(GCD.gcd(new int[] {}), 0);
59+
void testEmptyArrayReturnsZero() {
60+
Assertions.assertEquals(0, GCD.gcd(new int[] {}));
61+
}
62+
63+
@Test
64+
void testSameNumbers() {
65+
Assertions.assertEquals(7, GCD.gcd(7, 7));
66+
}
67+
68+
@Test
69+
void testPrimeNumbersHaveGcdOne() {
70+
Assertions.assertEquals(1, GCD.gcd(13, 17));
71+
}
72+
73+
@Test
74+
void testSingleElementArrayReturnsElement() {
75+
Assertions.assertEquals(42, GCD.gcd(new int[] {42}));
76+
}
77+
78+
@Test
79+
void testLargeNumbers() {
80+
Assertions.assertEquals(12, GCD.gcd(123456, 789012));
6181
}
6282
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.thealgorithms.physics;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import org.junit.jupiter.api.Test;
6+
7+
class ThinLensTest {
8+
9+
@Test
10+
void testConvexLensRealImage() {
11+
double v = ThinLens.imageDistance(10, 20);
12+
assertEquals(20, v, 1e-6);
13+
}
14+
15+
@Test
16+
void testMagnification() {
17+
assertEquals(2.0, ThinLens.magnification(20, 10), 1e-6);
18+
}
19+
}

0 commit comments

Comments
 (0)