diff --git a/config.json b/config.json index 024a11e696..1d22c21285 100644 --- a/config.json +++ b/config.json @@ -823,6 +823,17 @@ "control-flow (loops)" ] }, + { + "uuid": "7f4d5743-7ab8-42ca-b393-767f7e9a4e97", + "slug": "complex-numbers", + "core": false, + "unlocked_by": null, + "difficulty": 6, + "topics": [ + "tuples", + "mathematics" + ] + }, { "uuid": "e7351e8e-d3ff-4621-b818-cd55cf05bffd", "slug": "accumulate", diff --git a/exercises/complex-numbers/README.md b/exercises/complex-numbers/README.md new file mode 100644 index 0000000000..8a99bb3d02 --- /dev/null +++ b/exercises/complex-numbers/README.md @@ -0,0 +1,22 @@ +# Complex Numbers + +A complex number is a number in the form `a + b * i` where `a` and `b` are real and `i` satisfies `i^2 = -1`. + +Assume the programming language you are using does not have an implementation of complex numbers. + +### Submitting Exercises + +Note that, when trying to submit an exercise, make sure the solution is in the `exercism/python/` directory. + +For example, if you're submitting `bob.py` for the Bob exercise, the submit command would be something like `exercism submit /python/bob/bob.py`. + + +For more detailed information about running tests, code style and linting, +please see the [help page](http://exercism.io/languages/python). + +## Source + +Wikipedia [https://en.wikipedia.org/wiki/Complex_number](https://en.wikipedia.org/wiki/Complex_number) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/exercises/complex-numbers/complex_numbers.py b/exercises/complex-numbers/complex_numbers.py new file mode 100644 index 0000000000..c519389edd --- /dev/null +++ b/exercises/complex-numbers/complex_numbers.py @@ -0,0 +1,24 @@ +class ComplexNumber(object): + def __init__(self, real, imaginary): + pass + + def add(self, other): + pass + + def mul(self, other): + pass + + def sub(self, other): + pass + + def div(self, other): + pass + + def abs(self): + pass + + def conjugate(self): + pass + + def exp(self): + pass diff --git a/exercises/complex-numbers/complex_numbers_test.py b/exercises/complex-numbers/complex_numbers_test.py new file mode 100644 index 0000000000..6b0f725278 --- /dev/null +++ b/exercises/complex-numbers/complex_numbers_test.py @@ -0,0 +1,156 @@ +import unittest + +import math + +from complex_numbers import ComplexNumber + + +class ComplexNumbersTest(unittest.TestCase): + + def test_real_part_of_a_purely_real_number(self): + input_number = ComplexNumber(1, 0) + self.assertEqual(input_number.real, 1) + + def test_real_part_of_a_purely_imaginary_number(self): + input_number = ComplexNumber(0, 1) + self.assertEqual(input_number.real, 0) + + def test_real_part_of_a_number_with_real_and_imaginary_part(self): + input_number = ComplexNumber(1, 2) + self.assertEqual(input_number.real, 1) + + def test_imaginary_part_of_a_purely_real_number(self): + input_number = ComplexNumber(1, 0) + self.assertEqual(input_number.imaginary, 0) + + def test_imaginary_part_of_a_purely_imaginary_number(self): + input_number = ComplexNumber(0, 1) + self.assertEqual(input_number.imaginary, 1) + + def test_maginary_part_of_a_number_with_real_and_imaginary_part(self): + input_number = ComplexNumber(1, 2) + self.assertEqual(input_number.imaginary, 2) + + def test_add_purely_real_numbers(self): + first_input = ComplexNumber(1, 0) + second_input = ComplexNumber(3, 0) + self.assertEqual(first_input.add(second_input).real, 4) + self.assertEqual(first_input.add(second_input).imaginary, 0) + + def test_add_purely_imaginary_numbers(self): + first_input = ComplexNumber(0, 1) + second_input = ComplexNumber(0, 3) + self.assertEqual(first_input.add(second_input).real, 0) + self.assertEqual(first_input.add(second_input).imaginary, 4) + + def test_add_numbers_with_real_and_imaginary_part(self): + first_input = ComplexNumber(1, 2) + second_input = ComplexNumber(4, 6) + self.assertEqual(first_input.add(second_input).real, 5) + self.assertEqual(first_input.add(second_input).imaginary, 8) + + def test_subtract_purely_real_numbers(self): + first_input = ComplexNumber(1, 0) + second_input = ComplexNumber(-1, 0) + self.assertEqual(first_input.sub(second_input).real, 2) + self.assertEqual(first_input.sub(second_input).imaginary, 0) + + def test_substract_numbers_with_real_and_imaginary_part(self): + first_input = ComplexNumber(1, 2) + second_input = ComplexNumber(-2, -2) + self.assertEqual(first_input.sub(second_input).real, 3) + self.assertEqual(first_input.sub(second_input).imaginary, 4) + + def test_multiply_purely_real_numbers(self): + first_input = ComplexNumber(1, 0) + second_input = ComplexNumber(2, 0) + self.assertEqual(first_input.mul(second_input).real, 2) + self.assertEqual(first_input.mul(second_input).imaginary, 0) + + def test_multiply_numbers_with_real_and_imaginary_part(self): + first_input = ComplexNumber(1, 2) + second_input = ComplexNumber(-5, 10) + self.assertEqual(first_input.mul(second_input).real, -5) + self.assertEqual(first_input.mul(second_input).imaginary, 20) + + def test_divide_purely_real_numbers(self): + input_number = ComplexNumber(1.0, 0.0) + expected = ComplexNumber(0.5, 0.0) + divider = ComplexNumber(2.0, 0.0) + self.assertEqual(expected.real, input_number.div(divider).real) + self.assertEqual(expected.imaginary, + input_number.div(divider).imaginary) + + def test_divide_purely_imaginary_numbers(self): + input_number = ComplexNumber(0, 1) + expected = ComplexNumber(0.5, 0) + divider = ComplexNumber(0, 2) + self.assertEqual(expected.real, input_number.div(divider).real) + self.assertEqual(expected.imaginary, + input_number.div(divider).imaginary) + + def test_divide_numbers_with_real_and_imaginary_part(self): + input_number = ComplexNumber(1, 2) + expected = ComplexNumber(0.44, 0.08) + divider = ComplexNumber(3, 4) + self.assertEqual(expected.real, input_number.div(divider).real) + self.assertEqual(expected.imaginary, + input_number.div(divider).imaginary) + + def test_absolute_value_of_a_positive_purely_real_number(self): + self.assertEqual(ComplexNumber(5, 0).abs(), 5) + + def test_absolute_value_of_a_negative_purely_real_number(self): + self.assertEqual(ComplexNumber(-5, 0).abs(), 5) + + def test_absolute_value_of_imaginary_number_negative_imaginary_part(self): + self.assertEqual(ComplexNumber(0, -5).abs(), 5) + + def test_absolute_value_of_imaginary_number_positive_imaginary_part(self): + self.assertEqual(ComplexNumber(0, 5).abs(), 5) + + def test_absolute_value_of_a_number_with_real_and_imaginary_part(self): + self.assertEqual(ComplexNumber(3, 4).abs(), 5) + + def test_conjugate_a_purely_real_number(self): + input_number = ComplexNumber(5, 0) + expected = ComplexNumber(5, 0) + self.assertEqual(expected.real, input_number.conjugate().real) + self.assertEqual(expected.imaginary, + input_number.conjugate().imaginary) + + def test_conjugate_a_purely_imaginary_number(self): + input_number = ComplexNumber(0, 5) + expected = ComplexNumber(0, -5) + self.assertEqual(expected.real, input_number.conjugate().real) + self.assertEqual(expected.imaginary, + input_number.conjugate().imaginary) + + def conjugate_a_number_with_real_and_imaginary_part(self): + input_number = ComplexNumber(1, 1) + expected = ComplexNumber(1, -1) + self.assertEqual(expected.real, input_number.conjugate().real) + self.assertEqual(expected.imaginary, + input_number.conjugate().imaginary) + + def test_eulers_identity_formula(self): + input_number = ComplexNumber(0, math.pi) + expected = ComplexNumber(-1, 0) + self.assertEqual(expected.real, input_number.exp().real) + self.assertEqual(expected.imaginary, input_number.exp().imaginary) + + def test_exponential_of_0(self): + input_number = ComplexNumber(0, 0) + expected = ComplexNumber(1, 0) + self.assertEqual(expected.real, input_number.exp().real) + self.assertEqual(expected.imaginary, input_number.exp().imaginary) + + def test_exponential_of_a_purely_real_number(self): + input_number = ComplexNumber(1, 0) + expected = ComplexNumber(math.e, 0) + self.assertEqual(expected.real, input_number.exp().real) + self.assertEqual(expected.imaginary, input_number.exp().imaginary) + + +if __name__ == '__main__': + unittest.main() diff --git a/exercises/complex-numbers/example.py b/exercises/complex-numbers/example.py new file mode 100644 index 0000000000..2718d5d5dd --- /dev/null +++ b/exercises/complex-numbers/example.py @@ -0,0 +1,42 @@ +import math + + +class ComplexNumber(object): + def __init__(self, real, imaginary): + self.real = real + self.imaginary = imaginary + + def add(self, other): + r = self.real + other.real + i = self.imaginary + other.imaginary + return ComplexNumber(r, i) + + def mul(self, other): + r = self.real * other.real + i = self.imaginary * other.imaginary + return ComplexNumber(r, i) + + def sub(self, other): + r = self.real - other.real + i = self.imaginary - other.imaginary + return ComplexNumber(r, i) + + def div(self, other): + d = other.real * other.real + other.imaginary * other.imaginary + r = (self.real * other.real + self.imaginary * + other.imaginary) / float(d) + i = (self.imaginary * other.real - self.real * + self.real * other.imaginary) / float(d) + return ComplexNumber(r, i) + + def abs(self): + square_sum = self.real * self.real + self.imaginary * self.imaginary + return math.sqrt(square_sum) + + def conjugate(self): + return ComplexNumber(self.real, -1 * self.imaginary) + + def exp(self): + r = round(math.cos(self.imaginary), 8) * math.exp(self.real) + i = round(math.sin(self.imaginary), 8) * math.exp(self.real) + return ComplexNumber(r, i)