Skip to content

Commit 418be26

Browse files
committed
Merge branch 'main' of https://github.com/exercism/cpp into add-twelve-days-exercise
2 parents 2edf9c7 + 5286de5 commit 418be26

21 files changed

Lines changed: 24357 additions & 45 deletions
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name: Run Configlet Sync
2+
3+
on:
4+
workflow_dispatch:
5+
schedule:
6+
- cron: '0 0 15 * *'
7+
8+
jobs:
9+
configlet-sync:
10+
uses: exercism/github-actions/.github/workflows/configlet-sync.yml@main

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
exclude: 'test/(catch.hpp|tests-main.cpp)'
1+
exclude: 'test/(catch(_amalgamated)?.[ch]pp|tests-main.cpp)'
22

33
repos:
44
- repo: https://github.com/pre-commit/mirrors-clang-format

config.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1131,13 +1131,22 @@
11311131
"prerequisites": [],
11321132
"difficulty": 3
11331133
},
1134+
{
1135+
"slug": "flower-field",
1136+
"name": "Flower Field",
1137+
"uuid": "d17d040b-b214-4079-ad3e-b518f776aeeb",
1138+
"practices": [],
1139+
"prerequisites": [],
1140+
"difficulty": 5
1141+
},
11341142
{
11351143
"slug": "minesweeper",
11361144
"name": "Minesweeper",
11371145
"uuid": "3753a72a-78b7-429f-b79a-f68d55a00387",
11381146
"practices": [],
11391147
"prerequisites": [],
1140-
"difficulty": 5
1148+
"difficulty": 5,
1149+
"status": "deprecated"
11411150
},
11421151
{
11431152
"slug": "sublist",

exercises/concept/last-will/.docs/introduction.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Namespaces
44

5-
An important method for code organization are namespaces.
5+
An important method for code organization is the use of namespaces.
66
Two functions might have a naming collision, which can be resolved by putting them in different namespaces.
77
Namespaces can be nested, which might help to structure big code bases.
88
Access to the namespaces is done via the scope-resolution operator `::`.

exercises/practice/complex-numbers/CMakeLists.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,7 @@ else()
1717
set(exercise_cpp "")
1818
endif()
1919

20-
# Use the common Catch library?
21-
if(EXERCISM_COMMON_CATCH)
22-
# For Exercism track development only
23-
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h $<TARGET_OBJECTS:catchlib>)
24-
elseif(EXERCISM_TEST_SUITE)
20+
if(EXERCISM_TEST_SUITE)
2521
# The Exercism test suite is being run, the Docker image already
2622
# includes a pre-built version of Catch.
2723
find_package(Catch2 REQUIRED)
@@ -32,7 +28,11 @@ elseif(EXERCISM_TEST_SUITE)
3228
target_compile_definitions(${exercise} PRIVATE EXERCISM_TEST_SUITE)
3329
else()
3430
# Build executable from sources and headers
35-
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h test/tests-main.cpp)
31+
# Other exercises have a third case where we use a local Catch2 copy from `test/`,
32+
# which then only needs to be built once and not individually for each exercise.
33+
# However, for complex-numbers we currently use a different version of Catch2 and
34+
# therefore always build the version local to the exercise.
35+
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h test/catch_amalgamated.cpp test/tests-main.cpp)
3636
endif()
3737

