diff --git a/src/main/java/com/thealgorithms/maths/EvilNumber.java b/src/main/java/com/thealgorithms/maths/EvilNumber.java new file mode 100644 index 000000000000..419133702fd4 --- /dev/null +++ b/src/main/java/com/thealgorithms/maths/EvilNumber.java @@ -0,0 +1,39 @@ +package com.thealgorithms.maths; + +/** + * In number theory, an evil number is a non-negative integer that has an even number of 1s in its binary expansion. + * Non-negative integers that are not evil are called odious numbers. + * + * Evil Number Wiki: https://en.wikipedia.org/wiki/Evil_number + * Odious Number Wiki: https://en.wikipedia.org/wiki/Odious_number + */ +public final class EvilNumber { + + private EvilNumber() { + } + + // Function to count number of one bits in a number using bitwise operators + private static int countOneBits(int number) { + int oneBitCounter = 0; + while (number > 0) { + oneBitCounter += number & 1; // increment count if last bit is 1 + number >>= 1; // right shift to next bit + } + return oneBitCounter; + } + + /** + * Check either {@code number} is an Evil number or Odious number + * + * @param number the number + * @return {@code true} if {@code number} is an Evil number, otherwise false (in case of of Odious number) + */ + public static boolean isEvilNumber(int number) { + if (number < 0) { + throw new IllegalArgumentException("Negative numbers are not allowed."); + } + + int noOfOneBits = countOneBits(number); + return noOfOneBits % 2 == 0; + } +} diff --git a/src/test/java/com/thealgorithms/maths/EvilNumberTest.java b/src/test/java/com/thealgorithms/maths/EvilNumberTest.java new file mode 100644 index 000000000000..e59171fad25f --- /dev/null +++ b/src/test/java/com/thealgorithms/maths/EvilNumberTest.java @@ -0,0 +1,28 @@ +package com.thealgorithms.maths; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class EvilNumberTest { + @ParameterizedTest + @CsvSource({"0", "3", "10", "129", "222", "500", "777", "1198"}) + void evilNumbersTest(int n) { + assertTrue(EvilNumber.isEvilNumber(n)); + } + + @ParameterizedTest + @CsvSource({"1", "7", "100", "333", "555", "1199"}) + void odiousNumbersTest(int n) { + assertFalse(EvilNumber.isEvilNumber(n)); + } + + @ParameterizedTest + @CsvSource({"-1"}) + void throwsNegativeNumbersNotAllowed(int n) { + assertThrows(IllegalArgumentException.class, () -> EvilNumber.isEvilNumber(n)); + } +}