Skip to content

Commit 166b95a

Browse files
authored
Merge branch 'master' into affine_converter_improve
2 parents efefd65 + 7cf568c commit 166b95a

File tree

8 files changed

+211
-24
lines changed

8 files changed

+211
-24
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.thealgorithms.geometry;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collection;
5+
import java.util.List;
6+
7+
/**
8+
* Class to represent the Midpoint Circle Algorithm.
9+
* This algorithm calculates points on the circumference of a circle
10+
* using integer arithmetic for efficient computation.
11+
*/
12+
public final class MidpointCircle {
13+
14+
private MidpointCircle() {
15+
// Private Constructor to prevent instantiation.
16+
}
17+
18+
/**
19+
* Generates points on the circumference of a circle using the midpoint circle algorithm.
20+
*
21+
* @param centerX The x-coordinate of the circle's center.
22+
* @param centerY The y-coordinate of the circle's center.
23+
* @param radius The radius of the circle.
24+
* @return A list of points on the circle, each represented as an int[] with 2 elements [x, y].
25+
*/
26+
public static List<int[]> generateCirclePoints(int centerX, int centerY, int radius) {
27+
List<int[]> points = new ArrayList<>();
28+
29+
// Special case for radius 0, only the center point should be added.
30+
if (radius == 0) {
31+
points.add(new int[] {centerX, centerY});
32+
return points;
33+
}
34+
35+
// Start at (radius, 0)
36+
int x = radius;
37+
int y = 0;
38+
39+
// Decision parameter
40+
int p = 1 - radius;
41+
42+
// Add the initial points in all octants
43+
addSymmetricPoints(points, centerX, centerY, x, y);
44+
45+
// Iterate while x > y
46+
while (x > y) {
47+
y++;
48+
49+
if (p <= 0) {
50+
// Midpoint is inside or on the circle
51+
p = p + 2 * y + 1;
52+
} else {
53+
// Midpoint is outside the circle
54+
x--;
55+
p = p + 2 * y - 2 * x + 1;
56+
}
57+
58+
// Add points for this (x, y)
59+
addSymmetricPoints(points, centerX, centerY, x, y);
60+
}
61+
62+
return points;
63+
}
64+
65+
/**
66+
* Adds the symmetric points in all octants of the circle based on the current x and y values.
67+
*
68+
* @param points The list to which symmetric points will be added.
69+
* @param centerX The x-coordinate of the circle's center.
70+
* @param centerY The y-coordinate of the circle's center.
71+
* @param x The current x-coordinate on the circumference.
72+
* @param y The current y-coordinate on the circumference.
73+
*/
74+
private static void addSymmetricPoints(Collection<int[]> points, int centerX, int centerY, int x, int y) {
75+
// Octant symmetry points
76+
points.add(new int[] {centerX + x, centerY + y});
77+
points.add(new int[] {centerX - x, centerY + y});
78+
points.add(new int[] {centerX + x, centerY - y});
79+
points.add(new int[] {centerX - x, centerY - y});
80+
points.add(new int[] {centerX + y, centerY + x});
81+
points.add(new int[] {centerX - y, centerY + x});
82+
points.add(new int[] {centerX + y, centerY - x});
83+
points.add(new int[] {centerX - y, centerY - x});
84+
}
85+
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.thealgorithms.maths;
22

3+
import java.util.Collections;
4+
import java.util.PriorityQueue;
35
import java.util.Random;
46

57
/**
@@ -62,4 +64,19 @@ private static void swap(int[] array, int i, int j) {
6264
array[i] = array[j];
6365
array[j] = temp;
6466
}
67+
68+
public static int findKthMaxUsingHeap(int[] array, int k) {
69+
if (k <= 0 || k > array.length) {
70+
throw new IllegalArgumentException("k must be between 1 and the size of the array");
71+
}
72+
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder()); // using max-heap to store numbers.
73+
for (int num : array) {
74+
maxHeap.add(num);
75+
}
76+
while (k > 1) {
77+
maxHeap.poll(); // removing max number from heap
78+
k--;
79+
}
80+
return maxHeap.peek();
81+
}
6582
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,16 @@ public static boolean isPerfectSquare(final int number) {
1818
final int sqrt = (int) Math.sqrt(number);
1919
return sqrt * sqrt == number;
2020
}
21+
22+
/**
23+
* Check if a number is perfect square or not
24+
*
25+
* @param number number to be checked
26+
* @return {@code true} if {@code number} is perfect square, otherwise
27+
* {@code false}
28+
*/
29+
public static boolean isPerfectSquareUsingPow(long number) {
30+
long a = (long) Math.pow(number, 1.0 / 2);
31+
return a * a == number;
32+
}
2133
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ private PronicNumber() {
2121
* @return true if input number is a pronic number, false otherwise
2222
*/
2323
static boolean isPronic(int inputNumber) {
24+
if (inputNumber == 0) {
25+
return true;
26+
}
2427
// Iterating from 0 to input_number
2528
for (int i = 0; i <= inputNumber; i++) {
2629
// Checking if product of i and (i+1) is equals input_number
@@ -34,4 +37,15 @@ static boolean isPronic(int inputNumber) {
3437
// equals input_number
3538
return false;
3639
}
40+
41+
/**
42+
* This method checks if the given number is pronic number or non-pronic number using square root of number for finding divisors
43+
*
44+
* @param number Integer value which is to be checked if is a pronic number or not
45+
* @return true if input number is a pronic number, false otherwise
46+
*/
47+
public static boolean isPronicNumber(int number) {
48+
int squareRoot = (int) Math.sqrt(number); // finding just smaller divisor of the number than its square root.
49+
return squareRoot * (squareRoot + 1) == number;
50+
}
3751
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.thealgorithms.geometry;
2+
3+
import static org.junit.jupiter.api.Assertions.assertTrue;
4+
5+
import java.util.List;
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.params.ParameterizedTest;
8+
import org.junit.jupiter.params.provider.CsvSource;
9+
10+
/**
11+
* Test class for the {@code MidpointCircle} class
12+
*/
13+
class MidpointCircleTest {
14+
15+
/**
16+
* Parameterized test to check the generated points for different circles.
17+
* The points are checked based on the expected center and radius.
18+
*
19+
* @param centerX The x-coordinate of the circle's center.
20+
* @param centerY The y-coordinate of the circle's center.
21+
* @param radius The radius of the circle.
22+
*/
23+
@ParameterizedTest
24+
@CsvSource({
25+
"0, 0, 3", // Circle centered at (0, 0) with radius 3
26+
"10, 10, 2" // Circle centered at (10, 10) with radius 2
27+
})
28+
void
29+
testGenerateCirclePoints(int centerX, int centerY, int radius) {
30+
List<int[]> points = MidpointCircle.generateCirclePoints(centerX, centerY, radius);
31+
32+
// Ensure that all points satisfy the circle equation (x - centerX)^2 + (y - centerY)^2 = radius^2
33+
for (int[] point : points) {
34+
int x = point[0];
35+
int y = point[1];
36+
37+
int dx = x - centerX;
38+
int dy = y - centerY;
39+
int distanceSquared = dx * dx + dy * dy;
40+
41+
assertTrue(Math.abs(distanceSquared - radius * radius) <= 1, "Point (" + x + ", " + y + ") does not satisfy the circle equation.");
42+
}
43+
}
44+
45+
/**
46+
* Test to ensure the algorithm generates points for a zero-radius circle.
47+
*/
48+
@Test
49+
void testZeroRadiusCircle() {
50+
List<int[]> points = MidpointCircle.generateCirclePoints(0, 0, 0);
51+
52+
// A zero-radius circle should only have one point: (0, 0)
53+
assertTrue(points.size() == 1 && points.get(0)[0] == 0 && points.get(0)[1] == 0, "Zero-radius circle did not generate the correct point.");
54+
}
55+
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,37 +14,50 @@ public void testFindKthMaxTypicalCases() {
1414
assertEquals(3, FindKthNumber.findKthMax(array1, 3));
1515
assertEquals(4, FindKthNumber.findKthMax(array1, 2));
1616
assertEquals(5, FindKthNumber.findKthMax(array1, 1));
17+
assertEquals(3, FindKthNumber.findKthMaxUsingHeap(array1, 3));
18+
assertEquals(4, FindKthNumber.findKthMaxUsingHeap(array1, 2));
19+
assertEquals(5, FindKthNumber.findKthMaxUsingHeap(array1, 1));
1720

1821
int[] array2 = {7, 5, 8, 2, 1, 6};
1922
assertEquals(5, FindKthNumber.findKthMax(array2, 4));
2023
assertEquals(6, FindKthNumber.findKthMax(array2, 3));
2124
assertEquals(8, FindKthNumber.findKthMax(array2, 1));
25+
assertEquals(5, FindKthNumber.findKthMaxUsingHeap(array2, 4));
26+
assertEquals(6, FindKthNumber.findKthMaxUsingHeap(array2, 3));
27+
assertEquals(8, FindKthNumber.findKthMaxUsingHeap(array2, 1));
2228
}
2329

2430
@Test
2531
public void testFindKthMaxEdgeCases() {
2632
int[] array1 = {1};
2733
assertEquals(1, FindKthNumber.findKthMax(array1, 1));
34+
assertEquals(1, FindKthNumber.findKthMaxUsingHeap(array1, 1));
2835

2936
int[] array2 = {5, 3};
3037
assertEquals(5, FindKthNumber.findKthMax(array2, 1));
3138
assertEquals(3, FindKthNumber.findKthMax(array2, 2));
39+
assertEquals(5, FindKthNumber.findKthMaxUsingHeap(array2, 1));
40+
assertEquals(3, FindKthNumber.findKthMaxUsingHeap(array2, 2));
3241
}
3342

3443
@Test
3544
public void testFindKthMaxInvalidK() {
3645
int[] array = {1, 2, 3, 4, 5};
3746
assertThrows(IllegalArgumentException.class, () -> FindKthNumber.findKthMax(array, 0));
3847
assertThrows(IllegalArgumentException.class, () -> FindKthNumber.findKthMax(array, 6));
48+
assertThrows(IllegalArgumentException.class, () -> FindKthNumber.findKthMaxUsingHeap(array, 0));
49+
assertThrows(IllegalArgumentException.class, () -> FindKthNumber.findKthMaxUsingHeap(array, 6));
3950
}
4051

4152
@Test
4253
public void testFindKthMaxLargeArray() {
4354
int[] array = generateArray(1000);
4455
int k = new Random().nextInt(1, array.length);
4556
int result = FindKthNumber.findKthMax(array, k);
57+
int maxK = FindKthNumber.findKthMaxUsingHeap(array, k);
4658
Arrays.sort(array);
4759
assertEquals(array[array.length - k], result);
60+
assertEquals(array[array.length - k], maxK);
4861
}
4962

5063
public static int[] generateArray(int capacity) {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ public class PerfectSquareTest {
99
@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})
1010
void positiveTest(final int number) {
1111
Assertions.assertTrue(PerfectSquare.isPerfectSquare(number));
12+
Assertions.assertTrue(PerfectSquare.isPerfectSquareUsingPow(number));
1213
}
1314

1415
@ParameterizedTest
1516
@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})
1617
void negativeTest(final int number) {
1718
Assertions.assertFalse(PerfectSquare.isPerfectSquare(number));
19+
Assertions.assertFalse(PerfectSquare.isPerfectSquareUsingPow(number));
1820
}
1921
}
Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,22 @@
11
package com.thealgorithms.maths;
22

3-
import static org.junit.jupiter.api.Assertions.assertFalse;
4-
import static org.junit.jupiter.api.Assertions.assertTrue;
5-
6-
import org.junit.jupiter.api.Test;
3+
import org.junit.jupiter.api.Assertions;
4+
import org.junit.jupiter.params.ParameterizedTest;
5+
import org.junit.jupiter.params.provider.ValueSource;
76

87
public class PronicNumberTest {
98

10-
@Test
11-
void testForPronicNumber() {
12-
// given
13-
int number = 30;
14-
15-
// when
16-
boolean result = PronicNumber.isPronic(number);
17-
18-
// then
19-
assertTrue(result);
9+
@ParameterizedTest
10+
@ValueSource(ints = {0, 2, 6, 12, 20, 30, 42, 110, 272, 380, 420, 1260, 2550})
11+
void testForPronicNumber(final int number) {
12+
Assertions.assertTrue(PronicNumber.isPronic(number));
13+
Assertions.assertTrue(PronicNumber.isPronicNumber(number));
2014
}
2115

22-
@Test
23-
void testForNonPronicNumber() {
24-
// given
25-
int number = 21;
26-
27-
// when
28-
boolean result = PronicNumber.isPronic(number);
29-
30-
// then
31-
assertFalse(result);
16+
@ParameterizedTest
17+
@ValueSource(ints = {1, 4, 21, 36, 150, 2500})
18+
void testForNonPronicNumber(final int number) {
19+
Assertions.assertFalse(PronicNumber.isPronic(number));
20+
Assertions.assertFalse(PronicNumber.isPronicNumber(number));
3221
}
3322
}

0 commit comments

Comments
 (0)