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
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,14 @@
"practices": [],
"prerequisites": [],
"difficulty": 6
},
{
"slug": "complex-numbers",
"name": "Complex Numbers",
"uuid": "29567d07-2cf5-444b-aa82-5cbd6a9820d0",
"practices": [],
"prerequisites": [],
"difficulty": 6
}
]
},
Expand Down
5 changes: 5 additions & 0 deletions exercises/practice/complex-numbers/.busted
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
return {
default = {
ROOT = { '.' }
}
}
17 changes: 17 additions & 0 deletions exercises/practice/complex-numbers/.docs/instructions.append.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# dummy

## MoonScript-specific instructions

This is an object-oriented exercise: you're implementing ComplexNumbers as a class.

The tests will be comparing two complex number instances for equality.
This means your class will have to implement the `__eq` [metamethod][metamethods].

The tests also perform arithmetic operations on complex numbers, so there are arithmetic metamethods to implement.

~~~~exercism/caution
Some of the complex number functions will be doing math with floating point numbers.
Your "equality" will have to deal with numbers being _approximately equal_.
~~~~

[metamethods]: https://www.lua.org/manual/5.4/manual.html#2.4
100 changes: 100 additions & 0 deletions exercises/practice/complex-numbers/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Instructions

A **complex number** is expressed in the form `z = a + b * i`, where:

- `a` is the **real part** (a real number),

- `b` is the **imaginary part** (also a real number), and

- `i` is the **imaginary unit** satisfying `i^2 = -1`.

## Operations on Complex Numbers

### Conjugate

The conjugate of the complex number `z = a + b * i` is given by:

```text
zc = a - b * i
```

### Absolute Value

The absolute value (or modulus) of `z` is defined as:

```text
|z| = sqrt(a^2 + b^2)
```

The square of the absolute value is computed as the product of `z` and its conjugate `zc`:

```text
|z|^2 = z * zc = a^2 + b^2
```

### Addition

The sum of two complex numbers `z1 = a + b * i` and `z2 = c + d * i` is computed by adding their real and imaginary parts separately:

```text
z1 + z2 = (a + b * i) + (c + d * i)
= (a + c) + (b + d) * i
```

### Subtraction

The difference of two complex numbers is obtained by subtracting their respective parts:

```text
z1 - z2 = (a + b * i) - (c + d * i)
= (a - c) + (b - d) * i
```

### Multiplication

The product of two complex numbers is defined as:

```text
z1 * z2 = (a + b * i) * (c + d * i)
= (a * c - b * d) + (b * c + a * d) * i
```

### Reciprocal

The reciprocal of a non-zero complex number is given by:

```text
1 / z = 1 / (a + b * i)
= a / (a^2 + b^2) - b / (a^2 + b^2) * i
```

### Division

The division of one complex number by another is given by:

```text
z1 / z2 = z1 * (1 / z2)
= (a + b * i) / (c + d * i)
= (a * c + b * d) / (c^2 + d^2) + (b * c - a * d) / (c^2 + d^2) * i
```

### Exponentiation

Raising _e_ (the base of the natural logarithm) to a complex exponent can be expressed using Euler's formula:

```text
e^(a + b * i) = e^a * e^(b * i)
= e^a * (cos(b) + i * sin(b))
```

## Implementation Requirements

Given that you should not use built-in support for complex numbers, implement the following operations:

- **addition** of two complex numbers
- **subtraction** of two complex numbers
- **multiplication** of two complex numbers
- **division** of two complex numbers
- **conjugate** of a complex number
- **absolute value** of a complex number
- **exponentiation** of _e_ (the base of the natural logarithm) to a complex number
19 changes: 19 additions & 0 deletions exercises/practice/complex-numbers/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"glennj"
],
"files": {
"solution": [
"complex_numbers.moon"
],
"test": [
"complex_numbers_spec.moon"
],
"example": [
".meta/example.moon"
]
},
"blurb": "Implement complex numbers.",
"source": "Wikipedia",
"source_url": "https://en.wikipedia.org/wiki/Complex_number"
}
44 changes: 44 additions & 0 deletions exercises/practice/complex-numbers/.meta/example.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
class ComplexNumber
new: (@r, @i = 0) =>

real: => @r
imaginary: => @i

conjugate: => @@ @r, -@i

abs: => math.sqrt(@r^2 + @i^2)

