From d9503da7fd382afc6e302c2137490a0620f0652f Mon Sep 17 00:00:00 2001 From: Parth07-alt Date: Sat, 24 Jan 2026 22:58:25 +0530 Subject: [PATCH] Add Mobius function implementation with comprehensive tests --- Algorithm_tests/math_tests/mobius_test.py | 117 ++++++++++++++++++++++ Algorithms/math/mobius/mobius.py | 95 ++++++++++++++++++ 2 files changed, 212 insertions(+) create mode 100644 Algorithm_tests/math_tests/mobius_test.py create mode 100644 Algorithms/math/mobius/mobius.py diff --git a/Algorithm_tests/math_tests/mobius_test.py b/Algorithm_tests/math_tests/mobius_test.py new file mode 100644 index 0000000..46af813 --- /dev/null +++ b/Algorithm_tests/math_tests/mobius_test.py @@ -0,0 +1,117 @@ +# Import the mobius function +import sys +import unittest + +# For importing from different folders +# OBS: This is supposed to be done with automated testing, hence relative to folder we want to import from +sys.path.append("Algorithms/math/mobius") + +# If run from local: +# sys.path.append('../../Algorithms/math/mobius') + +from mobius import mobius + + +class TestMobius(unittest.TestCase): + """Test cases for the Mobius function.""" + + def test_mobius_one(self): + """Test μ(1) = 1 (special case, zero prime factors).""" + self.assertEqual(mobius(1), 1) + + def test_mobius_prime_two(self): + """Test μ(2) = -1 (single prime factor).""" + self.assertEqual(mobius(2), -1) + + def test_mobius_prime_three(self): + """Test μ(3) = -1 (single prime factor).""" + self.assertEqual(mobius(3), -1) + + def test_mobius_prime_large(self): + """Test μ(17) = -1 (single prime factor - larger prime).""" + self.assertEqual(mobius(17), -1) + + def test_mobius_two_primes(self): + """Test μ(6) = 1 (two distinct prime factors: 2 × 3).""" + self.assertEqual(mobius(6), 1) + + def test_mobius_two_primes_alternative(self): + """Test μ(10) = 1 (two distinct prime factors: 2 × 5).""" + self.assertEqual(mobius(10), 1) + + def test_mobius_three_primes(self): + """Test μ(30) = -1 (three distinct prime factors: 2 × 3 × 5).""" + self.assertEqual(mobius(30), -1) + + def test_mobius_three_primes_alternative(self): + """Test μ(42) = -1 (three distinct prime factors: 2 × 3 × 7).""" + self.assertEqual(mobius(42), -1) + + def test_mobius_four_primes(self): + """Test μ(210) = 1 (four distinct prime factors: 2 × 3 × 5 × 7).""" + self.assertEqual(mobius(210), 1) + + def test_mobius_five_primes(self): + """Test μ(2310) = -1 (five distinct prime factors: 2 × 3 × 5 × 7 × 11).""" + self.assertEqual(mobius(2310), -1) + + def test_mobius_squared_prime_four(self): + """Test μ(4) = 0 (4 = 2², has squared factor).""" + self.assertEqual(mobius(4), 0) + + def test_mobius_squared_prime_nine(self): + """Test μ(9) = 0 (9 = 3², has squared factor).""" + self.assertEqual(mobius(9), 0) + + def test_mobius_squared_factor_twelve(self): + """Test μ(12) = 0 (12 = 2² × 3, has squared factor).""" + self.assertEqual(mobius(12), 0) + + def test_mobius_squared_factor_eighteen(self): + """Test μ(18) = 0 (18 = 2 × 3², has squared factor).""" + self.assertEqual(mobius(18), 0) + + def test_mobius_squared_factor_large(self): + """Test μ(72) = 0 (72 = 2³ × 3², has squared factors).""" + self.assertEqual(mobius(72), 0) + + def test_mobius_squared_factor_hundred(self): + """Test μ(100) = 0 (100 = 2² × 5², has squared factors).""" + self.assertEqual(mobius(100), 0) + + def test_mobius_square_free_fifteen(self): + """Test μ(15) = 1 (15 = 3 × 5, two distinct primes).""" + self.assertEqual(mobius(15), 1) + + def test_mobius_square_free_thirtyfive(self): + """Test μ(35) = 1 (35 = 5 × 7, two distinct primes).""" + self.assertEqual(mobius(35), 1) + + def test_mobius_square_free_oneohfive(self): + """Test μ(105) = -1 (105 = 3 × 5 × 7, three distinct primes).""" + self.assertEqual(mobius(105), -1) + + def test_mobius_invalid_zero(self): + """Test that μ(0) raises ValueError.""" + with self.assertRaises(ValueError): + mobius(0) + + def test_mobius_invalid_negative(self): + """Test that μ(-5) raises ValueError.""" + with self.assertRaises(ValueError): + mobius(-5) + + def test_mobius_invalid_float(self): + """Test that μ(3.5) raises ValueError.""" + with self.assertRaises(ValueError): + mobius(3.5) + + def test_mobius_invalid_string(self): + """Test that μ('10') raises ValueError.""" + with self.assertRaises(ValueError): + mobius('10') + + +if __name__ == "__main__": + print("Running Mobius function tests:") + unittest.main() diff --git a/Algorithms/math/mobius/mobius.py b/Algorithms/math/mobius/mobius.py new file mode 100644 index 0000000..1fb0608 --- /dev/null +++ b/Algorithms/math/mobius/mobius.py @@ -0,0 +1,95 @@ +""" +The Mobius function μ(n) is an important function in number theory. + +Definition: +- μ(n) = 1 if n is a square-free positive integer with an even number of prime factors. +- μ(n) = -1 if n is a square-free positive integer with an odd number of prime factors. +- μ(n) = 0 if n has a squared prime factor (i.e., n is not square-free). + +A number is square-free if it is not divisible by any perfect square other than 1. + +Examples: +- μ(1) = 1 (by definition, 1 has zero prime factors, which is even) +- μ(2) = -1 (2 has one prime factor: 2, which is odd) +- μ(6) = 1 (6 = 2 × 3, two distinct prime factors, which is even) +- μ(12) = 0 (12 = 2² × 3, has a squared factor 2²) +- μ(30) = -1 (30 = 2 × 3 × 5, three distinct prime factors, which is odd) + +Time complexity: O(sqrt(n)) +Space complexity: O(1) + +Programmed by [Your Name] +* 2026-01-24 Initial implementation +""" + + +def mobius(n): + """ + Calculate the Mobius function μ(n) for a given positive integer n. + + Args: + n (int): A positive integer + + Returns: + int: The Mobius function value (1, -1, or 0) + + Raises: + ValueError: If n is not a positive integer + + Examples: + >>> mobius(1) + 1 + >>> mobius(2) + -1 + >>> mobius(6) + 1 + >>> mobius(12) + 0 + >>> mobius(30) + -1 + """ + if not isinstance(n, int) or n < 1: + raise ValueError("n must be a positive integer") + + # Special case: μ(1) = 1 + if n == 1: + return 1 + + prime_factor_count = 0 + + # Check for factor 2 + if n % 2 == 0: + prime_factor_count += 1 + n //= 2 + # If 2 appears more than once, n is not square-free + if n % 2 == 0: + return 0 + + # Check for odd factors from 3 onwards + i = 3 + while i * i <= n: + if n % i == 0: + prime_factor_count += 1 + n //= i + # If this prime appears more than once, n is not square-free + if n % i == 0: + return 0 + i += 2 + + # If n > 1, then it's a prime factor + if n > 1: + prime_factor_count += 1 + + # Return 1 if even number of prime factors, -1 if odd + return 1 if prime_factor_count % 2 == 0 else -1 + + +if __name__ == "__main__": + # Test examples + test_cases = [1, 2, 3, 6, 12, 30, 42, 105, 210] + + print("Mobius Function Examples:") + print("-" * 40) + for num in test_cases: + result = mobius(num) + print(f"μ({num:3d}) = {result:2d}")