diff --git a/.clang-format b/.clang-format index 9a9cbf817..ed9165255 100644 --- a/.clang-format +++ b/.clang-format @@ -3,4 +3,4 @@ BasedOnStyle: Google # Customize with larger indents IndentWidth: 4 -ObjCBlockIndentWidth: 4 \ No newline at end of file +ObjCBlockIndentWidth: 4 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee4ddf8d7..867639527 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: matrix: compiler: [clang++-15, g++-12] steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install Dependencies # Boost must be installed only because the CMake version (3.12) can't # detect the installed Boost version (1.69) @@ -32,12 +32,12 @@ jobs: linux-latest: name: Linux Latest Config needs: [linux-min] - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 strategy: matrix: compiler: [clang++, g++] steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install Dependencies # Boost must be installed only because the CMake version (3.12) can't # detect the installed Boost version (1.69) @@ -64,7 +64,7 @@ jobs: needs: [linux-min] runs-on: windows-2022 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Run Tests shell: powershell # Delete the exercises that require Boost to avoid issues with Windows setup. @@ -80,7 +80,7 @@ jobs: needs: [linux-min] runs-on: macOS-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Install Boost run: brew install boost - name: Run Tests @@ -88,4 +88,3 @@ jobs: cmake . cmake --build . -- test_hello-world cmake --build . - diff --git a/.github/workflows/format-code.yml b/.github/workflows/format-code.yml index 2270dffea..5fac99bbc 100644 --- a/.github/workflows/format-code.yml +++ b/.github/workflows/format-code.yml @@ -7,7 +7,7 @@ on: jobs: format: name: "Format C++ code" - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 if: github.event.issue.pull_request != '' && (contains(github.event.comment.body, '/format') || contains(github.event.comment.body, '/clang-format')) steps: - name: "Checkout code" diff --git a/.github/workflows/hello-world.yml b/.github/workflows/hello-world.yml index e417c495d..e75d287e1 100644 --- a/.github/workflows/hello-world.yml +++ b/.github/workflows/hello-world.yml @@ -19,10 +19,10 @@ on: jobs: hello-world-fails: name: Hello World Fails - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Check Hello World Fails run: bin/check-hello-world.sh env: - CXX: ${{ matrix.compiler }} \ No newline at end of file + CXX: ${{ matrix.compiler }} diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 64b372ed8..777d3396c 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -11,16 +11,14 @@ on: jobs: pre-commit: name: Pre-commit checks - runs-on: ubuntu-22.04 + runs-on: ubuntu-26.04 steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: ref: ${{github.event.pull_request.head.sha}} repository: ${{github.event.pull_request.head.repo.full_name}} - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.10" + uses: actions/setup-python@v7 - name: Run pre-commit checks on PR uses: pre-commit/action@v3.0.1 diff --git a/.github/workflows/run-configlet-sync.yml b/.github/workflows/run-configlet-sync.yml new file mode 100644 index 000000000..c175036c1 --- /dev/null +++ b/.github/workflows/run-configlet-sync.yml @@ -0,0 +1,10 @@ +name: Run Configlet Sync + +on: + workflow_dispatch: + schedule: + - cron: '0 0 15 * *' + +jobs: + configlet-sync: + uses: exercism/github-actions/.github/workflows/configlet-sync.yml@main diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 25c272ef7..2ee249660 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,9 +1,19 @@ -exclude: 'test/(catch.hpp|tests-main.cpp)' +exclude: | + (?x)^( + (.*/)?test/(catch(_amalgamated)?.[ch]pp|tests-main.cpp)| + .github/CODEOWNERS + )$ repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files - repo: https://github.com/pre-commit/mirrors-clang-format rev: v18.1.2 hooks: - id: clang-format exclude_types: [json] - diff --git a/.vscode/settings.json b/.vscode/settings.json index 216f5a77c..8b678e3fb 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -72,4 +72,4 @@ "cSpell.words": [ "stationprogress" ] -} \ No newline at end of file +} diff --git a/bin/check-hello-world.sh b/bin/check-hello-world.sh index a7e6f75cc..ac5edf7e7 100755 --- a/bin/check-hello-world.sh +++ b/bin/check-hello-world.sh @@ -25,4 +25,4 @@ if cmake --build .; then exit 1 fi -cd "$repo" \ No newline at end of file +cd "$repo" diff --git a/bin/make-stub-files.sh b/bin/make-stub-files.sh index e38ddc880..76eab0b27 100755 --- a/bin/make-stub-files.sh +++ b/bin/make-stub-files.sh @@ -21,10 +21,8 @@ for exercise_dir in "${exercises_dir}"/*; do header="$exercise_name.h" source="$exercise_name.cpp" if ! test -f "$header"; then - printf "#if !defined(${exercise_name^^}_H)\n" >> $header - printf "#define ${exercise_name^^}_H\n" >> $header + printf "#pragma once\n" >> $header printf "\nnamespace $exercise_name {\n\n} // namespace $exercise_name\n" >> $header - printf "\n#endif // ${exercise_name^^}_H" >> $header git add $header fi if ! test -f "$source"; then diff --git a/concepts/auto/links.json b/concepts/auto/links.json index 9c85e3634..87f0bf23d 100644 --- a/concepts/auto/links.json +++ b/concepts/auto/links.json @@ -7,4 +7,4 @@ "url": "https://www.learncpp.com/cpp-tutorial/type-deduction-for-objects-using-the-auto-keyword/", "description": "Learn C++ overview on the auto keyword and its usage" } -] \ No newline at end of file +] diff --git a/concepts/basics/about.md b/concepts/basics/about.md index 1a3ddc396..764b6b3e8 100644 --- a/concepts/basics/about.md +++ b/concepts/basics/about.md @@ -6,7 +6,7 @@ To set off the C++ journey we are starting with variables, function calls, and c Comments come in two flavors: single- and multi-line. Everything that comes after `//` on the same line is ignored by the compiler. -Multi-line comments are also known as C-style comments. +Multi-line comments are also known as C-style comments. They are surrounded by `/*` and `*/`. Anything that comes between these will be ignored as well. @@ -40,7 +40,7 @@ It cannot be stressed enough: avoid undefined behavior at all cost. ## Arithmetic Operations -Arithmetic operators like `*`, `+`, or `-` can be part of an expression like `3 * 2` or `tomatoes + potatoes`. +Arithmetic operators like `*`, `+`, or `-` can be part of an expression like `3 * 2` or `tomatoes + potatoes`. ## Updating Variables @@ -84,7 +84,7 @@ int total_fee(int vips, int adults, int kids) { */ int standard_fee{30}; int kids_discount{15}; - + int kids_total_fee = kids * (standard_fee - kids_discount); int vips_total_fee = vips * vip_fee(standard_fee); int adult_total_fee = adults * standard_fee; diff --git a/concepts/basics/introduction.md b/concepts/basics/introduction.md index 7e6a49ef6..c2512452f 100644 --- a/concepts/basics/introduction.md +++ b/concepts/basics/introduction.md @@ -6,7 +6,7 @@ To set off the C++ journey we are starting with variables, function calls, and c Comments come in two flavors: single- and multi-line. Everything that comes after `//` on the same line is ignored by the compiler. -Multi-line comments are also known as C-style comments. +Multi-line comments are also known as C-style comments. They are surrounded by `/*` and `*/`. Anything that comes between these will be ignored as well. @@ -40,7 +40,7 @@ It cannot be stressed enough: avoid undefined behavior at all cost. ## Arithmetic Operations -Arithmetic operators like `*`, `+`, or `-` can be part of an expression like `3 * 2` or `tomatoes + potatoes`. +Arithmetic operators like `*`, `+`, or `-` can be part of an expression like `3 * 2` or `tomatoes + potatoes`. ## Updating Variables @@ -84,7 +84,7 @@ int total_fee(int vips, int adults, int kids) { */ int standard_fee{30}; int kids_discount{15}; - + int kids_total_fee = kids * (standard_fee - kids_discount); int vips_total_fee = vips * vip_fee(standard_fee); int adult_total_fee = adults * standard_fee; diff --git a/concepts/basics/links.json b/concepts/basics/links.json index ab2f7aa15..690b9bc3d 100644 --- a/concepts/basics/links.json +++ b/concepts/basics/links.json @@ -11,4 +11,4 @@ "url": "https://isocpp.org/faq", "description": "C++ Super-FAQ" } -] \ No newline at end of file +] diff --git a/concepts/booleans/introduction.md b/concepts/booleans/introduction.md index 267063973..ad0ee9e12 100644 --- a/concepts/booleans/introduction.md +++ b/concepts/booleans/introduction.md @@ -35,4 +35,4 @@ If you use a number in a Boolean operation, everything except `0` is treated as !true && 0.0 // => false true + true + false // => 2 ``` -~~~~ \ No newline at end of file +~~~~ diff --git a/concepts/booleans/links.json b/concepts/booleans/links.json index 0df565316..3368e317b 100644 --- a/concepts/booleans/links.json +++ b/concepts/booleans/links.json @@ -3,4 +3,4 @@ "url": "https://en.cppreference.com/w/cpp/language/operator_logical", "description": "C++ reference on Logical operators" } -] \ No newline at end of file +] diff --git a/concepts/classes/about.md b/concepts/classes/about.md index d8c64f19f..bb94b0334 100644 --- a/concepts/classes/about.md +++ b/concepts/classes/about.md @@ -52,7 +52,7 @@ silverhand.cast_spell(); silverhand.name = "Laeral"; // damage is private: -silverhand.damage = 500; +silverhand.damage = 500; // => Compilation error ``` diff --git a/concepts/classes/introduction.md b/concepts/classes/introduction.md index b851e444e..e9a957bc5 100644 --- a/concepts/classes/introduction.md +++ b/concepts/classes/introduction.md @@ -51,7 +51,7 @@ silverhand.cast_spell(); silverhand.name = "Laeral"; // damage is private: -silverhand.damage = 500; +silverhand.damage = 500; // => Compilation error ``` @@ -102,4 +102,4 @@ Conventionally, the `struct` keyword is often used for **data-only structures**. The `class` keyword is preferred for objects that need to ensure certain properties. Such an invariant could be that the `damage` of your `Wizzard` `class` cannot turn negative. The `damage` variable is private and any function that changes the damage would ensure the invariant is preserved. -~~~~ \ No newline at end of file +~~~~ diff --git a/concepts/classes/links.json b/concepts/classes/links.json index 5afd99559..cd994028c 100644 --- a/concepts/classes/links.json +++ b/concepts/classes/links.json @@ -3,4 +3,4 @@ "url": "https://en.cppreference.com/w/cpp/language/classes", "description": "C++ reference on for classes" } -] \ No newline at end of file +] diff --git a/concepts/comparisons/about.md b/concepts/comparisons/about.md index 95803ef9b..ec34ac14f 100644 --- a/concepts/comparisons/about.md +++ b/concepts/comparisons/about.md @@ -27,7 +27,7 @@ Here are some common examples: ```cpp bool eq3 = 2 == 3; // false, integer comparison -bool eq4 = 2.1 != 2.2; // true, float comparison +bool eq4 = 2.1 != 2.2; // true, float comparison bool eq5 = "hello" == "hello"; // true, string comparison ``` diff --git a/concepts/comparisons/introduction.md b/concepts/comparisons/introduction.md index 103cf6b4e..f16a5b0d0 100644 --- a/concepts/comparisons/introduction.md +++ b/concepts/comparisons/introduction.md @@ -27,7 +27,7 @@ Here are some common examples: ```cpp bool eq3 = 2 == 3; // false, integer comparison -bool eq4 = 2.1 != 2.2; // true, float comparison +bool eq4 = 2.1 != 2.2; // true, float comparison bool eq5 = "hello" == "hello"; // true, string comparison ``` diff --git a/concepts/comparisons/links.json b/concepts/comparisons/links.json index 8be8cc9ab..be11e8132 100644 --- a/concepts/comparisons/links.json +++ b/concepts/comparisons/links.json @@ -3,4 +3,4 @@ "url": "https://en.cppreference.com/w/cpp/language/operator_comparison", "description": "C++ reference on comparison operators" } -] \ No newline at end of file +] diff --git a/concepts/enums/about.md b/concepts/enums/about.md index 809f97914..e0f1c4627 100644 --- a/concepts/enums/about.md +++ b/concepts/enums/about.md @@ -46,7 +46,7 @@ enum class WheelMaterial { plastic }; ``` -Although the wheels and the deck can both be made of _plastic_, the two cannot be confused. +Although the wheels and the deck can both be made of _plastic_, the two cannot be confused. They are different _types_: `DeckMaterial` plastic and `WheelMaterial` plastic. Each `enumeration` will have its `enumerators` in its own scope - its own `namespace`. This is the reason they are called `scoped enumerations`. @@ -57,7 +57,7 @@ You might be thinking that with a name like `scoped`, there would also be _`uns `Unscoped enumerations` are becoming less popular because they all share the same global namespace. Because of the sharing, you could not have two `unscoped enumerations` with the same `enumerators` like _plastic_ in the example above. -Also, `unscoped enumerations` implicitly convert to integers. +Also, `unscoped enumerations` implicitly convert to integers. Look at the example below for a surprising result: ```cpp @@ -84,4 +84,4 @@ If you want to convert `scoped enumerations` to integers you can use `static_cas -[magic numbers]: https://en.wikipedia.org/wiki/Magic_number_(programming) \ No newline at end of file +[magic numbers]: https://en.wikipedia.org/wiki/Magic_number_(programming) diff --git a/concepts/enums/introduction.md b/concepts/enums/introduction.md index a9b0f41be..ad4e4e4c9 100644 --- a/concepts/enums/introduction.md +++ b/concepts/enums/introduction.md @@ -46,7 +46,7 @@ enum class WheelMaterial { plastic }; ``` -Although the wheels and the deck can both be made of _plastic_, the two cannot be confused. +Although the wheels and the deck can both be made of _plastic_, the two cannot be confused. They are different _types_: `DeckMaterial` plastic and `WheelMaterial` plastic. Each `enumeration` will have its `enumerators` in its own scope - its own `namespace`. This is the reason they are called `scoped enumerations`. @@ -57,7 +57,7 @@ You might be thinking that with the name `scoped`, there would also be be `unsco `Unscoped enumerations` are becoming less popular because they all share the same global namespace. Because of the sharing, you could not have two `unscoped enumerations` with the same `enumerators` like _plastic_ in the example above. -Also, `unscoped enumerations` implicitly convert to integers. +Also, `unscoped enumerations` implicitly convert to integers. Look at the example below for a surprising result: ```cpp @@ -84,4 +84,4 @@ If you want to convert `scoped enumerations` to integers you can use `static_cas -[magic numbers]: https://en.wikipedia.org/wiki/Magic_number_(programming) \ No newline at end of file +[magic numbers]: https://en.wikipedia.org/wiki/Magic_number_(programming) diff --git a/concepts/enums/links.json b/concepts/enums/links.json index ca711b76f..30bc05dcd 100644 --- a/concepts/enums/links.json +++ b/concepts/enums/links.json @@ -3,4 +3,4 @@ "url": "https://en.cppreference.com/w/cpp/language/enum", "description": "C++ reference on enumerations" } -] \ No newline at end of file +] diff --git a/concepts/functions/links.json b/concepts/functions/links.json index c08cc662b..6d5b65a78 100644 --- a/concepts/functions/links.json +++ b/concepts/functions/links.json @@ -15,4 +15,4 @@ "url": "https://en.cppreference.com/w/cpp/language/default_arguments", "description": "C++ reference on default arguments" } -] \ No newline at end of file +] diff --git a/concepts/headers/about.md b/concepts/headers/about.md index b6a57a709..5983cd3ce 100644 --- a/concepts/headers/about.md +++ b/concepts/headers/about.md @@ -10,7 +10,7 @@ The header file will tell you _what_ a codebase has to offer without going into The most common file extension for header files is `.h`. Some projects use `.hpp` or skip the extension completely. -The definitions are located in a separate `.cpp` file. +The definitions are located in a separate `.cpp` file. To reunite the parts, the source file starts by _including_ the respective header file. If you want to write a library called "quick_math" that offers a function "super_root" that you want to use often, the files would look like this: @@ -18,17 +18,24 @@ If you want to write a library called "quick_math" that offers a function "super ```cpp // A file named quick_math.h #pragma once + namespace quick_math { - double super_root(double x, int n); + +double super_root(double x, int n); + } ``` ```cpp // A file named quick_math.cpp -#include "quick_math.h" #include + +#include "quick_math.h" + double quick_math::super_root(double x, int n) { - while(n) { x = std::sqrt(x), --n;} + while (n) { + x = std::sqrt(x), --n; + } return x; } ``` @@ -51,57 +58,81 @@ One possible layout is to keep all the implementation details in the source file // A file named robot_flower.h #if !defined(ROBOT_FLOWER_H) #define ROBOT_FLOWER_H + #include + namespace robots { - class Flower { - private: - bool needs_water{}; - int size{}; - std::string name{}; - public: - Flower(std::string name, int size = 0); - void give_water(); - std::string get_name(); - int get_size(); - void start_next_day(); - }; -} + +class Flower { + private: + bool needs_water{}; + int size{}; + std::string name{}; + + public: + Flower(std::string name, int size = 0); + void give_water(); + std::string get_name(); + int get_size(); + void start_next_day(); +}; +} // namespace robots #endif ``` ```cpp // A file named robot_flower.cpp #include "robot_flower.h" -robots::Flower::Flower(std::string name, int size) {this->name = "Robotica " + name; this->size = size;} -void robots::Flower::start_next_day() {if (!needs_water) ++size; needs_water = true;} -std::string robots::Flower::get_name() {return name;} -int robots::Flower::get_size() {return size;} + +robots::Flower::Flower(std::string name, int size) { + this->name = "Robotica " + name; + this->size = size; +} + +void robots::Flower::start_next_day() { + if (!needs_water) ++size; + needs_water = true; +} + +std::string robots::Flower::get_name() { return name; } + +int robots::Flower::get_size() { return size; } ``` When the header is used as an API overview, that is where a person would look for information like default values. The `size` parameter's default of the constructor is therefore handled in the header and not in the implementation. The definitions in the source file are prefixed with the namespace `robots` and the class type `Flower`. - + Another layout option is a _header only_ library, that does not have a `.cpp` file at all: ```cpp // A file named robot_flower.h #pragma once + #include + namespace robots { - class Flower { - private: - bool needs_water{}; - int size{}; - std::string name{}; - public: - Flower(std::string name, int size = 0) {this->name = "Robotica " + name; this->size = size;} - void give_water() {needs_water = false;} - std::string get_name() {return name;} - int get_size() {return size;} - void start_next_day() {if (!needs_water) ++size; needs_water = true;} - }; -} + +class Flower { + private: + bool needs_water{}; + int size{}; + std::string name{}; + + public: + Flower(std::string name, int size = 0) { + this->name = "Robotica " + name; + this->size = size; + } + void give_water() { needs_water = false; } + std::string get_name() { return name; } + int get_size() { return size; } + void start_next_day() { + if (!needs_water) ++size; + needs_water = true; + } +}; +} // namespace robots ``` Projects might use combinations of these layouts and there is a lot of discussion as to what might be the best fit for each use case. @@ -129,9 +160,7 @@ int myFunction(int n) { } } -int myOtherFunction(int m) { - return myFunction(m / 2); -} +int myOtherFunction(int m) { return myFunction(m / 2); } ``` When `myFunction` is defined, the compiler does not know about `myOtherFunction` yet. @@ -142,8 +171,8 @@ The compiler assumes that the definition will follow at some later point after t The next example shows how a forward declaration is used for functions. ```cpp -int myFunction(int n); // Forward declaration of myFunction -int myOtherFunction(int m); // Forward declaration of myOtherFunction +int myFunction(int n); // Forward declaration of myFunction +int myOtherFunction(int m); // Forward declaration of myOtherFunction // Definition of myFunction int myFunction(int n) { @@ -155,16 +184,14 @@ int myFunction(int n) { } // Definition of myOtherFunction -int myOtherFunction(int m) { - return myFunction(m / 2); -} +int myOtherFunction(int m) { return myFunction(m / 2); } ``` ## Include Guards via ifndef It does not matter if the same file is included multiple times within a project. Header files should not contain definitions. -The complete project cannot have the same definition more than once. +The complete project cannot have the same definition more than once. This is called the "One definition rule". It will be enforced by the compiler. @@ -178,10 +205,12 @@ The syntax can be seen below with `MY_HEADER_FILE_H` as a variable. ```cpp #ifndef MY_HEADER_FILE_H /* any name uniquely mapped to file name */ #define MY_HEADER_FILE_H + // file content + #endif ``` The problem with `#pragma once` is, that pragmas are not an official part of the C++ language and the implementation differs from compiler to compiler. Many big projects have switched to the simpler pragma method, but a few are still cautious. -~~~~ \ No newline at end of file +~~~~ diff --git a/concepts/headers/introduction.md b/concepts/headers/introduction.md index c8d9c68ff..978b94c63 100644 --- a/concepts/headers/introduction.md +++ b/concepts/headers/introduction.md @@ -10,7 +10,7 @@ The header file will tell you _what_ a codebase has to offer without going into The most common file extension for header files is `.h`. Some projects use `.hpp` or skip the extension completely. -The definitions are located in a separate `.cpp` file. +The definitions are located in a separate `.cpp` file. To reunite the parts, the source file starts by _including_ the respective header file. If you want to write a library called "quick_math" that offers a function "super_root" that you want to use often, the files would look like this: @@ -18,17 +18,24 @@ If you want to write a library called "quick_math" that offers a function "super ```cpp // A file named quick_math.h #pragma once + namespace quick_math { - double super_root(double x, int n); -} + +double super_root(double x, int n); + +} // namespace quick_math ``` ```cpp // A file named quick_math.cpp -#include "quick_math.h" #include + +#include "quick_math.h" + double quick_math::super_root(double x, int n) { - while(n) { x = std::sqrt(x), --n;} + while (n) { + x = std::sqrt(x), --n; + } return x; } ``` @@ -51,57 +58,88 @@ One possible layout is to keep all the implementation details in the source file // A file named robot_flower.h #if !defined(ROBOT_FLOWER_H) #define ROBOT_FLOWER_H + #include + namespace robots { - class Flower { - private: - bool needs_water{}; - int size{}; - std::string name{}; - public: - Flower(std::string name, int size = 0); - void give_water(); - std::string get_name(); - int get_size(); - void start_next_day(); - }; -} + +class Flower { + private: + bool needs_water{}; + int size{}; + std::string name{}; + + public: + Flower(std::string name, int size = 0); + void give_water(); + std::string get_name(); + int get_size(); + void start_next_day(); +}; + +} // namespace robots + #endif ``` ```cpp // A file named robot_flower.cpp #include "robot_flower.h" -robots::Flower::Flower(std::string name, int size) {this->name = "Robotica " + name; this->size = size;} -void robots::Flower::start_next_day() {if (!needs_water) ++size; needs_water = true;} -std::string robots::Flower::get_name() {return name;} -int robots::Flower::get_size() {return size;} + +robots::Flower::Flower(std::string name, int size) { + this->name = "Robotica " + name; + this->size = size; +} + +void robots::Flower::start_next_day() { + if (!needs_water) { + ++size; + } + needs_water = true; +} + +std::string robots::Flower::get_name() { return name; } + +int robots::Flower::get_size() { return size; } ``` When the header is used as an API overview, that is where a person would look for information like default values. The `size` parameter's default of the constructor is therefore handled in the header and not in the implementation. The definitions in the source file are prefixed with the namespace `robots` and the class type `Flower`. - + Another layout option is a _header only_ library, that does not have a `.cpp` file at all: ```cpp // A file named robot_flower.h #pragma once + #include + namespace robots { - class Flower { - private: - bool needs_water{}; - int size{}; - std::string name{}; - public: - Flower(std::string name, int size = 0) {this->name = "Robotica " + name; this->size = size;} - void give_water() {needs_water = false;} - std::string get_name() {return name;} - int get_size() {return size;} - void start_next_day() {if (!needs_water) ++size; needs_water = true;} - }; -} + +class Flower { + private: + bool needs_water{}; + int size{}; + std::string name{}; + + public: + Flower(std::string name, int size = 0) { + this->name = "Robotica " + name; + this->size = size; + } + void give_water() { needs_water = false; } + std::string get_name() { return name; } + int get_size() { return size; } + void start_next_day() { + if (!needs_water) { + ++size; + } + needs_water = true; + } +}; + +} // namespace robots ``` Projects might use combinations of these layouts and there is a lot of discussion as to what might be the best fit for each use case. diff --git a/concepts/headers/links.json b/concepts/headers/links.json index 5dcf350be..fa81042f8 100644 --- a/concepts/headers/links.json +++ b/concepts/headers/links.json @@ -7,4 +7,4 @@ "url": "https://www.learncpp.com/cpp-tutorial/classes-and-header-files/", "description": "More information about classes in header files" } -] \ No newline at end of file +] diff --git a/concepts/if-statements/about.md b/concepts/if-statements/about.md index 0473b4a8d..f2921bd27 100644 --- a/concepts/if-statements/about.md +++ b/concepts/if-statements/about.md @@ -41,4 +41,4 @@ if (int v{2 * num}; v > 10) { // => 14 ``` -> Note: any variables created in the initialization cannot be accesed after the end of the if statement. \ No newline at end of file +> Note: any variables created in the initialization cannot be accesed after the end of the if statement. diff --git a/concepts/if-statements/introduction.md b/concepts/if-statements/introduction.md index 48f930d49..ae4bb9344 100644 --- a/concepts/if-statements/introduction.md +++ b/concepts/if-statements/introduction.md @@ -41,4 +41,4 @@ if (int v{2 * num}; v > 10) { // => 14 ``` -> Note: any variables created in the initialization cannot be accesed after the end of the if statement. \ No newline at end of file +> Note: any variables created in the initialization cannot be accesed after the end of the if statement. diff --git a/concepts/if-statements/links.json b/concepts/if-statements/links.json index 0a9484653..7f0c14f80 100644 --- a/concepts/if-statements/links.json +++ b/concepts/if-statements/links.json @@ -3,4 +3,4 @@ "url": "https://en.cppreference.com/w/cpp/language/if", "description": "C++ reference on if statements" } -] \ No newline at end of file +] diff --git a/concepts/includes/about.md b/concepts/includes/about.md index 93fc9ed00..d9399b1e5 100644 --- a/concepts/includes/about.md +++ b/concepts/includes/about.md @@ -8,7 +8,7 @@ During compilation, the line with the directive is replaced by the content of th Namespaces are kept as they are in the original file after includes. ## The Standard Library - + The standard library offers many common functions, algorithms, and data structures. The standard library uses the `std` namespace. diff --git a/concepts/includes/introduction.md b/concepts/includes/introduction.md index 87cc4f3ca..581ef7cd1 100644 --- a/concepts/includes/introduction.md +++ b/concepts/includes/introduction.md @@ -11,7 +11,7 @@ During compilation, the line with the directive is replaced by the content of th Namespaces are kept as they are in the original file after includes. ## The Standard Library - + The standard library offers many common functions, algorithms, and data structures. The standard library uses the `std` namespace. diff --git a/concepts/includes/links.json b/concepts/includes/links.json index 2887e9531..41b93f13f 100644 --- a/concepts/includes/links.json +++ b/concepts/includes/links.json @@ -3,4 +3,4 @@ "url": "https://en.cppreference.com/w/cpp/preprocessor/include", "description": "C++ reference on Source File Inclusion" } -] \ No newline at end of file +] diff --git a/concepts/literals/links.json b/concepts/literals/links.json index 1b9edf60d..9f98210d0 100644 --- a/concepts/literals/links.json +++ b/concepts/literals/links.json @@ -3,4 +3,4 @@ "url": "https://www.learncpp.com/cpp-tutorial/literals/", "description": "Learn C++ overview on literals" } -] \ No newline at end of file +] diff --git a/concepts/loops/about.md b/concepts/loops/about.md index 10c335d34..b1fcd0f73 100644 --- a/concepts/loops/about.md +++ b/concepts/loops/about.md @@ -63,7 +63,7 @@ for (int i{1}; i < 10; ++i) { } ``` -This loop will sum the numbers from `1` to `9` (including `9`). +This loop will sum the numbers from `1` to `9` (including `9`). ## Break and Continue diff --git a/concepts/loops/introduction.md b/concepts/loops/introduction.md index d6793636f..521154ee2 100644 --- a/concepts/loops/introduction.md +++ b/concepts/loops/introduction.md @@ -63,7 +63,7 @@ for (int i{1}; i < 10; ++i) { } ``` -This loop will sum the numbers from `1` to `9` (including `9`). +This loop will sum the numbers from `1` to `9` (including `9`). ## Break and Continue diff --git a/concepts/loops/links.json b/concepts/loops/links.json index c814151ca..458f3a2d1 100644 --- a/concepts/loops/links.json +++ b/concepts/loops/links.json @@ -7,4 +7,4 @@ "url": "https://en.cppreference.com/w/cpp/language/while", "description": "C++ reference on while loops" } -] \ No newline at end of file +] diff --git a/concepts/namespaces/about.md b/concepts/namespaces/about.md index a2220d0cf..8c281986e 100644 --- a/concepts/namespaces/about.md +++ b/concepts/namespaces/about.md @@ -44,4 +44,4 @@ namespace o = my_other_ns; int also_my_result{m::foo() + o::foo() * m::my_inner_ns::baz()}; ``` -~~~~ \ No newline at end of file +~~~~ diff --git a/concepts/namespaces/links.json b/concepts/namespaces/links.json index 06397a0ec..9cb677f95 100644 --- a/concepts/namespaces/links.json +++ b/concepts/namespaces/links.json @@ -3,4 +3,4 @@ "url": "https://en.cppreference.com/w/cpp/language/namespace", "description": "C++ reference on namespaces" } -] \ No newline at end of file +] diff --git a/concepts/numbers/.meta/config.json b/concepts/numbers/.meta/config.json index 6c515a485..afae10271 100644 --- a/concepts/numbers/.meta/config.json +++ b/concepts/numbers/.meta/config.json @@ -6,4 +6,4 @@ "contributors": [ "tesarect" ] -} \ No newline at end of file +} diff --git a/concepts/numbers/about.md b/concepts/numbers/about.md index c0b79e0d6..223f35eb9 100644 --- a/concepts/numbers/about.md +++ b/concepts/numbers/about.md @@ -4,7 +4,7 @@ Integers are whole numbers like `0`, `691`, or `-2`. Floating point numbers are numbers with a decimal point like `6.02214076`, `0.1`, or `-1.616`. ## Integers -The following example shows the declaration and initialization of four different variables +The following example shows the declaration and initialization of four different variables ```cpp int m_morales{9241}; // base 10: 0-9 @@ -29,7 +29,7 @@ You can use an apostrophe to separate digits for easier readability. ## Floating-Point Numbers -The floating-point literals come in two flavors. +The floating-point literals come in two flavors. In addition to the intuitive `0.0024` it is possible to use its scientific notation `2.4e-3`. The most common floating-point type is `double`. @@ -66,9 +66,9 @@ These operators modify the current value of a variable by performing an operatio // we start with 0 people int people{}; // we need 0 eggs -int eggs{}; +int eggs{}; // two people joined: -people += 2; +people += 2; // people is now 2 // let's add 3 eggs per person eggs += 3 * people; diff --git a/concepts/numbers/introduction.md b/concepts/numbers/introduction.md index be17bde75..30c7fe2e5 100644 --- a/concepts/numbers/introduction.md +++ b/concepts/numbers/introduction.md @@ -4,7 +4,7 @@ Integers are whole numbers like `0`, `691`, or `-2`. Floating point numbers are numbers with a decimal point like `6.02214076`, `0.1`, or `-1.616`. ## Integers -The following example shows the declaration and initialization of four different variables +The following example shows the declaration and initialization of four different variables ```cpp int m_morales{9241}; // base 10: 0-9 @@ -29,7 +29,7 @@ You can use an apostrophe to separate digits for easier readability. ## Floating-Point Numbers -The floating-point literals come in two flavors. +The floating-point literals come in two flavors. In addition to the intuitive `0.0024` it is possible to use its scientific notation `2.4e-3`. The most common floating-point type is `double`. @@ -66,9 +66,9 @@ These operators modify the current value of a variable by performing an operatio // we start with 0 people int people{}; // we need 0 eggs -int eggs{}; +int eggs{}; // two people joined: -people += 2; +people += 2; // people is now 2 // let's add 3 eggs per person eggs += 3 * people; diff --git a/concepts/numbers/links.json b/concepts/numbers/links.json index f11210b04..894269e31 100644 --- a/concepts/numbers/links.json +++ b/concepts/numbers/links.json @@ -11,4 +11,4 @@ "url": "https://en.wikipedia.org/wiki/Double-precision_floating-point_format", "description": "Explanation on the floating point format" } - ] \ No newline at end of file + ] diff --git a/concepts/pointers/about.md b/concepts/pointers/about.md index d52302895..c5348a211 100644 --- a/concepts/pointers/about.md +++ b/concepts/pointers/about.md @@ -36,7 +36,7 @@ Dereferencing a pointer is done using the _indirection operator_ (`*`) operator. ```cpp std::string opponent{"Solomon Lane"}; // 'ethan' points to the address of the string opponent -std::string* ethan{&opponent}; +std::string* ethan{&opponent}; // Instead of ethan's, the opponent's name address is given to the passPort std::string passportName{*ethan}; ``` @@ -54,7 +54,7 @@ int gateCode[] = {462, 753, 218, 611, 977}; // 'ptr' points to the first element of 'gateCode' int* ptr{&gateCode[0]}; // Accesses the third Stargate address through pointer arithmetic -int dialedAddress{*(ptr + 2)}; +int dialedAddress{*(ptr + 2)}; // Chevron encoded! Dialing Stargate address: openStarGate(dialedAddress); ``` @@ -63,6 +63,8 @@ openStarGate(dialedAddress); Pointer arithmetic in C++ can easily lead to __undefined behavior__ if not handled carefully. Undefined behavior can manifest in unexpected program outcomes, crashes, or even security vulnerabilities. One infamous example of the consequences of undefined behavior occurred in the [explosion of the Ariane 5 rocket][ariane-flight-v88] in 1996, where a software exception caused by the conversion of a 64-bit floating-point number to a 16-bit signed integer led to a catastrophic failure. + +[ariane-flight-v88]: https://en.wikipedia.org/wiki/Ariane_flight_V88 ~~~~ ## Accessing member variables @@ -89,7 +91,7 @@ dianaPrince->superpower = "Lasso of Truth"; std::cout << "Wonder Woman, possesses the mighty " << dianaPrince->superpower; // Memory cleanup: -delete dianaPrince; +delete dianaPrince; ``` ## Pointers vs. references @@ -119,7 +121,7 @@ darkMarkBearer = new std::string{"Bellatrix Lestrange"}; // She has been defeated delete darkMarkBearer; // Reset pointer to null, symbolizing there is no more darkMarkBearer at the moment -darkMarkBearer = nullptr; +darkMarkBearer = nullptr; ``` A pointer should either hold the address of a valid object, or be set to `nullptr`. @@ -131,5 +133,4 @@ It is your responsibility to detect these cases and ensure those pointers are su In older code, you might encounter two alternatives to `nullptr`. Firstly, the literal `0` is specifically interpreted as a null value for pointers, though it's the only scenario where an integral literal can be assigned to a pointer. Secondly, the `preprocessor macro` `NULL`, inherited from C and defined in the `` header, is another representation of a null pointer, though its usage is less common in modern C++ code. -[ariane-flight-v88]: https://en.wikipedia.org/wiki/Ariane_flight_V88 ~~~~ diff --git a/concepts/pointers/introduction.md b/concepts/pointers/introduction.md index 3f64ba0f0..6db1296fc 100644 --- a/concepts/pointers/introduction.md +++ b/concepts/pointers/introduction.md @@ -36,7 +36,7 @@ Dereferencing a pointer is done using the _indirection operator_ (`*`) operator. ```cpp std::string opponent{"Solomon Lane"}; // 'ethan' points to the address of the string opponent -std::string* ethan{&opponent}; +std::string* ethan{&opponent}; // Instead of ethan's, the opponent's name address is given to the passPort std::string passportName{*ethan}; ``` @@ -54,7 +54,7 @@ int gateCode[] = {462, 753, 218, 611, 977}; // 'ptr' points to the first element of 'gateCode' int* ptr{&gateCode[0]}; // Accesses the third Stargate address through pointer arithmetic -int dialedAddress{*(ptr + 2)}; +int dialedAddress{*(ptr + 2)}; // Chevron encoded! Dialing Stargate address: openStarGate(dialedAddress); ``` @@ -63,6 +63,8 @@ openStarGate(dialedAddress); Pointer arithmetic in C++ can easily lead to __undefined behavior__ if not handled carefully. Undefined behavior can manifest in unexpected program outcomes, crashes, or even security vulnerabilities. One infamous example of the consequences of undefined behavior occurred in the [explosion of the Ariane 5 rocket][ariane-flight-v88] in 1996, where a software exception caused by the conversion of a 64-bit floating-point number to a 16-bit signed integer led to a catastrophic failure. + +[ariane-flight-v88]: https://en.wikipedia.org/wiki/Ariane_flight_V88 ~~~~ ## Accessing member variables @@ -86,7 +88,7 @@ dianaPrince->superpower = "Lasso of Truth"; // Using the -> operator to access member variable superpower: std::cout << "Wonder Woman, possesses the mighty " << dianaPrince->superpower; // Memory cleanup: -delete dianaPrince; +delete dianaPrince; ``` ## Pointers vs. references diff --git a/concepts/references/about.md b/concepts/references/about.md index 969025e09..86bafd3d8 100644 --- a/concepts/references/about.md +++ b/concepts/references/about.md @@ -52,8 +52,8 @@ int& future_budget; ## `void` -With the power of `references` you might not need to return a value from a function at all. -`void` is used as a return type in this scenario. +With the power of `references` you might not need to return a value from a function at all. +`void` is used as a return type in this scenario. ```cpp void increase_power(int& level) { @@ -65,4 +65,4 @@ increase_power(goku); // It's over 9000! ``` -[Reseating]: https://stackoverflow.com/questions/728233/why-are-references-not-reseatable-in-c \ No newline at end of file +[Reseating]: https://stackoverflow.com/questions/728233/why-are-references-not-reseatable-in-c diff --git a/concepts/references/introduction.md b/concepts/references/introduction.md index 9ab3909a9..b769dc5f4 100644 --- a/concepts/references/introduction.md +++ b/concepts/references/introduction.md @@ -52,8 +52,8 @@ int& future_budget; ## `void` -With the power of `references` you might not need to return a value from a function at all. -`void` is used as a return type in this scenario. +With the power of `references` you might not need to return a value from a function at all. +`void` is used as a return type in this scenario. ```cpp void increase_power(int& level) { @@ -63,4 +63,4 @@ int goku{8700}; increase_power(goku); // goku's power level? // It's over 9000! -``` \ No newline at end of file +``` diff --git a/concepts/references/links.json b/concepts/references/links.json index b5eca2e1f..2d90ebcd3 100644 --- a/concepts/references/links.json +++ b/concepts/references/links.json @@ -3,4 +3,4 @@ "url": "https://en.cppreference.com/w/cpp/language/reference", "description": "C++ reference on references" } -] \ No newline at end of file +] diff --git a/concepts/smart-pointers/about.md b/concepts/smart-pointers/about.md index ad66e0a3b..c74c0538a 100644 --- a/concepts/smart-pointers/about.md +++ b/concepts/smart-pointers/about.md @@ -6,7 +6,7 @@ They act as wrappers around raw pointers, adding additional functionality such a ## General Syntax Smart pointers are typically implemented as class templates in the C++ standard library. -The two most commonly used smart pointers are `std::unique_ptr` and `std::shared_ptr`. +The two most commonly used smart pointers are `std::unique_ptr` and `std::shared_ptr`. ## Unique Pointers @@ -83,7 +83,7 @@ auto your_flatmates_boyfriends_account = your_flatmates_account; ## `std::weak_ptr` and Cyclic Ownership -`std::weak_ptr` was designed to address the issue of cyclic ownership, also known as circular references, that can occur when using `std::shared_ptr`. +`std::weak_ptr` was designed to address the issue of cyclic ownership, also known as circular references, that can occur when using `std::shared_ptr`. In a cyclic ownership scenario, two or more `std::shared_ptr` objects are referencing each other, creating a cycle where none of the objects can be deleted because they have strong references to each other, leading to memory leaks. diff --git a/concepts/smart-pointers/introduction.md b/concepts/smart-pointers/introduction.md index 61c60f694..dd84b7882 100644 --- a/concepts/smart-pointers/introduction.md +++ b/concepts/smart-pointers/introduction.md @@ -6,7 +6,7 @@ They act as wrappers around raw pointers, adding additional functionality such a ## General Syntax Smart pointers are typically implemented as class templates in the C++ standard library. -The two most commonly used smart pointers are `std::unique_ptr` and `std::shared_ptr`. +The two most commonly used smart pointers are `std::unique_ptr` and `std::shared_ptr`. ## Unique Pointers @@ -82,7 +82,7 @@ auto your_flatmates_boyfriends_account = your_flatmates_account; ``` Weak pointers are useful in scenarios where cyclic references need to be broken to prevent memory leaks. -`std::weak_ptr` was designed to address the issue of cyclic ownership, also known as circular references, that can occur when using `std::shared_ptr`. +`std::weak_ptr` was designed to address the issue of cyclic ownership, also known as circular references, that can occur when using `std::shared_ptr`. In a cyclic ownership scenario, two or more `std::shared_ptr` objects are referencing each other, creating a cycle where none of the objects can be deleted because they have strong references to each other, leading to memory leaks. `std::weak_ptr` provides a solution to this problem by allowing weak references to shared objects without contributing to their reference count. This means that it can observe and access the shared object but doesn't prevent it from being deleted. diff --git a/concepts/smart-pointers/links.json b/concepts/smart-pointers/links.json index ebcb824f9..da71e152a 100644 --- a/concepts/smart-pointers/links.json +++ b/concepts/smart-pointers/links.json @@ -11,4 +11,4 @@ "url": "https://en.cppreference.com/w/cpp/memory/weak_ptr", "description": "C++ reference on std::weak_ptr" } -] \ No newline at end of file +] diff --git a/concepts/strings/about.md b/concepts/strings/about.md index c0aabb04d..1d5d48422 100644 --- a/concepts/strings/about.md +++ b/concepts/strings/about.md @@ -1,6 +1,6 @@ # About -A `string` in C++ is a mutable object that represents text as a sequence of characters (letters, digits, punctuation, etc.). +A `string` in C++ is a mutable object that represents text as a sequence of characters (letters, digits, punctuation, etc.). Strings are manipulated by calling the string's methods. ## Strings Library @@ -32,7 +32,7 @@ Later in the syllabus, you will learn more about member functions and the connec ```cpp std::string qualification{"awesome"}; // 1st argument: from the index to the end of the string: -std::string who_is_awesome = qualification.substr(5); +std::string who_is_awesome = qualification.substr(5); // => "me" // 2nd optional argument for the length: diff --git a/concepts/strings/introduction.md b/concepts/strings/introduction.md index 8d4aa19ad..171e651a4 100644 --- a/concepts/strings/introduction.md +++ b/concepts/strings/introduction.md @@ -1,6 +1,6 @@ # Introduction -A `string` in C++ is a mutable object that represents text as a sequence of characters (letters, digits, punctuation, etc.). +A `string` in C++ is a mutable object that represents text as a sequence of characters (letters, digits, punctuation, etc.). Strings are manipulated by calling the string's methods. ## Strings Library @@ -33,7 +33,7 @@ Later in the syllabus, you will learn more about member functions and the connec ```cpp std::string qualification{"awesome"}; // 1st argument: from the index to the end of the string: -std::string who_is_awesome = qualification.substr(5); +std::string who_is_awesome = qualification.substr(5); // => "me" // 2nd optional argument for the length: diff --git a/concepts/strings/links.json b/concepts/strings/links.json index 4715085de..5ba25e76f 100644 --- a/concepts/strings/links.json +++ b/concepts/strings/links.json @@ -3,4 +3,4 @@ "url": "https://en.cppreference.com/w/cpp/string/basic_string", "description": "C++ reference on strings" } -] \ No newline at end of file +] diff --git a/concepts/switch/about.md b/concepts/switch/about.md index 3a955a5b0..500c10176 100644 --- a/concepts/switch/about.md +++ b/concepts/switch/about.md @@ -67,4 +67,4 @@ Many languages can do switches based on boolean expression or even regular expre You can think of the C++ version is an extended goto/switch construct. Only the switch statement can jump to a label. Afterwards all other labels are ignored and you have to use the `break` statement to break out of the code block. -~~~~ \ No newline at end of file +~~~~ diff --git a/concepts/switch/links.json b/concepts/switch/links.json index d9d1a3335..477189236 100644 --- a/concepts/switch/links.json +++ b/concepts/switch/links.json @@ -2,9 +2,9 @@ { "url": "https://en.cppreference.com/w/cpp/language/switch", "description": "C++ reference on switch statements" - }, + }, { "url": "https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-break", "description": "CppCoreGuidelines' hints on switch statements" } -] \ No newline at end of file +] diff --git a/concepts/vector-arrays/about.md b/concepts/vector-arrays/about.md index 406ac5f73..09bab8b60 100644 --- a/concepts/vector-arrays/about.md +++ b/concepts/vector-arrays/about.md @@ -12,10 +12,10 @@ Arrays also need a size. Look at these examples to see the two container types' initializations: ```cpp -#include +#include #include -// std::array variable_name {list of elements} +// std::array variable_name {list of elements} std::array indie_rock {"yeah", "yeah", "yeah"}; // indie_rock contains the elements "yeah" three times ``` @@ -24,10 +24,10 @@ Vectors usually need more space, as they allocate memory for further growth. You do not need to specify a size: ```cpp -#include +#include -// std::vector variable_name {list of elements} -std::vector countdown {3, 2, 1}; +// std::vector variable_name {list of elements} +std::vector countdown {3, 2, 1}; // my_vector contains the elements 3, 2 and 1 ``` @@ -46,7 +46,7 @@ countdown.at(2); // => 1 countdown[1] = 4; // countdown now contains 3, 4 and 1 -indie_rock.back() = "yeahs"; +indie_rock.back() = "yeahs"; // indie_rock is now "yeah", "yeah", "yeahs" ``` @@ -55,12 +55,12 @@ indie_rock.back() = "yeahs"; ### Vector modifiers -As a `vector` is not fixed in size, it is possible to add or remove elements. +As a `vector` is not fixed in size, it is possible to add or remove elements. Two common functions for that purpose are `emplace_back` and `pop_back`. ```cpp std::vector witches {"Holly", "Alyssa", "Shannen"}; -witches.pop_back(); +witches.pop_back(); // Shannen is no longer with the witches witches.emplace_back("Rose"); // Rose has joined the team diff --git a/concepts/vector-arrays/introduction.md b/concepts/vector-arrays/introduction.md index ca28b607c..7e96cbb39 100644 --- a/concepts/vector-arrays/introduction.md +++ b/concepts/vector-arrays/introduction.md @@ -15,7 +15,7 @@ Look at these examples to see the two container types' initializations: #include #include -// std::array variable_name {list of elements} +// std::array variable_name {list of elements} std::array indie_rock {"yeah", "yeah", "yeah"}; // indie_rock contains the elements "yeah" three times ``` @@ -46,7 +46,7 @@ countdown.at(2); // => 1 countdown[1] = 4; // countdown now contains 3, 4 and 1 -indie_rock.back() = "yeahs"; +indie_rock.back() = "yeahs"; // indie_rock is now "yeah", "yeah", "yeahs" ``` @@ -55,12 +55,12 @@ indie_rock.back() = "yeahs"; ### Vector modifiers -As a `vector` is not fixed in size, it is possible to add or remove elements. +As a `vector` is not fixed in size, it is possible to add or remove elements. Two common functions for that purpose are `emplace_back` and `pop_back`. ```cpp std::vector witches {"Holly", "Alyssa", "Shannen"}; -witches.pop_back(); +witches.pop_back(); // Shannen is no longer with the witches witches.emplace_back("Rose"); // Rose has joined the team diff --git a/concepts/vector-arrays/links.json b/concepts/vector-arrays/links.json index 781f24945..2699bfe12 100644 --- a/concepts/vector-arrays/links.json +++ b/concepts/vector-arrays/links.json @@ -7,4 +7,4 @@ "url": "https://en.cppreference.com/w/cpp/container/vector", "description": "C++ reference on vectors" } -] \ No newline at end of file +] diff --git a/config.json b/config.json index af802c182..5e5b97153 100644 --- a/config.json +++ b/config.json @@ -1131,13 +1131,22 @@ "prerequisites": [], "difficulty": 3 }, + { + "slug": "flower-field", + "name": "Flower Field", + "uuid": "d17d040b-b214-4079-ad3e-b518f776aeeb", + "practices": [], + "prerequisites": [], + "difficulty": 5 + }, { "slug": "minesweeper", "name": "Minesweeper", "uuid": "3753a72a-78b7-429f-b79a-f68d55a00387", "practices": [], "prerequisites": [], - "difficulty": 5 + "difficulty": 5, + "status": "deprecated" }, { "slug": "sublist", @@ -1244,6 +1253,48 @@ "strings" ], "difficulty": 4 + }, + { + "slug": "affine-cipher", + "name": "Affine Cipher", + "uuid": "61374c16-0a99-4616-9244-a38919eafbe1", + "practices": [ + "math", + "exceptions" + ], + "prerequisites": [ + "functions", + "comparisons", + "loops", + "booleans" + ], + "difficulty": 6 + }, + { + "slug": "alphametics", + "name": "Alphametics", + "uuid": "0c69f8bd-c99a-4cb2-b113-82deaf0915ee", + "practices": [ + "auto", + "literals" + ], + "prerequisites": [ + "includes", + "namespaces", + "if-statements", + "booleans", + "headers", + "comparisons" + ], + "difficulty": 6 + }, + { + "slug": "twelve-days", + "name": "Twelve Days", + "uuid": "0daec3e8-a0d1-49e8-9de5-0ad73f9c3243", + "practices": [], + "prerequisites": [], + "difficulty": 3 } ], "foregone": [ diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index 58b44668d..aea73633f 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -103,4 +103,4 @@ MacOS users can install GCC with [Homebrew](http://brew.sh/) via [boost-website]: https://www.boost.org/ -[sourceforge-boost-binaries]: https://sourceforge.net/projects/boost/files/boost-binaries/ \ No newline at end of file +[sourceforge-boost-binaries]: https://sourceforge.net/projects/boost/files/boost-binaries/ diff --git a/docs/TESTS.md b/docs/TESTS.md index 829b516ef..5b659c291 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -74,8 +74,8 @@ $ make This example shows creating empty files for the implementation before running CMake. -Simply type `make` in the build directory to compile the tests. This should -generate compile time errors. Once the errors are fixed, `make` will build and +Simply type `make` in the build directory to compile the tests. This should +generate compile time errors. Once the errors are fixed, `make` will build and run the tests. ### Windows with Visual Studio @@ -98,7 +98,7 @@ $ cmake -G Xcode .. ``` This example generates the XCode files so that you can open the project in XCode. -With the project opened in XCode you may need to add another target. +With the project opened in XCode you may need to add another target. For a new target go to File -> New -> Target from the menu, _OS X \ Application \ Command Line Tool_ -> Next _C++_ as the language and provide a target name. Run the code using the target. If your terminal throws an `Xcode x.x not supported` error, it is highly likely that Xcode is not installed on your machine or that your version is out of date. diff --git a/exercises/concept/doctor-data/.docs/instructions.md b/exercises/concept/doctor-data/.docs/instructions.md index 309546279..52ae5f14c 100644 --- a/exercises/concept/doctor-data/.docs/instructions.md +++ b/exercises/concept/doctor-data/.docs/instructions.md @@ -38,7 +38,7 @@ You even got one of the enumerations: `BetaHydri`. Prepare the source and header files with your discovered information. You need two namespaces: `heaven` and `star_map`. The `heaven` namespace has a class `Vessel`, which can be called with two or three arguments. -The `System` enum is to be placed in the `star_map` namespace and has an `EpsilonEridani` enumeration. +The `System` enum is to be placed in the `star_map` namespace and has an `BetaHydri` enumeration. Keep an eye out for other enumerations, so that you can constantly update the `System` enum. ## 2. Find more details @@ -105,4 +105,4 @@ You see two functions, that are not members of the `Vessel` class, as they are n Implement the last missing functions from the recovered lines above. -[van-neumann-probes]: https://en.wikipedia.org/wiki/Self-replicating_spacecraft \ No newline at end of file +[van-neumann-probes]: https://en.wikipedia.org/wiki/Self-replicating_spacecraft diff --git a/exercises/concept/doctor-data/.docs/introduction.md b/exercises/concept/doctor-data/.docs/introduction.md index c8d9c68ff..e7db48e12 100644 --- a/exercises/concept/doctor-data/.docs/introduction.md +++ b/exercises/concept/doctor-data/.docs/introduction.md @@ -10,7 +10,7 @@ The header file will tell you _what_ a codebase has to offer without going into The most common file extension for header files is `.h`. Some projects use `.hpp` or skip the extension completely. -The definitions are located in a separate `.cpp` file. +The definitions are located in a separate `.cpp` file. To reunite the parts, the source file starts by _including_ the respective header file. If you want to write a library called "quick_math" that offers a function "super_root" that you want to use often, the files would look like this: @@ -81,7 +81,7 @@ int robots::Flower::get_size() {return size;} When the header is used as an API overview, that is where a person would look for information like default values. The `size` parameter's default of the constructor is therefore handled in the header and not in the implementation. The definitions in the source file are prefixed with the namespace `robots` and the class type `Flower`. - + Another layout option is a _header only_ library, that does not have a `.cpp` file at all: ```cpp diff --git a/exercises/concept/doctor-data/.docs/introduction.md.tpl b/exercises/concept/doctor-data/.docs/introduction.md.tpl index 70899ec3d..4bc156890 100644 --- a/exercises/concept/doctor-data/.docs/introduction.md.tpl +++ b/exercises/concept/doctor-data/.docs/introduction.md.tpl @@ -1,3 +1,3 @@ # Introduction -%{concept:headers} \ No newline at end of file +%{concept:headers} diff --git a/exercises/concept/doctor-data/doctor_data.cpp b/exercises/concept/doctor-data/doctor_data.cpp index 0771dfcfe..7e069e14c 100644 --- a/exercises/concept/doctor-data/doctor_data.cpp +++ b/exercises/concept/doctor-data/doctor_data.cpp @@ -1,4 +1,4 @@ // ERROR: FILE CORRUPTED. Please supply valid C++ Code. hp4,ölacöiömthö%Äsmaö%Äsubö(311040ö%Äspaö%Äaddö(311040ö%Ädacöiömthö%Äcountö.hpt,hp4ö%Äxctöhd2ö%Ädacöiöma1 -hp2,öjmpö. \ No newline at end of file +hp2,öjmpö. diff --git a/exercises/concept/doctor-data/test/catch.hpp b/exercises/concept/doctor-data/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/doctor-data/test/catch.hpp +++ b/exercises/concept/doctor-data/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/election-day/.docs/hints.md b/exercises/concept/election-day/.docs/hints.md index 62dc5315e..b21eed65f 100644 --- a/exercises/concept/election-day/.docs/hints.md +++ b/exercises/concept/election-day/.docs/hints.md @@ -16,10 +16,10 @@ - You need to create a function with a `reference` to an `ElectionResult`, in other words, a `ElectionResult&`. - - Although you are receiving a `reference` to an `ElectionResult`, you can change its member variables with the dot `.` notation, as if it wasn't a `reference`! -## 3. Vote counting and Presidency +## 3. Vote counting and Presidency - You can iterate a reference to a `vector` like a normal vector with a loop. - You can get the size of a vector with `myvector.size()`. -[learncpp-references]: https://www.learncpp.com/cpp-tutorial/lvalue-references/ \ No newline at end of file +[learncpp-references]: https://www.learncpp.com/cpp-tutorial/lvalue-references/ diff --git a/exercises/concept/election-day/.docs/instructions.md b/exercises/concept/election-day/.docs/instructions.md index 14a71a670..9a4a29946 100644 --- a/exercises/concept/election-day/.docs/instructions.md +++ b/exercises/concept/election-day/.docs/instructions.md @@ -22,7 +22,7 @@ struct ElectionResult { }; ``` -As all members in the `struct` are public, you don't need to write a `constructor` to initialize an `ElectionResult` object. +As all members in the `struct` are public, you don't need to write a `constructor` to initialize an `ElectionResult` object. You can use an `initializer list` instead: ```cpp @@ -53,12 +53,12 @@ vote_count(burr); // => 1804 ``` -## 3. Vote counting and Presidency +## 3. Vote counting and Presidency The school handed in their votes and it is now time to check the results for the winner. Create a function `determine_result` that receives a reference to a final count and returns a reference to the `ElectionResult` of the new president. -It should also change the name of the winner by prefixing it with "President". +It should also change the name of the winner by prefixing it with "President". The final count is given in the form of a `reference` to `std::vector`, a vector with `ElectionResults` of all the participating candidates. ```cpp @@ -74,4 +74,4 @@ winner.name; To keep things simple, you can assume the following: - The `vector` has at least one element. -- There will be no ties for first place. \ No newline at end of file +- There will be no ties for first place. diff --git a/exercises/concept/election-day/.docs/introduction.md b/exercises/concept/election-day/.docs/introduction.md index 2bf28e118..c0c5d2e69 100644 --- a/exercises/concept/election-day/.docs/introduction.md +++ b/exercises/concept/election-day/.docs/introduction.md @@ -54,8 +54,8 @@ int& future_budget; ### `void` -With the power of `references` you might not need to return a value from a function at all. -`void` is used as a return type in this scenario. +With the power of `references` you might not need to return a value from a function at all. +`void` is used as a return type in this scenario. ```cpp void increase_power(int& level) { diff --git a/exercises/concept/election-day/.docs/introduction.md.tpl b/exercises/concept/election-day/.docs/introduction.md.tpl index ee0e6b3df..d67949a9d 100644 --- a/exercises/concept/election-day/.docs/introduction.md.tpl +++ b/exercises/concept/election-day/.docs/introduction.md.tpl @@ -1,3 +1,3 @@ # Introduction -%{concept:references} \ No newline at end of file +%{concept:references} diff --git a/exercises/concept/election-day/.meta/design.md b/exercises/concept/election-day/.meta/design.md index 15393c32f..a7cc939ba 100644 --- a/exercises/concept/election-day/.meta/design.md +++ b/exercises/concept/election-day/.meta/design.md @@ -24,4 +24,4 @@ The Concepts this exercise unlocks are: ## Prerequisites - `classes` -- `strings` \ No newline at end of file +- `strings` diff --git a/exercises/concept/election-day/election_day.cpp b/exercises/concept/election-day/election_day.cpp index 01af92991..f568210bf 100644 --- a/exercises/concept/election-day/election_day.cpp +++ b/exercises/concept/election-day/election_day.cpp @@ -28,4 +28,4 @@ struct ElectionResult { // in the form of a `reference` to `std::vector`, a vector with // `ElectionResults` of all the participating candidates. -} // namespace election \ No newline at end of file +} // namespace election diff --git a/exercises/concept/election-day/test/catch.hpp b/exercises/concept/election-day/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/election-day/test/catch.hpp +++ b/exercises/concept/election-day/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/ellens-alien-game/.docs/hints.md b/exercises/concept/ellens-alien-game/.docs/hints.md index 279798ef6..0551e83f1 100644 --- a/exercises/concept/ellens-alien-game/.docs/hints.md +++ b/exercises/concept/ellens-alien-game/.docs/hints.md @@ -19,4 +19,4 @@ ## 5. The `collision_detection` Function -- All `public` member variables can be accessed from outside the class. \ No newline at end of file +- All `public` member variables can be accessed from outside the class. diff --git a/exercises/concept/ellens-alien-game/.docs/instructions.md b/exercises/concept/ellens-alien-game/.docs/instructions.md index 17184177f..0382739ab 100644 --- a/exercises/concept/ellens-alien-game/.docs/instructions.md +++ b/exercises/concept/ellens-alien-game/.docs/instructions.md @@ -36,7 +36,7 @@ Ellen wants to introduce shields at a later point, which would then report `fals ```cpp Alien alien {0, 0}; -alien.get_health(); +alien.get_health(); // => 3 (Initial health value) alien.hit(); // Decrements health by 1 point. @@ -80,7 +80,7 @@ alien.y_coordinate; ## 5. The `collision_detection` Function If the aliens can be hit by something, then they need to be able to detect when such a collision might occur. -Ellen needs to know if two aliens occupy the same coordinates. +Ellen needs to know if two aliens occupy the same coordinates. The `collision_detection()` function takes another alien object as an argument and returns a `bool`. ```cpp @@ -91,4 +91,4 @@ lrrr.collision_detection(ndnd); ndnd.teleport(3, 6); ndnd.collision_detection(lrrr); // => true -``` \ No newline at end of file +``` diff --git a/exercises/concept/ellens-alien-game/.docs/introduction.md b/exercises/concept/ellens-alien-game/.docs/introduction.md index f640213ad..75c25927d 100644 --- a/exercises/concept/ellens-alien-game/.docs/introduction.md +++ b/exercises/concept/ellens-alien-game/.docs/introduction.md @@ -54,7 +54,7 @@ silverhand.cast_spell(); silverhand.name = "Laeral"; // damage is private: -silverhand.damage = 500; +silverhand.damage = 500; // => Compilation error ``` diff --git a/exercises/concept/ellens-alien-game/.docs/introduction.md.tpl b/exercises/concept/ellens-alien-game/.docs/introduction.md.tpl index ccc7c42df..5fd766bb8 100644 --- a/exercises/concept/ellens-alien-game/.docs/introduction.md.tpl +++ b/exercises/concept/ellens-alien-game/.docs/introduction.md.tpl @@ -1,3 +1,3 @@ # Introduction -%{concept:classes} \ No newline at end of file +%{concept:classes} diff --git a/exercises/concept/ellens-alien-game/.meta/design.md b/exercises/concept/ellens-alien-game/.meta/design.md index b6c340710..ea87e7cea 100644 --- a/exercises/concept/ellens-alien-game/.meta/design.md +++ b/exercises/concept/ellens-alien-game/.meta/design.md @@ -41,4 +41,4 @@ These are the concepts/concept exercises the student needs to complete/understan ## Resources -- [Class (and struct) tutorial)](https://www.learncpp.com/cpp-tutorial/classes-and-class-members/) \ No newline at end of file +- [Class (and struct) tutorial)](https://www.learncpp.com/cpp-tutorial/classes-and-class-members/) diff --git a/exercises/concept/ellens-alien-game/.meta/exemplar.cpp b/exercises/concept/ellens-alien-game/.meta/exemplar.cpp index e670bc74a..85331a31c 100644 --- a/exercises/concept/ellens-alien-game/.meta/exemplar.cpp +++ b/exercises/concept/ellens-alien-game/.meta/exemplar.cpp @@ -28,4 +28,4 @@ class Alien { private: int health{3}; }; -} // namespace targets \ No newline at end of file +} // namespace targets diff --git a/exercises/concept/ellens-alien-game/ellens_alien_game.cpp b/exercises/concept/ellens-alien-game/ellens_alien_game.cpp index 98820f043..ccffc7258 100644 --- a/exercises/concept/ellens-alien-game/ellens_alien_game.cpp +++ b/exercises/concept/ellens-alien-game/ellens_alien_game.cpp @@ -1,4 +1,4 @@ namespace targets { // TODO: Insert the code for the alien class here -} // namespace targets \ No newline at end of file +} // namespace targets diff --git a/exercises/concept/ellens-alien-game/test/catch.hpp b/exercises/concept/ellens-alien-game/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/ellens-alien-game/test/catch.hpp +++ b/exercises/concept/ellens-alien-game/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/freelancer-rates/.docs/introduction.md b/exercises/concept/freelancer-rates/.docs/introduction.md index 729d2bcee..83c6c1419 100644 --- a/exercises/concept/freelancer-rates/.docs/introduction.md +++ b/exercises/concept/freelancer-rates/.docs/introduction.md @@ -4,7 +4,7 @@ Integers are whole numbers like `0`, `691`, or `-2`. Floating point numbers are numbers with a decimal point like `6.02214076`, `0.1`, or `-1.616`. ## Integers -The following example shows the declaration and initialization of four different variables +The following example shows the declaration and initialization of four different variables ```cpp int m_morales{9241}; // base 10: 0-9 @@ -29,7 +29,7 @@ You can use an apostrophe to separate digits for easier readability. ## Floating-Point Numbers -The floating-point literals come in two flavors. +The floating-point literals come in two flavors. In addition to the intuitive `0.0024` it is possible to use its scientific notation `2.4e-3`. The most common floating-point type is `double`. @@ -66,9 +66,9 @@ These operators modify the current value of a variable by performing an operatio // we start with 0 people int people{}; // we need 0 eggs -int eggs{}; +int eggs{}; // two people joined: -people += 2; +people += 2; // people is now 2 // let's add 3 eggs per person eggs += 3 * people; diff --git a/exercises/concept/freelancer-rates/.docs/introduction.md.tpl b/exercises/concept/freelancer-rates/.docs/introduction.md.tpl index 376f97b27..ce74d2829 100644 --- a/exercises/concept/freelancer-rates/.docs/introduction.md.tpl +++ b/exercises/concept/freelancer-rates/.docs/introduction.md.tpl @@ -1,3 +1,3 @@ # Introduction -%{concept:numbers} \ No newline at end of file +%{concept:numbers} diff --git a/exercises/concept/freelancer-rates/.meta/exemplar.cpp b/exercises/concept/freelancer-rates/.meta/exemplar.cpp index a1809a36b..82035a4be 100644 --- a/exercises/concept/freelancer-rates/.meta/exemplar.cpp +++ b/exercises/concept/freelancer-rates/.meta/exemplar.cpp @@ -31,4 +31,4 @@ int days_in_budget(int budget, double hourly_rate, double discount) { double discounted_daily{daily_rate(discounted_per_hour)}; return static_cast(budget / discounted_daily); -} \ No newline at end of file +} diff --git a/exercises/concept/freelancer-rates/freelancer_rates.cpp b/exercises/concept/freelancer-rates/freelancer_rates.cpp index cdf8897b5..3f57eb000 100644 --- a/exercises/concept/freelancer-rates/freelancer_rates.cpp +++ b/exercises/concept/freelancer-rates/freelancer_rates.cpp @@ -29,4 +29,4 @@ int days_in_budget(int budget, double hourly_rate, double discount) { // TODO: Implement a function that takes a budget, an hourly rate, and a // discount, and calculates how many complete days of work that covers. return 0; -} \ No newline at end of file +} diff --git a/exercises/concept/freelancer-rates/test/catch.hpp b/exercises/concept/freelancer-rates/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/freelancer-rates/test/catch.hpp +++ b/exercises/concept/freelancer-rates/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/interest-is-interesting/.meta/exemplar.cpp b/exercises/concept/interest-is-interesting/.meta/exemplar.cpp index 00b3e15e6..024d00274 100644 --- a/exercises/concept/interest-is-interesting/.meta/exemplar.cpp +++ b/exercises/concept/interest-is-interesting/.meta/exemplar.cpp @@ -31,4 +31,4 @@ int years_until_desired_balance(double balance, double target_balance) { balance = annual_balance_update(balance); } return years; -} \ No newline at end of file +} diff --git a/exercises/concept/interest-is-interesting/interest_is_interesting.cpp b/exercises/concept/interest-is-interesting/interest_is_interesting.cpp index 7fb33b4c7..a84f04f0d 100644 --- a/exercises/concept/interest-is-interesting/interest_is_interesting.cpp +++ b/exercises/concept/interest-is-interesting/interest_is_interesting.cpp @@ -22,4 +22,4 @@ double annual_balance_update(double balance) { int years_until_desired_balance(double balance, double target_balance) { // TODO: Implement the years_until_desired_balance function return 0; -} \ No newline at end of file +} diff --git a/exercises/concept/interest-is-interesting/test/catch.hpp b/exercises/concept/interest-is-interesting/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/interest-is-interesting/test/catch.hpp +++ b/exercises/concept/interest-is-interesting/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/lasagna-master/.docs/introduction.md.tpl b/exercises/concept/lasagna-master/.docs/introduction.md.tpl index 5c58bbfd4..81f4307de 100644 --- a/exercises/concept/lasagna-master/.docs/introduction.md.tpl +++ b/exercises/concept/lasagna-master/.docs/introduction.md.tpl @@ -1,3 +1,3 @@ # Introduction -%{concept:functions} \ No newline at end of file +%{concept:functions} diff --git a/exercises/concept/lasagna-master/.meta/design.md b/exercises/concept/lasagna-master/.meta/design.md index 5d9fbcb72..8368b8459 100644 --- a/exercises/concept/lasagna-master/.meta/design.md +++ b/exercises/concept/lasagna-master/.meta/design.md @@ -41,4 +41,4 @@ The following concepts are needed to solve the exercise: The story was inspired by the [Lasagna Master Exercise in the Javascipt track][javascript-lasagna-master]. Some tasks needed to be changed though to achieve an exercise that fits the C++ learning objectives. -[javascript-lasagna-master]: https://github.com/exercism/javascript/blob/main/exercises/concept/lasagna-master/.docs/instructions.md \ No newline at end of file +[javascript-lasagna-master]: https://github.com/exercism/javascript/blob/main/exercises/concept/lasagna-master/.docs/instructions.md diff --git a/exercises/concept/lasagna-master/test/catch.hpp b/exercises/concept/lasagna-master/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/lasagna-master/test/catch.hpp +++ b/exercises/concept/lasagna-master/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/lasagna/.docs/introduction.md.tpl b/exercises/concept/lasagna/.docs/introduction.md.tpl index 5f0e01404..cd2cef4ed 100644 --- a/exercises/concept/lasagna/.docs/introduction.md.tpl +++ b/exercises/concept/lasagna/.docs/introduction.md.tpl @@ -1,3 +1,3 @@ # Introduction -%{concept:basics} \ No newline at end of file +%{concept:basics} diff --git a/exercises/concept/lasagna/.meta/exemplar.cpp b/exercises/concept/lasagna/.meta/exemplar.cpp index 54e612475..ffbfc6635 100644 --- a/exercises/concept/lasagna/.meta/exemplar.cpp +++ b/exercises/concept/lasagna/.meta/exemplar.cpp @@ -21,4 +21,4 @@ int preparationTime(int numberOfLayers) { // far. int elapsedTime(int numberOfLayers, int actualMinutesInOven) { return preparationTime(numberOfLayers) + actualMinutesInOven; -} \ No newline at end of file +} diff --git a/exercises/concept/lasagna/test/catch.hpp b/exercises/concept/lasagna/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/lasagna/test/catch.hpp +++ b/exercises/concept/lasagna/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/last-will/.docs/introduction.md b/exercises/concept/last-will/.docs/introduction.md index cb69db98d..69218dcfb 100644 --- a/exercises/concept/last-will/.docs/introduction.md +++ b/exercises/concept/last-will/.docs/introduction.md @@ -2,7 +2,7 @@ ## Namespaces -An important method for code organization are namespaces. +An important method for code organization is the use of namespaces. Two functions might have a naming collision, which can be resolved by putting them in different namespaces. Namespaces can be nested, which might help to structure big code bases. Access to the namespaces is done via the scope-resolution operator `::`. diff --git a/exercises/concept/last-will/.docs/introduction.md.tpl b/exercises/concept/last-will/.docs/introduction.md.tpl index 10f577e26..58e43378d 100644 --- a/exercises/concept/last-will/.docs/introduction.md.tpl +++ b/exercises/concept/last-will/.docs/introduction.md.tpl @@ -1,3 +1,3 @@ # Introduction -%{concept:namespaces} \ No newline at end of file +%{concept:namespaces} diff --git a/exercises/concept/last-will/.meta/exemplar.cpp b/exercises/concept/last-will/.meta/exemplar.cpp index 8031c0089..ef8f15ae5 100644 --- a/exercises/concept/last-will/.meta/exemplar.cpp +++ b/exercises/concept/last-will/.meta/exemplar.cpp @@ -57,4 +57,4 @@ int assemble_code() { (zhang::blue::code_fragment() + garcia::blue::code_fragment() + khan::blue::code_fragment()); } -} // namespace estate_executor \ No newline at end of file +} // namespace estate_executor diff --git a/exercises/concept/last-will/last_will.cpp b/exercises/concept/last-will/last_will.cpp index d1321286d..3cb9fff85 100644 --- a/exercises/concept/last-will/last_will.cpp +++ b/exercises/concept/last-will/last_will.cpp @@ -42,4 +42,4 @@ int code_fragment() { return 923; } } // namespace blue } // namespace garcia -// Enter your code below \ No newline at end of file +// Enter your code below diff --git a/exercises/concept/last-will/test/catch.hpp b/exercises/concept/last-will/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/last-will/test/catch.hpp +++ b/exercises/concept/last-will/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/log-levels/.docs/introduction.md.tpl b/exercises/concept/log-levels/.docs/introduction.md.tpl index bd4f8dd2b..a0da96918 100644 --- a/exercises/concept/log-levels/.docs/introduction.md.tpl +++ b/exercises/concept/log-levels/.docs/introduction.md.tpl @@ -2,4 +2,4 @@ %{concept:includes} -%{concept:strings} \ No newline at end of file +%{concept:strings} diff --git a/exercises/concept/log-levels/test/catch.hpp b/exercises/concept/log-levels/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/log-levels/test/catch.hpp +++ b/exercises/concept/log-levels/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/making-the-grade/.meta/exemplar.cpp b/exercises/concept/making-the-grade/.meta/exemplar.cpp index 797dc9578..7c5cefee0 100644 --- a/exercises/concept/making-the-grade/.meta/exemplar.cpp +++ b/exercises/concept/making-the-grade/.meta/exemplar.cpp @@ -52,4 +52,4 @@ std::string perfect_score(std::vector student_scores, } return ""; -} \ No newline at end of file +} diff --git a/exercises/concept/making-the-grade/test/catch.hpp b/exercises/concept/making-the-grade/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/making-the-grade/test/catch.hpp +++ b/exercises/concept/making-the-grade/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/pacman-rules/.meta/exemplar.cpp b/exercises/concept/pacman-rules/.meta/exemplar.cpp index 734f47afb..0ca1c6da2 100644 --- a/exercises/concept/pacman-rules/.meta/exemplar.cpp +++ b/exercises/concept/pacman-rules/.meta/exemplar.cpp @@ -25,4 +25,4 @@ bool lost(bool power_pellet_active, bool touching_ghost) { bool won(bool has_eaten_all_dots, bool power_pellet_active, bool touching_ghost) { return has_eaten_all_dots && !lost(power_pellet_active, touching_ghost); -} \ No newline at end of file +} diff --git a/exercises/concept/pacman-rules/pacman_rules.cpp b/exercises/concept/pacman-rules/pacman_rules.cpp index 8160dc752..8625a2596 100644 --- a/exercises/concept/pacman-rules/pacman_rules.cpp +++ b/exercises/concept/pacman-rules/pacman_rules.cpp @@ -29,4 +29,4 @@ bool won(bool has_eaten_all_dots, bool power_pellet_active, bool touching_ghost) { // TODO: Please implement the won function return false; -} \ No newline at end of file +} diff --git a/exercises/concept/pacman-rules/test/catch.hpp b/exercises/concept/pacman-rules/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/pacman-rules/test/catch.hpp +++ b/exercises/concept/pacman-rules/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/power-of-troy/.docs/after.md b/exercises/concept/power-of-troy/.docs/after.md index 0c949ba6e..df322194f 100644 --- a/exercises/concept/power-of-troy/.docs/after.md +++ b/exercises/concept/power-of-troy/.docs/after.md @@ -6,7 +6,7 @@ They act as wrappers around raw pointers, adding additional functionality such a ## General Syntax Smart pointers are typically implemented as class templates in the C++ standard library. -The two most commonly used smart pointers are `std::unique_ptr` and `std::shared_ptr`. +The two most commonly used smart pointers are `std::unique_ptr` and `std::shared_ptr`. ## Unique Pointers @@ -82,7 +82,7 @@ auto your_flatmates_boyfriends_account = your_flatmates_account; ``` Weak pointers are useful in scenarios where cyclic references need to be broken to prevent memory leaks. -`std::weak_ptr` was designed to address the issue of cyclic ownership, also known as circular references, that can occur when using `std::shared_ptr`. +`std::weak_ptr` was designed to address the issue of cyclic ownership, also known as circular references, that can occur when using `std::shared_ptr`. In a cyclic ownership scenario, two or more `std::shared_ptr` objects are referencing each other, creating a cycle where none of the objects can be deleted because they have strong references to each other, leading to memory leaks. `std::weak_ptr` provides a solution to this problem by allowing weak references to shared objects without contributing to their reference count. This means that it can observe and access the shared object but doesn't prevent it from being deleted. diff --git a/exercises/concept/power-of-troy/.docs/introduction.md b/exercises/concept/power-of-troy/.docs/introduction.md index fb84567ca..329968d5f 100644 --- a/exercises/concept/power-of-troy/.docs/introduction.md +++ b/exercises/concept/power-of-troy/.docs/introduction.md @@ -49,7 +49,7 @@ They act as wrappers around raw pointers, adding additional functionality such a ## General Syntax Smart pointers are typically implemented as class templates in the C++ standard library. -The two most commonly used smart pointers are `std::unique_ptr` and `std::shared_ptr`. +The two most commonly used smart pointers are `std::unique_ptr` and `std::shared_ptr`. ## Unique Pointers diff --git a/exercises/concept/power-of-troy/.meta/exemplar.cpp b/exercises/concept/power-of-troy/.meta/exemplar.cpp index 0f7acea64..1c2ff464d 100644 --- a/exercises/concept/power-of-troy/.meta/exemplar.cpp +++ b/exercises/concept/power-of-troy/.meta/exemplar.cpp @@ -24,4 +24,4 @@ int power_intensity(const human& caster) { return caster.own_power.use_count(); } -} // namespace troy \ No newline at end of file +} // namespace troy diff --git a/exercises/concept/power-of-troy/.meta/exemplar.h b/exercises/concept/power-of-troy/.meta/exemplar.h index 5e871faf2..b74daa515 100644 --- a/exercises/concept/power-of-troy/.meta/exemplar.h +++ b/exercises/concept/power-of-troy/.meta/exemplar.h @@ -30,4 +30,4 @@ void manifest_power(human& receiver, std::string power_effect); void use_power(const human& caster, human& receiver); int power_intensity(const human& caster); -} // namespace troy \ No newline at end of file +} // namespace troy diff --git a/exercises/concept/power-of-troy/test/catch.hpp b/exercises/concept/power-of-troy/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/power-of-troy/test/catch.hpp +++ b/exercises/concept/power-of-troy/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/speedywagon/.docs/introduction.md b/exercises/concept/speedywagon/.docs/introduction.md index fe708ac3e..94297f94f 100644 --- a/exercises/concept/speedywagon/.docs/introduction.md +++ b/exercises/concept/speedywagon/.docs/introduction.md @@ -36,7 +36,7 @@ Dereferencing a pointer is done using the _indirection operator_ (`*`) operator. ```cpp std::string opponent{"Solomon Lane"}; // 'ethan' points to the address of the string opponent -std::string* ethan{&opponent}; +std::string* ethan{&opponent}; // Instead of ethan's, the opponent's name address is given to the passPort std::string passportName{*ethan}; ``` @@ -54,7 +54,7 @@ int gateCode[] = {462, 753, 218, 611, 977}; // 'ptr' points to the first element of 'gateCode' int* ptr{&gateCode[0]}; // Accesses the third Stargate address through pointer arithmetic -int dialedAddress{*(ptr + 2)}; +int dialedAddress{*(ptr + 2)}; // Chevron encoded! Dialing Stargate address: openStarGate(dialedAddress); ``` @@ -63,6 +63,8 @@ openStarGate(dialedAddress); Pointer arithmetic in C++ can easily lead to __undefined behavior__ if not handled carefully. Undefined behavior can manifest in unexpected program outcomes, crashes, or even security vulnerabilities. One infamous example of the consequences of undefined behavior occurred in the [explosion of the Ariane 5 rocket][ariane-flight-v88] in 1996, where a software exception caused by the conversion of a 64-bit floating-point number to a 16-bit signed integer led to a catastrophic failure. + +[ariane-flight-v88]: https://en.wikipedia.org/wiki/Ariane_flight_V88 ~~~~ ## Accessing member variables diff --git a/exercises/concept/speedywagon/.docs/introduction.md.tpl b/exercises/concept/speedywagon/.docs/introduction.md.tpl index 288c8554a..8ea648717 100644 --- a/exercises/concept/speedywagon/.docs/introduction.md.tpl +++ b/exercises/concept/speedywagon/.docs/introduction.md.tpl @@ -1,3 +1,3 @@ # Introduction -%{concept:pointers} \ No newline at end of file +%{concept:pointers} diff --git a/exercises/concept/speedywagon/test/catch.hpp b/exercises/concept/speedywagon/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/speedywagon/test/catch.hpp +++ b/exercises/concept/speedywagon/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/troll-the-trolls/.docs/hints.md b/exercises/concept/troll-the-trolls/.docs/hints.md index a096d4c4c..8f2cc9e8b 100644 --- a/exercises/concept/troll-the-trolls/.docs/hints.md +++ b/exercises/concept/troll-the-trolls/.docs/hints.md @@ -24,5 +24,3 @@ [switch]: https://www.learncpp.com/cpp-tutorial/switch-statement-basics/ [fallthrough]: https://www.learncpp.com/cpp-tutorial/switch-fallthrough-and-scoping/ - - diff --git a/exercises/concept/troll-the-trolls/.docs/instructions.md b/exercises/concept/troll-the-trolls/.docs/instructions.md index 288984313..2249d8b56 100644 --- a/exercises/concept/troll-the-trolls/.docs/instructions.md +++ b/exercises/concept/troll-the-trolls/.docs/instructions.md @@ -3,7 +3,7 @@ Your friend Helma made a small online game that rapidly gained popularity. It is called _HellMath_. The small community attracted some trolls who make the game and the forums pretty unpleasant. -Helma has asked you to work on a new permission system to separate troublemakers. +Helma has asked you to work on a new permission system to separate troublemakers. The forum supports three different actions: diff --git a/exercises/concept/troll-the-trolls/.docs/introduction.md b/exercises/concept/troll-the-trolls/.docs/introduction.md index 07718a20a..ca72911de 100644 --- a/exercises/concept/troll-the-trolls/.docs/introduction.md +++ b/exercises/concept/troll-the-trolls/.docs/introduction.md @@ -46,7 +46,7 @@ enum class WheelMaterial { plastic }; ``` -Although the wheels and the deck can both be made of _plastic_, the two cannot be confused. +Although the wheels and the deck can both be made of _plastic_, the two cannot be confused. They are different _types_: `DeckMaterial` plastic and `WheelMaterial` plastic. Each `enumeration` will have its `enumerators` in its own scope - its own `namespace`. This is the reason they are called `scoped enumerations`. @@ -57,7 +57,7 @@ You might be thinking that with a name like `scoped`, there would also be _`uns `Unscoped enumerations` are becoming less popular because they all share the same global namespace. Because of the sharing, you could not have two `unscoped enumerations` with the same `enumerators` like _plastic_ in the example above. -Also, `unscoped enumerations` implicitly convert to integers. +Also, `unscoped enumerations` implicitly convert to integers. Look at the example below for a surprising result: ```cpp diff --git a/exercises/concept/troll-the-trolls/.docs/introduction.md.tpl b/exercises/concept/troll-the-trolls/.docs/introduction.md.tpl index 18a9e7147..3c19d9078 100644 --- a/exercises/concept/troll-the-trolls/.docs/introduction.md.tpl +++ b/exercises/concept/troll-the-trolls/.docs/introduction.md.tpl @@ -2,4 +2,4 @@ %{concept:enums} -%{concept:switch} \ No newline at end of file +%{concept:switch} diff --git a/exercises/concept/troll-the-trolls/.meta/design.md b/exercises/concept/troll-the-trolls/.meta/design.md index d68ff7f4d..ccc203725 100644 --- a/exercises/concept/troll-the-trolls/.meta/design.md +++ b/exercises/concept/troll-the-trolls/.meta/design.md @@ -16,7 +16,7 @@ As this is an advanced exercise, there are no enum-related things that we should - `enums` - `switch` -- +- ## Prerequisites This exercise's prerequisites Concepts are: diff --git a/exercises/concept/troll-the-trolls/.meta/exemplar.cpp b/exercises/concept/troll-the-trolls/.meta/exemplar.cpp index 0641e605b..e8ee09166 100644 --- a/exercises/concept/troll-the-trolls/.meta/exemplar.cpp +++ b/exercises/concept/troll-the-trolls/.meta/exemplar.cpp @@ -41,4 +41,4 @@ bool has_priority(AccountStatus player1, AccountStatus player2) { return static_cast(player1) > static_cast(player2); } -} // namespace hellmath \ No newline at end of file +} // namespace hellmath diff --git a/exercises/concept/troll-the-trolls/test/catch.hpp b/exercises/concept/troll-the-trolls/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/troll-the-trolls/test/catch.hpp +++ b/exercises/concept/troll-the-trolls/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/troll-the-trolls/troll_the_trolls.cpp b/exercises/concept/troll-the-trolls/troll_the_trolls.cpp index 1ef38f9d6..a42c386b2 100644 --- a/exercises/concept/troll-the-trolls/troll_the_trolls.cpp +++ b/exercises/concept/troll-the-trolls/troll_the_trolls.cpp @@ -22,4 +22,4 @@ namespace hellmath { // `AccountStatus` arguments and returns `true`, if and only if the first // account has a strictly higher priority than the second. -} // namespace hellmath \ No newline at end of file +} // namespace hellmath diff --git a/exercises/concept/vehicle-purchase/.docs/introduction.md b/exercises/concept/vehicle-purchase/.docs/introduction.md index 424381018..ef98613bd 100644 --- a/exercises/concept/vehicle-purchase/.docs/introduction.md +++ b/exercises/concept/vehicle-purchase/.docs/introduction.md @@ -29,7 +29,7 @@ Here are some common examples: ```cpp bool eq3 = 2 == 3; // false, integer comparison -bool eq4 = 2.1 != 2.2; // true, float comparison +bool eq4 = 2.1 != 2.2; // true, float comparison bool eq5 = "hello" == "hello"; // true, string comparison ``` diff --git a/exercises/concept/vehicle-purchase/.docs/introduction.md.tpl b/exercises/concept/vehicle-purchase/.docs/introduction.md.tpl index 058d70afe..875c00fa2 100644 --- a/exercises/concept/vehicle-purchase/.docs/introduction.md.tpl +++ b/exercises/concept/vehicle-purchase/.docs/introduction.md.tpl @@ -2,4 +2,4 @@ %{concept:comparisons} -%{concept:if-statements} \ No newline at end of file +%{concept:if-statements} diff --git a/exercises/concept/vehicle-purchase/.meta/exemplar.cpp b/exercises/concept/vehicle-purchase/.meta/exemplar.cpp index 649671308..8a734eea7 100644 --- a/exercises/concept/vehicle-purchase/.meta/exemplar.cpp +++ b/exercises/concept/vehicle-purchase/.meta/exemplar.cpp @@ -30,4 +30,4 @@ double calculate_resell_price(double original_price, double age) { return original_price * discount; } -} // namespace vehicle_purchase \ No newline at end of file +} // namespace vehicle_purchase diff --git a/exercises/concept/vehicle-purchase/CMakeLists.txt b/exercises/concept/vehicle-purchase/CMakeLists.txt index 24d8a62a6..45a584fe0 100644 --- a/exercises/concept/vehicle-purchase/CMakeLists.txt +++ b/exercises/concept/vehicle-purchase/CMakeLists.txt @@ -70,4 +70,3 @@ endif() # Run the tests on every build add_custom_target(test_${exercise} ALL DEPENDS ${exercise} COMMAND ${exercise}) - diff --git a/exercises/concept/vehicle-purchase/test/catch.hpp b/exercises/concept/vehicle-purchase/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/concept/vehicle-purchase/test/catch.hpp +++ b/exercises/concept/vehicle-purchase/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/concept/vehicle-purchase/vehicle_purchase.cpp b/exercises/concept/vehicle-purchase/vehicle_purchase.cpp index b392d9bd3..613e11df4 100644 --- a/exercises/concept/vehicle-purchase/vehicle_purchase.cpp +++ b/exercises/concept/vehicle-purchase/vehicle_purchase.cpp @@ -23,4 +23,4 @@ double calculate_resell_price(double original_price, double age) { return 0.0; } -} // namespace vehicle_purchase \ No newline at end of file +} // namespace vehicle_purchase diff --git a/exercises/practice/acronym/.meta/example.h b/exercises/practice/acronym/.meta/example.h index 337c77ce0..ec7e4952f 100644 --- a/exercises/practice/acronym/.meta/example.h +++ b/exercises/practice/acronym/.meta/example.h @@ -1,5 +1,4 @@ -#if !defined(ACRONYM_H) -#define ACRONYM_H +#pragma once #include @@ -8,5 +7,3 @@ namespace acronym { std::string acronym(std::string const&); } - -#endif diff --git a/exercises/practice/acronym/acronym.h b/exercises/practice/acronym/acronym.h index 85b9b2a28..c0539a3c6 100644 --- a/exercises/practice/acronym/acronym.h +++ b/exercises/practice/acronym/acronym.h @@ -1,10 +1,7 @@ -#if !defined(ACRONYM_H) -#define ACRONYM_H +#pragma once namespace acronym { // TODO: add your solution here } // namespace acronym - -#endif // ACRONYM_H \ No newline at end of file diff --git a/exercises/practice/acronym/test/catch.hpp b/exercises/practice/acronym/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/practice/acronym/test/catch.hpp +++ b/exercises/practice/acronym/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/practice/affine-cipher/.docs/instructions.md b/exercises/practice/affine-cipher/.docs/instructions.md new file mode 100644 index 000000000..1603dbbce --- /dev/null +++ b/exercises/practice/affine-cipher/.docs/instructions.md @@ -0,0 +1,74 @@ +# Instructions + +Create an implementation of the affine cipher, an ancient encryption system created in the Middle East. + +The affine cipher is a type of monoalphabetic substitution cipher. +Each character is mapped to its numeric equivalent, encrypted with a mathematical function and then converted to the letter relating to its new numeric value. +Although all monoalphabetic ciphers are weak, the affine cipher is much stronger than the Atbash cipher, because it has many more keys. + +[//]: # " monoalphabetic as spelled by Merriam-Webster, compare to polyalphabetic " + +## Encryption + +The encryption function is: + +```text +E(x) = (ai + b) mod m +``` + +Where: + +- `i` is the letter's index from `0` to the length of the alphabet - 1. +- `m` is the length of the alphabet. + For the Latin alphabet `m` is `26`. +- `a` and `b` are integers which make up the encryption key. + +Values `a` and `m` must be _coprime_ (or, _relatively prime_) for automatic decryption to succeed, i.e., they have number `1` as their only common factor (more information can be found in the [Wikipedia article about coprime integers][coprime-integers]). +In case `a` is not coprime to `m`, your program should indicate that this is an error. +Otherwise it should encrypt or decrypt with the provided key. + +For the purpose of this exercise, digits are valid input but they are not encrypted. +Spaces and punctuation characters are excluded. +Ciphertext is written out in groups of fixed length separated by space, the traditional group size being `5` letters. +This is to make it harder to guess encrypted text based on word boundaries. + +## Decryption + +The decryption function is: + +```text +D(y) = (a^-1)(y - b) mod m +``` + +Where: + +- `y` is the numeric value of an encrypted letter, i.e., `y = E(x)` +- it is important to note that `a^-1` is the modular multiplicative inverse (MMI) of `a mod m` +- the modular multiplicative inverse only exists if `a` and `m` are coprime. + +The MMI of `a` is `x` such that the remainder after dividing `ax` by `m` is `1`: + +```text +ax mod m = 1 +``` + +More information regarding how to find a Modular Multiplicative Inverse and what it means can be found in the [related Wikipedia article][mmi]. + +## General Examples + +- Encrypting `"test"` gives `"ybty"` with the key `a = 5`, `b = 7` +- Decrypting `"ybty"` gives `"test"` with the key `a = 5`, `b = 7` +- Decrypting `"ybty"` gives `"lqul"` with the wrong key `a = 11`, `b = 7` +- Decrypting `"kqlfd jzvgy tpaet icdhm rtwly kqlon ubstx"` gives `"thequickbrownfoxjumpsoverthelazydog"` with the key `a = 19`, `b = 13` +- Encrypting `"test"` with the key `a = 18`, `b = 13` is an error because `18` and `26` are not coprime + +## Example of finding a Modular Multiplicative Inverse (MMI) + +Finding MMI for `a = 15`: + +- `(15 * x) mod 26 = 1` +- `(15 * 7) mod 26 = 1`, ie. `105 mod 26 = 1` +- `7` is the MMI of `15 mod 26` + +[mmi]: https://en.wikipedia.org/wiki/Modular_multiplicative_inverse +[coprime-integers]: https://en.wikipedia.org/wiki/Coprime_integers diff --git a/exercises/practice/affine-cipher/.meta/config.json b/exercises/practice/affine-cipher/.meta/config.json new file mode 100644 index 000000000..cf288d628 --- /dev/null +++ b/exercises/practice/affine-cipher/.meta/config.json @@ -0,0 +1,21 @@ +{ + "authors": [ + "marcelweikum" + ], + "files": { + "solution": [ + "affine_cipher.cpp", + "affine_cipher.h" + ], + "test": [ + "affine_cipher_test.cpp" + ], + "example": [ + ".meta/example.cpp", + ".meta/example.h" + ] + }, + "blurb": "Create an implementation of the Affine cipher, an ancient encryption algorithm from the Middle East.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Affine_cipher" +} diff --git a/exercises/practice/affine-cipher/.meta/example.cpp b/exercises/practice/affine-cipher/.meta/example.cpp new file mode 100644 index 000000000..886a571d2 --- /dev/null +++ b/exercises/practice/affine-cipher/.meta/example.cpp @@ -0,0 +1,65 @@ +#include +#include + +#include "affine_cipher.h" + +namespace affine_cipher { + +static int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } + +static int mod(int x, int m) { + int r = x % m; + return r < 0 ? r + m : r; +} + +static int modinv(int a, int m) { + int t = 0, newt = 1; + int r = m, newr = a; + while (newr != 0) { + int q = r / newr; + t -= q * newt; + std::swap(t, newt); + r -= q * newr; + std::swap(r, newr); + } + if (r != 1) throw std::invalid_argument("a and m must be coprime."); + return t < 0 ? t + m : t; +} + +std::string encode(const std::string& text, int a, int b) { + const int m = 26; + if (gcd(a, m) != 1) throw std::invalid_argument("a and m must be coprime."); + std::string out; + out.reserve(text.size()); + for (char ch : text) { + if (std::isalpha(ch)) { + int x = std::tolower(ch) - 'a'; + out += char('a' + mod(a * x + b, m)); + } else if (std::isdigit(ch)) { + out += ch; + } + } + for (int i = 5; i < (int)out.size(); i += 6) { + out.insert(out.begin() + i, ' '); + } + return out; +} + +std::string decode(const std::string& text, int a, int b) { + const int m = 26; + if (gcd(a, m) != 1) throw std::invalid_argument("a and m must be coprime."); + int inv = modinv(a, m); + std::string out; + out.reserve(text.size()); + for (char ch : text) { + if (std::isalpha(ch)) { + int y = std::tolower(ch) - 'a'; + out += char('a' + mod(inv * (y - b), m)); + } else if (std::isdigit(ch)) { + out += ch; + } + } + return out; +} + +} // namespace affine_cipher diff --git a/exercises/practice/affine-cipher/.meta/example.h b/exercises/practice/affine-cipher/.meta/example.h new file mode 100644 index 000000000..05cf34ce4 --- /dev/null +++ b/exercises/practice/affine-cipher/.meta/example.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace affine_cipher { + +std::string encode(const std::string& input, int a, int b); +std::string decode(const std::string& input, int a, int b); + +} // namespace affine_cipher diff --git a/exercises/practice/affine-cipher/.meta/tests.toml b/exercises/practice/affine-cipher/.meta/tests.toml new file mode 100644 index 000000000..07cce7c77 --- /dev/null +++ b/exercises/practice/affine-cipher/.meta/tests.toml @@ -0,0 +1,58 @@ +# 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. + +[2ee1d9af-1c43-416c-b41b-cefd7d4d2b2a] +description = "encode -> encode yes" + +[785bade9-e98b-4d4f-a5b0-087ba3d7de4b] +description = "encode -> encode no" + +[2854851c-48fb-40d8-9bf6-8f192ed25054] +description = "encode -> encode OMG" + +[bc0c1244-b544-49dd-9777-13a770be1bad] +description = "encode -> encode O M G" + +[381a1a20-b74a-46ce-9277-3778625c9e27] +description = "encode -> encode mindblowingly" + +[6686f4e2-753b-47d4-9715-876fdc59029d] +description = "encode -> encode numbers" + +[ae23d5bd-30a8-44b6-afbe-23c8c0c7faa3] +description = "encode -> encode deep thought" + +[c93a8a4d-426c-42ef-9610-76ded6f7ef57] +description = "encode -> encode all the letters" + +[0673638a-4375-40bd-871c-fb6a2c28effb] +description = "encode -> encode with a not coprime to m" + +[3f0ac7e2-ec0e-4a79-949e-95e414953438] +description = "decode -> decode exercism" + +[241ee64d-5a47-4092-a5d7-7939d259e077] +description = "decode -> decode a sentence" + +[33fb16a1-765a-496f-907f-12e644837f5e] +description = "decode -> decode numbers" + +[20bc9dce-c5ec-4db6-a3f1-845c776bcbf7] +description = "decode -> decode all the letters" + +[623e78c0-922d-49c5-8702-227a3e8eaf81] +description = "decode -> decode with no spaces in input" + +[58fd5c2a-1fd9-4563-a80a-71cff200f26f] +description = "decode -> decode with too many spaces" + +[b004626f-c186-4af9-a3f4-58f74cdb86d5] +description = "decode -> decode with a not coprime to m" diff --git a/exercises/practice/affine-cipher/CMakeLists.txt b/exercises/practice/affine-cipher/CMakeLists.txt new file mode 100644 index 000000000..dba98a931 --- /dev/null +++ b/exercises/practice/affine-cipher/CMakeLists.txt @@ -0,0 +1,67 @@ +# Get the exercise name from the current directory +get_filename_component(exercise ${CMAKE_CURRENT_SOURCE_DIR} NAME) + +# Basic CMake project +cmake_minimum_required(VERSION 3.5.1) + +# Name the project after the exercise +project(${exercise} CXX) + +# Get a source filename from the exercise name by replacing -'s with _'s +string(REPLACE "-" "_" file ${exercise}) + +# Implementation could be only a header +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.cpp) + set(exercise_cpp ${file}.cpp) +else() + set(exercise_cpp "") +endif() + +# Use the common Catch library? +if(EXERCISM_COMMON_CATCH) + # For Exercism track development only + add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h $) +elseif(EXERCISM_TEST_SUITE) + # The Exercism test suite is being run, the Docker image already + # includes a pre-built version of Catch. + find_package(Catch2 REQUIRED) + add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h) + target_link_libraries(${exercise} PRIVATE Catch2::Catch2WithMain) + # When Catch is installed system wide we need to include a different + # header, we need this define to use the correct one. + target_compile_definitions(${exercise} PRIVATE EXERCISM_TEST_SUITE) +else() + # Build executable from sources and headers + add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h test/tests-main.cpp) +endif() + +set_target_properties(${exercise} PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED OFF + CXX_EXTENSIONS OFF +) + +set(CMAKE_BUILD_TYPE Debug) + +if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(GNU|Clang)") + set_target_properties(${exercise} PROPERTIES + COMPILE_FLAGS "-Wall -Wextra -Wpedantic -Werror" + ) +endif() + +# Configure to run all the tests? +if(${EXERCISM_RUN_ALL_TESTS}) + target_compile_definitions(${exercise} PRIVATE EXERCISM_RUN_ALL_TESTS) +endif() + +# Tell MSVC not to warn us about unchecked iterators in debug builds +# Treat warnings as errors +# Treat type conversion warnings C4244 and C4267 as level 4 warnings, i.e. ignore them in level 3 +if(${MSVC}) + set_target_properties(${exercise} PROPERTIES + COMPILE_DEFINITIONS_DEBUG _SCL_SECURE_NO_WARNINGS + COMPILE_FLAGS "/WX /w44244 /w44267") +endif() + +# Run the tests on every build +add_custom_target(test_${exercise} ALL DEPENDS ${exercise} COMMAND ${exercise}) diff --git a/exercises/practice/affine-cipher/affine_cipher.cpp b/exercises/practice/affine-cipher/affine_cipher.cpp new file mode 100644 index 000000000..9f8665fcd --- /dev/null +++ b/exercises/practice/affine-cipher/affine_cipher.cpp @@ -0,0 +1,7 @@ +#include "affine_cipher.h" + +namespace affine_cipher { + +// TODO: add your solution here + +} // namespace affine_cipher diff --git a/exercises/practice/affine-cipher/affine_cipher.h b/exercises/practice/affine-cipher/affine_cipher.h new file mode 100644 index 000000000..b8d6ddfa7 --- /dev/null +++ b/exercises/practice/affine-cipher/affine_cipher.h @@ -0,0 +1,10 @@ +#ifndef AFFINE_CIPHER_H +#define AFFINE_CIPHER_H + +namespace affine_cipher { + +// TODO: add your solution here + +} // namespace affine_cipher + +#endif // AFFINE_CIPHER_H diff --git a/exercises/practice/affine-cipher/affine_cipher_test.cpp b/exercises/practice/affine-cipher/affine_cipher_test.cpp new file mode 100644 index 000000000..8cea17f79 --- /dev/null +++ b/exercises/practice/affine-cipher/affine_cipher_test.cpp @@ -0,0 +1,91 @@ +#include "affine_cipher.h" +#ifdef EXERCISM_TEST_SUITE +#include +#else +#include "test/catch.hpp" +#endif + +TEST_CASE("encode_yes", "[2ee1d9af-1c43-416c-b41b-cefd7d4d2b2a]") { + REQUIRE(affine_cipher::encode("yes", 5, 7) == "xbt"); +} + +#if defined(EXERCISM_RUN_ALL_TESTS) + +TEST_CASE("encode_no", "[785bade9-e98b-4d4f-a5b0-087ba3d7de4b]") { + REQUIRE(affine_cipher::encode("no", 15, 18) == "fu"); +} + +TEST_CASE("encode_OMG", "[2854851c-48fb-40d8-9bf6-8f192ed25054]") { + REQUIRE(affine_cipher::encode("OMG", 21, 3) == "lvz"); +} + +TEST_CASE("encode_O_M_G", "[bc0c1244-b544-49dd-9777-13a770be1bad]") { + REQUIRE(affine_cipher::encode("O M G", 25, 47) == "hjp"); +} + +TEST_CASE("encode_mindblowingly", "[381a1a20-b74a-46ce-9277-3778625c9e27]") { + REQUIRE(affine_cipher::encode("mindblowingly", 11, 15) == + "rzcwa gnxzc dgt"); +} + +TEST_CASE("encode_numbers", "[6686f4e2-753b-47d4-9715-876fdc59029d]") { + REQUIRE(affine_cipher::encode("Testing,1 2 3, testing.", 3, 4) == + "jqgjc rw123 jqgjc rw"); +} + +TEST_CASE("encode_deep_thought", "[ae23d5bd-30a8-44b6-afbe-23c8c0c7faa3]") { + REQUIRE(affine_cipher::encode("Truth is fiction.", 5, 17) == + "iynia fdqfb ifje"); +} + +TEST_CASE("encode_all_the_letters", "[c93a8a4d-426c-42ef-9610-76ded6f7ef57]") { + REQUIRE(affine_cipher::encode( + "The quick brown fox jumps over the lazy dog.", 17, 33) == + "swxtj npvyk lruol iejdc blaxk swxmh qzglf"); +} + +TEST_CASE("encode_with_a_not_coprime_to_m", + "[0673638a-4375-40bd-871c-fb6a2c28effb]") { + REQUIRE_THROWS_AS(affine_cipher::encode("This is a test.", 6, 17), + std::invalid_argument); +} + +TEST_CASE("decode_exercism", "[3f0ac7e2-ec0e-4a79-949e-95e414953438]") { + REQUIRE(affine_cipher::decode("tytgn fjr", 3, 7) == "exercism"); +} + +TEST_CASE("decode_a_sentence", "[241ee64d-5a47-4092-a5d7-7939d259e077]") { + REQUIRE(affine_cipher::decode("qdwju nqcro muwhn odqun oppmd aunwd o", 19, + 16) == "anobstacleisoftenasteppingstone"); +} + +TEST_CASE("decode_numbers", "[33fb16a1-765a-496f-907f-12e644837f5e]") { + REQUIRE(affine_cipher::decode("odpoz ub123 odpoz ub", 25, 7) == + "testing123testing"); +} + +TEST_CASE("decode_all_the_letters", "[20bc9dce-c5ec-4db6-a3f1-845c776bcbf7]") { + REQUIRE(affine_cipher::decode("swxtj npvyk lruol iejdc blaxk swxmh qzglf", + 17, + 33) == "thequickbrownfoxjumpsoverthelazydog"); +} + +TEST_CASE("decode_with_no_spaces_in_input", + "[623e78c0-922d-49c5-8702-227a3e8eaf81]") { + REQUIRE(affine_cipher::decode("swxtjnpvyklruoliejdcblaxkswxmhqzglf", 17, + 33) == "thequickbrownfoxjumpsoverthelazydog"); +} + +TEST_CASE("decode_with_too_many_spaces", + "[58fd5c2a-1fd9-4563-a80a-71cff200f26f]") { + REQUIRE(affine_cipher::decode("vszzm cly yd cg qdp", 15, 16) == + "jollygreengiant"); +} + +TEST_CASE("decode_with_a_not_coprime_to_m", + "[b004626f-c186-4af9-a3f4-58f74cdb86d5]") { + REQUIRE_THROWS_AS(affine_cipher::decode("Test", 13, 5), + std::invalid_argument); +} + +#endif diff --git a/exercises/practice/complex-numbers/test/catch.hpp b/exercises/practice/affine-cipher/test/catch.hpp similarity index 99% rename from exercises/practice/complex-numbers/test/catch.hpp rename to exercises/practice/affine-cipher/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/practice/complex-numbers/test/catch.hpp +++ b/exercises/practice/affine-cipher/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/practice/affine-cipher/test/tests-main.cpp b/exercises/practice/affine-cipher/test/tests-main.cpp new file mode 100644 index 000000000..0c7c351f4 --- /dev/null +++ b/exercises/practice/affine-cipher/test/tests-main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" diff --git a/exercises/practice/all-your-base/.approaches/in-parallel/content.md b/exercises/practice/all-your-base/.approaches/in-parallel/content.md index 52869d0bc..b72621f6c 100644 --- a/exercises/practice/all-your-base/.approaches/in-parallel/content.md +++ b/exercises/practice/all-your-base/.approaches/in-parallel/content.md @@ -13,7 +13,7 @@ A simple serial for-loop can be a lot faster for a small number than a [parallel ## Converting the `input_digits` -### Numeric's `accumulate` +### Numeric's `accumulate` The for-loop with `*` and `+` can be written with the [`accumulate`][acuumulate-function] function from the [`numeric`][numeric-header] header. @@ -94,10 +94,10 @@ unsigned int digit_limit{static_cast(std::log(intermediate) / std: std::vector output_digits(digit_limit); std::iota(output_digits.rbegin(), output_digits.rend(), 1); std::for_each(std::execution::par_unseq, - output_digits.begin(), - output_digits.end(), + output_digits.begin(), + output_digits.end(), [&](unsigned int digit) { - output_digits[digit_limit - digit] = + output_digits[digit_limit - digit] = intermediate / static_cast(std::pow(output_base, digit - 1)) % output_base; @@ -151,7 +151,7 @@ std::vector convert(unsigned int input_base, output_digits.begin(), output_digits.end(), [&](unsigned int digit) { - output_digits[digit_limit - digit] = + output_digits[digit_limit - digit] = intermediate / static_cast(std::pow(output_base, digit - 1)) % output_base; }); @@ -174,5 +174,5 @@ std::vector convert(unsigned int input_base, [execution-policies]: https://en.cppreference.com/w/cpp/algorithm/execution_policy_tag_t [tbb]: https://github.com/oneapi-src/oneTBB [in-sequence]: https://exercism.org/tracks/cpp/exercises/all-your-base/approaches/in-sequence -[for-loop]: https://en.cppreference.com/w/cpp/language/for +[for-loop]: https://en.cppreference.com/w/cpp/language/for [for-each]: https://en.cppreference.com/w/cpp/algorithm/for_each diff --git a/exercises/practice/all-your-base/.approaches/in-parallel/snippet.txt b/exercises/practice/all-your-base/.approaches/in-parallel/snippet.txt index 60e554324..1867dd631 100644 --- a/exercises/practice/all-your-base/.approaches/in-parallel/snippet.txt +++ b/exercises/practice/all-your-base/.approaches/in-parallel/snippet.txt @@ -5,4 +5,4 @@ unsigned int intermediate = std::transform_reduce(std::execution::par_unseq, positions.crbegin(), 0U, std::plus {}, [ & input_base](unsigned int d, unsigned int pos) { return d * std::pow(input_base, pos); - }); \ No newline at end of file + }); diff --git a/exercises/practice/all-your-base/.approaches/in-sequence/content.md b/exercises/practice/all-your-base/.approaches/in-sequence/content.md index 639082cfc..a35a900b8 100644 --- a/exercises/practice/all-your-base/.approaches/in-sequence/content.md +++ b/exercises/practice/all-your-base/.approaches/in-sequence/content.md @@ -75,7 +75,7 @@ When you need both the remainder and the quotient from a division operation, you ```cpp std::vector output_digits{}; -std::ldiv_t v{intermediate, 0}; +std::ldiv_t v{intermediate, 0}; while (v.quot > 0) { v = std::div(v.quot, output_base); output_digits.emplace_back(v.rem); @@ -107,19 +107,19 @@ std::vector convert(unsigned int input_base, throw std::invalid_argument("Bases must be at least 2"); unsigned int intermediate = 0; for (unsigned int d : input_digits) { - if (d >= input_base) + if (d >= input_base) throw std::invalid_argument("Digits cannot be bigger than the base"); intermediate = intermediate * input_base + d; } std::vector output_digits{}; - std::ldiv_t v{intermediate, 0}; + std::ldiv_t v{intermediate, 0}; while (v.quot > 0) { v = std::div(v.quot, output_base); output_digits.emplace_back(v.rem); } - + std::reverse(output_digits.begin(), output_digits.end()); - + return output_digits; } ``` @@ -129,7 +129,7 @@ std::vector convert(unsigned int input_base, [pow-function]: https://en.cppreference.com/w/cpp/numeric/math/pow [reverse-string]: https://exercism.org/tracks/cpp/exercises/reverse-string/dig_deeper [parallel-computing]: https://en.wikipedia.org/wiki/Parallel_computing -[while-loop]: https://en.cppreference.com/w/cpp/language/while -[for-loop]: https://en.cppreference.com/w/cpp/language/for +[while-loop]: https://en.cppreference.com/w/cpp/language/while +[for-loop]: https://en.cppreference.com/w/cpp/language/for [algorithm-header]: https://en.cppreference.com/w/cpp/algorithm [div-function]: https://en.cppreference.com/w/cpp/numeric/math/div diff --git a/exercises/practice/all-your-base/.approaches/in-sequence/snippet.txt b/exercises/practice/all-your-base/.approaches/in-sequence/snippet.txt index 34297d5d3..0918777ee 100644 --- a/exercises/practice/all-your-base/.approaches/in-sequence/snippet.txt +++ b/exercises/practice/all-your-base/.approaches/in-sequence/snippet.txt @@ -5,4 +5,4 @@ std::vector output_digits{}; while (intermediate > 0) { output_digits.emplace_back(intermediate % output_base); intermediate /= output_base; -} \ No newline at end of file +} diff --git a/exercises/practice/all-your-base/.approaches/introduction.md b/exercises/practice/all-your-base/.approaches/introduction.md index 78e55c97b..89788abbf 100644 --- a/exercises/practice/all-your-base/.approaches/introduction.md +++ b/exercises/practice/all-your-base/.approaches/introduction.md @@ -56,10 +56,10 @@ std::vector output_digits(digit_limit); std::iota(output_digits.rbegin(), output_digits.rend(), 1); std::for_each( std::execution::par_unseq, - output_digits.begin(), - output_digits.end(), + output_digits.begin(), + output_digits.end(), [&](unsigned int digit) { - output_digits[digit_limit - digit] = + output_digits[digit_limit - digit] = intermediate / static_cast(std::pow(output_base, digit - 1)) % output_base; diff --git a/exercises/practice/all-your-base/.meta/example.h b/exercises/practice/all-your-base/.meta/example.h index 77bb8015b..73fc87240 100644 --- a/exercises/practice/all-your-base/.meta/example.h +++ b/exercises/practice/all-your-base/.meta/example.h @@ -1,5 +1,4 @@ -#if !defined(ALL_YOUR_BASE_H) -#define ALL_YOUR_BASE_H +#pragma once #include @@ -9,5 +8,3 @@ std::vector convert(unsigned int input_base, const std::vector& input_digits, unsigned int output_base); } - -#endif diff --git a/exercises/practice/all-your-base/all_your_base.h b/exercises/practice/all-your-base/all_your_base.h index a2b6cfab3..408a1475f 100644 --- a/exercises/practice/all-your-base/all_your_base.h +++ b/exercises/practice/all-your-base/all_your_base.h @@ -1,10 +1,7 @@ -#if !defined(ALL_YOUR_BASE_H) -#define ALL_YOUR_BASE_H +#pragma once namespace all_your_base { // TODO: add your solution here } // namespace all_your_base - -#endif // ALL_YOUR_BASE_H \ No newline at end of file diff --git a/exercises/practice/all-your-base/test/catch.hpp b/exercises/practice/all-your-base/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/practice/all-your-base/test/catch.hpp +++ b/exercises/practice/all-your-base/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/practice/allergies/.docs/instructions.append.md b/exercises/practice/allergies/.docs/instructions.append.md index 72a9cd435..ce6eb03b8 100644 --- a/exercises/practice/allergies/.docs/instructions.append.md +++ b/exercises/practice/allergies/.docs/instructions.append.md @@ -1,5 +1,5 @@ # Instructions append - + ## Some Additional Notes for C++ Implementation This exercise uses the [`unordered_set`][set] diff --git a/exercises/practice/allergies/.meta/config.json b/exercises/practice/allergies/.meta/config.json index e419c99f8..ebd96d1bc 100644 --- a/exercises/practice/allergies/.meta/config.json +++ b/exercises/practice/allergies/.meta/config.json @@ -24,5 +24,5 @@ }, "blurb": "Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies.", "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", - "source_url": "https://turing.edu" + "source_url": "https://www.turing.edu/" } diff --git a/exercises/practice/allergies/.meta/example.h b/exercises/practice/allergies/.meta/example.h index cb03d6eaf..3d7c372e0 100644 --- a/exercises/practice/allergies/.meta/example.h +++ b/exercises/practice/allergies/.meta/example.h @@ -1,5 +1,4 @@ -#if !defined(ALLERGIES_H) -#define ALLERGIES_H +#pragma once #include #include @@ -23,5 +22,3 @@ class allergy_test { }; } // namespace allergies - -#endif diff --git a/exercises/practice/allergies/allergies.h b/exercises/practice/allergies/allergies.h index 95573e4a6..7a8097561 100644 --- a/exercises/practice/allergies/allergies.h +++ b/exercises/practice/allergies/allergies.h @@ -1,10 +1,7 @@ -#if !defined(ALLERGIES_H) -#define ALLERGIES_H +#pragma once namespace allergies { // TODO: add your solution here } // namespace allergies - -#endif // ALLERGIES_H \ No newline at end of file diff --git a/exercises/practice/allergies/test/catch.hpp b/exercises/practice/allergies/test/catch.hpp index 36eaeb27f..ff40b4fd6 100644 --- a/exercises/practice/allergies/test/catch.hpp +++ b/exercises/practice/allergies/test/catch.hpp @@ -3175,8 +3175,8 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val); - Detail::Approx operator "" _a(unsigned long long val); + Detail::Approx operator ""_a(long double val); + Detail::Approx operator ""_a(unsigned long long val); } // end namespace literals template<> @@ -7911,10 +7911,10 @@ namespace Detail { } // end namespace Detail namespace literals { - Detail::Approx operator "" _a(long double val) { + Detail::Approx operator ""_a(long double val) { return Detail::Approx(val); } - Detail::Approx operator "" _a(unsigned long long val) { + Detail::Approx operator ""_a(unsigned long long val) { return Detail::Approx(val); } } // end namespace literals diff --git a/exercises/practice/alphametics/.docs/instructions.md b/exercises/practice/alphametics/.docs/instructions.md new file mode 100644 index 000000000..ef2cbb4a7 --- /dev/null +++ b/exercises/practice/alphametics/.docs/instructions.md @@ -0,0 +1,29 @@ +# Instructions + +Given an alphametics puzzle, find the correct solution. + +[Alphametics][alphametics] is a puzzle where letters in words are replaced with numbers. + +For example `SEND + MORE = MONEY`: + +```text + S E N D + M O R E + +----------- +M O N E Y +``` + +Replacing these with valid numbers gives: + +```text + 9 5 6 7 + 1 0 8 5 + +----------- +1 0 6 5 2 +``` + +This is correct because every letter is replaced by a different number and the words, translated into numbers, then make a valid sum. + +Each letter must represent a different digit, and the leading digit of a multi-digit number must not be zero. + +[alphametics]: https://en.wikipedia.org/wiki/Alphametics diff --git a/exercises/practice/alphametics/.meta/config.json b/exercises/practice/alphametics/.meta/config.json new file mode 100644 index 000000000..4e31974f0 --- /dev/null +++ b/exercises/practice/alphametics/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "marcelweikum" + ], + "files": { + "solution": [ + "alphametics.cpp", + "alphametics.h" + ], + "test": [ + "alphametics_test.cpp" + ], + "example": [ + ".meta/example.cpp", + ".meta/example.h" + ] + }, + "blurb": "Given an alphametics puzzle, find the correct solution." +} diff --git a/exercises/practice/alphametics/.meta/example.cpp b/exercises/practice/alphametics/.meta/example.cpp new file mode 100644 index 000000000..3fc6eb0e2 --- /dev/null +++ b/exercises/practice/alphametics/.meta/example.cpp @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alphametics.h" + +namespace alphametics { + +std::optional> solve(const std::string& puzzle) { + auto sep = puzzle.find("=="); + if (sep == std::string::npos) return std::nullopt; + std::string left = puzzle.substr(0, sep); + std::string right = puzzle.substr(sep + 2); + + auto trim = [&](std::string& s) { + auto b = s.find_first_not_of(' '); + auto e = s.find_last_not_of(' '); + s = (b == std::string::npos) ? std::string() : s.substr(b, e - b + 1); + }; + trim(left); + trim(right); + + std::vector addends; + std::istringstream iss(left); + for (std::string part; std::getline(iss, part, '+');) { + trim(part); + addends.push_back(part); + } + trim(right); + std::string result = right; + + std::vector letters; + std::unordered_set seen, leading; + auto collect = [&](const std::string& w) { + if (w.size() > 1) leading.insert(w.front()); + for (char c : w) { + if (seen.insert(c).second) letters.push_back(c); + } + }; + for (auto& w : addends) collect(w); + collect(result); + if (letters.size() > 10) return std::nullopt; + + int n = letters.size(); + std::map idx; + for (int i = 0; i < n; ++i) idx[letters[i]] = i; + std::vector weight(n, 0); + + for (auto& w : addends) { + long long mult = 1; + for (int i = (int)w.size() - 1; i >= 0; --i) { + weight[idx[w[i]]] += mult; + mult *= 10; + } + } + { + long long mult = 1; + for (int i = (int)result.size() - 1; i >= 0; --i) { + weight[idx[result[i]]] -= mult; + mult *= 10; + } + } + + std::vector used(10, false); + std::map assign; + bool found = false; + std::map solution; + std::function dfs = [&](int pos, long long sum) { + if (found) return; + if (pos == n) { + if (sum == 0) { + found = true; + solution = assign; + } + return; + } + char c = letters[pos]; + for (int d = 0; d < 10 && !found; ++d) { + if (used[d] || (d == 0 && leading.count(c))) continue; + used[d] = true; + assign[c] = d; + dfs(pos + 1, sum + weight[pos] * d); + used[d] = false; + } + }; + + dfs(0, 0); + if (found) return solution; + return std::nullopt; +} + +} // namespace alphametics diff --git a/exercises/practice/alphametics/.meta/example.h b/exercises/practice/alphametics/.meta/example.h new file mode 100644 index 000000000..e5fbdc1bc --- /dev/null +++ b/exercises/practice/alphametics/.meta/example.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include +#include + +namespace alphametics { + +std::optional> solve(const std::string& puzzle); + +} // namespace alphametics diff --git a/exercises/practice/alphametics/.meta/tests.toml b/exercises/practice/alphametics/.meta/tests.toml new file mode 100644 index 000000000..f599b3da6 --- /dev/null +++ b/exercises/practice/alphametics/.meta/tests.toml @@ -0,0 +1,40 @@ +# 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. + +[e0c08b07-9028-4d5f-91e1-d178fead8e1a] +description = "puzzle with three letters" + +[a504ee41-cb92-4ec2-9f11-c37e95ab3f25] +description = "solution must have unique value for each letter" + +[4e3b81d2-be7b-4c5c-9a80-cd72bc6d465a] +description = "leading zero solution is invalid" + +[8a3e3168-d1ee-4df7-94c7-b9c54845ac3a] +description = "puzzle with two digits final carry" + +[a9630645-15bd-48b6-a61e-d85c4021cc09] +description = "puzzle with four letters" + +[3d905a86-5a52-4e4e-bf80-8951535791bd] +description = "puzzle with six letters" + +[4febca56-e7b7-4789-97b9-530d09ba95f0] +description = "puzzle with seven letters" + +[12125a75-7284-4f9a-a5fa-191471e0d44f] +description = "puzzle with eight letters" + +[fb05955f-38dc-477a-a0b6-5ef78969fffa] +description = "puzzle with ten letters" + +[9a101e81-9216-472b-b458-b513a7adacf7] +description = "puzzle with ten letters and 199 addends" diff --git a/exercises/practice/alphametics/CMakeLists.txt b/exercises/practice/alphametics/CMakeLists.txt new file mode 100644 index 000000000..dba98a931 --- /dev/null +++ b/exercises/practice/alphametics/CMakeLists.txt @@ -0,0 +1,67 @@ +# Get the exercise name from the current directory +get_filename_component(exercise ${CMAKE_CURRENT_SOURCE_DIR} NAME) + +# Basic CMake project +cmake_minimum_required(VERSION 3.5.1) + +# Name the project after the exercise +project(${exercise} CXX) + +# Get a source filename from the exercise name by replacing -'s with _'s +string(REPLACE "-" "_" file ${exercise}) + +# Implementation could be only a header +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.cpp) + set(exercise_cpp ${file}.cpp) +else() + set(exercise_cpp "") +endif() + +# Use the common Catch library? +if(EXERCISM_COMMON_CATCH) + # For Exercism track development only + add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h $) +elseif(EXERCISM_TEST_SUITE) + # The Exercism test suite is being run, the Docker image already + # includes a pre-built version of Catch. + find_package(Catch2 REQUIRED) + add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h) + target_link_libraries(${exercise} PRIVATE Catch2::Catch2WithMain) + # When Catch is installed system wide we need to include a different + # header, we need this define to use the correct one. + target_compile_definitions(${exercise} PRIVATE EXERCISM_TEST_SUITE) +else() + # Build executable from sources and headers + add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h test/tests-main.cpp) +endif() + +set_target_properties(${exercise} PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED OFF + CXX_EXTENSIONS OFF +) + +set(CMAKE_BUILD_TYPE Debug) + +if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(GNU|Clang)") + set_target_properties(${exercise} PROPERTIES + COMPILE_FLAGS "-Wall -Wextra -Wpedantic -Werror" + ) +endif() + +# Configure to run all the tests? +if(${EXERCISM_RUN_ALL_TESTS}) + target_compile_definitions(${exercise} PRIVATE EXERCISM_RUN_ALL_TESTS) +endif() + +# Tell MSVC not to warn us about unchecked iterators in debug builds +# Treat warnings as errors +# Treat type conversion warnings C4244 and C4267 as level 4 warnings, i.e. ignore them in level 3 +if(${MSVC}) + set_target_properties(${exercise} PROPERTIES + COMPILE_DEFINITIONS_DEBUG _SCL_SECURE_NO_WARNINGS + COMPILE_FLAGS "/WX /w44244 /w44267") +endif() + +# Run the tests on every build +add_custom_target(test_${exercise} ALL DEPENDS ${exercise} COMMAND ${exercise}) diff --git a/exercises/practice/alphametics/alphametics.cpp b/exercises/practice/alphametics/alphametics.cpp new file mode 100644 index 000000000..96a015394 --- /dev/null +++ b/exercises/practice/alphametics/alphametics.cpp @@ -0,0 +1,7 @@ +#include "alphametics.h" + +namespace alphametics { + +// TODO: add your solution here + +} // namespace alphametics diff --git a/exercises/practice/alphametics/alphametics.h b/exercises/practice/alphametics/alphametics.h new file mode 100644 index 000000000..b3b7f7261 --- /dev/null +++ b/exercises/practice/alphametics/alphametics.h @@ -0,0 +1,10 @@ +#if !defined(ALPHAMETICS_H) +#define ALPHAMETICS_H + +namespace alphametics { + +// TODO: add your solution here + +} // namespace alphametics + +#endif // ALPHAMETICS_H diff --git a/exercises/practice/alphametics/alphametics_test.cpp b/exercises/practice/alphametics/alphametics_test.cpp new file mode 100644 index 000000000..7dbdb0a1d --- /dev/null +++ b/exercises/practice/alphametics/alphametics_test.cpp @@ -0,0 +1,163 @@ +#include "alphametics.h" +#ifdef EXERCISM_TEST_SUITE +#include +#else +#include "test/catch.hpp" +#endif + +TEST_CASE("puzzle_with_three_letters", + "[e0c08b07-9028-4d5f-91e1-d178fead8e1a]") { + auto result = alphametics::solve("I + BB == ILL"); + REQUIRE(result.has_value()); + auto m = *result; + REQUIRE(m.at('I') == 1); + REQUIRE(m.at('B') == 9); + REQUIRE(m.at('L') == 0); +} + +#if defined(EXERCISM_RUN_ALL_TESTS) + +TEST_CASE("solution_must_have_unique_value_for_each_letter", + "[a504ee41-cb92-4ec2-9f11-c37e95ab3f25]") { + auto result = alphametics::solve("A == B"); + REQUIRE_FALSE(result.has_value()); +} + +TEST_CASE("leading_zero_solution_is_invalid", + "[4e3b81d2-be7b-4c5c-9a80-cd72bc6d465a]") { + auto result = alphametics::solve("ACA + DD == BD"); + REQUIRE_FALSE(result.has_value()); +} + +TEST_CASE("puzzle_with_two_digits_final_carry", + "[8a3e3168-d1ee-4df7-94c7-b9c54845ac3a]") { + auto result = alphametics::solve( + "A + A + A + A + A + A + A + A + A + A + A + B == BCC"); + REQUIRE(result.has_value()); + auto m = *result; + REQUIRE(m.at('A') == 9); + REQUIRE(m.at('B') == 1); + REQUIRE(m.at('C') == 0); +} + +TEST_CASE("puzzle_with_four_letters", + "[a9630645-15bd-48b6-a61e-d85c4021cc09]") { + auto result = alphametics::solve("AS + A == MOM"); + REQUIRE(result.has_value()); + auto m = *result; + REQUIRE(m.at('A') == 9); + REQUIRE(m.at('S') == 2); + REQUIRE(m.at('M') == 1); + REQUIRE(m.at('O') == 0); +} + +TEST_CASE("puzzle_with_six_letters", "[3d905a86-5a52-4e4e-bf80-8951535791bd]") { + auto result = alphametics::solve("NO + NO + TOO == LATE"); + REQUIRE(result.has_value()); + auto m = *result; + REQUIRE(m.at('N') == 7); + REQUIRE(m.at('O') == 4); + REQUIRE(m.at('T') == 9); + REQUIRE(m.at('L') == 1); + REQUIRE(m.at('A') == 0); + REQUIRE(m.at('E') == 2); +} + +TEST_CASE("puzzle_with_seven_letters", + "[4febca56-e7b7-4789-97b9-530d09ba95f0]") { + auto result = alphametics::solve("HE + SEES + THE == LIGHT"); + REQUIRE(result.has_value()); + auto m = *result; + REQUIRE(m.at('E') == 4); + REQUIRE(m.at('G') == 2); + REQUIRE(m.at('H') == 5); + REQUIRE(m.at('I') == 0); + REQUIRE(m.at('L') == 1); + REQUIRE(m.at('S') == 9); + REQUIRE(m.at('T') == 7); +} + +TEST_CASE("puzzle_with_eight_letters", + "[12125a75-7284-4f9a-a5fa-191471e0d44f]") { + auto result = alphametics::solve("SEND + MORE == MONEY"); + REQUIRE(result.has_value()); + auto m = *result; + REQUIRE(m.at('S') == 9); + REQUIRE(m.at('E') == 5); + REQUIRE(m.at('N') == 6); + REQUIRE(m.at('D') == 7); + REQUIRE(m.at('M') == 1); + REQUIRE(m.at('O') == 0); + REQUIRE(m.at('R') == 8); + REQUIRE(m.at('Y') == 2); +} + +TEST_CASE("puzzle_with_ten_letters", "[fb05955f-38dc-477a-a0b6-5ef78969fffa]") { + auto result = alphametics::solve( + "AND + A + STRONG + OFFENSE + AS + A + GOOD == DEFENSE"); + REQUIRE(result.has_value()); + auto m = *result; + REQUIRE(m.at('A') == 5); + REQUIRE(m.at('D') == 3); + REQUIRE(m.at('E') == 4); + REQUIRE(m.at('F') == 7); + REQUIRE(m.at('G') == 8); + REQUIRE(m.at('N') == 0); + REQUIRE(m.at('O') == 2); + REQUIRE(m.at('R') == 1); + REQUIRE(m.at('S') == 6); + REQUIRE(m.at('T') == 9); +} + +TEST_CASE("puzzle_with_ten_letters_and_199_addends", + "[9a101e81-9216-472b-b458-b513a7adacf7]") { + auto result = alphametics::solve( + "THIS + A + FIRE + THEREFORE + FOR + ALL + HISTORIES + I + TELL + A + " + "TALE + " + "THAT + FALSIFIES + ITS + TITLE + TIS + A + LIE + THE + TALE + OF + " + "THE + LAST + " + "FIRE + HORSES + LATE + AFTER + THE + FIRST + FATHERS + FORESEE + THE " + "+ HORRORS + " + "THE + LAST + FREE + TROLL + TERRIFIES + THE + HORSES + OF + FIRE + " + "THE + TROLL + " + "RESTS + AT + THE + HOLE + OF + LOSSES + IT + IS + THERE + THAT + SHE " + "+ STORES + " + "ROLES + OF + LEATHERS + AFTER + SHE + SATISFIES + HER + HATE + OFF + " + "THOSE + FEARS + " + "A + TASTE + RISES + AS + SHE + HEARS + THE + LEAST + FAR + HORSE + " + "THOSE + FAST + " + "HORSES + THAT + FIRST + HEAR + THE + TROLL + FLEE + OFF + TO + THE + " + "FOREST + THE + " + "HORSES + THAT + ALERTS + RAISE + THE + STARES + OF + THE + OTHERS + " + "AS + THE + TROLL + " + "ASSAILS + AT + THE + TOTAL + SHIFT + HER + TEETH + TEAR + HOOF + OFF " + "+ TORSO + AS + THE + " + "LAST + HORSE + FORFEITS + ITS + LIFE + THE + FIRST + FATHERS + HEAR + " + "OF + THE + HORRORS + " + "THEIR + FEARS + THAT + THE + FIRES + FOR + THEIR + FEASTS + ARREST + " + "AS + THE + FIRST + " + "FATHERS + RESETTLE + THE + LAST + OF + THE + FIRE + HORSES + THE + " + "LAST + TROLL + HARASSES + " + "THE + FOREST + HEART + FREE + AT + LAST + OF + THE + LAST + TROLL + " + "ALL + OFFER + THEIR + " + "FIRE + HEAT + TO + THE + ASSISTERS + FAR + OFF + THE + TROLL + FASTS " + "+ ITS + LIFE + SHORTER + " + "AS + STARS + RISE + THE + HORSES + REST + SAFE + AFTER + ALL + SHARE " + "+ HOT + FISH + AS + " + "THEIR + AFFILIATES + TAILOR + A + ROOFS + FOR + THEIR + SAFE == " + "FORTRESSES"); + REQUIRE(result.has_value()); + auto m = *result; + REQUIRE(m.at('A') == 1); + REQUIRE(m.at('E') == 0); + REQUIRE(m.at('F') == 5); + REQUIRE(m.at('H') == 8); + REQUIRE(m.at('I') == 7); + REQUIRE(m.at('L') == 2); + REQUIRE(m.at('O') == 6); + REQUIRE(m.at('R') == 3); + REQUIRE(m.at('S') == 4); + REQUIRE(m.at('T') == 9); +} + +#endif diff --git a/exercises/practice/alphametics/test/catch.hpp b/exercises/practice/alphametics/test/catch.hpp new file mode 100644 index 000000000..ff40b4fd6 --- /dev/null +++ b/exercises/practice/alphametics/test/catch.hpp @@ -0,0 +1,17937 @@ +/* + * Catch v2.13.6 + * Generated: 2021-04-16 18:23:38.044268 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2021 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +// start catch.hpp + + +#define CATCH_VERSION_MAJOR 2 +#define CATCH_VERSION_MINOR 13 +#define CATCH_VERSION_PATCH 6 + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// start catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ + // Because REQUIREs trigger GCC's -Wparentheses, and because still + // supported version of g++ have only buggy support for _Pragmas, + // Wparentheses have to be suppressed globally. +# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details + +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wpadded" +#endif +// end catch_suppress_warnings.h +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +# define CATCH_CONFIG_ALL_PARTS +#endif + +// In the impl file, we want to have access to all parts of the headers +// Can also be used to sanely support PCHs +#if defined(CATCH_CONFIG_ALL_PARTS) +# define CATCH_CONFIG_EXTERNAL_INTERFACES +# if defined(CATCH_CONFIG_DISABLE_MATCHERS) +# undef CATCH_CONFIG_DISABLE_MATCHERS +# endif +# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +# endif +#endif + +#if !defined(CATCH_CONFIG_IMPL_ONLY) +// start catch_platform.h + +// See e.g.: +// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html +#ifdef __APPLE__ +# include +# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \ + (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1) +# define CATCH_PLATFORM_MAC +# elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1) +# define CATCH_PLATFORM_IPHONE +# endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) +# define CATCH_PLATFORM_WINDOWS +#endif + +// end catch_platform.h + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// start catch_user_interfaces.h + +namespace Catch { + unsigned int rngSeed(); +} + +// end catch_user_interfaces.h +// start catch_tag_alias_autoregistrar.h + +// start catch_common.h + +// start catch_compiler_capabilities.h + +// Detect a number of compiler features - by compiler +// The following features are defined: +// +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? +// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? +// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +#ifdef __cplusplus + +# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) +# define CATCH_CPP14_OR_GREATER +# endif + +# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# define CATCH_CPP17_OR_GREATER +# endif + +#endif + +// Only GCC compiler should be used in this block, so other compilers trying to +// mask themselves as GCC should be ignored. +#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) + +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) + +#endif + +#if defined(__clang__) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) + +// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug +// which results in calls to destructors being emitted for each temporary, +// without a matching initialization. In practice, this can result in something +// like `std::string::~string` being called on an uninitialized value. +// +// For example, this code will likely segfault under IBM XL: +// ``` +// REQUIRE(std::string("12") + "34" == "1234") +// ``` +// +// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. +# if !defined(__ibmxl__) && !defined(__CUDACC__) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ +# endif + +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") + +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) + +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Assume that non-Windows platforms support posix signals by default +#if !defined(CATCH_PLATFORM_WINDOWS) + #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS +#endif + +//////////////////////////////////////////////////////////////////////////////// +// We know some environments not to support full POSIX signals +#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) + #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#endif + +#ifdef __OS400__ +# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +# define CATCH_CONFIG_COLOUR_NONE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Android somehow still does not support std::to_string +#if defined(__ANDROID__) +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Not all Windows environments support SEH properly +#if defined(__MINGW32__) +# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#endif + +//////////////////////////////////////////////////////////////////////////////// +// PS4 +#if defined(__ORBIS__) +# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Cygwin +#ifdef __CYGWIN__ + +// Required for some versions of Cygwin to declare gettimeofday +// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin +# define _BSD_SOURCE +// some versions of cygwin (most) do not support std::to_string. Use the libstd check. +// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 +# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ + && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) + +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING + +# endif +#endif // __CYGWIN__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#if defined(_MSC_VER) + +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) + +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# define CATCH_CONFIG_COLOUR_NONE +# else +# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# endif + +// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ +// _MSVC_TRADITIONAL == 0 means new conformant preprocessor +// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor +# if !defined(__clang__) // Handle Clang masquerading for msvc +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif // MSVC_TRADITIONAL +# endif // __clang__ + +#endif // _MSC_VER + +#if defined(_REENTRANT) || defined(_MSC_VER) +// Enable async processing, as -pthread is specified or no additional linking is required +# define CATCH_INTERNAL_CONFIG_USE_ASYNC +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// Check if we are compiled with -fno-exceptions or equivalent +#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) +# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED +#endif + +//////////////////////////////////////////////////////////////////////////////// +// DJGPP +#ifdef __DJGPP__ +# define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ + +//////////////////////////////////////////////////////////////////////////////// +// Embarcadero C++Build +#if defined(__BORLANDC__) + #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// Use of __COUNTER__ is suppressed during code analysis in +// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly +// handled by it. +// Otherwise all supported compilers support COUNTER macro, +// but user still might want to turn it off +#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) + #define CATCH_INTERNAL_CONFIG_COUNTER +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// RTX is a special version of Windows that is real time. +// This means that it is detected as Windows, but does not provide +// the same set of capabilities as real Windows does. +#if defined(UNDER_RTSS) || defined(RTX64_BUILD) + #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH + #define CATCH_INTERNAL_CONFIG_NO_ASYNC + #define CATCH_CONFIG_COLOUR_NONE +#endif + +#if !defined(_GLIBCXX_USE_C99_MATH_TR1) +#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Various stdlib support checks that require __has_include +#if defined(__has_include) + // Check if string_view is available and usable + #if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW + #endif + + // Check if optional is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if byte is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # include + # if __cpp_lib_byte > 0 + # define CATCH_INTERNAL_CONFIG_CPP17_BYTE + # endif + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + + // Check if variant is available and usable + # if __has_include() && defined(CATCH_CPP17_OR_GREATER) + # if defined(__clang__) && (__clang_major__ < 8) + // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 + // fix should be in clang 8, workaround in libstdc++ 8.2 + # include + # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # define CATCH_CONFIG_NO_CPP17_VARIANT + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) + # else + # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT + # endif // defined(__clang__) && (__clang_major__ < 8) + # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) + +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) +# define CATCH_CONFIG_WINDOWS_SEH +#endif +// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. +#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) +# define CATCH_CONFIG_POSIX_SIGNALS +#endif +// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. +#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) +# define CATCH_CONFIG_WCHAR +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) +# define CATCH_CONFIG_CPP11_TO_STRING +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) +# define CATCH_CONFIG_CPP17_OPTIONAL +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) +# define CATCH_CONFIG_CPP17_STRING_VIEW +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) +# define CATCH_CONFIG_CPP17_VARIANT +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +# define CATCH_CONFIG_CPP17_BYTE +#endif + +#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) +# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) +# define CATCH_CONFIG_NEW_CAPTURE +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +# define CATCH_CONFIG_DISABLE_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) +# define CATCH_CONFIG_POLYFILL_ISNAN +#endif + +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +# define CATCH_CONFIG_USE_ASYNC +#endif + +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +# define CATCH_CONFIG_ANDROID_LOGWRITE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#endif + +// Even if we do not think the compiler has that warning, we still have +// to provide a macro that can be used by the code. +#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS +#endif + +// The goal of this macro is to avoid evaluation of the arguments, but +// still have the compiler warn on problems inside... +#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) +# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) +#endif + +#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#elif defined(__clang__) && (__clang_major__ < 5) +# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif + +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_TRY if ((true)) +#define CATCH_CATCH_ALL if ((false)) +#define CATCH_CATCH_ANON(type) if ((false)) +#else +#define CATCH_TRY try +#define CATCH_CATCH_ALL catch (...) +#define CATCH_CATCH_ANON(type) catch (type) +#endif + +#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) +#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#endif + +// end catch_compiler_capabilities.h +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#include +#include +#include + +// We need a dummy global operator<< so we can bring it into Catch namespace later +struct Catch_global_namespace_dummy {}; +std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); + +namespace Catch { + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; + + protected: + NonCopyable(); + virtual ~NonCopyable(); + }; + + struct SourceLineInfo { + + SourceLineInfo() = delete; + SourceLineInfo( char const* _file, std::size_t _line ) noexcept + : file( _file ), + line( _line ) + {} + + SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo( SourceLineInfo&& ) noexcept = default; + SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; + + bool empty() const noexcept { return file[0] == '\0'; } + bool operator == ( SourceLineInfo const& other ) const noexcept; + bool operator < ( SourceLineInfo const& other ) const noexcept; + + char const* file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // Bring in operator<< from global namespace into Catch namespace + // This is necessary because the overload of operator<< above makes + // lookup stop at namespace Catch + using ::operator<<; + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() const; + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO \ + ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) + +// end catch_common.h +namespace Catch { + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION + +// end catch_tag_alias_autoregistrar.h +// start catch_test_registry.h + +// start catch_interfaces_testcase.h + +#include + +namespace Catch { + + class TestSpec; + + struct ITestInvoker { + virtual void invoke () const = 0; + virtual ~ITestInvoker(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool isThrowSafe( TestCase const& testCase, IConfig const& config ); + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +// end catch_interfaces_testcase.h +// start catch_stringref.h + +#include +#include +#include +#include + +namespace Catch { + + /// A non-owning string class (similar to the forthcoming std::string_view) + /// Note that, because a StringRef may be a substring of another string, + /// it may not be null terminated. + class StringRef { + public: + using size_type = std::size_t; + using const_iterator = const char*; + + private: + static constexpr char const* const s_empty = ""; + + char const* m_start = s_empty; + size_type m_size = 0; + + public: // construction + constexpr StringRef() noexcept = default; + + StringRef( char const* rawChars ) noexcept; + + constexpr StringRef( char const* rawChars, size_type size ) noexcept + : m_start( rawChars ), + m_size( size ) + {} + + StringRef( std::string const& stdString ) noexcept + : m_start( stdString.c_str() ), + m_size( stdString.size() ) + {} + + explicit operator std::string() const { + return std::string(m_start, m_size); + } + + public: // operators + auto operator == ( StringRef const& other ) const noexcept -> bool; + auto operator != (StringRef const& other) const noexcept -> bool { + return !(*this == other); + } + + auto operator[] ( size_type index ) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } + + public: // named queries + constexpr auto empty() const noexcept -> bool { + return m_size == 0; + } + constexpr auto size() const noexcept -> size_type { + return m_size; + } + + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception + auto c_str() const -> char const*; + + public: // substrings and searches + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr( size_type start, size_type length ) const noexcept -> StringRef; + + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; + + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } + + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } + }; + + auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; + auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; + + constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + return StringRef( rawChars, size ); + } +} // namespace Catch + +constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { + return Catch::StringRef( rawChars, size ); +} + +// end catch_stringref.h +// start catch_preprocessor.hpp + + +#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ +#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) + +#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ +// MSVC needs more evaluations +#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#else +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#endif + +#define CATCH_REC_END(...) +#define CATCH_REC_OUT + +#define CATCH_EMPTY() +#define CATCH_DEFER(id) id CATCH_EMPTY() + +#define CATCH_REC_GET_END2() 0, CATCH_REC_END +#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 +#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 +#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) + +#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) + +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) + +// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, +// and passes userdata as the first parameter to each invocation, +// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ +#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ +#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) +#else +// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) +#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) +#endif + +#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ +#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) + +#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) + +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#else +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#endif + +#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ + CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) + +#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) +#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) +#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) +#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) +#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) +#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) +#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) +#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) +#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) + +#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N + +#define INTERNAL_CATCH_TYPE_GEN\ + template struct TypeList {};\ + template\ + constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ + template class...> struct TemplateTypeList{};\ + template class...Cs>\ + constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ + template\ + struct append;\ + template\ + struct rewrap;\ + template class, typename...>\ + struct create;\ + template class, typename>\ + struct convert;\ + \ + template \ + struct append { using type = T; };\ + template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ + struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ + template< template class L1, typename...E1, typename...Rest>\ + struct append, TypeList, Rest...> { using type = L1; };\ + \ + template< template class Container, template class List, typename...elems>\ + struct rewrap, List> { using type = TypeList>; };\ + template< template class Container, template class List, class...Elems, typename...Elements>\ + struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ + \ + template