Skip to content

Commit

Permalink
feat(test): port complex numbers exercise (resolves #153) (#157)
Browse files Browse the repository at this point in the history
  • Loading branch information
m-charlton authored Sep 8, 2023
1 parent c5f3a16 commit d8861e5
Show file tree
Hide file tree
Showing 7 changed files with 657 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,14 @@
"prerequisites": [],
"difficulty": 4
},
{
"uuid": "26f834d8-6182-4f41-aa4f-a376e0c83def",
"slug": "complex-numbers",
"name": "Complex Numbers",
"practices": [],
"prerequisites": [],
"difficulty": 5
},
{
"uuid": "df360057-385e-4166-96e1-ed0629c02ca3",
"slug": "two-fer",
Expand Down
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 @@
# Instructions

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.

Assume the programming language you are using does not have an implementation of complex numbers.
11 changes: 11 additions & 0 deletions exercises/practice/complex-numbers/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"authors": ["m-charlton"],
"files": {
"solution": ["complex-numbers.v"],
"test": ["run_test.v"],
"example": [".meta/example.v"]
},
"blurb": "Implement complex numbers.",
"source": "Wikipedia",
"source_url": "https://en.wikipedia.org/wiki/Complex_number"
}
116 changes: 116 additions & 0 deletions exercises/practice/complex-numbers/.meta/example.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
module main

import math { cos, pow, sin }

struct Complex {
real f64
imaginary f64
}

fn (c Complex) additive(other Complex, op fn (f64, f64) f64) Complex {
return Complex.new(op(c.real, other.real), op(c.imaginary, other.imaginary))
}

fn (c Complex) reciprocal() Complex {
denominator := pow(c.real, 2.0) + pow(c.imaginary, 2.0)
return Complex.new(c.real / denominator, -c.imaginary / denominator)
}

// build a Complex number
pub fn Complex.new(real f64, imaginary f64) Complex {
return Complex{real, imaginary}
}

pub fn (c Complex) real() f64 {
return c.real
}

pub fn (c Complex) imaginary() f64 {
return c.imaginary
}

pub fn (c Complex) conjugate() Complex {
return Complex.new(c.real, -c.imaginary)
}

pub fn (c Complex) abs() f64 {
return math.hypot(c.real, c.imaginary)
}

pub fn (c Complex) add(other Complex) Complex {
return c.additive(other, fn (a f64, b f64) f64 {
return a + b
})
}

pub fn (c Complex) sub(other Complex) Complex {
return c.additive(other, fn (a f64, b f64) f64 {
return a - b
})
}

pub fn (c Complex) exp() Complex {
e_to_creal := math.exp(c.real)
return Complex.new(e_to_creal * cos(c.imaginary), e_to_creal * sin(c.imaginary))
}

pub fn (c Complex) mul(other Complex) Complex {
return Complex.new(c.real * other.real - c.imaginary * other.imaginary,
c.imaginary * other.real + c.real * other.imaginary)
}

pub fn (c Complex) div(other Complex) Complex {
return c.mul(other.reciprocal())
}

// add a real number 'r' to complex number 'c'
// c + r
pub fn (c Complex) add_real(r f64) Complex {
return Complex.new(c.real + r, c.imaginary)
}

// add a complex number 'c' to a real number 'r':
// r + c
pub fn (c Complex) real_add(r f64) Complex {
// addition is commutative.
// r + c == c + r
return c.add_real(r)
}

// subtract a real number 'r' from a complex number 'c':
// c - r
pub fn (c Complex) sub_real(r f64) Complex {
return c.add_real(-r)
}

// subtract a complex number 'c' from 'r':
// r - c
pub fn (c Complex) real_sub(r f64) Complex {
return Complex.new(r - c.real, -c.imaginary)
}

// multiply a complex number 'c' by real number 'r'
// c * r
pub fn (c Complex) mul_by_real(r f64) Complex {
return Complex.new(r * c.real, r * c.imaginary)
}

// multiply a real number 'r' by a complex number 'c':
// r * c
pub fn (c Complex) real_mul(r f64) Complex {
// multiplication is commutative.
// r * c == c * r
return c.mul_by_real(r)
}

// divide complex number 'c' by real number 'r'
// c / r
pub fn (c Complex) div_by_real(r f64) Complex {
return Complex.new(c.real / r, c.imaginary / r)
}

// divide a real number 'r' by a complex number 'c'
// r / c
pub fn (c Complex) real_div(r f64) Complex {
return c.reciprocal().mul_by_real(r)
}
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"
75 changes: 75 additions & 0 deletions exercises/practice/complex-numbers/complex-numbers.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
module main

struct Complex {
}

// build a Complex number
pub fn Complex.new(real f64, imaginary f64) Complex {
}

pub fn (c Complex) real() f64 {
}

pub fn (c Complex) imaginary() f64 {
}

pub fn (c Complex) conjugate() Complex {
}

pub fn (c Complex) abs() f64 {
}

pub fn (c Complex) add(other Complex) Complex {
}

pub fn (c Complex) sub(other Complex) Complex {
}

pub fn (c Complex) exp() Complex {
}

pub fn (c Complex) mul(other Complex) Complex {
}

pub fn (c Complex) div(other Complex) Complex {
}

// add a real number 'r' to complex number 'c'
// c + r
pub fn (c Complex) add_real(r f64) Complex {
}

// add a complex number 'c' to a real number 'r':
// r + c
pub fn (c Complex) real_add(r f64) Complex {
}

// subtract a real number 'r' from a complex number 'c':
// c - r
pub fn (c Complex) sub_real(r f64) Complex {
}

// subtract a complex number 'c' from 'r':
// r - c
pub fn (c Complex) real_sub(r f64) Complex {
}

// multiply a complex number 'c' by real number 'r'
// c * r
pub fn (c Complex) mul_by_real(r f64) Complex {
}

// multiply a real number 'r' by a complex number 'c':
// r * c
pub fn (c Complex) real_mul(r f64) Complex {
}

// divide complex number 'c' by real number 'r'
// c / r
pub fn (c Complex) div_by_real(r f64) Complex {
}

// divide a real number 'r' by a complex number 'c'
// r / c
pub fn (c Complex) real_div(r f64) Complex {
}
Loading

0 comments on commit d8861e5

Please sign in to comment.