Skip to content

[#765] New practice exercise complex-numbers #769

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

Merged
merged 8 commits into from
Jun 19, 2021
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
16 changes: 16 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2430,6 +2430,22 @@
],
"difficulty": 4
},
{
"slug": "complex-numbers",
"name": "Complex Numbers",
"uuid": "0cc86a92-7118-4cb9-8417-db4557baf364",
"prerequisites": [
"pattern-matching",
"erlang-libraries",
"floating-point-numbers",
"tuples"
],
"practices": [
"erlang-libraries",
"floating-point-numbers"
],
"difficulty": 4
},
{
"slug": "yacht",
"name": "Yacht",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
In this exercise, complex numbers are represented as a tuple-pair containing the real and imaginary parts.

For example, the real number `1` is `{1, 0}`, the imaginary number `i` is `{0, 1}` and the complex number `4+3i` is `{4, 3}'.
29 changes: 29 additions & 0 deletions exercises/practice/complex-numbers/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Description

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`.

Raising e to a complex exponent can be expressed as `e^(a + i * b) = e^a * e^(i * b)`, the last term of which is given by Euler's formula `e^(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.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would like to see a description of how the complex pair is represented with a tuple to represent the real and imaginary part.

Ex) "For this exercise, a complex number will be a tuple-pair where the number 4+3i would be represented by {4, 3}."

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea, thank you!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

All the documentation I saw discouraged me from changing the description of the exercise, so I updated the @typedoc instead.

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Just a word of explanation: we're not supposed to change anything in instructions.md because there will be a script soon that allows synchronizing it with the problem specifications repository in case of changes, and then track-specific changes would get overwritten. That's why there's an append file for this.


Assume the programming language you are using does not have an implementation of complex numbers.
4 changes: 4 additions & 0 deletions exercises/practice/complex-numbers/.formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
21 changes: 21 additions & 0 deletions exercises/practice/complex-numbers/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"blurb": "Implement complex numbers.",
"authors": [
"jiegillet"
],
"contributors": [
],
"files": {
"solution": [
"lib/complex_numbers.ex"
],
"test": [
"test/complex_numbers_test.exs"
],
"example": [
".meta/example.ex"
]
},
"source": "Wikipedia",
"source_url": "https://en.wikipedia.org/wiki/Complex_number"
}
64 changes: 64 additions & 0 deletions exercises/practice/complex-numbers/.meta/example.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
defmodule ComplexNumbers do
@typedoc """
In this module, complex numbers are represented as a tuple-pair containing the real and
imaginary parts.
For example, the real number `1` is `{1, 0}`, the imaginary number `i` is `{0, 1}` and
the complex number `4+3i` is `{4, 3}'.
"""
@type complex :: {float, float}

@doc """
Return the real part of a complex number
"""
@spec real(a :: complex) :: float
def real({real, _im}), do: real

@doc """
Return the imaginary part of a complex number
"""
@spec imaginary(a :: complex) :: float
def imaginary({_real, im}), do: im

@doc """
Multiply two complex numbers
"""
@spec mul(a :: complex, b :: complex) :: complex
def mul({a, b}, {c, d}), do: {a * c - b * d, b * c + a * d}

@doc """
Add two complex numbers
"""
@spec add(a :: complex, b :: complex) :: complex
def add({a, b}, {c, d}), do: {a + c, b + d}

@doc """
Subtract two complex numbers
"""
@spec sub(a :: complex, b :: complex) :: complex
def sub({a, b}, {c, d}), do: {a - c, b - d}

@doc """
Divide two complex numbers
"""
@spec div(a :: complex, b :: complex) :: complex
def div({a, b}, {c, d}),
do: {(a * c + b * d) / (c * c + d * d), (b * c - a * d) / (c * c + d * d)}

@doc """
Absolute value of a complex number
"""
@spec abs(a :: complex) :: float
def abs({a, b}), do: :math.sqrt(a * a + b * b)

@doc """
Conjugate of a complex number
"""
@spec conjugate(a :: complex) :: complex
def conjugate({a, b}), do: {a, -b}

@doc """
Exponential of a complex number
"""
@spec exp(a :: complex) :: complex
def exp({a, b}), do: {:math.exp(a) * :math.cos(b), -:math.exp(a) * :math.sin(b)}
end
96 changes: 96 additions & 0 deletions exercises/practice/complex-numbers/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# This is an auto-generated file. Regular comments will be removed when this
# file is regenerated. Regenerating will not touch any manually added keys,
# so comments can be added in a "comment" key.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[08eedacc-5a95-44fc-8789-1547b27a8702]
description = "Exponential of a number with real and imaginary part"
72 changes: 72 additions & 0 deletions exercises/practice/complex-numbers/lib/complex_numbers.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
defmodule ComplexNumbers do
@typedoc """
In this module, complex numbers are represented as a tuple-pair containing the real and
imaginary parts.
For example, the real number `1` is `{1, 0}`, the imaginary number `i` is `{0, 1}` and
the complex number `4+3i` is `{4, 3}'.
"""
@type complex :: {float, float}

@doc """
Return the real part of a complex number
"""
@spec real(a :: complex) :: float
def real(a) do
end

@doc """
Return the imaginary part of a complex number
"""
@spec imaginary(a :: complex) :: float
def imaginary(a) do
end

@doc """
Multiply two complex numbers
"""
@spec mul(a :: complex, b :: complex) :: complex
def mul(a, b) do
end

@doc """
Add two complex numbers
"""
@spec add(a :: complex, b :: complex) :: complex
def add(a, b) do
end

@doc """
Subtract two complex numbers
"""
@spec sub(a :: complex, b :: complex) :: complex
def sub(a, b) do
end

@doc """
Divide two complex numbers
"""
@spec div(a :: complex, b :: complex) :: complex
def div(a, b) do
end

@doc """
Absolute value of a complex number
"""
@spec abs(a :: complex) :: float
def abs(a) do
end

@doc """
Conjugate of a complex number
"""
@spec conjugate(a :: complex) :: complex
def conjugate(a) do
end

@doc """
Exponential of a complex number
"""
@spec exp(a :: complex) :: complex
def exp(a) do
end
end
28 changes: 28 additions & 0 deletions exercises/practice/complex-numbers/mix.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
defmodule ComplexNumbers.MixProject do
use Mix.Project

def project do
[
app: :complex_numbers,
version: "0.1.0",
# elixir: "~> 1.8",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end

# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end

# Run "mix help deps" to learn about dependencies.
defp deps do
[
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
end
end
Loading