Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 10 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,16 @@
"Regular expressions"
]
},
{
"uuid": "a0eecb1c-0dd1-4180-1d19-c6ab92bc23ca163ee56",
"slug": "complex-numbers",
"core": false,
"unlocked_by": "space-age",
"difficulty": 4,
"topics": [
"Mathematics"
]
},
{
"uuid": "213ea396-0c25-e480-4e76-5876975bdd54ac4890c",
"slug": "isbn-verifier",
Expand Down
68 changes: 68 additions & 0 deletions exercises/complex-numbers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# 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`.

`a` is called the real part and `b` is called the imaginary part of `z`.
The conjugate of the number `a + b * i` is the number `a - b * i`.
The absolute value of a complex number `z = a + b * i` is a real number `|z| = sqrt(a^2 + b^2)`. The square of the absolute value `|z|^2` is the result of multiplication of `z` by its complex conjugate.

The sum/difference of two complex numbers involves adding/subtracting their real and imaginary parts separately:
`(a + i * b) + (c + i * d) = (a + c) + (b + d) * i`,
`(a + i * b) - (c + i * d) = (a - c) + (b - d) * i`.

Multiplication result is by definition
`(a + i * b) * (c + i * d) = (a * c - b * d) + (b * c + a * d) * i`.

The reciprocal of a non-zero complex number is
`1 / (a + i * b) = a/(a^2 + b^2) - b/(a^2 + b^2) * i`.

Dividing a complex number `a + i * b` by another `c + i * d` gives:
`(a + i * b) / (c + i * d) = (a * c + b * d)/(c^2 + d^2) + (b * c - a * d)/(c^2 + d^2) * i`.

Exponent of a complex number can be expressed as
`exp(a + i * b) = exp(a) * exp(i * b)`,
and the last term is given by Euler's formula `exp(i * b) = cos(b) + i * sin(b)`.


Implement the following operations:
- addition, subtraction, multiplication and division of two complex numbers,
- conjugate, absolute value, exponent of a given complex number.


Assume the programming language you are using does not have an implementation of complex numbers.

## Setup

Go through the setup instructions for ECMAScript to
install the necessary dependencies:

http://exercism.io/languages/ecmascript/installation

## Requirements

Install assignment dependencies:

```bash
$ npm install
```

## Making the test suite pass

Execute the tests with:

```bash
$ npm test
```

In the test suites all tests but the first have been skipped.

Once you get a test passing, you can enable the next one by
changing `xtest` to `test`.


## 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.
216 changes: 216 additions & 0 deletions exercises/complex-numbers/complex-numbers.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
import ComplexNumber from './complex-numbers.js';

describe('Complex numbers', () => {
test('Real part of a purely real number', () => {
const expected = 1;
const actual = new ComplexNumber(1, 0).real;

expect(actual).toEqual(expected);
});

xtest('Real part of a purely imaginary number', () => {
const expected = 0;
const actual = new ComplexNumber(0, 1).real;

expect(actual).toEqual(expected);
});

xtest('Real part of a number with real and imaginary part', () => {
const expected = 1;
const actual = new ComplexNumber(1, 2).real;

expect(actual).toEqual(expected);
});

xtest('Imaginary part of a purely real number', () => {
const expected = 0;
const actual = new ComplexNumber(1, 0).imag;

expect(actual).toEqual(expected);
});

xtest('Imaginary part of a purely imaginary number', () => {
const expected = 1;
const actual = new ComplexNumber(0, 1).imag;

expect(actual).toEqual(expected);
});

xtest('Imaginary part of a number with real and imaginary part', () => {
const expected = 2;
const actual = new ComplexNumber(1, 2).imag;

expect(actual).toEqual(expected);
});

xtest('Add purely real numbers', () => {
const expected = new ComplexNumber(3, 0);
const actual = new ComplexNumber(1, 0).add(new ComplexNumber(2, 0));

expect(actual).toEqual(expected);
});

xtest('Add purely imaginary numbers', () => {
const expected = new ComplexNumber(0, 3);
const actual = new ComplexNumber(0, 1).add(new ComplexNumber(0, 2));

expect(actual).toEqual(expected);
});

xtest('Add numbers with real and imaginary part', () => {
const expected = new ComplexNumber(4, 6);
const actual = new ComplexNumber(1, 2).add(new ComplexNumber(3, 4));

expect(actual).toEqual(expected);
});

xtest('Subtract purely real numbers', () => {
const expected = new ComplexNumber(-1, 0);
const actual = new ComplexNumber(1, 0).sub(new ComplexNumber(2, 0));

expect(actual).toEqual(expected);
});

xtest('Subtract purely imaginary numbers', () => {
const expected = new ComplexNumber(0, -1);
const actual = new ComplexNumber(0, 1).sub(new ComplexNumber(0, 2));

expect(actual).toEqual(expected);
});

xtest('Subtract numbers with real and imaginary part', () => {
const expected = new ComplexNumber(-2, -2);
const actual = new ComplexNumber(1, 2).sub(new ComplexNumber(3, 4));

expect(actual).toEqual(expected);
});

xtest('Multiply purely real numbers', () => {
const expected = new ComplexNumber(2, 0);
const actual = new ComplexNumber(1, 0).mul(new ComplexNumber(2, 0));

expect(actual).toEqual(expected);
});

xtest('Multiply imaginary unit', () => {
const expected = new ComplexNumber(-1, 0);
const actual = new ComplexNumber(0, 1).mul(new ComplexNumber(0, 1));

expect(actual).toEqual(expected);
});

xtest('Multiply purely imaginary numbers', () => {
const expected = new ComplexNumber(-2, 0);
const actual = new ComplexNumber(0, 1).mul(new ComplexNumber(0, 2));

expect(actual).toEqual(expected);
});

xtest('Multiply numbers with real and imaginary part', () => {
const expected = new ComplexNumber(-5, 10);
const actual = new ComplexNumber(1, 2).mul(new ComplexNumber(3, 4));

expect(actual).toEqual(expected);
});

xtest('Divide purely real numbers', () => {
const expected = new ComplexNumber(0.5, 0);
const actual = new ComplexNumber(1, 0).div(new ComplexNumber(2, 0));

expect(actual).toEqual(expected);
});

xtest('Divide purely imaginary numbers', () => {
const expected = new ComplexNumber(0.5, 0);
const actual = new ComplexNumber(0, 1).div(new ComplexNumber(0, 2));

expect(actual).toEqual(expected);
});

xtest('Divide numbers with real and imaginary part', () => {
const expected = new ComplexNumber(0.44, 0.08);
const actual = new ComplexNumber(1, 2).div(new ComplexNumber(3, 4));

expect(actual).toEqual(expected);
});

xtest('Absolute value of a positive purely real number', () => {
const expected = 5;
const actual = new ComplexNumber(5, 0).abs;

expect(actual).toEqual(expected);
});

xtest('Absolute value of a negative purely real number', () => {
const expected = 5;
const actual = new ComplexNumber(-5, 0).abs;

expect(actual).toEqual(expected);
});

xtest('Absolute value of a purely imaginary number with positive imaginary part', () => {
const expected = 5;
const actual = new ComplexNumber(0, 5).abs;

expect(actual).toEqual(expected);
});

xtest('Absolute value of a purely imaginary number with negative imaginary part', () => {
const expected = 5;
const actual = new ComplexNumber(0, -5).abs;

expect(actual).toEqual(expected);
});

xtest('Absolute value of a number with real and imaginary part', () => {
const expected = 5;
const actual = new ComplexNumber(3, 4).abs;

expect(actual).toEqual(expected);
});

xtest('Conjugate a purely real number', () => {
const expected = new ComplexNumber(5, 0);
const actual = new ComplexNumber(5, 0).conj;

expect(actual).toEqual(expected);
});

xtest('Conjugate a purely imaginary number', () => {
const expected = new ComplexNumber(0, -5);
const actual = new ComplexNumber(0, 5).conj;

expect(actual).toEqual(expected);
});

xtest('Conjugate a number with real and imaginary part', () => {
const expected = new ComplexNumber(1, -1);
const actual = new ComplexNumber(1, 1).conj;

expect(actual).toEqual(expected);
});

xtest('Euler\'s identity/formula', () => {
const expected = new ComplexNumber(-1, 0);
const actual = new ComplexNumber(0, Math.PI).exp;

expect(actual.real).toBeCloseTo(expected.real);
expect(actual.imag).toBeCloseTo(expected.imag);
});

xtest('Exponential of 0', () => {
const expected = new ComplexNumber(1, 0);
const actual = new ComplexNumber(0, 0).exp;

expect(actual.real).toBeCloseTo(expected.real);
expect(actual.imag).toBeCloseTo(expected.imag);
});

xtest('Exponential of a purely real number', () => {
const expected = new ComplexNumber(Math.E, 0);
const actual = new ComplexNumber(1, 0).exp;

expect(actual.real).toBeCloseTo(expected.real);
expect(actual.imag).toBeCloseTo(expected.imag);
});
});
43 changes: 43 additions & 0 deletions exercises/complex-numbers/example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export default class ComplexNumber {

constructor(real, imag) {
this.real = real;
this.imag = imag;
}

add(other) {
return new ComplexNumber(this.real + other.real, this.imag + other.imag);
}

sub(other) {
return new ComplexNumber(this.real - other.real, this.imag - other.imag);
}

mul(other) {
return new ComplexNumber(
(this.real * other.real) - (this.imag * other.imag),
(this.imag * other.real) + (this.real * other.imag));
}

div(other) {
return new ComplexNumber(
((this.real * other.real) + (this.imag * other.imag))
/ ((other.real * other.real) + (other.imag * other.imag)),
((this.imag * other.real) - (this.real * other.imag))
/ ((other.real * other.real) + (other.imag * other.imag)));
}

get abs() {
return Math.sqrt((this.real * this.real) + (this.imag * this.imag));
}

get conj() {
return new ComplexNumber(this.real, this.imag !== 0 ? -this.imag : 0);
}

get exp() {
return new ComplexNumber(
Math.exp(this.real) * Math.cos(this.imag),
Math.exp(this.real) * Math.sin(this.imag));
}
}
Loading