__add: (other) =>
@@ (@r + other.r), (@i + other.i)

__sub: (other) =>
@@ (@r - other.r), (@i - other.i)

__mul: (other) =>
a = @r * other.r - @i * other.i
b = @i * other.r + @r * other.i
@@ a, b

reciprocal: =>
denom = @r^2 + @i^2
@@ @r / denom, -@i / denom

__div: (other) => self * other\reciprocal!

exp: =>
factor = math.exp(@r)
@@ factor * math.cos(@i), factor * math.sin(@i)

__eq: (other) =>
approx_equal = (a, b) -> math.abs(a - b) <= 1e-15
approx_equal(@r, other.r) and approx_equal(@i, other.i)


tocomplex = (a) -> if type(a) == 'number' then ComplexNumber a else a

add = (a, b) -> tocomplex(a) + tocomplex(b)
sub = (a, b) -> tocomplex(a) - tocomplex(b)
mul = (a, b) -> tocomplex(a) * tocomplex(b)
div = (a, b) -> tocomplex(a) / tocomplex(b)

{ :ComplexNumber, :add, :sub, :mul, :div }
52 changes: 52 additions & 0 deletions exercises/practice/complex-numbers/.meta/spec_generator.moon
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
op = add: '+', sub: '-', mul: '*', div: '/'

cn = (z) ->
switch type(z)
when 'number' then z
when 'table' then "ComplexNumber(#{z[1]}, #{z[2]})"


require 'moon.all'
{
module_imports: {'ComplexNumber', 'add', 'sub', 'mul', 'div'},

test_helpers: [[
pi = math.pi
e = math.exp(1)
ln = math.log
]]

generate_test: (case, level) ->
local lines
switch case.property
when 'real', 'imaginary', 'abs'
lines = {
"c = #{cn case.input.z}",
"result = c\\#{case.property}!",
"assert.are.equal #{case.expected}, result"
}
when 'add', 'sub', 'mul', 'div'
if type(case.input.z1) == 'number' or type(case.input.z2) == 'number'
lines = {
"result = #{case.property} #{cn case.input.z1}, #{cn case.input.z2}",
"expected = #{cn case.expected}",
"assert.are.equal expected, result"
}
else
lines = {
"c1 = #{cn case.input.z1}",
"c2 = #{cn case.input.z2}",
"result = c1 #{op[case.property]} c2",
"expected = #{cn case.expected}",
"assert.are.equal expected, result"
}
when 'conjugate', 'exp'
lines = {
"c = #{cn case.input.z}",
"result = c\\#{case.property}!",
"expected = #{cn case.expected}",
"assert.are.equal expected, result"
}

table.concat [indent line, level for line in *lines], '\n'
}
130 changes: 130 additions & 0 deletions exercises/practice/complex-numbers/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[9f98e133-eb7f-45b0-9676-cce001cd6f7a]
description = "Real part -> Real part of a purely real number"

[07988e20-f287-4bb7-90cf-b32c4bffe0f3]
description = "Real part -> Real part of a purely imaginary number"

[4a370e86-939e-43de-a895-a00ca32da60a]
description = "Real part -> Real part of a number with real and imaginary part"

[9b3fddef-4c12-4a99-b8f8-e3a42c7ccef6]
description = "Imaginary part -> Imaginary part of a purely real number"

[a8dafedd-535a-4ed3-8a39-fda103a2b01e]
description = "Imaginary part -> Imaginary part of a purely imaginary number"

[0f998f19-69ee-4c64-80ef-01b086feab80]
description = "Imaginary part -> Imaginary part of a number with real and imaginary part"

[a39b7fd6-6527-492f-8c34-609d2c913879]
description = "Imaginary unit"

[9a2c8de9-f068-4f6f-b41c-82232cc6c33e]
description = "Arithmetic -> Addition -> Add purely real numbers"

[657c55e1-b14b-4ba7-bd5c-19db22b7d659]
description = "Arithmetic -> Addition -> Add purely imaginary numbers"

[4e1395f5-572b-4ce8-bfa9-9a63056888da]
description = "Arithmetic -> Addition -> Add numbers with real and imaginary part"

[1155dc45-e4f7-44b8-af34-a91aa431475d]
description = "Arithmetic -> Subtraction -> Subtract purely real numbers"

