From dea073d118807ca4bf0c5f6b476bad9343abfcda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20B=20Nagy?= <20251272+BNAndras@users.noreply.github.com> Date: Sat, 23 Mar 2024 07:51:23 -0700 Subject: [PATCH 01/69] Sync pangram tests (#848) --- exercises/practice/pangram/.meta/tests.toml | 18 +++++++++++++++--- exercises/practice/pangram/pangram_test.cpp | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/exercises/practice/pangram/.meta/tests.toml b/exercises/practice/pangram/.meta/tests.toml index 8075c5ba3..10b5a335a 100644 --- a/exercises/practice/pangram/.meta/tests.toml +++ b/exercises/practice/pangram/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [64f61791-508e-4f5c-83ab-05de042b0149] description = "empty sentence" @@ -31,3 +38,8 @@ description = "mixed case and punctuation" [2577bf54-83c8-402d-a64b-a2c0f7bb213a] description = "case insensitive" +include = false + +[7138e389-83e4-4c6e-8413-1e40a0076951] +description = "a-m and A-M are 26 different characters but not a pangram" +reimplements = "2577bf54-83c8-402d-a64b-a2c0f7bb213a" diff --git a/exercises/practice/pangram/pangram_test.cpp b/exercises/practice/pangram/pangram_test.cpp index 740082fbc..703352622 100644 --- a/exercises/practice/pangram/pangram_test.cpp +++ b/exercises/practice/pangram/pangram_test.cpp @@ -46,8 +46,8 @@ TEST_CASE("pangram_with_mixed_case_and_punctuation") REQUIRE(pangram::is_pangram("\"Five quacking Zephyrs jolt my wax bed.\"")); } -TEST_CASE("upper_and_lower_should_not_be_counted_separately") +TEST_CASE("a_to_m_and_A_to_M_are_26_different_characters_but_not_a_pangram") { - REQUIRE(!pangram::is_pangram("the quick brown fox jumps over with lazy FX")); + REQUIRE(!pangram::is_pangram("abcdefghijklm ABCDEFGHIJKLM")); } #endif From 89b0b56793f50027c1f279825783c1a7a2fad31d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20B=20Nagy?= <20251272+BNAndras@users.noreply.github.com> Date: Sat, 23 Mar 2024 14:26:10 -0700 Subject: [PATCH 02/69] Sync isogram tests (#849) --- exercises/practice/isogram/.meta/tests.toml | 16 +++++++++++++--- exercises/practice/isogram/isogram_test.cpp | 9 +++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/exercises/practice/isogram/.meta/tests.toml b/exercises/practice/isogram/.meta/tests.toml index 7187c340a..ba04c6645 100644 --- a/exercises/practice/isogram/.meta/tests.toml +++ b/exercises/practice/isogram/.meta/tests.toml @@ -1,6 +1,13 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# 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. [a0e97d2d-669e-47c7-8134-518a1e2c4555] description = "empty string" @@ -40,3 +47,6 @@ description = "duplicated character in the middle" [310ac53d-8932-47bc-bbb4-b2b94f25a83e] description = "same first and last characters" + +[0d0b8644-0a1e-4a31-a432-2b3ee270d847] +description = "word with duplicated character and with two hyphens" diff --git a/exercises/practice/isogram/isogram_test.cpp b/exercises/practice/isogram/isogram_test.cpp index 7e8085b25..eeea4c83a 100644 --- a/exercises/practice/isogram/isogram_test.cpp +++ b/exercises/practice/isogram/isogram_test.cpp @@ -127,4 +127,13 @@ TEST_CASE("same_first_and_last_characters") REQUIRE(expected == actual); } +TEST_CASE("word_with_duplicated_character_and_with_two_hyphens") +{ + const bool actual = isogram::is_isogram("up-to-date"); + + const bool expected {false}; + + REQUIRE(expected == actual); +} + #endif From fadf06a4bc6f5f0ce921180cef819dd15330532c Mon Sep 17 00:00:00 2001 From: Christian Willner <34183939+vaeng@users.noreply.github.com> Date: Wed, 27 Mar 2024 09:51:25 +0100 Subject: [PATCH 03/69] fix: vector-approx macro (#840) --- exercises/concept/lasagna-master/lasagna_master_test.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/exercises/concept/lasagna-master/lasagna_master_test.cpp b/exercises/concept/lasagna-master/lasagna_master_test.cpp index cf3ec60d7..66ae15fe6 100644 --- a/exercises/concept/lasagna-master/lasagna_master_test.cpp +++ b/exercises/concept/lasagna-master/lasagna_master_test.cpp @@ -5,6 +5,8 @@ #include "test/catch.hpp" #endif +#include + using namespace lasagna_master; // As long as we have catch2 v2 and v3 in parallel, we can't use either @@ -12,7 +14,7 @@ using namespace lasagna_master; #define REQUIRE_VECTOR_APROX_EQUAL(vec1, vec2, margin) \ REQUIRE(vec1.size() == vec2.size()); \ for (size_t i = 0; i < vec1.size(); i++) { \ - REQUIRE( vec1.at(i) - vec2.at(i) < margin); \ + REQUIRE( std::abs(vec1.at(i) - vec2.at(i)) < margin); \ } TEST_CASE("preparationTime: Preparation time for many layers with custom average time", "[task_1]") { From 17fc5b67493da969e4c2d1909c393ad9f1406ffe Mon Sep 17 00:00:00 2001 From: Exercism Bot Date: Wed, 27 Mar 2024 21:07:21 +0000 Subject: [PATCH 04/69] =?UTF-8?q?=F0=9F=A4=96=20Sync=20org-wide=20files=20?= =?UTF-8?q?to=20upstream=20repo=20(#851)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit More info: https://github.com/exercism/org-wide-files/commit/45ce43faa93a84c84f407748aae3aa028383ec77 --- .github/workflows/no-important-files-changed.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/no-important-files-changed.yml b/.github/workflows/no-important-files-changed.yml index b940c5991..812e91296 100644 --- a/.github/workflows/no-important-files-changed.yml +++ b/.github/workflows/no-important-files-changed.yml @@ -16,7 +16,7 @@ permissions: pull-requests: write jobs: - pause: + check: uses: exercism/github-actions/.github/workflows/check-no-important-files-changed.yml@main with: repository: ${{ github.event.pull_request.head.repo.owner.login }}/${{ github.event.pull_request.head.repo.name }} From 0caa281030e999ca4b1cae23a7086c7210ba3058 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Mon, 1 Apr 2024 08:57:58 +0200 Subject: [PATCH 05/69] Sync the `sieve` exercise's docs with the latest data. (#853) --- .../practice/sieve/.docs/instructions.md | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/exercises/practice/sieve/.docs/instructions.md b/exercises/practice/sieve/.docs/instructions.md index 3adf1d551..085c0a57d 100644 --- a/exercises/practice/sieve/.docs/instructions.md +++ b/exercises/practice/sieve/.docs/instructions.md @@ -1,28 +1,42 @@ # Instructions -Your task is to create a program that implements the Sieve of Eratosthenes algorithm to find prime numbers. +Your task is to create a program that implements the Sieve of Eratosthenes algorithm to find all prime numbers less than or equal to a given number. -A prime number is a number that is only divisible by 1 and itself. +A prime number is a number larger than 1 that is only divisible by 1 and itself. For example, 2, 3, 5, 7, 11, and 13 are prime numbers. - -The Sieve of Eratosthenes is an ancient algorithm that works by taking a list of numbers and crossing out all the numbers that aren't prime. - -A number that is **not** prime is called a "composite number". +By contrast, 6 is _not_ a prime number as it not only divisible by 1 and itself, but also by 2 and 3. To use the Sieve of Eratosthenes, you first create a list of all the numbers between 2 and your given number. Then you repeat the following steps: -1. Find the next unmarked number in your list. This is a prime number. -2. Mark all the multiples of that prime number as composite (not prime). +1. Find the next unmarked number in your list (skipping over marked numbers). + This is a prime number. +2. Mark all the multiples of that prime number as **not** prime. You keep repeating these steps until you've gone through every number in your list. At the end, all the unmarked numbers are prime. ~~~~exercism/note -[Wikipedia's Sieve of Eratosthenes article][eratosthenes] has a useful graphic that explains the algorithm. - The tests don't check that you've implemented the algorithm, only that you've come up with the correct list of primes. -A good first test is to check that you do not use division or remainder operations. - -[eratosthenes]: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes +To check you are implementing the Sieve correctly, a good first test is to check that you do not use division or remainder operations. ~~~~ + +## Example + +Let's say you're finding the primes less than or equal to 10. + +- List out 2, 3, 4, 5, 6, 7, 8, 9, 10, leaving them all unmarked. +- 2 is unmarked and is therefore a prime. + Mark 4, 6, 8 and 10 as "not prime". +- 3 is unmarked and is therefore a prime. + Mark 6 and 9 as not prime _(marking 6 is optional - as it's already been marked)_. +- 4 is marked as "not prime", so we skip over it. +- 5 is unmarked and is therefore a prime. + Mark 10 as not prime _(optional - as it's already been marked)_. +- 6 is marked as "not prime", so we skip over it. +- 7 is unmarked and is therefore a prime. +- 8 is marked as "not prime", so we skip over it. +- 9 is marked as "not prime", so we skip over it. +- 10 is marked as "not prime", so we stop as there are no more numbers to check. + +You've examined all numbers and found 2, 3, 5, and 7 are still unmarked, which means they're the primes less than or equal to 10. From 5041ca50449a910633bf0bdc7ff3ac53e9874199 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Mon, 1 Apr 2024 08:58:18 +0200 Subject: [PATCH 06/69] Sync the `two-fer` exercise's docs with the latest data. (#854) --- exercises/practice/two-fer/.docs/instructions.md | 5 ++--- exercises/practice/two-fer/.docs/introduction.md | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/exercises/practice/two-fer/.docs/instructions.md b/exercises/practice/two-fer/.docs/instructions.md index 37aa75297..adc534879 100644 --- a/exercises/practice/two-fer/.docs/instructions.md +++ b/exercises/practice/two-fer/.docs/instructions.md @@ -2,14 +2,13 @@ Your task is to determine what you will say as you give away the extra cookie. -If your friend likes cookies, and is named Do-yun, then you will say: +If you know the person's name (e.g. if they're named Do-yun), then you will say: ```text One for Do-yun, one for me. ``` -If your friend doesn't like cookies, you give the cookie to the next person in line at the bakery. -Since you don't know their name, you will say _you_ instead. +If you don't know the person's name, you will say _you_ instead. ```text One for you, one for me. diff --git a/exercises/practice/two-fer/.docs/introduction.md b/exercises/practice/two-fer/.docs/introduction.md index 8c124394a..5947a2230 100644 --- a/exercises/practice/two-fer/.docs/introduction.md +++ b/exercises/practice/two-fer/.docs/introduction.md @@ -5,4 +5,4 @@ Two-for-one is a way of saying that if you buy one, you also get one for free. So the phrase "two-fer" often implies a two-for-one offer. Imagine a bakery that has a holiday offer where you can buy two cookies for the price of one ("two-fer one!"). -You go for the offer and (very generously) decide to give the extra cookie to a friend. +You take the offer and (very generously) decide to give the extra cookie to someone else in the queue. From fc46fcd02e631ac3d4719d3f8088e15aa03fe5b2 Mon Sep 17 00:00:00 2001 From: Alexander Hans Date: Tue, 9 Apr 2024 09:56:13 +0200 Subject: [PATCH 07/69] fix(check-formatting.sh): use relative directory (#835) The `bin/check-formatting.sh` script changed its directory to `bin` as the first step, consequently expecting paths of files to check to be relative to `bin`, when typically they would be given relative to the working directory. When not finding a file, the script would just print a warning, but still exit with error code 0, which is probably the reason why this went unnoticed for quite a while. This commit fixes the relative directory issue. Further, when a given path cannot be checked, we return a non-zero code now. Lastly, the script would count the number of files with formatting issues and return that number as error code. This has the issue that if the number of violating files is a multiple of 256, error code would falsly be returned. --- bin/check-formatting.sh | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/bin/check-formatting.sh b/bin/check-formatting.sh index ae2708743..81b3a42f9 100755 --- a/bin/check-formatting.sh +++ b/bin/check-formatting.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +set -e print_help() { echo "This script verifies if one or more files are formatted using the provided" @@ -13,8 +14,6 @@ print_help() { echo " warnings are returned for each invalid path." } -cd "$(dirname "$0")" - # Get files list FILES=() while [[ $# -gt 0 ]] @@ -31,40 +30,24 @@ do shift done -# Verifies a single file is formatted following .clang-format style -run_check() { - local FILE="$1" - CHECK_RESULT=0 - # Get diff between current content and formatted content - local OUTPUT=$(diff -u <(cat "$FILE") <(clang-format --style=file "$FILE")) - # Shows diff output only if files are different - if [[ $OUTPUT != "" ]]; then - echo "$OUTPUT" - CHECK_RESULT=1 - fi -} - -# Result of this script, incremented by one for each unformatted file +# Result of this script RESULT=0 -# List of warnings -WARNINGS=() # Iterate files to run format check for INDEX in "${!FILES[@]}"; do FILE="${FILES[$INDEX]}" if [[ -f "$FILE" ]]; then - run_check $FILE - RESULT=$(( RESULT + CHECK_RESULT )) + if ! clang-format --dry-run --Werror "$FILE"; then + RESULT=1 + fi elif [[ -d "$FILE" ]]; then - WARNINGS+=("Path is a directory: $FILE") + echo "Path is a directory: $FILE" + RESULT=1 else - WARNINGS+=("File not found: $FILE") + echo "File not found: $FILE" + RESULT=1 fi done -for INDEX in "${!WARNINGS[@]}"; do - echo "${WARNINGS[$INDEX]}" -done - echo "Done" exit $RESULT From 38eaa89d373f12ca44590c032e61f658996a6683 Mon Sep 17 00:00:00 2001 From: Christian Willner <34183939+vaeng@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:57:49 +0200 Subject: [PATCH 08/69] feat: add literals concept (#847) --- concepts/literals/.meta/config.json | 8 +++ concepts/literals/about.md | 75 +++++++++++++++++++++++++++++ concepts/literals/introduction.md | 75 +++++++++++++++++++++++++++++ concepts/literals/links.json | 6 +++ config.json | 5 ++ 5 files changed, 169 insertions(+) create mode 100644 concepts/literals/.meta/config.json create mode 100644 concepts/literals/about.md create mode 100644 concepts/literals/introduction.md create mode 100644 concepts/literals/links.json diff --git a/concepts/literals/.meta/config.json b/concepts/literals/.meta/config.json new file mode 100644 index 000000000..2be09684a --- /dev/null +++ b/concepts/literals/.meta/config.json @@ -0,0 +1,8 @@ +{ + "blurb": "C++ literals represent fixed values, including strings and different numeric formats.", + "authors": [ + "vaeng" + ], + "contributors": [ + ] +} diff --git a/concepts/literals/about.md b/concepts/literals/about.md new file mode 100644 index 000000000..c32446754 --- /dev/null +++ b/concepts/literals/about.md @@ -0,0 +1,75 @@ +# About + +Literals are fixed values that are used directly in code. +They do not need any computation during run-time. +They come in various forms to represent different types of data efficiently. +The most frequent literals are of numeric nature, but there are also literal operators for date, time and string types. +A later concept will show how user-defined literal operators can be used. + +## Numeric Literals + +Numeric literals include decimal, octal, hexadecimal, and binary representations. +These basics were already covered in the [numbers concept][numbers-concept]. + +All representations like `23`, `0x50f7ba11` and `0xba5eba11` are understood as `int` by the compiler. +The general `int` type is signed and ([depending on the compiler and the system][in-depth-integers]), often has a range of `-2'147'483'648` to `2'147'483'647`. +This is sufficient most of the time and you don't need to worry about the specific type. + +Some use-cases demand larger ranges or very small memory footprints of programs. +To be explicit one can directly state specific integer types with the numeric literal. + +When negative numbers aren't needed, but the added range is desired the `u` or `U` suffix are used for _unsigned_ integers. +For greater ranges `L` or even `LL` can be used for long and long long types. + +~~~~exercism/caution +The use of lower-case `l` is permitted, but it is easily confused with the number `1` and thus discouraged. +~~~~ + +```cpp +auto net_worth_christian_grey{2'500'000'000U}; // out of range for 32-bit integers +auto net_worth_carlisle_cullen{46'000'000'000LL}; // int and uint are not enough +``` + +Floating-point numbers usually resolve to `double` during compilation. +This is a good default case and use-cases with the narrower `float` type are less frequent than the unsigned example above. + +```cpp +auto light_year_in_m{9.46073e+15f}; // well in the range of float +auto earth_to_edge_comoving_distance_in_nm{4.32355e+32}; // needs double type for magnitude +auto eulers_number{2.718281828459045d}; // needs double type for precision +``` + +~~~~exercism/advanced +## Character and String Literals + +Other concepts already used character literals with single quotes like `'}'` or `'@'`. + +In C++ `char` is limited to the first 128 [ascii character codes][ascii-code]. +To use several ascii chars or extended ascii characters like `‰` or even unicode characters like `麗` and `ẞ` other types are needed. +In previous concept string literals were introduced with _double quotes_: `"一体どういう意味ですか。C++です"`. +The actual type of this Japanese phrase is `const char (&)[46]`, a C-style string. + +The use of string literals is not activated by default. +To use the _string_ literal `""s` or the _string-view_ literal `""sv`, the user has to specify their use by using the related namespace: + +```cpp +#include +#include + +using namespace std::literals; + +auto green_light{"무궁화 꽃 이 피었 습니다"}; +// green_light type is const char (&)[36] +auto umbrella{"달고나"s}; +// umbrella type is std::basic_string, the same as std::string +auto il_nam{"보는 것이 하는 것보다 더 재미있을 수가 없지"sv}; +// il_nam type is std::basic_string_view +``` + +A _string_view_ can be seen as a reference to a const string. + +~~~~ + +[numbers-concept]: https://exercism.org/tracks/cpp/concepts/numbers +[in-depth-integers]: https://www.learncpp.com/cpp-tutorial/fixed-width-integers-and-size-t/ +[ascii-code]: https://www.ascii-code.com/ diff --git a/concepts/literals/introduction.md b/concepts/literals/introduction.md new file mode 100644 index 000000000..e89c7b112 --- /dev/null +++ b/concepts/literals/introduction.md @@ -0,0 +1,75 @@ +# Introduction + +Literals are fixed values that are used directly in code. +They do not need any computation during run-time. +They come in various forms to represent different types of data efficiently. +The most frequent literals are of numeric nature, but there are also literal operators for date, time and string types. +A later concept will show how user-defined literal operators can be used. + +## Numeric Literals + +Numeric literals include decimal, octal, hexadecimal, and binary representations. +These basics were already covered in the [numbers concept][numbers-concept]. + +All representations like `23`, `0x50f7ba11` and `0xba5eba11` are understood as `int` by the compiler. +The general `int` type is signed and ([depending on the compiler and the system][in-depth-integers]), often has a range of `-2'147'483'648` to `2'147'483'647`. +This is sufficient most of the time and you don't need to worry about the specific type. + +Some use-cases demand larger ranges or very small memory footprints of programs. +To be explicit one can directly state specific integer types with the numeric literal. + +When negative numbers aren't needed, but the added range is desired the `u` or `U` suffix are used for _unsigned_ integers. +For greater ranges `L` or even `LL` can be used for long and long long types. + +~~~~exercism/caution +The use of lower-case `l` is permitted, but it is easily confused with the number `1` and thus discouraged. +~~~~ + +```cpp +auto net_worth_christian_grey{2'500'000'000U}; // out of range for 32-bit integers +auto net_worth_carlisle_cullen{46'000'000'000LL}; // int and uint are not enough +``` + +Floating-point numbers usually resolve to `double` during compilation. +This is a good default case and use-cases with the narrower `float` type are less frequent than the unsigned example above. + +```cpp +auto light_year_in_m{9.46073e+15f}; // well in the range of float +auto earth_to_edge_comoving_distance_in_nm{4.32355e+32}; // needs double type for magnitude +auto eulers_number{2.718281828459045d}; // needs double type for precision +``` + +~~~~exercism/advanced +## Character and String Literals + +Other concepts already used character literals with single quotes like `'}'` or `'@'`. + +In C++ `char` is limited to the first 128 [ascii character codes][ascii-code]. +To use several ascii chars or extended ascii characters like `‰` or even unicode characters like `麗` and `ẞ` other types are needed. +In previous concept string literals were introduced with _double quotes_: `"一体どういう意味ですか。C++です"`. +The actual type of this Japanese phrase is `const char (&)[46]`, a C-style string. + +The use of string literals is not activated by default. +To use the _string_ literal `""s` or the _string-view_ literal `""sv`, the user has to specify their use by using the related namespace: + +```cpp +#include +#include + +using namespace std::literals; + +auto green_light{"무궁화 꽃 이 피었 습니다"}; +// green_light type is const char (&)[36] +auto umbrella{"달고나"s}; +// umbrella type is std::basic_string, the same as std::string +auto il_nam{"보는 것이 하는 것보다 더 재미있을 수가 없지"sv}; +// il_nam type is std::basic_string_view +``` + +A _string_view_ can be seen as a reference to a const string. + +~~~~ + +[numbers-concept]: https://exercism.org/tracks/cpp/concepts/numbers +[in-depth-integers]: https://www.learncpp.com/cpp-tutorial/fixed-width-integers-and-size-t/ +[ascii-code]: https://www.ascii-code.com/ diff --git a/concepts/literals/links.json b/concepts/literals/links.json new file mode 100644 index 000000000..1b9edf60d --- /dev/null +++ b/concepts/literals/links.json @@ -0,0 +1,6 @@ +[ + { + "url": "https://www.learncpp.com/cpp-tutorial/literals/", + "description": "Learn C++ overview on literals" + } +] \ No newline at end of file diff --git a/config.json b/config.json index 503b43a67..6227107de 100644 --- a/config.json +++ b/config.json @@ -1294,6 +1294,11 @@ "uuid": "da0a69e5-33ec-4458-8c70-80457715ada6", "slug": "auto", "name": "Auto" + }, + { + "uuid": "5de475cc-5321-476f-bd19-a82b60284f5a", + "slug": "literals", + "name": "Literals" } ], "key_features": [ From 95d650d7249e4e7ff87c52bd5951945b56a23155 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 13:04:04 +0200 Subject: [PATCH 09/69] build(deps): bump actions/checkout from 4.1.2 to 4.1.3 (#862) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/9bb56186c3b09b4f86b1c65136769dd318469633...1d96c772d19495a3b5c517cd2bc0cb401ea0529f) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/hello-world.yml | 2 +- .github/workflows/verify-code-formatting.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9170552d..79eaa595d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: matrix: compiler: [clang++-6.0, g++-10] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f - name: Install Dependencies # Boost must be installed only because the CMake version (3.12) can't # detect the installed Boost version (1.69) @@ -37,7 +37,7 @@ jobs: matrix: compiler: [clang++, g++] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f - 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@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f - 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@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f - name: Install Boost run: brew install boost - name: Run Tests diff --git a/.github/workflows/hello-world.yml b/.github/workflows/hello-world.yml index 0bb255741..dfdbb579b 100644 --- a/.github/workflows/hello-world.yml +++ b/.github/workflows/hello-world.yml @@ -21,7 +21,7 @@ jobs: name: Hello World Fails runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f - name: Check Hello World Fails run: bin/check-hello-world.sh env: diff --git a/.github/workflows/verify-code-formatting.yml b/.github/workflows/verify-code-formatting.yml index e3f79d2ac..9e41bf33a 100644 --- a/.github/workflows/verify-code-formatting.yml +++ b/.github/workflows/verify-code-formatting.yml @@ -21,7 +21,7 @@ jobs: runs-on: [ubuntu-22.04] steps: - name: "Checkout code" - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + uses: actions/checkout@1d96c772d19495a3b5c517cd2bc0cb401ea0529f - name: "Verify formatting of all files" if: github.ref == 'refs/heads/master' From b10d38b9063fb4e73706f75a14ffdaea9d3e00eb Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Tue, 23 Apr 2024 13:04:33 +0200 Subject: [PATCH 10/69] Sync the `scrabble-score` exercise's docs with the latest data. (#858) --- .../scrabble-score/.docs/instructions.md | 47 +++++++------------ .../scrabble-score/.docs/introduction.md | 7 +++ 2 files changed, 23 insertions(+), 31 deletions(-) create mode 100644 exercises/practice/scrabble-score/.docs/introduction.md diff --git a/exercises/practice/scrabble-score/.docs/instructions.md b/exercises/practice/scrabble-score/.docs/instructions.md index 3f986c947..738f928c5 100644 --- a/exercises/practice/scrabble-score/.docs/instructions.md +++ b/exercises/practice/scrabble-score/.docs/instructions.md @@ -1,40 +1,25 @@ # Instructions -Given a word, compute the Scrabble score for that word. +Your task is to compute a word's Scrabble score by summing the values of its letters. -## Letter Values +The letters are valued as follows: -You'll need these: +| Letter | Value | +| ---------------------------- | ----- | +| A, E, I, O, U, L, N, R, S, T | 1 | +| D, G | 2 | +| B, C, M, P | 3 | +| F, H, V, W, Y | 4 | +| K | 5 | +| J, X | 8 | +| Q, Z | 10 | -```text -Letter Value -A, E, I, O, U, L, N, R, S, T 1 -D, G 2 -B, C, M, P 3 -F, H, V, W, Y 4 -K 5 -J, X 8 -Q, Z 10 -``` - -## Examples - -"cabbage" should be scored as worth 14 points: +For example, the word "cabbage" is worth 14 points: - 3 points for C -- 1 point for A, twice -- 3 points for B, twice +- 1 point for A +- 3 points for B +- 3 points for B +- 1 point for A - 2 points for G - 1 point for E - -And to total: - -- `3 + 2*1 + 2*3 + 2 + 1` -- = `3 + 2 + 6 + 3` -- = `5 + 9` -- = 14 - -## Extensions - -- You can play a double or a triple letter. -- You can play a double or a triple word. diff --git a/exercises/practice/scrabble-score/.docs/introduction.md b/exercises/practice/scrabble-score/.docs/introduction.md new file mode 100644 index 000000000..8821f240b --- /dev/null +++ b/exercises/practice/scrabble-score/.docs/introduction.md @@ -0,0 +1,7 @@ +# Introduction + +[Scrabble][wikipedia] is a word game where players place letter tiles on a board to form words. +Each letter has a value. +A word's score is the sum of its letters' values. + +[wikipedia]: https://en.wikipedia.org/wiki/Scrabble From 877a1be009adf602608ca4543866fb9b28b4b57e Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Tue, 23 Apr 2024 13:04:58 +0200 Subject: [PATCH 11/69] Sync the `minesweeper` exercise's docs with the latest data. (#859) --- .../minesweeper/.docs/instructions.md | 20 +++++++------------ .../minesweeper/.docs/introduction.md | 5 +++++ 2 files changed, 12 insertions(+), 13 deletions(-) create mode 100644 exercises/practice/minesweeper/.docs/introduction.md diff --git a/exercises/practice/minesweeper/.docs/instructions.md b/exercises/practice/minesweeper/.docs/instructions.md index f5f918bdf..7c1df2e4b 100644 --- a/exercises/practice/minesweeper/.docs/instructions.md +++ b/exercises/practice/minesweeper/.docs/instructions.md @@ -1,19 +1,13 @@ # Instructions -Add the mine counts to a completed Minesweeper board. +Your task is to add the mine counts to empty squares in a completed Minesweeper board. +The board itself is a rectangle composed of squares that are either empty (`' '`) or a mine (`'*'`). -Minesweeper is a popular game where the user has to find the mines using numeric hints that indicate how many mines are directly adjacent (horizontally, vertically, diagonally) to a square. +For each empty square, count the number of mines adjacent to it (horizontally, vertically, diagonally). +If the empty square has no adjacent mines, leave it empty. +Otherwise replace it with the adjacent mines count. -In this exercise you have to create some code that counts the number of mines adjacent to a given empty square and replaces that square with the count. - -The board is a rectangle composed of blank space (' ') characters. -A mine is represented by an asterisk (`*`) character. - -If a given space has no adjacent mines at all, leave that square blank. - -## Examples - -For example you may receive a 5 x 4 board like this (empty spaces are represented here with the '·' character for display on screen): +For example, you may receive a 5 x 4 board like this (empty spaces are represented here with the '·' character for display on screen): ```text ·*·*· @@ -22,7 +16,7 @@ For example you may receive a 5 x 4 board like this (empty spaces are represente ····· ``` -And your code will transform it into this: +Which your code should transform into this: ```text 1*3*1 diff --git a/exercises/practice/minesweeper/.docs/introduction.md b/exercises/practice/minesweeper/.docs/introduction.md new file mode 100644 index 000000000..5f74a742b --- /dev/null +++ b/exercises/practice/minesweeper/.docs/introduction.md @@ -0,0 +1,5 @@ +# Introduction + +[Minesweeper][wikipedia] is a popular game where the user has to find the mines using numeric hints that indicate how many mines are directly adjacent (horizontally, vertically, diagonally) to a square. + +[wikipedia]: https://en.wikipedia.org/wiki/Minesweeper_(video_game) From a43701f83eb9b40f6f20d3c7d27b4d2e548e0ea9 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Tue, 23 Apr 2024 13:05:29 +0200 Subject: [PATCH 12/69] Sync the `dnd-character` exercise's docs with the latest data. (#860) --- .../practice/dnd-character/.docs/instructions.md | 11 ++++++----- .../practice/dnd-character/.docs/introduction.md | 10 ++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 exercises/practice/dnd-character/.docs/introduction.md diff --git a/exercises/practice/dnd-character/.docs/instructions.md b/exercises/practice/dnd-character/.docs/instructions.md index b0a603591..e14e7949d 100644 --- a/exercises/practice/dnd-character/.docs/instructions.md +++ b/exercises/practice/dnd-character/.docs/instructions.md @@ -3,13 +3,13 @@ For a game of [Dungeons & Dragons][dnd], each player starts by generating a character they can play with. This character has, among other things, six abilities; strength, dexterity, constitution, intelligence, wisdom and charisma. These six abilities have scores that are determined randomly. -You do this by rolling four 6-sided dice and record the sum of the largest three dice. +You do this by rolling four 6-sided dice and recording the sum of the largest three dice. You do this six times, once for each ability. Your character's initial hitpoints are 10 + your character's constitution modifier. You find your character's constitution modifier by subtracting 10 from your character's constitution, divide by 2 and round down. -Write a random character generator that follows the rules above. +Write a random character generator that follows the above rules. For example, the six throws of four dice may look like: @@ -22,10 +22,11 @@ For example, the six throws of four dice may look like: Because constitution is 3, the constitution modifier is -4 and the hitpoints are 6. -## Notes - +~~~~exercism/note Most programming languages feature (pseudo-)random generators, but few programming languages are designed to roll dice. One such language is [Troll][troll]. -[dnd]: https://en.wikipedia.org/wiki/Dungeons_%26_Dragons [troll]: https://di.ku.dk/Ansatte/?pure=da%2Fpublications%2Ftroll-a-language-for-specifying-dicerolls(84a45ff0-068b-11df-825d-000ea68e967b)%2Fexport.html +~~~~ + +[dnd]: https://en.wikipedia.org/wiki/Dungeons_%26_Dragons diff --git a/exercises/practice/dnd-character/.docs/introduction.md b/exercises/practice/dnd-character/.docs/introduction.md new file mode 100644 index 000000000..5301f6182 --- /dev/null +++ b/exercises/practice/dnd-character/.docs/introduction.md @@ -0,0 +1,10 @@ +# Introduction + +After weeks of anticipation, you and your friends get together for your very first game of [Dungeons & Dragons][dnd] (D&D). +Since this is the first session of the game, each player has to generate a character to play with. +The character's abilities are determined by rolling 6-sided dice, but where _are_ the dice? +With a shock, you realize that your friends are waiting for _you_ to produce the dice; after all it was your idea to play D&D! +Panicking, you realize you forgot to bring the dice, which would mean no D&D game. +As you have some basic coding skills, you quickly come up with a solution: you'll write a program to simulate dice rolls. + +[dnd]: https://en.wikipedia.org/wiki/Dungeons_%26_Dragons From 1a053766a0ef108604b3994aef17c817e22345ad Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Tue, 23 Apr 2024 13:06:17 +0200 Subject: [PATCH 13/69] Sync the `all-your-base` exercise's docs with the latest data. (#861) --- .../all-your-base/.docs/instructions.md | 21 +++++++------------ .../all-your-base/.docs/introduction.md | 8 +++++++ 2 files changed, 16 insertions(+), 13 deletions(-) create mode 100644 exercises/practice/all-your-base/.docs/introduction.md diff --git a/exercises/practice/all-your-base/.docs/instructions.md b/exercises/practice/all-your-base/.docs/instructions.md index 4602b5cfa..1b688b691 100644 --- a/exercises/practice/all-your-base/.docs/instructions.md +++ b/exercises/practice/all-your-base/.docs/instructions.md @@ -1,14 +1,11 @@ # Instructions -Convert a number, represented as a sequence of digits in one base, to any other base. +Convert a sequence of digits in one base, representing a number, into a sequence of digits in another base, representing the same number. -Implement general base conversion. -Given a number in base **a**, represented as a sequence of digits, convert it to base **b**. - -## Note - -- Try to implement the conversion yourself. - Do not use something else to perform the conversion for you. +~~~~exercism/note +Try to implement the conversion yourself. +Do not use something else to perform the conversion for you. +~~~~ ## About [Positional Notation][positional-notation] @@ -16,17 +13,15 @@ In positional notation, a number in base **b** can be understood as a linear com The number 42, _in base 10_, means: -`(4 * 10^1) + (2 * 10^0)` +`(4 × 10¹) + (2 × 10⁰)` The number 101010, _in base 2_, means: -`(1 * 2^5) + (0 * 2^4) + (1 * 2^3) + (0 * 2^2) + (1 * 2^1) + (0 * 2^0)` +`(1 × 2⁵) + (0 × 2⁴) + (1 × 2³) + (0 × 2²) + (1 × 2¹) + (0 × 2⁰)` The number 1120, _in base 3_, means: -`(1 * 3^3) + (1 * 3^2) + (2 * 3^1) + (0 * 3^0)` - -I think you got the idea! +`(1 × 3³) + (1 × 3²) + (2 × 3¹) + (0 × 3⁰)` _Yes. Those three numbers above are exactly the same. Congratulations!_ diff --git a/exercises/practice/all-your-base/.docs/introduction.md b/exercises/practice/all-your-base/.docs/introduction.md new file mode 100644 index 000000000..68aaffbed --- /dev/null +++ b/exercises/practice/all-your-base/.docs/introduction.md @@ -0,0 +1,8 @@ +# Introduction + +You've just been hired as professor of mathematics. +Your first week went well, but something is off in your second week. +The problem is that every answer given by your students is wrong! +Luckily, your math skills have allowed you to identify the problem: the student answers _are_ correct, but they're all in base 2 (binary)! +Amazingly, it turns out that each week, the students use a different base. +To help you quickly verify the student answers, you'll be building a tool to translate between bases. From b7268352c5c0d8381d33a9cebf605c71424a6906 Mon Sep 17 00:00:00 2001 From: Rajat Nai <96529504+rajatnai49@users.noreply.github.com> Date: Tue, 23 Apr 2024 16:37:49 +0530 Subject: [PATCH 14/69] Add practice exercise Zebra Puzzle (#788) --- config.json | 8 + .../zebra-puzzle/.docs/instructions.md | 6 + .../zebra-puzzle/.docs/introduction.md | 24 + .../practice/zebra-puzzle/.meta/config.json | 19 + .../practice/zebra-puzzle/.meta/example.cpp | 266 + .../practice/zebra-puzzle/.meta/example.h | 17 + .../practice/zebra-puzzle/.meta/tests.toml | 17 + .../practice/zebra-puzzle/CMakeLists.txt | 64 + .../practice/zebra-puzzle/test/catch.hpp | 17937 ++++++++++++++++ .../practice/zebra-puzzle/test/tests-main.cpp | 2 + .../practice/zebra-puzzle/zebra_puzzle.cpp | 3 + .../practice/zebra-puzzle/zebra_puzzle.h | 15 + .../zebra-puzzle/zebra_puzzle_test.cpp | 18 + 13 files changed, 18396 insertions(+) create mode 100644 exercises/practice/zebra-puzzle/.docs/instructions.md create mode 100644 exercises/practice/zebra-puzzle/.docs/introduction.md create mode 100644 exercises/practice/zebra-puzzle/.meta/config.json create mode 100644 exercises/practice/zebra-puzzle/.meta/example.cpp create mode 100644 exercises/practice/zebra-puzzle/.meta/example.h create mode 100644 exercises/practice/zebra-puzzle/.meta/tests.toml create mode 100644 exercises/practice/zebra-puzzle/CMakeLists.txt create mode 100644 exercises/practice/zebra-puzzle/test/catch.hpp create mode 100644 exercises/practice/zebra-puzzle/test/tests-main.cpp create mode 100644 exercises/practice/zebra-puzzle/zebra_puzzle.cpp create mode 100644 exercises/practice/zebra-puzzle/zebra_puzzle.h create mode 100644 exercises/practice/zebra-puzzle/zebra_puzzle_test.cpp diff --git a/config.json b/config.json index 6227107de..935751bff 100644 --- a/config.json +++ b/config.json @@ -1123,6 +1123,14 @@ "prerequisites": [], "difficulty": 5 }, + { + "slug": "zebra-puzzle", + "name": "Zebra Puzzle", + "uuid": "2badf89b-efc4-46f1-af8d-b7d2440e61c0", + "practices": [], + "prerequisites": [], + "difficulty": 7 + }, { "slug": "list-ops", "name": "List Ops", diff --git a/exercises/practice/zebra-puzzle/.docs/instructions.md b/exercises/practice/zebra-puzzle/.docs/instructions.md new file mode 100644 index 000000000..c435573ef --- /dev/null +++ b/exercises/practice/zebra-puzzle/.docs/instructions.md @@ -0,0 +1,6 @@ +# Instructions + +Your task is to solve the ‘Zebra Puzzle’ also known as ‘The Einstein's Puzzle’ but how you do it that depends on you, best way to solve this problem is first you solve it with your pen and paper, it will take time but it will improve your logical thinking and its provide programmatic way to solve this problem. + +**!!Spoiler warning!!** +You can learn more about this problem on [Zebra Puzzle](https://en.wikipedia.org/wiki/Zebra_Puzzle) diff --git a/exercises/practice/zebra-puzzle/.docs/introduction.md b/exercises/practice/zebra-puzzle/.docs/introduction.md new file mode 100644 index 000000000..6d62d18e4 --- /dev/null +++ b/exercises/practice/zebra-puzzle/.docs/introduction.md @@ -0,0 +1,24 @@ +# Instructions + +Solve the zebra puzzle. + +1. There are five houses. +2. The Englishman lives in the red house. +3. The Spaniard owns the dog. +4. Coffee is drunk in the green house. +5. The Ukrainian drinks tea. +6. The green house is immediately to the right of the ivory house. +7. The Old Gold smoker owns snails. +8. Kools are smoked in the yellow house. +9. Milk is drunk in the middle house. +10. The Norwegian lives in the first house. +11. The man who smokes Chesterfields lives in the house next to the man with the fox. +12. Kools are smoked in the house next to the house where the horse is kept. +13. The Lucky Strike smoker drinks orange juice. +14. The Japanese smokes Parliaments. +15. The Norwegian lives next to the blue house. + +Each of the five houses is painted a different color, and their inhabitants are of different national extractions, own different pets, drink different beverages and smoke different brands of cigarettes. + +Which of the residents drinks water? +Who owns the zebra? diff --git a/exercises/practice/zebra-puzzle/.meta/config.json b/exercises/practice/zebra-puzzle/.meta/config.json new file mode 100644 index 000000000..b733b8033 --- /dev/null +++ b/exercises/practice/zebra-puzzle/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": ["rajatnai49", "siebenschlaefer"], + "files": { + "solution": [ + "zebra_puzzle.cpp", + "zebra_puzzle.h" + ], + "test": [ + "zebra_puzzle_test.cpp" + ], + "example": [ + ".meta/example.cpp", + ".meta/example.h" + ] + }, + "blurb": "Solve the zebra puzzle.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Zebra_Puzzle" +} diff --git a/exercises/practice/zebra-puzzle/.meta/example.cpp b/exercises/practice/zebra-puzzle/.meta/example.cpp new file mode 100644 index 000000000..f6926e9ed --- /dev/null +++ b/exercises/practice/zebra-puzzle/.meta/example.cpp @@ -0,0 +1,266 @@ +#include +#include +#include +#include +#include + +#include "zebra_puzzle.h" + +using namespace std; + +namespace zebra_puzzle { + +enum Color { Red, Green, Ivory, Yellow, Blue }; +enum Nationality { Englishman, Spaniard, Ukrainian, Norwegian, Japanese }; +enum Pet { Dog, Snails, Fox, Horse, Zebra }; +enum Drink { Tea, Coffee, Milk, OrangeJuice, Water }; +enum Cigarette { OldGold, Kools, Chesterfields, LuckyStrike, Parliaments }; + +map nationalityStrings = {{Englishman, "Englishman"}, + {Spaniard, "Spaniard"}, + {Ukrainian, "Ukrainian"}, + {Norwegian, "Norwegian"}, + {Japanese, "Japanese"}}; + +struct House { + Color color; + Nationality nationality; + Pet pet; + Drink drink; + Cigarette cigarette; +}; + +vector houses(5); + +bool check_constraints_cigarette_drink() { + for (size_t i = 0; i < houses.size(); i++) { + const auto& house = houses[i]; + + // Constraint 9: Milk is drunk in the middle house. + if ((i == 2) && (house.drink != Milk)) { + return false; + } + + // Constraint 13: The Lucky Strike smoker drinks orange juice. + if ((house.cigarette == LuckyStrike) && (house.drink != OrangeJuice)) { + return false; + } + } + return true; +} + +bool check_constraints_cigarette_drink_pet() { + for (size_t i = 0; i < houses.size(); i++) { + const auto& house = houses[i]; + + // Constraint 7: The Old Gold smoker owns snails. + if ((house.pet == Snails) && (house.cigarette != OldGold)) { + return false; + } + + // Constraint 11: The man who smokes Chesterfields lives in the house + // next to the man with the fox. + if (((i > 0) && (house.pet == Fox) && + (houses[i - 1].cigarette != Chesterfields)) && + ((i < 4) && (house.pet == Fox) && + (houses[i + 1].cigarette != Chesterfields))) { + return false; + } + + if ((i == 0) && (house.pet == Fox) && + (houses[i + 1].cigarette != Chesterfields)) { + return false; + } + + if ((i == 4) && (house.pet == Fox) && + (houses[i - 1].cigarette != Chesterfields)) { + return false; + } + + // Constraint 12: Kools are smoked in a house next to the house where + // the horse is kept. + if (((i > 0) && (house.pet == Horse) && + (houses[i - 1].cigarette != Kools)) && + ((i < 4) && (house.pet == Horse) && + (houses[i + 1].cigarette != Kools))) { + return false; + } + + if ((i == 0) && (house.pet == Horse) && + (houses[i + 1].cigarette != Kools)) { + return false; + } + + if ((i == 4) && (house.pet == Horse) && + (houses[i - 1].cigarette != Kools)) { + return false; + } + } + return true; +} + +bool check_constraints_cigarette_drink_pet_nationality() { + for (size_t i = 0; i < houses.size(); i++) { + const auto& house = houses[i]; + + // Constraint 3: The Spaniard owns the dog. + if ((house.nationality == Spaniard) && (house.pet != Dog)) { + return false; + } + + // Constraint 5: The Ukrainian drinks tea. + if ((house.nationality == Ukrainian) && (house.drink != Tea)) { + return false; + } + + // Constraint 10: The Norwegian lives in the first house. + if ((i == 0) && (house.nationality != Norwegian)) { + return false; + } + + // Constraint 14: The Japanese smokes Parliaments. + if ((house.nationality == Japanese) && + (house.cigarette != Parliaments)) { + return false; + } + } + return true; +} + +bool check_constraints_cigarette_drink_pet_nationality_color() { + for (size_t i = 0; i < houses.size(); i++) { + const auto& house = houses[i]; + + // Constraint 2: The Englishman lives in the red house. + if ((house.color == Red) && (house.nationality != Englishman)) { + return false; + } + + // Constraint 4: Coffee is drunk in the green house. + if ((house.color == Green) && (house.drink != Coffee)) { + return false; + } + + // Constraint 6: The green house is immediately to the right of the + // ivory house. + if ((i > 0) && (house.color == Green) && + (houses[i - 1].color != Ivory)) { + return false; + } + + if ((i == 0) && (house.color == Green)) { + return false; + } + + // Constraint 8: Kools are smoked in the yellow house. + if ((house.color == Yellow) && (house.cigarette != Kools)) { + return false; + } + + // Constraint 15: The Norwegian lives next to the blue house. + if (((i > 0) && (house.nationality == Norwegian) && + (houses[i - 1].color != Blue)) && + ((i < 4) && (house.nationality == Norwegian) && + (houses[i + 1].color != Blue))) { + return false; + } + + if ((i == 0) && (house.nationality == Norwegian) && + (houses[i + 1].color != Blue)) { + return false; + } + + if ((i == 4) && (house.nationality == Norwegian) && + (houses[i - 1].color != Blue)) { + return false; + } + } + return true; +} + +void solve_with_permutation() { + vector colors = {Red, Green, Ivory, Yellow, Blue}; + vector nationalities = {Englishman, Spaniard, Ukrainian, + Norwegian, Japanese}; + vector pets = {Dog, Snails, Fox, Horse, Zebra}; + vector drinks = {Tea, Coffee, Milk, OrangeJuice, Water}; + vector cigarettes = {OldGold, Kools, Chesterfields, LuckyStrike, + Parliaments}; + + do { + for (size_t i = 0; i < 5; i++) { + houses[i].cigarette = cigarettes[i]; + } + + do { + for (size_t i = 0; i < 5; i++) { + houses[i].drink = drinks[i]; + } + + if (!check_constraints_cigarette_drink()) { + continue; + } + + do { + for (size_t i = 0; i < 5; i++) { + houses[i].pet = pets[i]; + } + + if (!check_constraints_cigarette_drink_pet()) { + continue; + } + + do { + for (size_t i = 0; i < 5; i++) { + houses[i].nationality = nationalities[i]; + } + + if (!check_constraints_cigarette_drink_pet_nationality()) { + continue; + } + + do { + for (size_t i = 0; i < 5; i++) { + houses[i].color = colors[i]; + } + + if (check_constraints_cigarette_drink_pet_nationality_color()) { + return; + } + + } while (next_permutation(colors.begin(), colors.end())); + + } while (next_permutation(nationalities.begin(), + nationalities.end())); + + } while (next_permutation(pets.begin(), pets.end())); + + } while (next_permutation(drinks.begin(), drinks.end())); + + } while (next_permutation(cigarettes.begin(), cigarettes.end())); +} + +Solution solve() { + solve_with_permutation(); + Solution solution; + + // find the house with the zebra + for (size_t i = 0; i < houses.size(); i++) { + if (houses[i].pet == Zebra) { + solution.ownsZebra = nationalityStrings[houses[i].nationality]; + break; + } + } + + // find the house with the water + for (size_t i = 0; i < houses.size(); i++) { + if (houses[i].drink == Water) { + solution.drinksWater = nationalityStrings[houses[i].nationality]; + break; + } + } + + return solution; +} + +} // namespace zebra_puzzle \ No newline at end of file diff --git a/exercises/practice/zebra-puzzle/.meta/example.h b/exercises/practice/zebra-puzzle/.meta/example.h new file mode 100644 index 000000000..64ad4bf3e --- /dev/null +++ b/exercises/practice/zebra-puzzle/.meta/example.h @@ -0,0 +1,17 @@ +#if !defined(ZEBRA_PUZZLE_H) +#define ZEBRA_PUZZLE_H + +#include + +namespace zebra_puzzle { + +struct Solution { + std::string drinksWater; + std::string ownsZebra; +}; + +Solution solve(); + +} // namespace zebra_puzzle + +#endif diff --git a/exercises/practice/zebra-puzzle/.meta/tests.toml b/exercises/practice/zebra-puzzle/.meta/tests.toml new file mode 100644 index 000000000..38c82da54 --- /dev/null +++ b/exercises/practice/zebra-puzzle/.meta/tests.toml @@ -0,0 +1,17 @@ +# 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. + +[16efb4e4-8ad7-4d5e-ba96-e5537b66fd42] +description = "resident who drinks water" + +[084d5b8b-24e2-40e6-b008-c800da8cd257] +description = "resident who owns zebra" + diff --git a/exercises/practice/zebra-puzzle/CMakeLists.txt b/exercises/practice/zebra-puzzle/CMakeLists.txt new file mode 100644 index 000000000..3b0589fd0 --- /dev/null +++ b/exercises/practice/zebra-puzzle/CMakeLists.txt @@ -0,0 +1,64 @@ +# 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 +if(${MSVC}) + set_target_properties(${exercise} PROPERTIES + COMPILE_DEFINITIONS_DEBUG _SCL_SECURE_NO_WARNINGS) +endif() + +# Run the tests on every build +add_custom_target(test_${exercise} ALL DEPENDS ${exercise} COMMAND ${exercise}) diff --git a/exercises/practice/zebra-puzzle/test/catch.hpp b/exercises/practice/zebra-puzzle/test/catch.hpp new file mode 100644 index 000000000..36eaeb27f --- /dev/null +++ b/exercises/practice/zebra-puzzle/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