package com.thealgorithms.searches; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Random; import java.util.stream.Collectors; import org.junit.jupiter.api.Test; class QuickSelectTest { @Test void quickSelectMinimumOfOneElement() { List elements = Collections.singletonList(42); int minimum = QuickSelect.select(elements, 0); assertEquals(42, minimum); } @Test void quickSelectMinimumOfTwoElements() { List elements1 = Arrays.asList(42, 90); List elements2 = Arrays.asList(90, 42); int minimum1 = QuickSelect.select(elements1, 0); int minimum2 = QuickSelect.select(elements2, 0); assertEquals(42, minimum1); assertEquals(42, minimum2); } @Test void quickSelectMinimumOfThreeElements() { List elements1 = Arrays.asList(1, 2, 3); List elements2 = Arrays.asList(2, 1, 3); List elements3 = Arrays.asList(2, 3, 1); int minimum1 = QuickSelect.select(elements1, 0); int minimum2 = QuickSelect.select(elements2, 0); int minimum3 = QuickSelect.select(elements3, 0); assertEquals(1, minimum1); assertEquals(1, minimum2); assertEquals(1, minimum3); } @Test void quickSelectMinimumOfManyElements() { List elements = generateRandomIntegers(NUM_RND_ELEMENTS); int actual = QuickSelect.select(elements, 0); int expected = elements.stream().min(Comparator.naturalOrder()).get(); assertEquals(expected, actual); } @Test void quickSelectMaximumOfOneElement() { List elements = Collections.singletonList(42); int maximum = QuickSelect.select(elements, 0); assertEquals(42, maximum); } @Test void quickSelectMaximumOfTwoElements() { List elements1 = Arrays.asList(42, 90); List elements2 = Arrays.asList(90, 42); int maximum1 = QuickSelect.select(elements1, 1); int maximum2 = QuickSelect.select(elements2, 1); assertEquals(90, maximum1); assertEquals(90, maximum2); } @Test void quickSelectMaximumOfThreeElements() { List elements1 = Arrays.asList(1, 2, 3); List elements2 = Arrays.asList(2, 1, 3); List elements3 = Arrays.asList(2, 3, 1); int maximum1 = QuickSelect.select(elements1, 2); int maximum2 = QuickSelect.select(elements2, 2); int maximum3 = QuickSelect.select(elements3, 2); assertEquals(3, maximum1); assertEquals(3, maximum2); assertEquals(3, maximum3); } @Test void quickSelectMaximumOfManyElements() { List elements = generateRandomIntegers(NUM_RND_ELEMENTS); int actual = QuickSelect.select(elements, NUM_RND_ELEMENTS - 1); int expected = elements.stream().max(Comparator.naturalOrder()).get(); assertEquals(expected, actual); } @Test void quickSelectMedianOfOneElement() { List elements = Collections.singletonList(42); int median = QuickSelect.select(elements, 0); assertEquals(42, median); } @Test void quickSelectMedianOfThreeElements() { List elements1 = Arrays.asList(1, 2, 3); List elements2 = Arrays.asList(2, 1, 3); List elements3 = Arrays.asList(2, 3, 1); int median1 = QuickSelect.select(elements1, 1); int median2 = QuickSelect.select(elements2, 1); int median3 = QuickSelect.select(elements3, 1); assertEquals(2, median1); assertEquals(2, median2); assertEquals(2, median3); } @Test void quickSelectMedianOfManyElements() { int medianIndex = NUM_RND_ELEMENTS / 2; List elements = generateRandomIntegers(NUM_RND_ELEMENTS); int actual = QuickSelect.select(elements, medianIndex); List elementsSorted = getSortedCopyOfList(elements); assertEquals(elementsSorted.get(medianIndex), actual); } @Test void quickSelect30thPercentileOf10Elements() { List elements = generateRandomIntegers(10); int actual = QuickSelect.select(elements, 2); List elementsSorted = getSortedCopyOfList(elements); assertEquals(elementsSorted.get(2), actual); } @Test void quickSelect30thPercentileOfManyElements() { int percentile30th = NUM_RND_ELEMENTS / 10 * 3; List elements = generateRandomIntegers(NUM_RND_ELEMENTS); int actual = QuickSelect.select(elements, percentile30th); List elementsSorted = getSortedCopyOfList(elements); assertEquals(elementsSorted.get(percentile30th), actual); } @Test void quickSelect70thPercentileOf10Elements() { List elements = generateRandomIntegers(10); int actual = QuickSelect.select(elements, 6); List elementsSorted = getSortedCopyOfList(elements); assertEquals(elementsSorted.get(6), actual); } @Test void quickSelect70thPercentileOfManyElements() { int percentile70th = NUM_RND_ELEMENTS / 10 * 7; List elements = generateRandomIntegers(NUM_RND_ELEMENTS); int actual = QuickSelect.select(elements, percentile70th); List elementsSorted = getSortedCopyOfList(elements); assertEquals(elementsSorted.get(percentile70th), actual); } @Test void quickSelectMedianOfThreeCharacters() { List elements = Arrays.asList('X', 'Z', 'Y'); char actual = QuickSelect.select(elements, 1); assertEquals(actual, 'Y'); } @Test void quickSelectMedianOfManyCharacters() { List elements = generateRandomCharacters(NUM_RND_ELEMENTS); char actual = QuickSelect.select(elements, NUM_RND_ELEMENTS / 30); List elementsSorted = getSortedCopyOfList(elements); assertEquals(elementsSorted.get(NUM_RND_ELEMENTS / 30), actual); } @Test void quickSelectNullList() { NullPointerException exception = assertThrows(NullPointerException.class, () -> QuickSelect.select(null, 0)); String expectedMsg = "The list of elements must not be null."; assertEquals(expectedMsg, exception.getMessage()); } @Test void quickSelectEmptyList() { List objects = Collections.emptyList(); IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> QuickSelect.select(objects, 0)); String expectedMsg = "The list of elements must not be empty."; assertEquals(expectedMsg, exception.getMessage()); } @Test void quickSelectIndexOutOfLeftBound() { IndexOutOfBoundsException exception = assertThrows(IndexOutOfBoundsException.class, () -> QuickSelect.select(Collections.singletonList(1), -1)); String expectedMsg = "The index must not be negative."; assertEquals(expectedMsg, exception.getMessage()); } @Test void quickSelectIndexOutOfRightBound() { IndexOutOfBoundsException exception = assertThrows(IndexOutOfBoundsException.class, () -> QuickSelect.select(Collections.singletonList(1), 1)); String expectedMsg = "The index must be less than the number of elements."; assertEquals(expectedMsg, exception.getMessage()); } private static final int NUM_RND_ELEMENTS = 99; private static final Random RANDOM = new Random(42); private static final int ASCII_A = 0x41; private static final int ASCII_Z = 0x5A; private static List generateRandomIntegers(int n) { return RANDOM.ints(n).boxed().collect(Collectors.toList()); } private static List generateRandomCharacters(int n) { return RANDOM.ints(n, ASCII_A, ASCII_Z).mapToObj(i -> (char) i).collect(Collectors.toList()); } private static > List getSortedCopyOfList(Collection list) { return list.stream().sorted().collect(Collectors.toList()); } }