[f95e9da8-acd5-4da4-ac7c-c861b02f774b]
description = "Arithmetic -> Subtraction -> Subtract purely imaginary numbers"

[f876feb1-f9d1-4d34-b067-b599a8746400]
description = "Arithmetic -> Subtraction -> Subtract numbers with real and imaginary part"

[8a0366c0-9e16-431f-9fd7-40ac46ff4ec4]
description = "Arithmetic -> Multiplication -> Multiply purely real numbers"

[e560ed2b-0b80-4b4f-90f2-63cefc911aaf]
description = "Arithmetic -> Multiplication -> Multiply purely imaginary numbers"

[4d1d10f0-f8d4-48a0-b1d0-f284ada567e6]
description = "Arithmetic -> Multiplication -> Multiply numbers with real and imaginary part"

[b0571ddb-9045-412b-9c15-cd1d816d36c1]
description = "Arithmetic -> Division -> Divide purely real numbers"

[5bb4c7e4-9934-4237-93cc-5780764fdbdd]
description = "Arithmetic -> Division -> Divide purely imaginary numbers"

[c4e7fef5-64ac-4537-91c2-c6529707701f]
description = "Arithmetic -> Division -> Divide numbers with real and imaginary part"

[c56a7332-aad2-4437-83a0-b3580ecee843]
description = "Absolute value -> Absolute value of a positive purely real number"

[cf88d7d3-ee74-4f4e-8a88-a1b0090ecb0c]
description = "Absolute value -> Absolute value of a negative purely real number"

[bbe26568-86c1-4bb4-ba7a-da5697e2b994]
description = "Absolute value -> Absolute value of a purely imaginary number with positive imaginary part"

[3b48233d-468e-4276-9f59-70f4ca1f26f3]
description = "Absolute value -> Absolute value of a purely imaginary number with negative imaginary part"

[fe400a9f-aa22-4b49-af92-51e0f5a2a6d3]
description = "Absolute value -> Absolute value of a number with real and imaginary part"

[fb2d0792-e55a-4484-9443-df1eddfc84a2]
description = "Complex conjugate -> Conjugate a purely real number"

[e37fe7ac-a968-4694-a460-66cb605f8691]
description = "Complex conjugate -> Conjugate a purely imaginary number"

[f7704498-d0be-4192-aaf5-a1f3a7f43e68]
description = "Complex conjugate -> Conjugate a number with real and imaginary part"

[6d96d4c6-2edb-445b-94a2-7de6d4caaf60]
description = "Complex exponential function -> Euler's identity/formula"

[2d2c05a0-4038-4427-a24d-72f6624aa45f]
description = "Complex exponential function -> Exponential of 0"

[ed87f1bd-b187-45d6-8ece-7e331232c809]
description = "Complex exponential function -> Exponential of a purely real number"

[08eedacc-5a95-44fc-8789-1547b27a8702]
description = "Complex exponential function -> Exponential of a number with real and imaginary part"

[d2de4375-7537-479a-aa0e-d474f4f09859]
description = "Complex exponential function -> Exponential resulting in a number with real and imaginary part"

[06d793bf-73bd-4b02-b015-3030b2c952ec]
description = "Operations between real numbers and complex numbers -> Add real number to complex number"

[d77dbbdf-b8df-43f6-a58d-3acb96765328]
description = "Operations between real numbers and complex numbers -> Add complex number to real number"

[20432c8e-8960-4c40-ba83-c9d910ff0a0f]
description = "Operations between real numbers and complex numbers -> Subtract real number from complex number"

[b4b38c85-e1bf-437d-b04d-49bba6e55000]
description = "Operations between real numbers and complex numbers -> Subtract complex number from real number"

[dabe1c8c-b8f4-44dd-879d-37d77c4d06bd]
description = "Operations between real numbers and complex numbers -> Multiply complex number by real number"

[6c81b8c8-9851-46f0-9de5-d96d314c3a28]
description = "Operations between real numbers and complex numbers -> Multiply real number by complex number"

[8a400f75-710e-4d0c-bcb4-5e5a00c78aa0]
description = "Operations between real numbers and complex numbers -> Divide complex number by real number"

[9a867d1b-d736-4c41-a41e-90bd148e9d5e]
description = "Operations between real numbers and complex numbers -> Divide real number by complex number"
Loading
Loading