Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement exercise complex-numbers #523

Merged
merged 7 commits into from
Sep 8, 2017
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,17 @@
"control-flow (loops)"
]
},
{
"uuid": "7f4d5743-7ab8-42ca-b393-767f7e9a4e97",
"slug": "complex-numbers",
"core": false,
"unlocked_by": null,
"difficulty": 6,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same for difficulty.
What affected the score to be 6?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, same hear. Took it from C# track. As I understood, difficulty grade is kinda... subjective.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Maybe we can come with some sort of formula to compute it, what do you think?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this question maybe hurried somewhere in general discussions repo. Btw, will difficulty be used at all in version 2, or there would be relying on "unlocked_by" prerequisites?

In general, it could be done, of course, simplest heuristic would be to split topics that we have in to tiers, from simplest to hardest and add the difficulty level for each additional topic for exercise. So if basically tier_level1+....tier_level2

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lilislilit, hm, this a really good point, thanks! I haven't thought about it this way
I've created the following issue exercism/discussions#193 in general discussion, feel free to add your thoughts there

"topics": [
"tuples",
"mathematics"
]
},
{
"uuid": "e7351e8e-d3ff-4621-b818-cd55cf05bffd",
"slug": "accumulate",
Expand Down
22 changes: 22 additions & 0 deletions exercises/complex-numbers/README.md
Original file line number Diff line number Diff line change
@@ -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/<exerciseName>` directory.

For example, if you're submitting `bob.py` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/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.
24 changes: 24 additions & 0 deletions exercises/complex-numbers/complex_numbers.py
Original file line number Diff line number Diff line change
@@ -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
156 changes: 156 additions & 0 deletions exercises/complex-numbers/complex_numbers_test.py
Original file line number Diff line number Diff line change
@@ -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()
42 changes: 42 additions & 0 deletions exercises/complex-numbers/example.py
Original file line number Diff line number Diff line change
@@ -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)