package com.thealgorithms.maths; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.Vector; import org.junit.jupiter.api.Test; /** * Test class for {@link Means}. *

* This class provides comprehensive test coverage for all mean calculation * methods, * including edge cases, various collection types, and error conditions. *

*/ class MeansTest { private static final double EPSILON = 1e-9; // ========== Arithmetic Mean Tests ========== @Test void testArithmeticMeanThrowsExceptionForEmptyList() { List numbers = new ArrayList<>(); IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> Means.arithmetic(numbers)); assertTrue(exception.getMessage().contains("Empty list")); } @Test void testArithmeticMeanSingleNumber() { List numbers = Arrays.asList(2.5); assertEquals(2.5, Means.arithmetic(numbers), EPSILON); } @Test void testArithmeticMeanTwoNumbers() { List numbers = Arrays.asList(2.0, 4.0); assertEquals(3.0, Means.arithmetic(numbers), EPSILON); } @Test void testArithmeticMeanMultipleNumbers() { List numbers = Arrays.asList(1.0, 2.0, 3.0, 4.0, 5.0); assertEquals(3.0, Means.arithmetic(numbers), EPSILON); } @Test void testArithmeticMeanWithTreeSet() { Set numbers = new TreeSet<>(Arrays.asList(1.0, 2.5, 83.3, 25.9999, 46.0001, 74.7, 74.5)); assertEquals(44.0, Means.arithmetic(numbers), EPSILON); } @Test void testArithmeticMeanWithNegativeNumbers() { List numbers = Arrays.asList(-5.0, -3.0, -1.0, 1.0, 3.0, 5.0); assertEquals(0.0, Means.arithmetic(numbers), EPSILON); } @Test void testArithmeticMeanWithDecimalNumbers() { List numbers = Arrays.asList(1.1, 2.2, 3.3, 4.4, 5.5); assertEquals(3.3, Means.arithmetic(numbers), EPSILON); } @Test void testArithmeticMeanWithVector() { Vector numbers = new Vector<>(Arrays.asList(10.0, 20.0, 30.0)); assertEquals(20.0, Means.arithmetic(numbers), EPSILON); } // ========== Geometric Mean Tests ========== @Test void testGeometricMeanThrowsExceptionForEmptyList() { List numbers = new ArrayList<>(); IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> Means.geometric(numbers)); assertTrue(exception.getMessage().contains("Empty list")); } @Test void testGeometricMeanSingleNumber() { Set numbers = new LinkedHashSet<>(Arrays.asList(2.5)); assertEquals(2.5, Means.geometric(numbers), EPSILON); } @Test void testGeometricMeanTwoNumbers() { List numbers = Arrays.asList(2.0, 8.0); assertEquals(4.0, Means.geometric(numbers), EPSILON); } @Test void testGeometricMeanMultipleNumbers() { LinkedList numbers = new LinkedList<>(Arrays.asList(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 1.25)); assertEquals(2.6426195539300585, Means.geometric(numbers), EPSILON); } @Test void testGeometricMeanPerfectSquares() { List numbers = Arrays.asList(1.0, 4.0, 9.0, 16.0); double expected = Math.pow(1.0 * 4.0 * 9.0 * 16.0, 1.0 / 4.0); assertEquals(expected, Means.geometric(numbers), EPSILON); } @Test void testGeometricMeanIdenticalNumbers() { List numbers = Arrays.asList(5.0, 5.0, 5.0, 5.0); assertEquals(5.0, Means.geometric(numbers), EPSILON); } @Test void testGeometricMeanWithLinkedHashSet() { LinkedHashSet numbers = new LinkedHashSet<>(Arrays.asList(2.0, 4.0, 8.0)); double expected = Math.pow(2.0 * 4.0 * 8.0, 1.0 / 3.0); assertEquals(expected, Means.geometric(numbers), EPSILON); } // ========== Harmonic Mean Tests ========== @Test void testHarmonicMeanThrowsExceptionForEmptyList() { List numbers = new ArrayList<>(); IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> Means.harmonic(numbers)); assertTrue(exception.getMessage().contains("Empty list")); } @Test void testHarmonicMeanSingleNumber() { LinkedHashSet numbers = new LinkedHashSet<>(Arrays.asList(2.5)); assertEquals(2.5, Means.harmonic(numbers), EPSILON); } @Test void testHarmonicMeanTwoNumbers() { List numbers = Arrays.asList(2.0, 4.0); double expected = 2.0 / (1.0 / 2.0 + 1.0 / 4.0); assertEquals(expected, Means.harmonic(numbers), EPSILON); } @Test void testHarmonicMeanMultipleNumbers() { Vector numbers = new Vector<>(Arrays.asList(1.0, 2.5, 83.3, 25.9999, 46.0001, 74.7, 74.5)); assertEquals(4.6697322801074135, Means.harmonic(numbers), EPSILON); } @Test void testHarmonicMeanThreeNumbers() { List numbers = Arrays.asList(1.0, 2.0, 4.0); double expected = 3.0 / (1.0 / 1.0 + 1.0 / 2.0 + 1.0 / 4.0); assertEquals(expected, Means.harmonic(numbers), EPSILON); } @Test void testHarmonicMeanIdenticalNumbers() { List numbers = Arrays.asList(6.0, 6.0, 6.0); assertEquals(6.0, Means.harmonic(numbers), EPSILON); } @Test void testHarmonicMeanWithLinkedList() { LinkedList numbers = new LinkedList<>(Arrays.asList(3.0, 6.0, 9.0)); double expected = 3.0 / (1.0 / 3.0 + 1.0 / 6.0 + 1.0 / 9.0); assertEquals(expected, Means.harmonic(numbers), EPSILON); } // ========== Additional Edge Case Tests ========== @Test void testArithmeticMeanWithVeryLargeNumbers() { List numbers = Arrays.asList(1e100, 2e100, 3e100); assertEquals(2e100, Means.arithmetic(numbers), 1e90); } @Test void testArithmeticMeanWithVerySmallNumbers() { List numbers = Arrays.asList(1e-100, 2e-100, 3e-100); assertEquals(2e-100, Means.arithmetic(numbers), 1e-110); } @Test void testGeometricMeanWithOnes() { List numbers = Arrays.asList(1.0, 1.0, 1.0, 1.0); assertEquals(1.0, Means.geometric(numbers), EPSILON); } @Test void testAllMeansConsistencyForIdenticalValues() { List numbers = Arrays.asList(7.5, 7.5, 7.5, 7.5); double arithmetic = Means.arithmetic(numbers); double geometric = Means.geometric(numbers); double harmonic = Means.harmonic(numbers); assertEquals(7.5, arithmetic, EPSILON); assertEquals(7.5, geometric, EPSILON); assertEquals(7.5, harmonic, EPSILON); } @Test void testMeansRelationship() { // For positive numbers, harmonic mean ≤ geometric mean ≤ arithmetic mean List numbers = Arrays.asList(2.0, 4.0, 8.0); double arithmetic = Means.arithmetic(numbers); double geometric = Means.geometric(numbers); double harmonic = Means.harmonic(numbers); assertTrue(harmonic <= geometric, "Harmonic mean should be ≤ geometric mean"); assertTrue(geometric <= arithmetic, "Geometric mean should be ≤ arithmetic mean"); } }