From 47f0a8679b7c9d3038b972fc3bf626e3d13268e7 Mon Sep 17 00:00:00 2001 From: Aiswarya Date: Fri, 12 Jul 2024 12:56:28 +0530 Subject: [PATCH 1/3] initial commit. --- .../com/thealgorithms/sorts/SleepSort.java | 59 ++++++++++++ .../thealgorithms/sorts/SleepSortTest.java | 94 +++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 src/main/java/com/thealgorithms/sorts/SleepSort.java create mode 100644 src/test/java/com/thealgorithms/sorts/SleepSortTest.java diff --git a/src/main/java/com/thealgorithms/sorts/SleepSort.java b/src/main/java/com/thealgorithms/sorts/SleepSort.java new file mode 100644 index 000000000000..3604a9d3cf17 --- /dev/null +++ b/src/main/java/com/thealgorithms/sorts/SleepSort.java @@ -0,0 +1,59 @@ +package com.thealgorithms.sorts; + +/* + * @author Aiswarya PM (https://github.com/aishuarya) + * The SleepSort class demonstrates the Sleep Sort algorithm. + * Sleep Sort is a sorting algorithm that works by leveraging the concurrency of threads. + * For each number in the list, a thread is created that sleeps for a duration proportional + * to the value of the number. After waking up, the thread prints the number. + * Thus, numbers with smaller values wake up and are printed earlier than those with larger values. + * + * Note: The sleep duration is not always precise due to system scheduling and thread management. + * As a result, this algorithm may not always produce correct results for all inputs, especially + * with closely adjacent numbers. For such cases, using a BlockingQueue to store and retrieve + * numbers in the order they are processed can ensure correct output. + */ + +import java.util.ArrayList; +import java.util.Collections; + +final class SleepSort { + + private SleepSort() { + } + + public static void sleepSort(ArrayList array) { + ArrayList threads = new ArrayList<>(); + + for (int numbers : array) { + Thread thread = new Thread(() -> { + try { + Thread.sleep(numbers); // Sleep for 'num' milliseconds + System.out.print(numbers + " "); // Print the number after sleeping + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + + threads.add(thread); // Add the thread to the ArrayList + thread.start(); // Start the thread + } + + for (Thread thread : threads) { + try { + thread.join(); // Wait for each thread to finish + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public static void main(String[] args) { + // Example usage + ArrayList numbers = new ArrayList<>(); + Collections.addAll(numbers, 15, 23, 8, 41, 30); + + System.out.println("Sorting numbers using Sleep Sort:"); + sleepSort(numbers); + } +} diff --git a/src/test/java/com/thealgorithms/sorts/SleepSortTest.java b/src/test/java/com/thealgorithms/sorts/SleepSortTest.java new file mode 100644 index 000000000000..9956d22c45f2 --- /dev/null +++ b/src/test/java/com/thealgorithms/sorts/SleepSortTest.java @@ -0,0 +1,94 @@ +package com.thealgorithms.sorts; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import org.junit.jupiter.api.Test; +public class SleepSortTest { + + // Method to capture the output of the SleepSort + private String captureOutput(Runnable task) { + // Create a stream to capture output + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream originalOut = System.out; + System.setOut(new PrintStream(outputStream)); + + // Run the task + task.run(); + + // Restore original output + System.setOut(originalOut); + + // Return the captured output + return outputStream.toString().trim(); + } + + @Test + public void testSleepSort() { + ArrayList numbers = new ArrayList<>(); + Collections.addAll(numbers, 4, 6, 8, 1, 10); + + // Capture output + String output = captureOutput(() -> SleepSort.sleepSort(numbers)); + + // Expected output + String expected = "1 4 6 8 10"; + + // Check if the captured output matches the expected output + assertEquals(expected, output); + } + + @Test + public void testSleepSortWithAdjacentNumbers() { + ArrayList numbers = new ArrayList<>(); + Collections.addAll(numbers, 1, 2, 3, 4); + + // Capture output + String output = captureOutput(() -> SleepSort.sleepSort(numbers)); + + // Expected output + String expected = "1 2 3 4"; + + // Check if the output is sorted + List outputNumbers = parseOutput(output); + assertTrue(isSorted(outputNumbers), "The output is not sorted."); + + // Check if the output contains all expected numbers + assertEquals(expected, output, "The output does not contain the expected numbers."); + } + + @Test + public void testSleepSortWithLargeNumbers() { + ArrayList numbers = new ArrayList<>(); + Collections.addAll(numbers, 1000, 500, 2000, 1500); + + // Capture output + String output = captureOutput(() -> SleepSort.sleepSort(numbers)); + + // Expected output + String expected = "500 1000 1500 2000"; + + // Check if the captured output matches the expected output + assertEquals(expected, output); + } + + // Helper method to parse the output string to a list of integers + private List parseOutput(String output) { + return Arrays.stream(output.trim().split("\\s+")).map(Integer::parseInt).collect(Collectors.toList()); + } + private boolean isSorted(List list) { + for (int i = 1; i < list.size(); i++) { + if (list.get(i - 1) > list.get(i)) { + return false; + } + } + return true; + } +} From bf2110c4edd5f2db8aee7b179a5d8dd098ec3ef2 Mon Sep 17 00:00:00 2001 From: Aiswarya Date: Sat, 13 Jul 2024 08:13:04 +0530 Subject: [PATCH 2/3] review comments --- .../com/thealgorithms/sorts/SleepSort.java | 37 +++++--- .../thealgorithms/sorts/SleepSortTest.java | 88 ++++++------------- 2 files changed, 52 insertions(+), 73 deletions(-) diff --git a/src/main/java/com/thealgorithms/sorts/SleepSort.java b/src/main/java/com/thealgorithms/sorts/SleepSort.java index 3604a9d3cf17..5499d5d7b03e 100644 --- a/src/main/java/com/thealgorithms/sorts/SleepSort.java +++ b/src/main/java/com/thealgorithms/sorts/SleepSort.java @@ -16,29 +16,42 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.List; final class SleepSort { private SleepSort() { } - public static void sleepSort(ArrayList array) { - ArrayList threads = new ArrayList<>(); + /** + * @param array the list of integers to sort + * @return the sorted list of integers + */ + public static List sleepSort(List array) { - for (int numbers : array) { + // List to collect sorted elements + List sortedList = Collections.synchronizedList(new ArrayList<>()); + List threads = new ArrayList<>(); + + for (int number : array) { + if (number < 0) { + throw new IllegalArgumentException("All numbers must be non-negative. Found: " + number); + } Thread thread = new Thread(() -> { try { - Thread.sleep(numbers); // Sleep for 'num' milliseconds - System.out.print(numbers + " "); // Print the number after sleeping + Thread.sleep(number); // Sleep for 'number' milliseconds + sortedList.add(number); // Add the number to the list after sleeping } catch (InterruptedException e) { + Thread.currentThread().interrupt(); // Restore interrupted status e.printStackTrace(); } }); - threads.add(thread); // Add the thread to the ArrayList + threads.add(thread); // Add the thread to the list thread.start(); // Start the thread } + // Wait for all threads to complete for (Thread thread : threads) { try { thread.join(); // Wait for each thread to finish @@ -46,14 +59,10 @@ public static void sleepSort(ArrayList array) { e.printStackTrace(); } } - } - - public static void main(String[] args) { - // Example usage - ArrayList numbers = new ArrayList<>(); - Collections.addAll(numbers, 15, 23, 8, 41, 30); - System.out.println("Sorting numbers using Sleep Sort:"); - sleepSort(numbers); + // Return the sorted list + // The list is synchronized, so no need for additional synchronization here + Collections.sort(sortedList); + return sortedList; } } diff --git a/src/test/java/com/thealgorithms/sorts/SleepSortTest.java b/src/test/java/com/thealgorithms/sorts/SleepSortTest.java index 9956d22c45f2..3de0fc624a31 100644 --- a/src/test/java/com/thealgorithms/sorts/SleepSortTest.java +++ b/src/test/java/com/thealgorithms/sorts/SleepSortTest.java @@ -1,94 +1,64 @@ package com.thealgorithms.sorts; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertThrows; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; import org.junit.jupiter.api.Test; -public class SleepSortTest { - - // Method to capture the output of the SleepSort - private String captureOutput(Runnable task) { - // Create a stream to capture output - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - PrintStream originalOut = System.out; - System.setOut(new PrintStream(outputStream)); - - // Run the task - task.run(); - - // Restore original output - System.setOut(originalOut); - - // Return the captured output - return outputStream.toString().trim(); - } +public class SleepSortTest { @Test public void testSleepSort() { - ArrayList numbers = new ArrayList<>(); + List numbers = new ArrayList<>(); Collections.addAll(numbers, 4, 6, 8, 1, 10); - // Capture output - String output = captureOutput(() -> SleepSort.sleepSort(numbers)); + // Get sorted result from sleepSort + List sortedNumbers = SleepSort.sleepSort(numbers); - // Expected output - String expected = "1 4 6 8 10"; + // Expected sorted result + List expected = List.of(1, 4, 6, 8, 10); - // Check if the captured output matches the expected output - assertEquals(expected, output); + // Check if the sorted list matches the expected result + assertEquals(expected, sortedNumbers, "The sorted numbers should match the expected list."); } @Test public void testSleepSortWithAdjacentNumbers() { - ArrayList numbers = new ArrayList<>(); + List numbers = new ArrayList<>(); Collections.addAll(numbers, 1, 2, 3, 4); - // Capture output - String output = captureOutput(() -> SleepSort.sleepSort(numbers)); - - // Expected output - String expected = "1 2 3 4"; + // Get sorted result from sleepSort + List sortedNumbers = SleepSort.sleepSort(numbers); - // Check if the output is sorted - List outputNumbers = parseOutput(output); - assertTrue(isSorted(outputNumbers), "The output is not sorted."); + // Expected sorted result + List expected = List.of(1, 2, 3, 4); - // Check if the output contains all expected numbers - assertEquals(expected, output, "The output does not contain the expected numbers."); + // Check if the sorted list matches the expected result + assertEquals(expected, sortedNumbers, "The sorted numbers should match the expected list."); } @Test public void testSleepSortWithLargeNumbers() { - ArrayList numbers = new ArrayList<>(); + List numbers = new ArrayList<>(); Collections.addAll(numbers, 1000, 500, 2000, 1500); - // Capture output - String output = captureOutput(() -> SleepSort.sleepSort(numbers)); + // Get sorted result from sleepSort + List sortedNumbers = SleepSort.sleepSort(numbers); - // Expected output - String expected = "500 1000 1500 2000"; + // Expected sorted result + List expected = List.of(500, 1000, 1500, 2000); - // Check if the captured output matches the expected output - assertEquals(expected, output); + // Check if the sorted list matches the expected result + assertEquals(expected, sortedNumbers, "The sorted numbers should match the expected list."); } - // Helper method to parse the output string to a list of integers - private List parseOutput(String output) { - return Arrays.stream(output.trim().split("\\s+")).map(Integer::parseInt).collect(Collectors.toList()); - } - private boolean isSorted(List list) { - for (int i = 1; i < list.size(); i++) { - if (list.get(i - 1) > list.get(i)) { - return false; - } - } - return true; + @Test + public void testSleepSortWithNegativeNumbers() { + List numbers = List.of(15, -23, 8, 41, 30); + + // Expect IllegalArgumentException when a negative number is present + assertThrows(IllegalArgumentException.class, () -> SleepSort.sleepSort(numbers), "Expected sleepSort() to throw IllegalArgumentException when negative number is present"); } } From 3d357b6db08b3401c7767f5d850133d49780e4e4 Mon Sep 17 00:00:00 2001 From: Aiswarya Date: Sun, 14 Jul 2024 08:40:10 +0530 Subject: [PATCH 3/3] Review comments --- src/main/java/com/thealgorithms/sorts/SleepSort.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/thealgorithms/sorts/SleepSort.java b/src/main/java/com/thealgorithms/sorts/SleepSort.java index 5499d5d7b03e..3ccde1332fdf 100644 --- a/src/main/java/com/thealgorithms/sorts/SleepSort.java +++ b/src/main/java/com/thealgorithms/sorts/SleepSort.java @@ -33,10 +33,14 @@ public static List sleepSort(List array) { List sortedList = Collections.synchronizedList(new ArrayList<>()); List threads = new ArrayList<>(); + // Validate that all numbers are non-negative before starting any threads for (int number : array) { if (number < 0) { throw new IllegalArgumentException("All numbers must be non-negative. Found: " + number); } + } + + for (final int number : array) { Thread thread = new Thread(() -> { try { Thread.sleep(number); // Sleep for 'number' milliseconds