Repository: jaidevd/numerizer

Issue:
Problems unifying numbers
Found some cases in which the library fails to unify numbers.
Some cases identified:
* thirty two and forty one
    - Expected: 32 and 41
    - Gets: 32 and 40 1
* thirty two and forty one thousand
    - Expected: 32 and 41000
    - Gets: 32 and 40 1000

Reason found:
there's a method called `andition` that I could understand have the goal of unifying numbers when separated by whitespace and magnitude of them are such that should be following the way of reading (from left to right).

A fix was implemented in #21 . The tests are running without any failure.  
New tests where added to control the issue. 

Discussion:

Patch:
diff --git a/numerizer/numerizer.py b/numerizer/numerizer.py
index 4b18cab..a9f3464 100644
--- a/numerizer/numerizer.py
+++ b/numerizer/numerizer.py
@@ -239,15 +239,25 @@ def postprocess(s, ignore=None):
 def andition(s):
     pat = re.compile(r'<num>(\d+)( | and )<num>(\d+)(?=[^\w]|$)', flags=re.IGNORECASE)
     while True:
-        m = re.search(pat, s)
-        if m is not None:
-            if (m.group(2) == 'and') or (len(m.group(1)) > len(m.group(3))):
-                s = re.sub(pat, lambda m: '<num>' + str(int(m.group(1)) + int(m.group(3))),
-                           s, count=1)
-            else:
-                break
+        matches = list(re.finditer(pat, s))
+
+        # If there are no matches found, break out of the loop
+        if len(matches) == 0:
+            break
 
-        else:
+        substitutions = 0
+        # Iterate through matches in reverse order
+        for match in reversed(matches):
+            # Check if the numbers should be unified
+            if (match.group(2) == 'and') or (len(match.group(1)) > len(match.group(3))):
+                # Replace the matched part with the unified number
+                s = s[:match.start()] + '<num>'\
+                    + str(int(match.group(1)) +
+                          int(match.group(3))) + s[match.end():]
+                substitutions += 1
+
+        # If there were no substitutions, break out of the loop
+        if not substitutions:
             break
     return s
 


Test patch:
diff --git a/test_numerize.py b/test_numerize.py
index 1480c05..9636adc 100644
--- a/test_numerize.py
+++ b/test_numerize.py
@@ -242,6 +242,20 @@ def test_misc():
     actual = numerize("two hundred twenty five thousand seven hundred and fifty-five")
     assert ideal == actual
 
+def test_andition():
+    tests = {
+        "thirty two and forty one": "32 and 41",
+        "thirty two and forty one thousand": "32 and 41000",
+        "one hundred and twenty three": "123",
+        "two thousand and thirty four": "2034",
+        "forty five and sixty seven": "45 and 67",
+        "one hundred and twenty three thousand and forty five": "123045",
+        "twenty five and seventy four and one": "25 and 74 and 1",
+        "twenty five and seventy four and one thousand": "25 and 74 and 1000",
+    }
+
+    for test in tests.items():
+        assert test[1] == numerize(test[0])
 
 # Test the spacy extensions
 condt = """Please install spacy models as follows: