diff --git a/pom.xml b/pom.xml index 0347ccdba919..86922e1f0a98 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.thealgorithms Java @@ -52,6 +52,11 @@ commons-lang3 3.12.0 + + org.apache.commons + commons-collections4 + 4.4 + diff --git a/src/main/java/com/thealgorithms/maths/Means.java b/src/main/java/com/thealgorithms/maths/Means.java new file mode 100644 index 000000000000..dccc820b172e --- /dev/null +++ b/src/main/java/com/thealgorithms/maths/Means.java @@ -0,0 +1,54 @@ +package com.thealgorithms.maths; + +import java.util.stream.StreamSupport; +import org.apache.commons.collections4.IterableUtils; + +/** + * https://en.wikipedia.org/wiki/Mean + *

+ * by: Punit Patel + */ +public final class Means { + + private Means() { + } + + /** + * @brief computes the [Arithmetic Mean](https://en.wikipedia.org/wiki/Arithmetic_mean) of the input + * @param numbers the input numbers + * @throws IllegalArgumentException empty input + * @return the arithmetic mean of the input numbers + */ + public static Double arithmetic(final Iterable numbers) { + checkIfNotEmpty(numbers); + return StreamSupport.stream(numbers.spliterator(), false).reduce((x, y) -> x + y).get() / IterableUtils.size(numbers); + } + + /** + * @brief computes the [Geometric Mean](https://en.wikipedia.org/wiki/Geometric_mean) of the input + * @param numbers the input numbers + * @throws IllegalArgumentException empty input + * @return the geometric mean of the input numbers + */ + public static Double geometric(final Iterable numbers) { + checkIfNotEmpty(numbers); + return Math.pow(StreamSupport.stream(numbers.spliterator(), false).reduce((x, y) -> x * y).get(), 1d / IterableUtils.size(numbers)); + } + + /** + * @brief computes the [Harmonic Mean](https://en.wikipedia.org/wiki/Harmonic_mean) of the input + * @param numbers the input numbers + * @throws IllegalArgumentException empty input + * @return the harmonic mean of the input numbers + */ + public static Double harmonic(final Iterable numbers) { + checkIfNotEmpty(numbers); + return IterableUtils.size(numbers) / StreamSupport.stream(numbers.spliterator(), false).reduce(0d, (x, y) -> x + 1d / y); + } + + private static void checkIfNotEmpty(final Iterable numbers) { + if (!numbers.iterator().hasNext()) { + throw new IllegalArgumentException("Emtpy list given for Mean computation."); + } + } +} diff --git a/src/test/java/com/thealgorithms/maths/MeansTest.java b/src/test/java/com/thealgorithms/maths/MeansTest.java new file mode 100644 index 000000000000..fa17cea68f7c --- /dev/null +++ b/src/test/java/com/thealgorithms/maths/MeansTest.java @@ -0,0 +1,71 @@ +package com.thealgorithms.maths; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.Vector; +import org.assertj.core.util.Lists; +import org.assertj.core.util.Sets; +import org.junit.jupiter.api.Test; + +class MeansTest { + + @Test + void arithmeticMeanZeroNumbers() throws IllegalArgumentException { + List numbers = new ArrayList<>(); + assertThrows(IllegalArgumentException.class, () -> Means.arithmetic(numbers)); + } + + @Test + void geometricMeanZeroNumbers() throws IllegalArgumentException { + List numbers = new ArrayList<>(); + assertThrows(IllegalArgumentException.class, () -> Means.geometric(numbers)); + } + + @Test + void harmonicMeanZeroNumbers() throws IllegalArgumentException { + List numbers = new ArrayList<>(); + assertThrows(IllegalArgumentException.class, () -> Means.harmonic(numbers)); + } + + @Test + void arithmeticMeanSingleNumber() { + List numbers = Lists.newArrayList(2.5); + assertEquals(2.5, Means.arithmetic(numbers)); + } + + @Test + void geometricMeanSingleNumber() { + Set numbers = Sets.newHashSet(Lists.newArrayList(2.5)); + assertEquals(2.5, Means.geometric(numbers)); + } + + @Test + void harmonicMeanSingleNumber() { + LinkedHashSet numbers = Sets.newLinkedHashSet(2.5); + assertEquals(2.5, Means.harmonic(numbers)); + } + + @Test + void arithmeticMeanMultipleNumbers() { + Set numbers = Sets.newTreeSet(1d, 2.5, 83.3, 25.9999, 46.0001, 74.7, 74.5); + assertEquals(44, Means.arithmetic(numbers)); + } + + @Test + void geometricMeanMultipleNumbers() { + LinkedList numbers = new LinkedList<>() {}; + numbers.addAll(Lists.newArrayList(1d, 2d, 3d, 4d, 5d, 6d, 1.25)); + assertEquals(2.6426195539300585, Means.geometric(numbers)); + } + + @Test + void harmonicMeanMultipleNumbers() { + Vector numbers = new Vector<>(Lists.newArrayList(1d, 2.5, 83.3, 25.9999, 46.0001, 74.7, 74.5)); + assertEquals(4.6697322801074135, Means.harmonic(numbers)); + } +}