From 48b83fbfb8c422fa9254deb50a510518e6e0c2b1 Mon Sep 17 00:00:00 2001 From: Mithun Dutta Date: Mon, 16 Mar 2026 15:02:39 +0530 Subject: [PATCH 1/5] Add skeleton functions and test structure for complex numbers --- complex.py | 0 test_complex.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 complex.py create mode 100644 test_complex.py diff --git a/complex.py b/complex.py new file mode 100644 index 0000000..e69de29 diff --git a/test_complex.py b/test_complex.py new file mode 100644 index 0000000..e69de29 From 19b067d5053624e8d41c13d2bb7bde5c8e999586 Mon Sep 17 00:00:00 2001 From: Mithun Dutta Date: Mon, 16 Mar 2026 15:11:48 +0530 Subject: [PATCH 2/5] Add skeleton functions and test structure for complex numbers --- complex.py | 55 +++++++++++++++++++++++++++++++++++++++++++++++ test_complex.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/complex.py b/complex.py index e69de29..7f5d58f 100644 --- a/complex.py +++ b/complex.py @@ -0,0 +1,55 @@ +# complex.py + +def parse_complex_string(expression): + """ + Member 1: Parses an input string like '(3 + 2j) * (5+ 3j)'[cite: 119]. + Extracts the two complex numbers and the mathematical operator. + Must support the standard a + bj representation[cite: 121]. + """ + pass + +def add_complex(c1, c2): + """ + Member 2: Handles the addition of two complex numbers[cite: 120]. + """ + pass + +def subtract_complex(c1, c2): + """ + Member 2: Handles the subtraction of c2 from c1[cite: 120]. + """ + pass + +def multiply_complex(c1, c2): + """ + Member 3: Handles the multiplication of two complex numbers[cite: 120]. + """ + pass + +def divide_complex(c1, c2): + """ + Member 3: Handles the division of c1 by c2[cite: 120]. + Must include error handling for division by zero. + """ + pass + +def compute_magnitude(c): + """ + Member 4: Calculates the magnitude of a single complex number[cite: 122]. + """ + pass + +def compute_phase(c): + """ + Member 4: Calculates the phase (angle) of a single complex number[cite: 122]. + """ + pass + +def evaluate_complex_expression(expression): + """ + Member 5 (Integrator): The main runner function. + Takes the raw string, passes it to parse_complex_string, + routes the parsed data to the correct math function above, + and returns the final string result. + """ + pass \ No newline at end of file diff --git a/test_complex.py b/test_complex.py index e69de29..ac71034 100644 --- a/test_complex.py +++ b/test_complex.py @@ -0,0 +1,57 @@ +# test_complex.py +import unittest +from complex import ( + parse_complex_string, add_complex, subtract_complex, + multiply_complex, divide_complex, compute_magnitude, + compute_phase, evaluate_complex_expression +) + +class TestComplexArithmetic(unittest.TestCase): + + # --- Member 1 Tests --- + def test_parse_complex_string_valid(self): + # Test normal valid strings here + pass + + def test_parse_complex_string_invalid(self): + # Test malformed strings or missing brackets here + pass + + # --- Member 2 Tests --- + def test_add_complex(self): + # Test normal addition and negative addition + pass + + def test_subtract_complex(self): + # Test normal subtraction + pass + + # --- Member 3 Tests --- + def test_multiply_complex(self): + # Lab manual example test case + self.assertEqual(multiply_complex('1+2j', '3+4j'), '-5+10j') + + def test_divide_complex(self): + # Test normal division + pass + + def test_divide_complex_by_zero(self): + # Test division by zero exception handling + pass + + # --- Member 4 Tests --- + def test_compute_magnitude(self): + # Test magnitude calculations + pass + + def test_compute_phase(self): + # Test phase calculations (check against known angles) + pass + + # --- Member 5 Tests (Integration) --- + def test_evaluate_complex_expression(self): + # Test the full pipeline from raw string to final output + pass + +if __name__ == "__main__": + unittest.main() \ No newline at end of file From 3717a410b2783eae4f456f0522814b507aa94800 Mon Sep 17 00:00:00 2001 From: Billionaire25 Date: Mon, 16 Mar 2026 16:12:42 +0530 Subject: [PATCH 3/5] Added multiplication, division and test cases --- complex.py | 29 +++++++++++++++++++++++++--- test_complex.py | 50 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/complex.py b/complex.py index 7f5d58f..63c52b4 100644 --- a/complex.py +++ b/complex.py @@ -1,4 +1,5 @@ # complex.py +from calculator import Calculator def parse_complex_string(expression): """ @@ -24,14 +25,36 @@ def multiply_complex(c1, c2): """ Member 3: Handles the multiplication of two complex numbers[cite: 120]. """ - pass + + # c1 and c2 are tuples: (real, imag) + calc = Calculator() + a, b = c1 + c, d = c2 + # (a+bi)*(c+di) = (ac - bd) + (ad + bc)i + real_part = calc.subtract(calc.multiply(a, c), calc.multiply(b, d)) + imag_part = calc.add(calc.multiply(a, d), calc.multiply(b, c)) + return (real_part, imag_part) def divide_complex(c1, c2): """ Member 3: Handles the division of c1 by c2[cite: 120]. Must include error handling for division by zero. """ - pass + # c1 and c2 are tuples: (real, imag) + calc = Calculator() + a, b = c1 + c, d = c2 + # denominator = c^2 + d^2 + denominator = calc.add(calc.multiply(c, c), calc.multiply(d, d)) + if denominator == 0: + raise ValueError("Division by zero in complex division") + # real part: (ac + bd) / (c^2 + d^2) + real_num = calc.add(calc.multiply(a, c), calc.multiply(b, d)) + real_part = calc.divide(real_num, denominator) + # imag part: (bc - ad) / (c^2 + d^2) + imag_num = calc.subtract(calc.multiply(b, c), calc.multiply(a, d)) + imag_part = calc.divide(imag_num, denominator) + return (real_part, imag_part) def compute_magnitude(c): """ @@ -52,4 +75,4 @@ def evaluate_complex_expression(expression): routes the parsed data to the correct math function above, and returns the final string result. """ - pass \ No newline at end of file + \ No newline at end of file diff --git a/test_complex.py b/test_complex.py index ac71034..aea19a0 100644 --- a/test_complex.py +++ b/test_complex.py @@ -27,17 +27,57 @@ def test_subtract_complex(self): pass # --- Member 3 Tests --- + def test_multiply_complex(self): - # Lab manual example test case - self.assertEqual(multiply_complex('1+2j', '3+4j'), '-5+10j') + # Normal cases + self.assertEqual(multiply_complex((3, 2), (5, 3)), (9, 19)) # (3+2j)*(5+3j) = (3*5-2*3, 3*3+2*5) = (15-6, 9+10) = (9, 19) + self.assertEqual(multiply_complex((0, 0), (5, 3)), (0, 0)) # Zero times anything + self.assertEqual(multiply_complex((1, 0), (0, 1)), (0, 1)) # (1+0j)*(0+1j) = (0, 1) + self.assertEqual(multiply_complex((2, -3), (-1, 4)), (10, 11)) # (2-3j)*(-1+4j) = (2*-1-(-3)*4, 2*4+(-3)*-1) = (-2+12, 8+3) = (10, 11) + + # Boundary cases + self.assertEqual(multiply_complex((0, 0), (0, 0)), (0, 0)) # Both zero + self.assertEqual(multiply_complex((999999, 0), (0, 999999)), (0, 999999*999999)) + self.assertEqual(multiply_complex((-1, -1), (-1, -1)), (0, 2)) + + # Invalid input handling + with self.assertRaises(TypeError): + multiply_complex((1,), (2, 3)) # Too few elements + with self.assertRaises(TypeError): + multiply_complex((1, 2, 3), (2, 3)) # Too many elements + with self.assertRaises(TypeError): + multiply_complex((1, 'a'), (2, 3)) # Non-numeric + with self.assertRaises(TypeError): + multiply_complex('not a tuple', (2, 3)) + def test_divide_complex(self): - # Test normal division - pass + # Normal cases + self.assertEqual(divide_complex((3, 2), (5, 3)), (0.6341463414634146, 0.04878048780487805)) + self.assertEqual(divide_complex((0, 0), (5, 3)), (0.0, 0.0)) + self.assertEqual(divide_complex((1, 0), (1, 0)), (1.0, 0.0)) + self.assertEqual(divide_complex((2, -3), (-1, 4)), (-0.6470588235294118, -0.5294117647058824)) + + # Boundary cases + self.assertEqual(divide_complex((0, 0), (0, 1)), (0.0, 0.0)) + self.assertEqual(divide_complex((999999, 0), (0, 999999)), (0.0, -1.0)) + self.assertEqual(divide_complex((-1, -1), (-1, -1)), (1.0, 0.0)) + + # Invalid input handling + with self.assertRaises(TypeError): + divide_complex((1,), (2, 3)) # Too few elements + with self.assertRaises(TypeError): + divide_complex((1, 2, 3), (2, 3)) # Too many elements + with self.assertRaises(TypeError): + divide_complex((1, 'a'), (2, 3)) # Non-numeric + with self.assertRaises(TypeError): + divide_complex('not a tuple', (2, 3)) + def test_divide_complex_by_zero(self): # Test division by zero exception handling - pass + with self.assertRaises(ValueError): + divide_complex((1, 2), (0, 0)) # --- Member 4 Tests --- def test_compute_magnitude(self): From b9d2a2873981370eeffb457851ccb5b04e9a655a Mon Sep 17 00:00:00 2001 From: Mithun Dutta Date: Thu, 19 Mar 2026 00:03:41 +0530 Subject: [PATCH 4/5] Implement parsar and unit test --- complex.py | 27 ++++++++++++++++++++++++--- test_complex.py | 13 ++++++++----- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/complex.py b/complex.py index 7f5d58f..94e0d23 100644 --- a/complex.py +++ b/complex.py @@ -1,12 +1,33 @@ # complex.py +import re +import cmath + +def _format_complex(c): + """ + Helper function to format a Python complex object back into a + clean 'a+bj' string without parentheses to match lab requirements. + """ + res = str(c).replace(' ', '') + if res.startswith('(') and res.endswith(')'): + res = res[1:-1] + return res def parse_complex_string(expression): """ - Member 1: Parses an input string like '(3 + 2j) * (5+ 3j)'[cite: 119]. + Parses an input string like '(3+2j) * (5+3j)'. Extracts the two complex numbers and the mathematical operator. - Must support the standard a + bj representation[cite: 121]. """ - pass + # Regex to capture everything inside the parentheses and the operator between them + pattern = r'\s*\(([^)]+)\)\s*([+\-*/])\s*\(([^)]+)\)\s*' + match = re.match(pattern, expression) + + if not match: + raise ValueError("Invalid complex expression format. Expected: '(a+bj) op (c+dj)'") + + c1_str, operator, c2_str = match.groups() + + # Remove any internal spaces (e.g., '3 + 2j' becomes '3+2j') + return c1_str.replace(' ', ''), operator, c2_str.replace(' ', '') def add_complex(c1, c2): """ diff --git a/test_complex.py b/test_complex.py index ac71034..7be77b4 100644 --- a/test_complex.py +++ b/test_complex.py @@ -8,14 +8,17 @@ class TestComplexArithmetic(unittest.TestCase): - # --- Member 1 Tests --- + # --- Parser Tests --- def test_parse_complex_string_valid(self): - # Test normal valid strings here - pass + c1, op, c2 = parse_complex_string('(3 + 2j) * (5+ 3j)') + self.assertEqual(c1, '3+2j') + self.assertEqual(op, '*') + self.assertEqual(c2, '5+3j') def test_parse_complex_string_invalid(self): - # Test malformed strings or missing brackets here - pass + # Boundary Condition: Missing brackets should raise a ValueError + with self.assertRaises(ValueError): + parse_complex_string('3+2j * 5+3j') # --- Member 2 Tests --- def test_add_complex(self): From 80767fba8034cf287f6b6eaec7d1ee9c2135b2d4 Mon Sep 17 00:00:00 2001 From: Feluda2005 <2023csb020.sabyasachi@students.iiests.ac.in> Date: Fri, 20 Mar 2026 19:06:07 +0530 Subject: [PATCH 5/5] Added multiplication, division and test cases --- __pycache__/calculator.cpython-313.pyc | Bin 0 -> 987 bytes __pycache__/complex.cpython-313.pyc | Bin 0 -> 3180 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 __pycache__/calculator.cpython-313.pyc create mode 100644 __pycache__/complex.cpython-313.pyc diff --git a/__pycache__/calculator.cpython-313.pyc b/__pycache__/calculator.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..969ff6b70db043f3cabb71e66bbff1409318ca8e GIT binary patch literal 987 zcmah|L2DC16n?Y2X|`!%VkA;Rg;j#EP-`#sP{fPPO#(6~1p~t**@T77Zk^p#(vv4q zym-lv$S?38crJL6!JDVvB#U_U&1}}TQpg;>nK$$1y>Gv7HmlVtfaCesFaCW3@KXiF zuvUv~8y9ofhI>Gv4U`-h`H6su;hMuDU(HxUk8BsGIrKpg3c{d7nAB*4u&9Yxq88!? zEg_cahOj4P*Ory1JQ$_{Pa<)y>I}`imPXZ5#hKzehvVi0oI9`}y#*{xX~kYJmV`?( zh*g^7II??m*r(ArdCP_8bi;`sdY}nS6Tm zqq%c-=i#^J{#kW@Wsg=&tKM@rrOjB#rygUn!q_w#rGZ*k8GD`bV0BVwZ0w6T3Gms3 z5o4l;Eksj6OF`xvk8`$9#9chq<&;IgOhU*Xqe5CsK+tvm0@lFNW&i*H literal 0 HcmV?d00001 diff --git a/__pycache__/complex.cpython-313.pyc b/__pycache__/complex.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6195042aea1ed1d351465dec6e57197d737518f6 GIT binary patch literal 3180 zcmcIm&2JM&6yJ3md;OJ|5WYz@RJ7O-tk_8^)g>i?1V|~gsuL6mqG-GxCmZZtcXk&- zBqVdHP!DYmh(tYvTay#eOLFAUa}{YXXw?H!)kCEo5a}P#_tv``Fu0ThBkh}+oi}fO z^FHRi?L;CfKs#-3D0)N?{=kXX0`6dY7zX!*f>01I3SWp^Btju@P~d?=8_>2w5NNQ_ z4z#@x0valWfrbkbP^l0B8kvozV}GHzv}i}q(u!t;3%3P}wIr|2L9FKkl zT+-X_BkTee{CE<{YtRt4b*J08@jw-PwPyM#!3b|#sfxo09JOS&x1DS#ln6fQWTP)fl3`%x{Gg_H}Krrlx zQl+!b5MMKJI=3}^FX>73&HDi`?T1e<1E~xD#D)0Y?@!f7pT-h*M(ZPP_bl0cKe3cp zF0EEqs%seIG^nC)idr z!rg`C;A&ze@qk+UPpnNmoL-;a%vvXht4CINI*WJ_#FP5qp=m6j) zl;~jl3iFNGs84*S$?fD<(J@VUsZkwEO9e_h4JNNwRJ|n1HPCFM7;-pDq(lvh8?Zi-HO`rA zz_G@he;%Pl?FNIrSX^>um|SfLC_@lcyaE=ALdck2*~CLldOE~zK+saKs#oOg6q39b zn9t(|d=>6A3Y5#~s2#;5*{HD_ZveifPPxUMY6kNj$MAC;#8JK@%c