3838
set_target_properties(${exercise} PROPERTIES

exercises/practice/complex-numbers/complex_numbers_test.cpp

Lines changed: 59 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
#include "complex_numbers.h"
22

33
#include <cmath>
4+
#include <sstream>
45

56
#ifdef EXERCISM_TEST_SUITE
67
#include <catch2/catch.hpp>
78
#else
8-
#include "test/catch.hpp"
9+
#include "test/catch_amalgamated.hpp"
910
#endif
1011

1112
// Complex Numbers exercise test case data version 1.3.0
@@ -22,12 +23,35 @@ using complex_numbers::Complex;
2223

2324
// Define a margin to use for float comparisons. Catch does not compute a good
2425
// epsilon for float values near 0.
25-
static const double eps = 0.005;
26+
static constexpr double eps = 0.005;
2627

27-
// Helper function for comparing Complex numbers with approximate float values.
28-
static void require_approx_equal(const Complex& lhs, const Complex& rhs) {
29-
REQUIRE_THAT(lhs.real(), Catch::Matchers::WithinAbs(rhs.real(), eps));
30-
REQUIRE_THAT(lhs.imag(), Catch::Matchers::WithinAbs(rhs.imag(), eps));
28+
// Custom Catch2 matcher for approximate equality of Complex numbers
29+
class ComplexApproxMatcher : public Catch::Matchers::MatcherBase<Complex> {
30+
public:
31+
ComplexApproxMatcher(const Complex& expected, double epsilon)
32+
: expected{expected}, epsilon{epsilon} {}
33+
34+
bool match(const Complex& actual) const override {
35+
return std::abs(actual.real() - expected.real()) <= epsilon &&
36+
std::abs(actual.imag() - expected.imag()) <= epsilon;
37+
}
38+
39+
std::string describe() const override {
40+
std::ostringstream ss;
41+
ss << "is approximately equal to (" << expected.real() << ", "
42+
<< expected.imag() << "i) with epsilon " << epsilon;
43+
return ss.str();
44+
}
45+
46+
private:
47+
Complex expected;
48+
double epsilon;
49+
};
50+
51+
// Helper function to create the matcher
52+
inline ComplexApproxMatcher ComplexWithinAbs(const Complex& expected,
53+
double epsilon) {
54+
return ComplexApproxMatcher{expected, epsilon};
3155
}
3256

3357
TEST_CASE("Real part -> Real part of a purely real number",
@@ -78,47 +102,47 @@ TEST_CASE("Imaginary unit", "[a39b7fd6-6527-492f-8c34-609d2c913879]") {
78102
const Complex c1{0.0, 1.0};
79103
const Complex c2{0.0, 1.0};
80104

81-
require_approx_equal(Complex(-1.0, 0.0), c1 * c2);
105+
REQUIRE_THAT(c1 * c2, ComplexWithinAbs(Complex{-1.0, 0.0}, eps));
82106
}
83107

84108
TEST_CASE("Arithmetic -> Addition -> Add purely real numbers",
85109
"[9a2c8de9-f068-4f6f-b41c-82232cc6c33e]") {
86110
const Complex c1{1.0, 0.0};
87111
const Complex c2{2.0, 0.0};
88112

89-
require_approx_equal(Complex(3.0, 0.0), c1 + c2);
113+
REQUIRE_THAT(c1 + c2, ComplexWithinAbs(Complex{3.0, 0.0}, eps));
90114
}
91115

92116
TEST_CASE("Arithmetic -> Addition -> Add purely imaginary numbers",
93117
"[657c55e1-b14b-4ba7-bd5c-19db22b7d659]") {
94118
const Complex c1{0.0, 1.0};
95119
const Complex c2{0.0, 2.0};
96120

97-
require_approx_equal(Complex(0.0, 3.0), c1 + c2);
121+
REQUIRE_THAT(c1 + c2, ComplexWithinAbs(Complex{0.0, 3.0}, eps));
98122
}
99123

100124
TEST_CASE("Arithmetic -> Addition -> Add numbers with real and imaginary part",
101125
"[4e1395f5-572b-4ce8-bfa9-9a63056888da]") {
102126
const Complex c1{1.0, 2.0};
103127
const Complex c2{3.0, 4.0};
104128

105-
require_approx_equal(Complex(4.0, 6.0), c1 + c2);
129+
REQUIRE_THAT(c1 + c2, ComplexWithinAbs(Complex{4.0, 6.0}, eps));
106130
}
107131

108132
TEST_CASE("Arithmetic -> Subtraction -> Subtract purely real numbers",
109133
"[1155dc45-e4f7-44b8-af34-a91aa431475d]") {
110134
const Complex c1{1.0, 0.0};
111135
const Complex c2{2.0, 0.0};
112136

113-
require_approx_equal(Complex(-1.0, 0.0), c1 - c2);
137+
REQUIRE_THAT(c1 - c2, ComplexWithinAbs(Complex{-1.0, 0.0}, eps));
114138
}
115139

116140
TEST_CASE("Arithmetic -> Subtraction -> Subtract purely imaginary numbers",
117141
"[f95e9da8-acd5-4da4-ac7c-c861b02f774b]") {
118142
const Complex c1{0.0, 1.0};
119143
const Complex c2{0.0, 2.0};
120144

121-
require_approx_equal(Complex(0.0, -1.0), c1 - c2);
145+
REQUIRE_THAT(c1 - c2, ComplexWithinAbs(Complex{0.0, -1.0}, eps));
122146
}
123147

124148
TEST_CASE(
@@ -129,23 +153,23 @@ TEST_CASE(
129153
const Complex c1{1.0, 2.0};
130154
const Complex c2{3.0, 4.0};
131155

132-
require_approx_equal(Complex(-2.0, -2.0), c1 - c2);
156+
REQUIRE_THAT(c1 - c2, ComplexWithinAbs(Complex{-2.0, -2.0}, eps));
133157
}
134158

135159
TEST_CASE("Arithmetic -> Multiplication -> Multiply purely real numbers",
136160
"[8a0366c0-9e16-431f-9fd7-40ac46ff4ec4]") {
137161
const Complex c1{1.0, 0.0};
138162
const Complex c2{2.0, 0.0};
139163

140-
require_approx_equal(Complex(2.0, 0.0), c1 * c2);
164+
REQUIRE_THAT(c1 * c2, ComplexWithinAbs(Complex{2.0, 0.0}, eps));
141165
}
142166

143167
TEST_CASE("Arithmetic -> Multiplication -> Multiply purely imaginary numbers",
144168
"[e560ed2b-0b80-4b4f-90f2-63cefc911aaf]") {
145169
const Complex c1{0.0, 1.0};
146170
const Complex c2{0.0, 2.0};
147171

148-
require_approx_equal(Complex(-2.0, 0.0), c1 * c2);
172+
REQUIRE_THAT(c1 * c2, ComplexWithinAbs(Complex{-2.0, 0.0}, eps));
149173
}
150174

151175
TEST_CASE(
@@ -156,23 +180,23 @@ TEST_CASE(
156180
const Complex c1{1.0, 2.0};
157181
const Complex c2{3.0, 4.0};
158182

159-
require_approx_equal(Complex(-5.0, 10.0), c1 * c2);
183+
REQUIRE_THAT(c1 * c2, ComplexWithinAbs(Complex{-5.0, 10.0}, eps));
160184
}
161185

162186
TEST_CASE("Arithmetic -> Division -> Divide purely real numbers",
163187
"[b0571ddb-9045-412b-9c15-cd1d816d36c1]") {
164188
const Complex c1{1.0, 0.0};
165189
const Complex c2{2.0, 0.0};
166190

167-
require_approx_equal(Complex(0.5, 0.0), c1 / c2);
191+
REQUIRE_THAT(c1 / c2, ComplexWithinAbs(Complex{0.5, 0.0}, eps));
168192
}
169193

170194
TEST_CASE("Arithmetic -> Division -> Divide purely imaginary numbers",
171195
"[5bb4c7e4-9934-4237-93cc-5780764fdbdd]") {
172196
const Complex c1{0.0, 1.0};
173197
const Complex c2{0.0, 2.0};
174198

175-
require_approx_equal(Complex(0.5, 0.0), c1 / c2);
199+
REQUIRE_THAT(c1 / c2, ComplexWithinAbs(Complex{0.5, 0.0}, eps));
176200
}
177201

178202
TEST_CASE(
@@ -181,7 +205,7 @@ TEST_CASE(
181205
const Complex c1{1.0, 2.0};
182206
const Complex c2{3.0, 4.0};
183207

184-
require_approx_equal(Complex(0.44, 0.08), c1 / c2);
208+
REQUIRE_THAT(c1 / c2, ComplexWithinAbs(Complex{0.44, 0.08}, eps));
185209
}
186210

187211
TEST_CASE("Absolute value -> Absolute value of a positive purely real number",
@@ -230,43 +254,43 @@ TEST_CASE("Complex conjugate -> Conjugate a purely real number",
230254
"[fb2d0792-e55a-4484-9443-df1eddfc84a2]") {
231255
const Complex c{5.0, 0.0};
232256

233-
require_approx_equal(Complex(5.0, 0.0), c.conj());
257+
REQUIRE_THAT(c.conj(), ComplexWithinAbs(Complex{5.0, 0.0}, eps));
234258
}
235259

236260
TEST_CASE("Complex conjugate -> Conjugate a purely imaginary number",
237261
"[e37fe7ac-a968-4694-a460-66cb605f8691]") {
238262
const Complex c{0.0, 5.0};
239263

240-
require_approx_equal(Complex(0.0, -5.0), c.conj());
264+
REQUIRE_THAT(c.conj(), ComplexWithinAbs(Complex{0.0, -5.0}, eps));
241265
}
242266

243267
TEST_CASE(
244268
"Complex conjugate -> Conjugate a number with real and imaginary part",
245269
"[f7704498-d0be-4192-aaf5-a1f3a7f43e68]") {
246270
const Complex c{1.0, 1.0};
247271

248-
require_approx_equal(Complex(1.0, -1.0), c.conj());
272+
REQUIRE_THAT(c.conj(), ComplexWithinAbs(Complex{1.0, -1.0}, eps));
249273
}
250274

251275
TEST_CASE("Complex exponential function -> Euler's identity/formula",
252276
"[6d96d4c6-2edb-445b-94a2-7de6d4caaf60]") {
253277
const Complex c{0.0, M_PI};
254278

255-
require_approx_equal(Complex(-1.0, 0.0), c.exp());
279+
REQUIRE_THAT(c.exp(), ComplexWithinAbs(Complex{-1.0, 0.0}, eps));
256280
}
257281

258282
TEST_CASE("Complex exponential function -> Exponential of 0",
259283
"[2d2c05a0-4038-4427-a24d-72f6624aa45f]") {
260284
const Complex c{0.0, 0.0};
261285

262-
require_approx_equal(Complex(1.0, 0.0), c.exp());
286+
REQUIRE_THAT(c.exp(), ComplexWithinAbs(Complex{1.0, 0.0}, eps));
263287
}
264288

265289
TEST_CASE("Complex exponential function -> Exponential of a purely real number",
266290
"[ed87f1bd-b187-45d6-8ece-7e331232c809]") {
267291
const Complex c{1.0, 0.0};
268292

269-
require_approx_equal(Complex(M_E, 0.0), c.exp());
293+
REQUIRE_THAT(c.exp(), ComplexWithinAbs(Complex(M_E, 0.0), eps));
270294
}
271295

272296
// Extra Credit
@@ -277,7 +301,7 @@ TEST_CASE(
277301
"[08eedacc-5a95-44fc-8789-1547b27a8702]") {
278302
const Complex c{std::log(2.0), M_PI};
279303

280-
require_approx_equal(Complex(-2.0, 0.0), c.exp());
304+
REQUIRE_THAT(c.exp(), ComplexWithinAbs(Complex{-2.0, 0.0}, eps));
281305
}
282306

283307
TEST_CASE(
@@ -287,7 +311,7 @@ TEST_CASE(
287311
"[d2de4375-7537-479a-aa0e-d474f4f09859]") {
288312
const Complex c{std::log(2.0) / 2.0, M_PI / 4.0};
289313

290-
require_approx_equal(Complex(1.0, 1.0), c.exp());
314+
REQUIRE_THAT(c.exp(), ComplexWithinAbs(Complex{1.0, 1.0}, eps));
291315
}
292316

293317
TEST_CASE(
@@ -297,7 +321,7 @@ TEST_CASE(
297321
"[06d793bf-73bd-4b02-b015-3030b2c952ec]") {
298322
const Complex c{1.0, 2.0};
299323

300-
require_approx_equal(Complex(6.0, 2.0), c + 5.0);
324+
REQUIRE_THAT(c + 5.0, ComplexWithinAbs(Complex{6.0, 2.0}, eps));
301325
}
302326

303327
TEST_CASE(
@@ -307,7 +331,7 @@ TEST_CASE(
307331
"[d77dbbdf-b8df-43f6-a58d-3acb96765328]") {
308332
const Complex c{1.0, 2.0};
309333

310-
require_approx_equal(Complex(6.0, 2.0), 5.0 + c);
334+
REQUIRE_THAT(5.0 + c, ComplexWithinAbs(Complex{6.0, 2.0}, eps));
311335
}
312336

313337
TEST_CASE(
@@ -317,7 +341,7 @@ TEST_CASE(
317341
"[20432c8e-8960-4c40-ba83-c9d910ff0a0f]") {
318342
const Complex c{5.0, 7.0};
319343

320-
require_approx_equal(Complex(1.0, 7.0), c - 4.0);
344+
REQUIRE_THAT(c - 4.0, ComplexWithinAbs(Complex{1.0, 7.0}, eps));
321345
}
322346

323347
TEST_CASE(
@@ -327,7 +351,7 @@ TEST_CASE(
327351
"[b4b38c85-e1bf-437d-b04d-49bba6e55000]") {
328352
const Complex c{5.0, 7.0};
329353

330-
require_approx_equal(Complex(-1.0, -7.0), 4.0 - c);
354+
REQUIRE_THAT(4.0 - c, ComplexWithinAbs(Complex{-1.0, -7.0}, eps));
331355
}
332356

333357
TEST_CASE(
@@ -337,7 +361,7 @@ TEST_CASE(
337361
"[dabe1c8c-b8f4-44dd-879d-37d77c4d06bd]") {
338362
const Complex c{2.0, 5.0};
339363

340-
require_approx_equal(Complex(10.0, 25.0), c * 5.0);
364+
REQUIRE_THAT(c * 5.0, ComplexWithinAbs(Complex{10.0, 25.0}, eps));
341365
}
342366

343367
TEST_CASE(
@@ -347,7 +371,7 @@ TEST_CASE(
347371
"[6c81b8c8-9851-46f0-9de5-d96d314c3a28]") {
348372
const Complex c{2.0, 5.0};
349373

350-
require_approx_equal(Complex(10.0, 25.0), 5.0 * c);
374+
REQUIRE_THAT(5.0 * c, ComplexWithinAbs(Complex{10.0, 25.0}, eps));
351375
}
352376

353377
TEST_CASE(
@@ -357,7 +381,7 @@ TEST_CASE(
357381
"[8a400f75-710e-4d0c-bcb4-5e5a00c78aa0]") {
358382
const Complex c{10.0, 100.0};
359383

360-
require_approx_equal(Complex(1.0, 10.0), c / 10.0);
384+
REQUIRE_THAT(c / 10.0, ComplexWithinAbs(Complex{1.0, 10.0}, eps));
361385
}
362386

363387
TEST_CASE(
@@ -367,7 +391,7 @@ TEST_CASE(
367391
"[9a867d1b-d736-4c41-a41e-90bd148e9d5e]") {
368392
const Complex c{1.0, 1.0};
369393

370-
require_approx_equal(Complex(2.5, -2.5), 5.0 / c);
394+
REQUIRE_THAT(5.0 / c, ComplexWithinAbs(Complex{2.5, -2.5}, eps));
371395
}
372396

373397
#endif

0 commit comments

Comments
 (0)