From 2592a088e7759675224a6d6ba608aa9019b15bd4 Mon Sep 17 00:00:00 2001 From: Hardik Pawar <97388607+Hardvan@users.noreply.github.com> Date: Mon, 7 Oct 2024 17:56:21 +0530 Subject: [PATCH] Enhance readability, add comments & function docs to SkylineProblem.java (#5534) --- DIRECTORY.md | 12 +++ .../thealgorithms/others/SkylineProblem.java | 99 +++++++++++-------- .../others/SkylineProblemTest.java | 86 ++++++++++++++++ 3 files changed, 154 insertions(+), 43 deletions(-) create mode 100644 src/test/java/com/thealgorithms/others/SkylineProblemTest.java diff --git a/DIRECTORY.md b/DIRECTORY.md index 6b44fa336..0d34492fd 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -27,6 +27,7 @@ * [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) * [IsPowerTwo](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/IsPowerTwo.java) + * [LowestSetBit](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/bitmanipulation/LowestSetBit.java) * [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) @@ -280,6 +281,12 @@ * [MinimizingLateness](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/MinimizingLateness.java) * io * [BufferedReader](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/io/BufferedReader.java) + * lineclipping + * [CohenSutherland](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/lineclipping/CohenSutherland.java) + * [LiangBarsky](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/lineclipping/LiangBarsky.java) + * utils + * [Line](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/lineclipping/utils/Line.java) + * [Point](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/lineclipping/utils/Point.java) * maths * [AbsoluteMax](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/AbsoluteMax.java) * [AbsoluteMin](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/maths/AbsoluteMin.java) @@ -615,6 +622,7 @@ * [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) * [IsPowerTwoTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/IsPowerTwoTest.java) + * [LowestSetBitTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/LowestSetBitTest.java) * [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) @@ -785,6 +793,9 @@ * [MinimizingLatenessTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessTest.java) * io * [BufferedReaderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/io/BufferedReaderTest.java) + * lineclipping + * [CohenSutherlandTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/lineclipping/CohenSutherlandTest.java) + * [LiangBarskyTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/lineclipping/LiangBarskyTest.java) * maths * [AbsoluteMaxTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/AbsoluteMaxTest.java) * [AbsoluteMinTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/maths/AbsoluteMinTest.java) @@ -912,6 +923,7 @@ * [QueueUsingTwoStacksTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/QueueUsingTwoStacksTest.java) * [RemoveDuplicateFromStringTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/RemoveDuplicateFromStringTest.java) * [ReverseStackUsingRecursionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/ReverseStackUsingRecursionTest.java) + * [SkylineProblemTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/SkylineProblemTest.java) * [TestPrintMatrixInSpiralOrder](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/TestPrintMatrixInSpiralOrder.java) * [TwoPointersTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/TwoPointersTest.java) * [WorstFitCPUTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/WorstFitCPUTest.java) diff --git a/src/main/java/com/thealgorithms/others/SkylineProblem.java b/src/main/java/com/thealgorithms/others/SkylineProblem.java index ece398e70..e84a5c5b5 100644 --- a/src/main/java/com/thealgorithms/others/SkylineProblem.java +++ b/src/main/java/com/thealgorithms/others/SkylineProblem.java @@ -1,69 +1,68 @@ package com.thealgorithms.others; import java.util.ArrayList; -import java.util.Iterator; -import java.util.Scanner; +/** + * The {@code SkylineProblem} class is used to solve the skyline problem using a + * divide-and-conquer approach. + * It reads input for building data, processes it to find the skyline, and + * prints the skyline. + */ public class SkylineProblem { Building[] building; int count; - public void run() { - Scanner sc = new Scanner(System.in); - - int num = sc.nextInt(); - this.building = new Building[num]; - - for (int i = 0; i < num; i++) { - String input = sc.next(); - String[] data = input.split(","); - this.add(Integer.parseInt(data[0]), Integer.parseInt(data[1]), Integer.parseInt(data[2])); - } - this.print(this.findSkyline(0, num - 1)); - - sc.close(); - } - + /** + * Adds a building with the given left, height, and right values to the + * buildings list. + * + * @param left The left x-coordinate of the building. + * @param height The height of the building. + * @param right The right x-coordinate of the building. + */ public void add(int left, int height, int right) { building[count++] = new Building(left, height, right); } - public void print(ArrayList skyline) { - Iterator it = skyline.iterator(); - - while (it.hasNext()) { - Skyline temp = it.next(); - System.out.print(temp.coordinates + "," + temp.height); - if (it.hasNext()) { - System.out.print(","); - } - } - } - + /** + * Computes the skyline for a range of buildings using the divide-and-conquer + * strategy. + * + * @param start The starting index of the buildings to process. + * @param end The ending index of the buildings to process. + * @return A list of {@link Skyline} objects representing the computed skyline. + */ public ArrayList findSkyline(int start, int end) { + // Base case: only one building, return its skyline. if (start == end) { ArrayList list = new ArrayList<>(); list.add(new Skyline(building[start].left, building[start].height)); - list.add(new Skyline(building[end].right, 0)); - + list.add(new Skyline(building[end].right, 0)); // Add the end of the building return list; } int mid = (start + end) / 2; - ArrayList sky1 = this.findSkyline(start, mid); - ArrayList sky2 = this.findSkyline(mid + 1, end); - - return this.mergeSkyline(sky1, sky2); + ArrayList sky1 = this.findSkyline(start, mid); // Find the skyline of the left half + ArrayList sky2 = this.findSkyline(mid + 1, end); // Find the skyline of the right half + return this.mergeSkyline(sky1, sky2); // Merge the two skylines } + /** + * Merges two skylines (sky1 and sky2) into one combined skyline. + * + * @param sky1 The first skyline list. + * @param sky2 The second skyline list. + * @return A list of {@link Skyline} objects representing the merged skyline. + */ public ArrayList mergeSkyline(ArrayList sky1, ArrayList sky2) { int currentH1 = 0; int currentH2 = 0; ArrayList skyline = new ArrayList<>(); int maxH = 0; + // Merge the two skylines while (!sky1.isEmpty() && !sky2.isEmpty()) { if (sky1.get(0).coordinates < sky2.get(0).coordinates) { int currentX = sky1.get(0).coordinates; @@ -96,6 +95,7 @@ public class SkylineProblem { } } + // Add any remaining points from sky1 or sky2 while (!sky1.isEmpty()) { skyline.add(sky1.get(0)); sky1.remove(0); @@ -109,32 +109,45 @@ public class SkylineProblem { return skyline; } + /** + * A class representing a point in the skyline with its x-coordinate and height. + */ public class Skyline { - public int coordinates; public int height; + /** + * Constructor for the {@code Skyline} class. + * + * @param coordinates The x-coordinate of the skyline point. + * @param height The height of the skyline at the given coordinate. + */ public Skyline(int coordinates, int height) { this.coordinates = coordinates; this.height = height; } } + /** + * A class representing a building with its left, height, and right + * x-coordinates. + */ public class Building { - public int left; public int height; public int right; + /** + * Constructor for the {@code Building} class. + * + * @param left The left x-coordinate of the building. + * @param height The height of the building. + * @param right The right x-coordinate of the building. + */ public Building(int left, int height, int right) { this.left = left; this.height = height; this.right = right; } } - - public static void main(String[] args) { - SkylineProblem skylineProblem = new SkylineProblem(); - skylineProblem.run(); - } } diff --git a/src/test/java/com/thealgorithms/others/SkylineProblemTest.java b/src/test/java/com/thealgorithms/others/SkylineProblemTest.java new file mode 100644 index 000000000..1ed5ced70 --- /dev/null +++ b/src/test/java/com/thealgorithms/others/SkylineProblemTest.java @@ -0,0 +1,86 @@ +package com.thealgorithms.others; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.ArrayList; +import org.junit.jupiter.api.Test; + +public class SkylineProblemTest { + + @Test + public void testSingleBuildingSkyline() { + SkylineProblem skylineProblem = new SkylineProblem(); + skylineProblem.building = new SkylineProblem.Building[1]; + skylineProblem.add(2, 10, 9); + + ArrayList result = skylineProblem.findSkyline(0, 0); + + assertEquals(2, result.get(0).coordinates); + assertEquals(10, result.get(0).height); + assertEquals(9, result.get(1).coordinates); + assertEquals(0, result.get(1).height); + } + + @Test + public void testTwoBuildingsSkyline() { + SkylineProblem skylineProblem = new SkylineProblem(); + skylineProblem.building = new SkylineProblem.Building[2]; + skylineProblem.add(1, 11, 5); + skylineProblem.add(2, 6, 7); + + ArrayList result = skylineProblem.findSkyline(0, 1); + + // Expected skyline points: (1, 11), (5, 6), (7, 0) + assertEquals(1, result.get(0).coordinates); + assertEquals(11, result.get(0).height); + assertEquals(5, result.get(1).coordinates); + assertEquals(6, result.get(1).height); + assertEquals(7, result.get(2).coordinates); + assertEquals(0, result.get(2).height); + } + + @Test + public void testMergeSkyline() { + SkylineProblem skylineProblem = new SkylineProblem(); + ArrayList sky1 = new ArrayList<>(); + ArrayList sky2 = new ArrayList<>(); + + sky1.add(skylineProblem.new Skyline(2, 10)); + sky1.add(skylineProblem.new Skyline(9, 0)); + + sky2.add(skylineProblem.new Skyline(3, 15)); + sky2.add(skylineProblem.new Skyline(7, 0)); + + ArrayList result = skylineProblem.mergeSkyline(sky1, sky2); + + // Expected merged skyline: (2, 10), (3, 15), (7, 10), (9, 0) + assertEquals(2, result.get(0).coordinates); + assertEquals(10, result.get(0).height); + assertEquals(3, result.get(1).coordinates); + assertEquals(15, result.get(1).height); + assertEquals(7, result.get(2).coordinates); + assertEquals(10, result.get(2).height); + assertEquals(9, result.get(3).coordinates); + assertEquals(0, result.get(3).height); + } + + @Test + public void testMultipleBuildingsSkyline() { + SkylineProblem skylineProblem = new SkylineProblem(); + skylineProblem.building = new SkylineProblem.Building[3]; + skylineProblem.add(1, 10, 5); + skylineProblem.add(2, 15, 7); + skylineProblem.add(3, 12, 9); + + ArrayList result = skylineProblem.findSkyline(0, 2); + + assertEquals(1, result.get(0).coordinates); + assertEquals(10, result.get(0).height); + assertEquals(2, result.get(1).coordinates); + assertEquals(15, result.get(1).height); + assertEquals(7, result.get(2).coordinates); + assertEquals(12, result.get(2).height); + assertEquals(9, result.get(3).coordinates); + assertEquals(0, result.get(3).height); + } +}