Skip to content

Commit 0f9547d

Browse files
[Swift 6]: Update Exercises batch 22 (#816)
* Update Swift tools version to 6.0 and add new Position struct for saddle points exercise * Format files * Re generate test file * Fix template of poker * Re generate saddle points test * Bump numerics version * Update instructions.append.md Co-authored-by: András B Nagy <[email protected]> * Update instructions.append.md Co-authored-by: András B Nagy <[email protected]> --------- Co-authored-by: András B Nagy <[email protected]>
1 parent 847121c commit 0f9547d

File tree

21 files changed

+1421
-1099
lines changed

21 files changed

+1421
-1099
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Append
2+
3+
You will have to implement your own equality operator for the `ComplexNumber` object.
4+
This will pose the challenge of comparing two floating point numbers.
5+
It might be useful to use the method `isApproximatelyEqual(to:absoluteTolerance:)` which can be found in the [Numerics][swift-numberics] library.
6+
A given tolerance of `0.00001` should be enough to pass the tests.
7+
The library is already imported in the project so it is just to import it in your file.
8+
9+
You are also free to implement your own method to compare the two complex numbers.
10+
11+
[swift-numberics]: https://github.com/apple/swift-numerics
Lines changed: 89 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,100 @@
11
# Instructions
22

3-
A complex number is a number in the form `a + b * i` where `a` and `b` are real and `i` satisfies `i^2 = -1`.
3+
A **complex number** is expressed in the form `z = a + b * i`, where:
44

5-
`a` is called the real part and `b` is called the imaginary part of `z`.
6-
The conjugate of the number `a + b * i` is the number `a - b * i`.
7-
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.
5+
- `a` is the **real part** (a real number),
86

9-
The sum/difference of two complex numbers involves adding/subtracting their real and imaginary parts separately:
10-
`(a + i * b) + (c + i * d) = (a + c) + (b + d) * i`,
11-
`(a + i * b) - (c + i * d) = (a - c) + (b - d) * i`.
7+
- `b` is the **imaginary part** (also a real number), and
128

13-
Multiplication result is by definition
14-
`(a + i * b) * (c + i * d) = (a * c - b * d) + (b * c + a * d) * i`.
9+
- `i` is the **imaginary unit** satisfying `i^2 = -1`.
1510

16-
The reciprocal of a non-zero complex number is
17-
`1 / (a + i * b) = a/(a^2 + b^2) - b/(a^2 + b^2) * i`.
11+
## Operations on Complex Numbers
1812

19-
Dividing a complex number `a + i * b` by another `c + i * d` gives:
20-
`(a + i * b) / (c + i * d) = (a * c + b * d)/(c^2 + d^2) + (b * c - a * d)/(c^2 + d^2) * i`.
13+
### Conjugate
2114

22-
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)`.
15+
The conjugate of the complex number `z = a + b * i` is given by:
2316

24-
Implement the following operations:
17+
```text
18+
zc = a - b * i
19+
```
2520

26-
- addition, subtraction, multiplication and division of two complex numbers,
27-
- conjugate, absolute value, exponent of a given complex number.
21+
### Absolute Value
2822

29-
Assume the programming language you are using does not have an implementation of complex numbers.
23+
The absolute value (or modulus) of `z` is defined as:
24+
25+
```text
26+
|z| = sqrt(a^2 + b^2)
27+
```
28+
29+
The square of the absolute value is computed as the product of `z` and its conjugate `zc`:
30+
31+
```text
32+
|z|^2 = z * zc = a^2 + b^2
33+
```
34+
35+
### Addition
36+
37+
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:
38+
39+
```text
40+
z1 + z2 = (a + b * i) + (c + d * i)
41+
= (a + c) + (b + d) * i
42+
```
43+
44+
### Subtraction
45+
46+
The difference of two complex numbers is obtained by subtracting their respective parts:
47+
48+
```text
49+
z1 - z2 = (a + b * i) - (c + d * i)
50+
= (a - c) + (b - d) * i
51+
```
52+
53+
### Multiplication
54+
55+
The product of two complex numbers is defined as:
56+
57+
```text
58+
z1 * z2 = (a + b * i) * (c + d * i)
59+
= (a * c - b * d) + (b * c + a * d) * i
60+
```
61+
62+
### Reciprocal
63+
64+
The reciprocal of a non-zero complex number is given by:
65+
66+
```text
67+
1 / z = 1 / (a + b * i)
68+
= a / (a^2 + b^2) - b / (a^2 + b^2) * i
69+
```
70+
71+
### Division
72+
73+
The division of one complex number by another is given by:
74+
75+
```text
76+
z1 / z2 = z1 * (1 / z2)
77+
= (a + b * i) / (c + d * i)
78+
= (a * c + b * d) / (c^2 + d^2) + (b * c - a * d) / (c^2 + d^2) * i
79+
```
80+
81+
### Exponentiation
82+
83+
Raising _e_ (the base of the natural logarithm) to a complex exponent can be expressed using Euler's formula:
84+
85+
```text
86+
e^(a + b * i) = e^a * e^(b * i)
87+
= e^a * (cos(b) + i * sin(b))
88+
```
89+
90+
## Implementation Requirements
91+
92+
Given that you should not use built-in support for complex numbers, implement the following operations:
93+
94+
- **addition** of two complex numbers
95+
- **subtraction** of two complex numbers
96+
- **multiplication** of two complex numbers
97+
- **division** of two complex numbers
98+
- **conjugate** of a complex number
99+
- **absolute value** of a complex number
100+
- **exponentiation** of _e_ (the base of the natural logarithm) to a complex number
Lines changed: 58 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,60 @@
11
import Foundation
2-
3-
struct ComplexNumber {
4-
5-
var realComponent: Double
6-
7-
var imaginaryComponent: Double
8-
9-
func getRealComponent() -> Double {
10-
11-
return self.realComponent
12-
}
13-
14-
func getImaginaryComponent() -> Double {
15-
16-
return self.imaginaryComponent
17-
}
18-
19-
func add(complexNumber: ComplexNumber) -> ComplexNumber {
20-
21-
return ComplexNumber(realComponent: self.realComponent + complexNumber.realComponent, imaginaryComponent: self.imaginaryComponent + complexNumber.imaginaryComponent)
22-
23-
}
24-
25-
func subtract(complexNumber: ComplexNumber) -> ComplexNumber {
26-
27-
return ComplexNumber(realComponent: self.realComponent - complexNumber.realComponent, imaginaryComponent: self.imaginaryComponent - complexNumber.imaginaryComponent)
28-
}
29-
30-
func multiply(complexNumber: ComplexNumber) -> ComplexNumber {
31-
32-
return ComplexNumber(realComponent: self.realComponent * complexNumber.realComponent - self.imaginaryComponent * complexNumber.imaginaryComponent, imaginaryComponent: self.imaginaryComponent * complexNumber.realComponent + self.realComponent * complexNumber.imaginaryComponent)
33-
}
34-
35-
func divide(complexNumber: ComplexNumber) -> ComplexNumber {
36-
37-
let amplitudeOfComplexNumber = (complexNumber.realComponent * complexNumber.realComponent) + (complexNumber.imaginaryComponent * complexNumber.imaginaryComponent)
38-
39-
let realPartOfQuotient = (self.realComponent * complexNumber.realComponent + self.imaginaryComponent * complexNumber.imaginaryComponent) / amplitudeOfComplexNumber
40-
41-
let imaginaryPartOfQuotient = (self.imaginaryComponent * complexNumber.realComponent - self.realComponent * self.realComponent * complexNumber.imaginaryComponent) / amplitudeOfComplexNumber
42-
43-
return ComplexNumber(realComponent: realPartOfQuotient, imaginaryComponent: imaginaryPartOfQuotient)
44-
}
45-
46-
func conjugate() -> ComplexNumber {
47-
48-
return ComplexNumber(realComponent: self.realComponent, imaginaryComponent: (-1 * self.imaginaryComponent))
49-
}
50-
51-
func absolute() -> Double {
52-
53-
return sqrt(pow(self.realComponent, 2.0) + pow(self.imaginaryComponent, 2.0))
54-
}
55-
56-
func exponent() -> ComplexNumber {
57-
58-
let realPartOfResult = cos(self.imaginaryComponent)
59-
let imaginaryPartOfResult = sin(self.imaginaryComponent)
60-
let factor = exp(self.realComponent)
61-
62-
return ComplexNumber(realComponent: realPartOfResult * factor, imaginaryComponent: imaginaryPartOfResult * factor)
63-
64-
}
65-
2+
import Numerics
3+
4+
struct ComplexNumbers: Equatable {
5+
6+
var real: Double
7+
var imaginary: Double
8+
9+
init(realComponent: Double, imaginaryComponent: Double? = 0) {
10+
real = realComponent
11+
imaginary = imaginaryComponent ?? 0
12+
}
13+
14+
func add(complexNumber: ComplexNumbers) -> ComplexNumbers {
15+
ComplexNumbers(
16+
realComponent: real + complexNumber.real,
17+
imaginaryComponent: imaginary + complexNumber.imaginary)
18+
}
19+
20+
func sub(complexNumber: ComplexNumbers) -> ComplexNumbers {
21+
ComplexNumbers(
22+
realComponent: real - complexNumber.real,
23+
imaginaryComponent: imaginary - complexNumber.imaginary)
24+
}
25+
26+
func mul(complexNumber: ComplexNumbers) -> ComplexNumbers {
27+
ComplexNumbers(
28+
realComponent: real * complexNumber.real - imaginary * complexNumber.imaginary,
29+
imaginaryComponent: real * complexNumber.imaginary + imaginary * complexNumber.real)
30+
}
31+
32+
func div(complexNumber: ComplexNumbers) -> ComplexNumbers {
33+
let denominator =
34+
complexNumber.real * complexNumber.real + complexNumber.imaginary * complexNumber.imaginary
35+
let realComponent =
36+
(real * complexNumber.real + imaginary * complexNumber.imaginary) / denominator
37+
let imaginaryComponent =
38+
(imaginary * complexNumber.real - real * complexNumber.imaginary) / denominator
39+
return ComplexNumbers(realComponent: realComponent, imaginaryComponent: imaginaryComponent)
40+
}
41+
42+
func absolute() -> Double {
43+
sqrt(Double(real * real + imaginary * imaginary))
44+
}
45+
46+
func conjugate() -> ComplexNumbers {
47+
ComplexNumbers(realComponent: real, imaginaryComponent: -imaginary)
48+
}
49+
50+
func exponent() -> ComplexNumbers {
51+
let expReal = exp(Double(real)) * cos(Double(imaginary))
52+
let expImaginary = exp(Double(real)) * sin(Double(imaginary))
53+
return ComplexNumbers(realComponent: expReal, imaginaryComponent: expImaginary)
54+
}
55+
56+
static func == (lhs: ComplexNumbers, rhs: ComplexNumbers) -> Bool {
57+
lhs.real.isApproximatelyEqual(to: rhs.real, absoluteTolerance: 0.0001)
58+
&& lhs.imaginary.isApproximatelyEqual(to: rhs.imaginary, absoluteTolerance: 0.0001)
59+
}
6660
}

exercises/practice/complex-numbers/.meta/config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"authors": [
3-
"AlwynC"
3+
"AlwynC",
4+
"meatball133"
45
],
56
"contributors": [
67
"bhargavg",
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import Testing
2+
import Foundation
3+
4+
@testable import {{exercise|camelCase}}
5+
6+
let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false
7+
8+
@Suite struct {{exercise|camelCase}}Tests {
9+
{% outer: for case in cases %}
10+
{%- if case.cases %}
11+
{%- for subCases in case.cases %}
12+
{%- if subCases.cases %}
13+
{%- for subSubCases in subCases.cases %}
14+
@Test("{{subSubCases.description}}", .enabled(if: RUNALL))
15+
func test{{subSubCases.description |camelCase }}() {
16+
let complexNumberOne = {{exercise|camelCase}}(realComponent: {{subSubCases.input.z1[0]}}, imaginaryComponent: {{subSubCases.input.z1[1]}})
17+
let complexNumberTwo = {{exercise|camelCase}}(realComponent: {{subSubCases.input.z2[0]}}, imaginaryComponent: {{subSubCases.input.z2[1]}})
18+
let result = complexNumberOne.{{subSubCases.property}}(complexNumber: complexNumberTwo)
19+
let expected = {{exercise|camelCase}}(realComponent: {{subSubCases.expected[0]}}, imaginaryComponent: {{subSubCases.expected[1]}})
20+
#expect(expected == result)
21+
}
22+
{%- endfor %}
23+
{%- else %}
24+
{%- if forloop.outer.first and forloop.first %}
25+
@Test("{{subCases.description}}")
26+
{%- else %}
27+
@Test("{{subCases.description}}", .enabled(if: RUNALL))
28+
{%- endif %}
29+
func test{{subCases.description |camelCase }}() {
30+
{%- if subCases.property == "real" or subCases.property == "imaginary" or subCases.property == "abs" or subCases.property == "conjugate" or subCases.property == "exp" %}
31+
let complexNumber = {{exercise|camelCase}}(realComponent: {{subCases.input.z[0] | complexNumber}}, imaginaryComponent: {{subCases.input.z[1] | complexNumber}})
32+
{%- if subCases.property == "real" %}
33+
#expect(complexNumber.real == {{subCases.expected}})
34+
{%- elif subCases.property == "imaginary" %}
35+
#expect(complexNumber.imaginary == {{subCases.expected}})
36+
{%- elif subCases.property == "abs" %}
37+
#expect(complexNumber.absolute() == {{subCases.expected}})
38+
{%- elif subCases.property == "conjugate" %}
39+
let expected = {{exercise|camelCase}}(realComponent: {{subCases.expected[0]}}, imaginaryComponent: {{subCases.expected[1]}})
40+
#expect(complexNumber.conjugate() == expected)
41+
{%- elif subCases.property == "exp" %}
42+
let expected = {{exercise|camelCase}}(realComponent: {{subCases.expected[0] | complexNumber}}, imaginaryComponent: {{subCases.expected[1]}})
43+
#expect(complexNumber.exponent() == expected)
44+
{%- elif subCases.property == "add" or subCases.property == "sub" or subCases.property == "mul" or subCases.property == "div" %}
45+
{%- endif %}
46+
{%- else %}
47+
{%- if subCases.input.z1[0] %}
48+
let complexNumberOne = {{exercise|camelCase}}(realComponent: {{subCases.input.z1[0]}}, imaginaryComponent: {{subCases.input.z1[1]}})
49+
let complexNumberTwo = {{exercise|camelCase}}(realComponent: {{subCases.input.z2}}, imaginaryComponent: nil)
50+
{%- else %}
51+
let complexNumberOne = {{exercise|camelCase}}(realComponent: {{subCases.input.z1}}, imaginaryComponent: nil)
52+
let complexNumberTwo = {{exercise|camelCase}}(realComponent: {{subCases.input.z2[0]}}, imaginaryComponent: {{subCases.input.z2[1]}})
53+
{%- endif %}
54+
let result = complexNumberOne.{{subCases.property}}(complexNumber: complexNumberTwo)
55+
let expected = {{exercise|camelCase}}(realComponent: {{subCases.expected[0]}}, imaginaryComponent: {{subCases.expected[1]}})
56+
#expect(expected == result)
57+
{%- endif %}
58+
}
59+
{%- endif %}
60+
{% endfor -%}
61+
{%- else %}
62+
@Test("{{case.description}}", .enabled(if: RUNALL))
63+
func test{{case.description |camelCase }}() {
64+
let complexNumberOne = {{exercise|camelCase}}(realComponent: {{case.input.z1[0]}}, imaginaryComponent: {{case.input.z1[1]}})
65+
let complexNumberTwo = {{exercise|camelCase}}(realComponent: {{case.input.z2[0]}}, imaginaryComponent: {{case.input.z2[1]}})
66+
let result = complexNumberOne.{{case.property}}(complexNumber: complexNumberTwo)
67+
let expected = {{exercise|camelCase}}(realComponent: {{case.expected[0]}}, imaginaryComponent: {{case.expected[1]}})
68+
#expect(expected == result)
69+
}
70+
{%- endif %}
71+
{% endfor -%}
72+
}

exercises/practice/complex-numbers/.meta/tests.toml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,30 @@ description = "Complex exponential function -> Exponential of a purely real numb
101101

102102
[08eedacc-5a95-44fc-8789-1547b27a8702]
103103
description = "Complex exponential function -> Exponential of a number with real and imaginary part"
104+
105+
[d2de4375-7537-479a-aa0e-d474f4f09859]
106+
description = "Complex exponential function -> Exponential resulting in a number with real and imaginary part"
107+
108+
[06d793bf-73bd-4b02-b015-3030b2c952ec]
109+
description = "Operations between real numbers and complex numbers -> Add real number to complex number"
110+
111+
[d77dbbdf-b8df-43f6-a58d-3acb96765328]
112+
description = "Operations between real numbers and complex numbers -> Add complex number to real number"
113+
114+
[20432c8e-8960-4c40-ba83-c9d910ff0a0f]
115+
description = "Operations between real numbers and complex numbers -> Subtract real number from complex number"
116+
117+
[b4b38c85-e1bf-437d-b04d-49bba6e55000]
118+
description = "Operations between real numbers and complex numbers -> Subtract complex number from real number"
119+
120+
[dabe1c8c-b8f4-44dd-879d-37d77c4d06bd]
121+
description = "Operations between real numbers and complex numbers -> Multiply complex number by real number"
122+
123+
[6c81b8c8-9851-46f0-9de5-d96d314c3a28]
124+
description = "Operations between real numbers and complex numbers -> Multiply real number by complex number"
125+
126+
[8a400f75-710e-4d0c-bcb4-5e5a00c78aa0]
127+
description = "Operations between real numbers and complex numbers -> Divide complex number by real number"
128+
129+
[9a867d1b-d736-4c41-a41e-90bd148e9d5e]
130+
description = "Operations between real numbers and complex numbers -> Divide real number by complex number"

0 commit comments

Comments
 (0)