diff --git a/include/tcframe/validator/core.hpp b/include/tcframe/validator/core.hpp index 640c452..7c022b3 100644 --- a/include/tcframe/validator/core.hpp +++ b/include/tcframe/validator/core.hpp @@ -38,14 +38,14 @@ inline ScalarValidator valueOf(T val) { template> struct VectorElementValidator { private: - const vector& val; + const vector& vec; public: - explicit VectorElementValidator(const vector& _val) : val(_val) {} + explicit VectorElementValidator(const vector& _vec) : vec(_vec) {} bool isBetween(T minVal, T maxVal) { - for (T v : val) { - if (!valueOf(v).isBetween(minVal, maxVal)) { + for (T e : vec) { + if (!valueOf(e).isBetween(minVal, maxVal)) { return false; } } @@ -53,8 +53,8 @@ struct VectorElementValidator { } bool satisfies(function predicate) { - for (T v : val) { - if (!predicate(v)) { + for (T e : vec) { + if (!predicate(e)) { return false; } } @@ -63,21 +63,21 @@ struct VectorElementValidator { }; template> -inline VectorElementValidator eachElementOf(const vector& val) { - return VectorElementValidator(val); +inline VectorElementValidator eachElementOf(const vector& vec) { + return VectorElementValidator(vec); } template> struct VectorElementsValidator { private: - const vector& val; + const vector& vec; public: - explicit VectorElementsValidator(const vector& _val) : val(_val) {} + explicit VectorElementsValidator(const vector& _vec) : vec(_vec) {} bool areAscending() { - for (size_t i = 1; i < val.size(); ++i) { - if (val[i - 1] >= val[i]) { + for (size_t i = 1; i < vec.size(); ++i) { + if (vec[i - 1] >= vec[i]) { return false; } } @@ -85,8 +85,8 @@ struct VectorElementsValidator { } bool areDescending() { - for (size_t i = 1; i < val.size(); ++i) { - if (val[i - 1] <= val[i]) { + for (size_t i = 1; i < vec.size(); ++i) { + if (vec[i - 1] <= vec[i]) { return false; } } @@ -94,8 +94,8 @@ struct VectorElementsValidator { } bool areNonAscending() { - for (size_t i = 1; i < val.size(); ++i) { - if (val[i - 1] < val[i]) { + for (size_t i = 1; i < vec.size(); ++i) { + if (vec[i - 1] < vec[i]) { return false; } } @@ -103,8 +103,8 @@ struct VectorElementsValidator { } bool areNonDescending() { - for (size_t i = 1; i < val.size(); ++i) { - if (val[i - 1] > val[i]) { + for (size_t i = 1; i < vec.size(); ++i) { + if (vec[i - 1] > vec[i]) { return false; } } @@ -112,7 +112,7 @@ struct VectorElementsValidator { } bool areUnique() { - vector v = val; + vector v = vec; sort(v.begin(), v.end()); size_t ns = unique(v.begin(), v.end()) - v.begin(); return ns == v.size(); @@ -120,20 +120,20 @@ struct VectorElementsValidator { }; template> -inline VectorElementsValidator elementsOf(const vector& val) { - return VectorElementsValidator(val); +inline VectorElementsValidator elementsOf(const vector& vec) { + return VectorElementsValidator(vec); } struct StringElementValidator { private: - const string& val; + const string& str; public: - explicit StringElementValidator(const string& _val) : val(_val) {} + explicit StringElementValidator(const string& _str) : str(_str) {} bool isBetween(char minVal, char maxVal) { - for (char v : val) { - if (!valueOf(v).isBetween(minVal, maxVal)) { + for (char c : str) { + if (!valueOf(c).isBetween(minVal, maxVal)) { return false; } } @@ -141,20 +141,20 @@ struct StringElementValidator { } }; -inline StringElementValidator eachCharacterOf(const string& val) { - return StringElementValidator(val); +inline StringElementValidator eachCharacterOf(const string& str) { + return StringElementValidator(str); } template> struct MatrixElementValidator { private: - const vector>& val; + const vector>& mat; public: - explicit MatrixElementValidator(const vector>& _val) : val(_val) {} + explicit MatrixElementValidator(const vector>& _mat) : mat(_mat) {} bool isBetween(T minVal, T maxVal) { - for (const vector& v : val) { + for (const vector& v : mat) { if (!eachElementOf(v).isBetween(minVal, maxVal)) { return false; } @@ -163,7 +163,7 @@ struct MatrixElementValidator { } bool satisfies(function predicate) { - for (const vector& v : val) { + for (const vector& v : mat) { if (!eachElementOf(v).satisfies(predicate)) { return false; } @@ -173,8 +173,8 @@ struct MatrixElementValidator { }; template> -inline MatrixElementValidator eachElementOf(const vector>& val) { - return MatrixElementValidator(val); +inline MatrixElementValidator eachElementOf(const vector>& mat) { + return MatrixElementValidator(mat); } } diff --git a/web/docs/api/04-validators/01-core.md b/web/docs/api/04-validators/01-core.md new file mode 100644 index 0000000..580f23f --- /dev/null +++ b/web/docs/api/04-validators/01-core.md @@ -0,0 +1,174 @@ +--- +toc_max_heading_level: 4 +--- + +# Core validators + +## Validating a scalar value + +A scalar type is defined as: + +```cpp +template +using ScalarType = std::enable_if_t>; +``` + +Or in simple words, it includes `int`, `long long`, `double`, and `char`. + +To instantiate the validator for a value, say `val`, call the following function: + +### `valueOf(val)` + +```cpp +template> +ScalarValidator valueOf(T val); +``` + +This validator contains the following function: + +#### `.isBetween()` + +```cpp +bool ScalarValidator::isBetween(T minVal, T maxVal); +``` + +Returns whether `val` is between `minVal` and `maxVal`, inclusive. + +--- + +## Validating each element of a vector + +To instantiate the validator for a each element of a vector, say `vec`, call the following function: + +### `eachElementOf(vec)` + +```cpp +template> +VectorElementValidator eachElementOf(const std::vector& vec); +``` + +This validator contains the following functions: + +#### `.isBetween()` + +```cpp +bool VectorElementValidator::isBetween(T minVal, T maxVal); +``` + +Returns whether each element of `vec` is between `minVal` and `maxVal`, inclusive. + +#### `.satisfies()` + +```cpp +bool VectorElementValidator::satisfies(std::function predicate); +``` + +Returns whether `predicate(e)` returns true for each `e` element of `vec`. + +--- + +## Validating each element of a matrix + +To instantiate the validator for a each element of a matrix, say `mat`, call the following function: + +### `eachElementOf(mat)` + +```cpp +template> +MatrixElementValidator eachElementOf(const std::vector>& mat); +``` + +This validator contains the following functions: + +#### `.isBetween()` + +```cpp +bool MatrixElementValidator::isBetween(T minVal, T maxVal); +``` + +Returns whether each element of `mat` is between `minVal` and `maxVal`, inclusive. + +#### `.satisfies()` + +```cpp +bool MatrixElementValidator::satisfies(std::function predicate); +``` + +Returns whether `predicate(e)` returns true for each `e` element of `mat`. + +--- + +## Validating each character of a string + +To instantiate the validator for a each character of a string, say `str`, call the following function: + +### `eachCharacterOf(str)` + +```cpp +StringElementValidator eachCharacterOf(const std::string& str); +``` + +This validator contains the following functions: + +#### `.isBetween()` + +```cpp +bool StringElementValidator::isBetween(char minVal, char maxVal); +``` + +Returns whether each character of `str` is between `minVal` and `maxVal`, inclusive. + +--- + +## Validating all elements of a vector + +To instantiate the validator for all elements of a vector, say `vec`, call the following function: + +### `elementsOf(vec)` + +```cpp +template> +VectorElementsValidator elementsOf(const std::vector& vec); +``` + +This validator contains the following functions: + +#### `.areAscending()` + +```cpp +bool VectorElementsValidator::areAscending(); +``` + +Returns whether the elements of `vec` are in a strictly ascending order. + +#### `.areDescending()` + +```cpp +bool VectorElementsValidator::areDescending(); +``` + +Returns whether the elements of `vec` are in a strictly descending order. + +#### `.areNonAscending()` + +```cpp +bool VectorElementsValidator::areNonAscending(); +``` + +Returns whether the elements of `vec` are in a non-ascending order. + +#### `.areNonDescending()` + +```cpp +bool VectorElementsValidator::areNonDescending(); +``` + +Returns whether the elements of `vec` are in a non-descending order. + +#### `.areUnique()` + +```cpp +bool VectorElementsValidator::areUnique(); +``` + +Returns whether the elements of `vec` are unique (all different). diff --git a/web/docs/api/04-validators/_category_.yml b/web/docs/api/04-validators/_category_.yml new file mode 100644 index 0000000..045ddda --- /dev/null +++ b/web/docs/api/04-validators/_category_.yml @@ -0,0 +1,5 @@ +label: Validators +link: + type: generated-index + slug: /api/validators + description: TCFrame provides several validators, which can be used to validate the I/O variables in problem spec. diff --git a/web/docs/api/04-runner.md b/web/docs/api/05-runner.md similarity index 100% rename from web/docs/api/04-runner.md rename to web/docs/api/05-runner.md diff --git a/web/docs/api/05-helper.md b/web/docs/api/06-helpers.md similarity index 100% rename from web/docs/api/05-helper.md rename to web/docs/api/06-helpers.md diff --git a/web/docs/topic-guides/05-constraints.md b/web/docs/topic-guides/05-constraints.md index 2f50647..88f408c 100644 --- a/web/docs/topic-guides/05-constraints.md +++ b/web/docs/topic-guides/05-constraints.md @@ -24,7 +24,11 @@ void Constraints() { } ``` -The constraint definition can be pulled directly from the constraints section in the actual problem description. For example: "1 ≤ **A** ≤ 1,000" can be specified by `CONS(1 <= A && A <= 1000)`. "1 ≤ **A**, **B** ≤ 1,000" translates into two specifications: `CONS(1 <= A && A <= 1000)` and `CONS(1 <= B && B <= 1000)`. "1 ≤ **A** ≤ **B** ≤ 1,000" translates into `CONS(1 <= A && A <= B && B <= 1000)`. +The constraint definition can be pulled directly from the constraints section in the actual problem description. For example: + +- "1 ≤ **A** ≤ 1,000" can be specified by `CONS(1 <= A && A <= 1000)`. +- "1 ≤ **A**, **B** ≤ 1,000" translates into two specifications: `CONS(1 <= A && A <= 1000)` and `CONS(1 <= B && B <= 1000)`. +- "1 ≤ **A** ≤ **B** ≤ 1,000" translates into `CONS(1 <= A && A <= B && B <= 1000)`. How about more complex predicates, such as "1 ≤ **A**[i] ≤ 1,000"? You can write a private method for this purpose. For example, it can be translated into `CONS(eachElementBetween(A, 1, 1000))` and a private method as follows: @@ -41,6 +45,9 @@ bool eachElementBetween(const vector& X, int lo, int hi) { This also applies to even more complex predicates, such as "It is guaranteed that the given graph is a tree". This can be translated to `CONS(graphIsTree())` and define the appropriate private boolean method. -## Notes +## Using built-in validators + +To simplify constraint specifications, TCFrame provides built-in [validators](../api/validators). For example: -It is tedious to write `eachElementBetween()` predicate over and over again as it is very common in problems. We are working on providing such helper methods as core part of TCFrame in the next versions. +- `CONS(1 <= A && A <= 1000)` can be rewritten as `CONS(valueOf(A).isBetween(1, 1000))` +- `CONS(eachElementBetween(A, 1, 1000))` and the `eachElementBetween()` function can be rewritten as `CONS(eachElementOf(A).isBetween(1, 1000))`. diff --git a/web/docs/topic-guides/11-grading.md b/web/docs/topic-guides/11-grading.md index 16527db..1d8439a 100644 --- a/web/docs/topic-guides/11-grading.md +++ b/web/docs/topic-guides/11-grading.md @@ -64,7 +64,7 @@ This will override what is set in `GradingConfig()`. ## Helper programs -If [helper programs](../api/helper) are present, they must be compiled prior to the local grading. +If [helper programs](../api/helpers) are present, they must be compiled prior to the local grading. ### Scorer diff --git a/web/src/components/HomepageFeatures/index.js b/web/src/components/HomepageFeatures/index.js index 6e685bf..5bd04b6 100644 --- a/web/src/components/HomepageFeatures/index.js +++ b/web/src/components/HomepageFeatures/index.js @@ -16,8 +16,8 @@ void OutputFormat() { const constraints = `void Constraints() { - CONS(1 <= N && N <= 1000); - CONS(eachElementBetween(A, 1, 1000000)); + CONS(valueOf(N).isBetween(1, 1000); + CONS(eachElementOf(A).isBetween(1, 10)); }` const testCases =