Просмотр исходного кода

Added some utility functions to find (prime) dividers of a number.

Taddeus Kroes 14 лет назад
Родитель
Сommit
b024e0c230
2 измененных файлов с 68 добавлено и 1 удалено
  1. 41 0
      src/rules/utils.py
  2. 27 1
      tests/test_rules_utils.py

+ 41 - 0
src/rules/utils.py

@@ -135,6 +135,47 @@ def divides(m, n):
     return not divmod(n, m)[1]
 
 
+def dividers(n):
+    """
+    Find all integers that divide n, except for 1.
+    """
+    def m_dividers(m):
+        result, rest = divmod(n, m)
+
+        if not rest:
+            return [m, result] if m != result else [m]
+
+    below_sqrt = filter(None, map(m_dividers, xrange(2, int(n ** .5) + 1)))
+    div = reduce(lambda a, b: a + b, below_sqrt, [])
+    div.sort()
+
+    return div
+
+
+def is_prime(n):
+    """
+    Check if n is a prime.
+    """
+    if n == 2:
+        return True
+
+    if n < 2 or not n & 1:
+        return False
+
+    for i in xrange(3, int(n ** .5) + 1, 2):
+        if not divmod(n, i)[1]:
+            return False
+
+    return True
+
+
+def prime_dividers(n):
+    """
+    Find all primes that divide n.
+    """
+    return filter(is_prime, dividers(n))
+
+
 def is_numeric_node(node):
     """
     Check if a node is numeric.

+ 27 - 1
tests/test_rules_utils.py

@@ -1,7 +1,7 @@
 from src.rules import utils
 from src.rules.utils import least_common_multiple, is_fraction, partition, \
         find_variables, first_sorted_variable, find_variable, substitute, \
-        divides, evals_to_numeric
+        divides, dividers, is_prime, prime_dividers, evals_to_numeric
 from tests.rulestestcase import tree, RulesTestCase
 
 
@@ -66,6 +66,32 @@ class TestRulesUtils(RulesTestCase):
         self.assertFalse(divides(4, 2))
         self.assertFalse(divides(2, 3))
 
+    def test_dividers(self):
+        self.assertEqual(dividers(1), [])
+        self.assertEqual(dividers(2), [])
+        self.assertEqual(dividers(4), [2])
+        self.assertEqual(dividers(6), [2, 3])
+        self.assertEqual(dividers(10), [2, 5])
+        self.assertEqual(dividers(21), [3, 7])
+        self.assertEqual(dividers(20), [2, 4, 5, 10])
+        self.assertEqual(dividers(1000000), [2, 4, 5, 8, 10, 16, 20, 25, 32,
+            40, 50, 64, 80, 100, 125, 160, 200, 250, 320, 400, 500, 625, 800,
+            1000, 1250, 1600, 2000, 2500, 3125, 4000, 5000, 6250, 8000, 10000,
+            12500, 15625, 20000, 25000, 31250, 40000, 50000, 62500, 100000,
+            125000, 200000, 250000, 500000])
+
+    def test_is_prime(self):
+        self.assertFalse(is_prime(1))
+        self.assertTrue(is_prime(2))
+        self.assertTrue(is_prime(3))
+        self.assertFalse(is_prime(6))
+        self.assertTrue(is_prime(19))
+        self.assertTrue(is_prime(43))
+
+    def test_prime_dividers(self):
+        self.assertEqual(prime_dividers(6), [2, 3])
+        self.assertEqual(prime_dividers(20), [2, 5])
+
     def test_evals_to_numeric(self):
         self.assertTrue(evals_to_numeric(tree('1')))
         self.assertFalse(evals_to_numeric(tree('a')))