diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..4f9cfdef0c --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +# CI +.github/**/* @exercism/maintainers-admin diff --git a/.github/workflow-tests/immutability-check/canonical-data-changed-scenarios-after.json b/.github/workflow-tests/immutability-check/canonical-data-changed-scenarios-after.json new file mode 100644 index 0000000000..c13fdabbba --- /dev/null +++ b/.github/workflow-tests/immutability-check/canonical-data-changed-scenarios-after.json @@ -0,0 +1,369 @@ +{ + "exercise": "complex-numbers", + "comments": [ + " The canonical data assumes mathematically correct real ", + " numbers. The testsuites should consider rounding errors ", + " instead of testing for exact values for any non-integer ", + " tests. ", + " Complex numbers z are represented as arrays [x, y] so ", + " that z = x + i * y. ", + " Pi is represented as a string \"pi\", euler's number is ", + " represented as \"e\". " + ], + "cases": [ + { + "description": "Real part", + "cases": [ + { + "uuid": "9f98e133-eb7f-45b0-9676-cce001cd6f7a", + "description": "Real part of a purely real number", + "property": "real", + "input": { + "z": [1, 0] + }, + "expected": 1 + }, + { + "uuid": "07988e20-f287-4bb7-90cf-b32c4bffe0f3", + "description": "Real part of a purely imaginary number", + "property": "real", + "input": { + "z": [0, 1] + }, + "expected": 0 + }, + { + "uuid": "4a370e86-939e-43de-a895-a00ca32da60a", + "description": "Real part of a number with real and imaginary part", + "scenarios": ["a", "b"], + "property": "real", + "input": { + "z": [1, 2] + }, + "expected": 1 + } + ] + }, + { + "description": "Imaginary part", + "cases": [ + { + "uuid": "9b3fddef-4c12-4a99-b8f8-e3a42c7ccef6", + "description": "Imaginary part of a purely real number", + "property": "imaginary", + "input": { + "z": [1, 0] + }, + "expected": 0 + }, + { + "uuid": "a8dafedd-535a-4ed3-8a39-fda103a2b01e", + "description": "Imaginary part of a purely imaginary number", + "property": "imaginary", + "input": { + "z": [0, 1] + }, + "expected": 1 + }, + { + "uuid": "0f998f19-69ee-4c64-80ef-01b086feab80", + "description": "Imaginary part of a number with real and imaginary part", + "property": "imaginary", + "input": { + "z": [1, 2] + }, + "expected": 2 + } + ] + }, + { + "uuid": "a39b7fd6-6527-492f-8c34-609d2c913879", + "description": "Imaginary unit", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 1] + }, + "expected": [-1, 0] + }, + { + "description": "Arithmetic", + "cases": [ + { + "description": "Addition", + "cases": [ + { + "uuid": "9a2c8de9-f068-4f6f-b41c-82232cc6c33e", + "description": "Add purely real numbers", + "property": "add", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [3, 0] + }, + { + "uuid": "657c55e1-b14b-4ba7-bd5c-19db22b7d659", + "description": "Add purely imaginary numbers", + "property": "add", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0, 3] + }, + { + "uuid": "4e1395f5-572b-4ce8-bfa9-9a63056888da", + "description": "Add numbers with real and imaginary part", + "property": "add", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [4, 6] + } + ] + }, + { + "description": "Subtraction", + "cases": [ + { + "uuid": "1155dc45-e4f7-44b8-af34-a91aa431475d", + "description": "Subtract purely real numbers", + "property": "sub", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [-1, 0] + }, + { + "uuid": "f95e9da8-acd5-4da4-ac7c-c861b02f774b", + "description": "Subtract purely imaginary numbers", + "property": "sub", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0, -1] + }, + { + "uuid": "f876feb1-f9d1-4d34-b067-b599a8746400", + "description": "Subtract numbers with real and imaginary part", + "property": "sub", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-2, -2] + } + ] + }, + { + "description": "Multiplication", + "cases": [ + { + "uuid": "8a0366c0-9e16-431f-9fd7-40ac46ff4ec4", + "description": "Multiply purely real numbers", + "property": "mul", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [2, 0] + }, + { + "uuid": "e560ed2b-0b80-4b4f-90f2-63cefc911aaf", + "description": "Multiply purely imaginary numbers", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [-2, 0] + }, + { + "uuid": "4d1d10f0-f8d4-48a0-b1d0-f284ada567e6", + "description": "Multiply numbers with real and imaginary part", + "property": "mul", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-5, 10] + } + ] + }, + { + "description": "Division", + "cases": [ + { + "uuid": "b0571ddb-9045-412b-9c15-cd1d816d36c1", + "description": "Divide purely real numbers", + "property": "div", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [0.5, 0] + }, + { + "uuid": "5bb4c7e4-9934-4237-93cc-5780764fdbdd", + "description": "Divide purely imaginary numbers", + "property": "div", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0.5, 0] + }, + { + "uuid": "c4e7fef5-64ac-4537-91c2-c6529707701f", + "description": "Divide numbers with real and imaginary part", + "property": "div", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [0.44, 0.08] + } + ] + } + ] + }, + { + "description": "Absolute value", + "cases": [ + { + "uuid": "c56a7332-aad2-4437-83a0-b3580ecee843", + "description": "Absolute value of a positive purely real number", + "property": "abs", + "input": { + "z": [5, 0] + }, + "expected": 5 + }, + { + "uuid": "cf88d7d3-ee74-4f4e-8a88-a1b0090ecb0c", + "description": "Absolute value of a negative purely real number", + "property": "abs", + "input": { + "z": [-5, 0] + }, + "expected": 5 + }, + { + "uuid": "bbe26568-86c1-4bb4-ba7a-da5697e2b994", + "description": "Absolute value of a purely imaginary number with positive imaginary part", + "property": "abs", + "input": { + "z": [0, 5] + }, + "expected": 5 + }, + { + "uuid": "3b48233d-468e-4276-9f59-70f4ca1f26f3", + "description": "Absolute value of a purely imaginary number with negative imaginary part", + "property": "abs", + "input": { + "z": [0, -5] + }, + "expected": 5 + }, + { + "uuid": "fe400a9f-aa22-4b49-af92-51e0f5a2a6d3", + "description": "Absolute value of a number with real and imaginary part", + "property": "abs", + "input": { + "z": [3, 4] + }, + "expected": 5 + } + ] + }, + { + "description": "Complex conjugate", + "cases": [ + { + "uuid": "fb2d0792-e55a-4484-9443-df1eddfc84a2", + "description": "Conjugate a purely real number", + "property": "conjugate", + "input": { + "z": [5, 0] + }, + "expected": [5, 0] + }, + { + "uuid": "e37fe7ac-a968-4694-a460-66cb605f8691", + "description": "Conjugate a purely imaginary number", + "property": "conjugate", + "input": { + "z": [0, 5] + }, + "expected": [0, -5] + }, + { + "uuid": "f7704498-d0be-4192-aaf5-a1f3a7f43e68", + "description": "Conjugate a number with real and imaginary part", + "property": "conjugate", + "input": { + "z": [1, 1] + }, + "expected": [1, -1] + } + ] + }, + { + "description": "Complex exponential function", + "comments": [ + " Defining the exponential function can be optional. ", + " If the language used does not have sine and cosine ", + " functions in the standard library, this will be ", + " significantly more difficult than the rest of the exer- ", + " cise and should probably not be part of the problem. ", + " The recommended implementation uses Euler's formula ", + " exp(ix) = cos(x) + i * sin(x). This is not an ideal sol- ", + " ution but works for the purpose of teaching complex ", + " numbers. " + ], + "cases": [ + { + "uuid": "6d96d4c6-2edb-445b-94a2-7de6d4caaf60", + "description": "Euler's identity/formula", + "property": "exp", + "input": { + "z": [0, "pi"] + }, + "expected": [-1, 0] + }, + { + "uuid": "2d2c05a0-4038-4427-a24d-72f6624aa45f", + "description": "Exponential of 0", + "property": "exp", + "input": { + "z": [0, 0] + }, + "expected": [1, 0] + }, + { + "uuid": "ed87f1bd-b187-45d6-8ece-7e331232c809", + "description": "Exponential of a purely real number", + "property": "exp", + "input": { + "z": [1, 0] + }, + "expected": ["e", 0] + }, + { + "uuid": "08eedacc-5a95-44fc-8789-1547b27a8702", + "description": "Exponential of a number with real and imaginary part", + "property": "exp", + "input": { + "z": ["ln(2)", "pi"] + }, + "expected": [-2, 0] + } + ] + } + ] +} diff --git a/.github/workflow-tests/immutability-check/canonical-data-changed-scenarios-before.json b/.github/workflow-tests/immutability-check/canonical-data-changed-scenarios-before.json new file mode 100644 index 0000000000..9b4f65bfba --- /dev/null +++ b/.github/workflow-tests/immutability-check/canonical-data-changed-scenarios-before.json @@ -0,0 +1,369 @@ +{ + "exercise": "complex-numbers", + "comments": [ + " The canonical data assumes mathematically correct real ", + " numbers. The testsuites should consider rounding errors ", + " instead of testing for exact values for any non-integer ", + " tests. ", + " Complex numbers z are represented as arrays [x, y] so ", + " that z = x + i * y. ", + " Pi is represented as a string \"pi\", euler's number is ", + " represented as \"e\". " + ], + "cases": [ + { + "description": "Real part", + "cases": [ + { + "uuid": "9f98e133-eb7f-45b0-9676-cce001cd6f7a", + "description": "Real part of a purely real number", + "property": "real", + "input": { + "z": [1, 0] + }, + "expected": 1 + }, + { + "uuid": "07988e20-f287-4bb7-90cf-b32c4bffe0f3", + "description": "Real part of a purely imaginary number", + "property": "real", + "input": { + "z": [0, 1] + }, + "expected": 0 + }, + { + "uuid": "4a370e86-939e-43de-a895-a00ca32da60a", + "description": "Real part of a number with real and imaginary part", + "scenarios": ["a", "b", "c"], + "property": "real", + "input": { + "z": [1, 2] + }, + "expected": 1 + } + ] + }, + { + "description": "Imaginary part", + "cases": [ + { + "uuid": "9b3fddef-4c12-4a99-b8f8-e3a42c7ccef6", + "description": "Imaginary part of a purely real number", + "property": "imaginary", + "input": { + "z": [1, 0] + }, + "expected": 0 + }, + { + "uuid": "a8dafedd-535a-4ed3-8a39-fda103a2b01e", + "description": "Imaginary part of a purely imaginary number", + "property": "imaginary", + "input": { + "z": [0, 1] + }, + "expected": 1 + }, + { + "uuid": "0f998f19-69ee-4c64-80ef-01b086feab80", + "description": "Imaginary part of a number with real and imaginary part", + "property": "imaginary", + "input": { + "z": [1, 2] + }, + "expected": 2 + } + ] + }, + { + "uuid": "a39b7fd6-6527-492f-8c34-609d2c913879", + "description": "Imaginary unit", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 1] + }, + "expected": [-1, 0] + }, + { + "description": "Arithmetic", + "cases": [ + { + "description": "Addition", + "cases": [ + { + "uuid": "9a2c8de9-f068-4f6f-b41c-82232cc6c33e", + "description": "Add purely real numbers", + "property": "add", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [3, 0] + }, + { + "uuid": "657c55e1-b14b-4ba7-bd5c-19db22b7d659", + "description": "Add purely imaginary numbers", + "property": "add", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0, 3] + }, + { + "uuid": "4e1395f5-572b-4ce8-bfa9-9a63056888da", + "description": "Add numbers with real and imaginary part", + "property": "add", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [4, 6] + } + ] + }, + { + "description": "Subtraction", + "cases": [ + { + "uuid": "1155dc45-e4f7-44b8-af34-a91aa431475d", + "description": "Subtract purely real numbers", + "property": "sub", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [-1, 0] + }, + { + "uuid": "f95e9da8-acd5-4da4-ac7c-c861b02f774b", + "description": "Subtract purely imaginary numbers", + "property": "sub", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0, -1] + }, + { + "uuid": "f876feb1-f9d1-4d34-b067-b599a8746400", + "description": "Subtract numbers with real and imaginary part", + "property": "sub", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-2, -2] + } + ] + }, + { + "description": "Multiplication", + "cases": [ + { + "uuid": "8a0366c0-9e16-431f-9fd7-40ac46ff4ec4", + "description": "Multiply purely real numbers", + "property": "mul", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [2, 0] + }, + { + "uuid": "e560ed2b-0b80-4b4f-90f2-63cefc911aaf", + "description": "Multiply purely imaginary numbers", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [-2, 0] + }, + { + "uuid": "4d1d10f0-f8d4-48a0-b1d0-f284ada567e6", + "description": "Multiply numbers with real and imaginary part", + "property": "mul", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-5, 10] + } + ] + }, + { + "description": "Division", + "cases": [ + { + "uuid": "b0571ddb-9045-412b-9c15-cd1d816d36c1", + "description": "Divide purely real numbers", + "property": "div", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [0.5, 0] + }, + { + "uuid": "5bb4c7e4-9934-4237-93cc-5780764fdbdd", + "description": "Divide purely imaginary numbers", + "property": "div", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0.5, 0] + }, + { + "uuid": "c4e7fef5-64ac-4537-91c2-c6529707701f", + "description": "Divide numbers with real and imaginary part", + "property": "div", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [0.44, 0.08] + } + ] + } + ] + }, + { + "description": "Absolute value", + "cases": [ + { + "uuid": "c56a7332-aad2-4437-83a0-b3580ecee843", + "description": "Absolute value of a positive purely real number", + "property": "abs", + "input": { + "z": [5, 0] + }, + "expected": 5 + }, + { + "uuid": "cf88d7d3-ee74-4f4e-8a88-a1b0090ecb0c", + "description": "Absolute value of a negative purely real number", + "property": "abs", + "input": { + "z": [-5, 0] + }, + "expected": 5 + }, + { + "uuid": "bbe26568-86c1-4bb4-ba7a-da5697e2b994", + "description": "Absolute value of a purely imaginary number with positive imaginary part", + "property": "abs", + "input": { + "z": [0, 5] + }, + "expected": 5 + }, + { + "uuid": "3b48233d-468e-4276-9f59-70f4ca1f26f3", + "description": "Absolute value of a purely imaginary number with negative imaginary part", + "property": "abs", + "input": { + "z": [0, -5] + }, + "expected": 5 + }, + { + "uuid": "fe400a9f-aa22-4b49-af92-51e0f5a2a6d3", + "description": "Absolute value of a number with real and imaginary part", + "property": "abs", + "input": { + "z": [3, 4] + }, + "expected": 5 + } + ] + }, + { + "description": "Complex conjugate", + "cases": [ + { + "uuid": "fb2d0792-e55a-4484-9443-df1eddfc84a2", + "description": "Conjugate a purely real number", + "property": "conjugate", + "input": { + "z": [5, 0] + }, + "expected": [5, 0] + }, + { + "uuid": "e37fe7ac-a968-4694-a460-66cb605f8691", + "description": "Conjugate a purely imaginary number", + "property": "conjugate", + "input": { + "z": [0, 5] + }, + "expected": [0, -5] + }, + { + "uuid": "f7704498-d0be-4192-aaf5-a1f3a7f43e68", + "description": "Conjugate a number with real and imaginary part", + "property": "conjugate", + "input": { + "z": [1, 1] + }, + "expected": [1, -1] + } + ] + }, + { + "description": "Complex exponential function", + "comments": [ + " Defining the exponential function can be optional. ", + " If the language used does not have sine and cosine ", + " functions in the standard library, this will be ", + " significantly more difficult than the rest of the exer- ", + " cise and should probably not be part of the problem. ", + " The recommended implementation uses Euler's formula ", + " exp(ix) = cos(x) + i * sin(x). This is not an ideal sol- ", + " ution but works for the purpose of teaching complex ", + " numbers. " + ], + "cases": [ + { + "uuid": "6d96d4c6-2edb-445b-94a2-7de6d4caaf60", + "description": "Euler's identity/formula", + "property": "exp", + "input": { + "z": [0, "pi"] + }, + "expected": [-1, 0] + }, + { + "uuid": "2d2c05a0-4038-4427-a24d-72f6624aa45f", + "description": "Exponential of 0", + "property": "exp", + "input": { + "z": [0, 0] + }, + "expected": [1, 0] + }, + { + "uuid": "ed87f1bd-b187-45d6-8ece-7e331232c809", + "description": "Exponential of a purely real number", + "property": "exp", + "input": { + "z": [1, 0] + }, + "expected": ["e", 0] + }, + { + "uuid": "08eedacc-5a95-44fc-8789-1547b27a8702", + "description": "Exponential of a number with real and imaginary part", + "property": "exp", + "input": { + "z": ["ln(2)", "pi"] + }, + "expected": [-2, 0] + } + ] + } + ] +} diff --git a/.github/workflow-tests/immutability-check/canonical-data-deleted-case.json b/.github/workflow-tests/immutability-check/canonical-data-deleted-case.json new file mode 100644 index 0000000000..83cd8e1861 --- /dev/null +++ b/.github/workflow-tests/immutability-check/canonical-data-deleted-case.json @@ -0,0 +1,359 @@ +{ + "exercise": "complex-numbers", + "comments": [ + " The canonical data assumes mathematically correct real ", + " numbers. The testsuites should consider rounding errors ", + " instead of testing for exact values for any non-integer ", + " tests. ", + " Complex numbers z are represented as arrays [x, y] so ", + " that z = x + i * y. ", + " Pi is represented as a string \"pi\", euler's number is ", + " represented as \"e\". " + ], + "cases": [ + { + "description": "Real part", + "cases": [ + { + "uuid": "9f98e133-eb7f-45b0-9676-cce001cd6f7a", + "description": "Real part of a purely real number", + "property": "real", + "input": { + "z": [1, 0] + }, + "expected": 1 + }, + { + "uuid": "4a370e86-939e-43de-a895-a00ca32da60a", + "description": "Real part of a number with real and imaginary part", + "property": "real", + "input": { + "z": [1, 2] + }, + "expected": 1 + } + ] + }, + { + "description": "Imaginary part", + "cases": [ + { + "uuid": "9b3fddef-4c12-4a99-b8f8-e3a42c7ccef6", + "description": "Imaginary part of a purely real number", + "property": "imaginary", + "input": { + "z": [1, 0] + }, + "expected": 0 + }, + { + "uuid": "a8dafedd-535a-4ed3-8a39-fda103a2b01e", + "description": "Imaginary part of a purely imaginary number", + "property": "imaginary", + "input": { + "z": [0, 1] + }, + "expected": 1 + }, + { + "uuid": "0f998f19-69ee-4c64-80ef-01b086feab80", + "description": "Imaginary part of a number with real and imaginary part", + "property": "imaginary", + "input": { + "z": [1, 2] + }, + "expected": 2 + } + ] + }, + { + "uuid": "a39b7fd6-6527-492f-8c34-609d2c913879", + "description": "Imaginary unit", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 1] + }, + "expected": [-1, 0] + }, + { + "description": "Arithmetic", + "cases": [ + { + "description": "Addition", + "cases": [ + { + "uuid": "9a2c8de9-f068-4f6f-b41c-82232cc6c33e", + "description": "Add purely real numbers", + "property": "add", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [3, 0] + }, + { + "uuid": "657c55e1-b14b-4ba7-bd5c-19db22b7d659", + "description": "Add purely imaginary numbers", + "property": "add", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0, 3] + }, + { + "uuid": "4e1395f5-572b-4ce8-bfa9-9a63056888da", + "description": "Add numbers with real and imaginary part", + "property": "add", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [4, 6] + } + ] + }, + { + "description": "Subtraction", + "cases": [ + { + "uuid": "1155dc45-e4f7-44b8-af34-a91aa431475d", + "description": "Subtract purely real numbers", + "property": "sub", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [-1, 0] + }, + { + "uuid": "f95e9da8-acd5-4da4-ac7c-c861b02f774b", + "description": "Subtract purely imaginary numbers", + "property": "sub", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0, -1] + }, + { + "uuid": "f876feb1-f9d1-4d34-b067-b599a8746400", + "description": "Subtract numbers with real and imaginary part", + "property": "sub", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-2, -2] + } + ] + }, + { + "description": "Multiplication", + "cases": [ + { + "uuid": "8a0366c0-9e16-431f-9fd7-40ac46ff4ec4", + "description": "Multiply purely real numbers", + "property": "mul", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [2, 0] + }, + { + "uuid": "e560ed2b-0b80-4b4f-90f2-63cefc911aaf", + "description": "Multiply purely imaginary numbers", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [-2, 0] + }, + { + "uuid": "4d1d10f0-f8d4-48a0-b1d0-f284ada567e6", + "description": "Multiply numbers with real and imaginary part", + "property": "mul", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-5, 10] + } + ] + }, + { + "description": "Division", + "cases": [ + { + "uuid": "b0571ddb-9045-412b-9c15-cd1d816d36c1", + "description": "Divide purely real numbers", + "property": "div", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [0.5, 0] + }, + { + "uuid": "5bb4c7e4-9934-4237-93cc-5780764fdbdd", + "description": "Divide purely imaginary numbers", + "property": "div", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0.5, 0] + }, + { + "uuid": "c4e7fef5-64ac-4537-91c2-c6529707701f", + "description": "Divide numbers with real and imaginary part", + "property": "div", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [0.44, 0.08] + } + ] + } + ] + }, + { + "description": "Absolute value", + "cases": [ + { + "uuid": "c56a7332-aad2-4437-83a0-b3580ecee843", + "description": "Absolute value of a positive purely real number", + "property": "abs", + "input": { + "z": [5, 0] + }, + "expected": 5 + }, + { + "uuid": "cf88d7d3-ee74-4f4e-8a88-a1b0090ecb0c", + "description": "Absolute value of a negative purely real number", + "property": "abs", + "input": { + "z": [-5, 0] + }, + "expected": 5 + }, + { + "uuid": "bbe26568-86c1-4bb4-ba7a-da5697e2b994", + "description": "Absolute value of a purely imaginary number with positive imaginary part", + "property": "abs", + "input": { + "z": [0, 5] + }, + "expected": 5 + }, + { + "uuid": "3b48233d-468e-4276-9f59-70f4ca1f26f3", + "description": "Absolute value of a purely imaginary number with negative imaginary part", + "property": "abs", + "input": { + "z": [0, -5] + }, + "expected": 5 + }, + { + "uuid": "fe400a9f-aa22-4b49-af92-51e0f5a2a6d3", + "description": "Absolute value of a number with real and imaginary part", + "property": "abs", + "input": { + "z": [3, 4] + }, + "expected": 5 + } + ] + }, + { + "description": "Complex conjugate", + "cases": [ + { + "uuid": "fb2d0792-e55a-4484-9443-df1eddfc84a2", + "description": "Conjugate a purely real number", + "property": "conjugate", + "input": { + "z": [5, 0] + }, + "expected": [5, 0] + }, + { + "uuid": "e37fe7ac-a968-4694-a460-66cb605f8691", + "description": "Conjugate a purely imaginary number", + "property": "conjugate", + "input": { + "z": [0, 5] + }, + "expected": [0, -5] + }, + { + "uuid": "f7704498-d0be-4192-aaf5-a1f3a7f43e68", + "description": "Conjugate a number with real and imaginary part", + "property": "conjugate", + "input": { + "z": [1, 1] + }, + "expected": [1, -1] + } + ] + }, + { + "description": "Complex exponential function", + "comments": [ + " Defining the exponential function can be optional. ", + " If the language used does not have sine and cosine ", + " functions in the standard library, this will be ", + " significantly more difficult than the rest of the exer- ", + " cise and should probably not be part of the problem. ", + " The recommended implementation uses Euler's formula ", + " exp(ix) = cos(x) + i * sin(x). This is not an ideal sol- ", + " ution but works for the purpose of teaching complex ", + " numbers. " + ], + "cases": [ + { + "uuid": "6d96d4c6-2edb-445b-94a2-7de6d4caaf60", + "description": "Euler's identity/formula", + "property": "exp", + "input": { + "z": [0, "pi"] + }, + "expected": [-1, 0] + }, + { + "uuid": "2d2c05a0-4038-4427-a24d-72f6624aa45f", + "description": "Exponential of 0", + "property": "exp", + "input": { + "z": [0, 0] + }, + "expected": [1, 0] + }, + { + "uuid": "ed87f1bd-b187-45d6-8ece-7e331232c809", + "description": "Exponential of a purely real number", + "property": "exp", + "input": { + "z": [1, 0] + }, + "expected": ["e", 0] + }, + { + "uuid": "08eedacc-5a95-44fc-8789-1547b27a8702", + "description": "Exponential of a number with real and imaginary part", + "property": "exp", + "input": { + "z": ["ln(2)", "pi"] + }, + "expected": [-2, 0] + } + ] + } + ] +} diff --git a/.github/workflow-tests/immutability-check/canonical-data-mutated-and-deleted.json b/.github/workflow-tests/immutability-check/canonical-data-mutated-and-deleted.json new file mode 100644 index 0000000000..f93719ffb3 --- /dev/null +++ b/.github/workflow-tests/immutability-check/canonical-data-mutated-and-deleted.json @@ -0,0 +1,358 @@ +{ + "exercise": "complex-numbers", + "comments": [ + " The canonical data assumes mathematically correct real ", + " numbers. The testsuites should consider rounding errors ", + " instead of testing for exact values for any non-integer ", + " tests. ", + " Complex numbers z are represented as arrays [x, y] so ", + " that z = x + i * y. ", + " Pi is represented as a string \"pi\", euler's number is ", + " represented as \"e\". " + ], + "cases": [ + { + "description": "Real part", + "cases": [ + { + "uuid": "9f98e133-eb7f-45b0-9676-cce001cd6f7a", + "description": "Real part of a purely real number", + "property": "real", + "input": { + "z": [2, 0] + }, + "expected": 2 + }, + { + "uuid": "07988e20-f287-4bb7-90cf-b32c4bffe0f3", + "description": "Real part of a purely imaginary number", + "property": "real", + "input": { + "z": [0, 2] + }, + "expected": 0 + }, + { + "uuid": "4a370e86-939e-43de-a895-a00ca32da60a", + "description": "Real part of a number with real and imaginary part", + "property": "real", + "input": { + "z": [1, 2] + }, + "expected": 1 + } + ] + }, + { + "description": "Imaginary part", + "cases": [ + { + "uuid": "9b3fddef-4c12-4a99-b8f8-e3a42c7ccef6", + "description": "Imaginary part of a purely real number", + "property": "imaginary", + "input": { + "z": [1, 0] + }, + "expected": 0 + }, + { + "uuid": "a8dafedd-535a-4ed3-8a39-fda103a2b01e", + "description": "Imaginary part of a purely imaginary number", + "property": "imaginary", + "input": { + "z": [0, 1] + }, + "expected": 1 + }, + { + "uuid": "0f998f19-69ee-4c64-80ef-01b086feab80", + "description": "Imaginary part of a number with real and imaginary part", + "property": "imaginary", + "input": { + "z": [1, 2] + }, + "expected": 2 + } + ] + }, + { + "uuid": "a39b7fd6-6527-492f-8c34-609d2c913879", + "description": "Imaginary unit", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 1] + }, + "expected": [-1, 0] + }, + { + "description": "Arithmetic", + "cases": [ + { + "description": "Addition", + "cases": [ + { + "uuid": "9a2c8de9-f068-4f6f-b41c-82232cc6c33e", + "description": "Add purely real numbers", + "property": "add", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [3, 0] + }, + { + "uuid": "4e1395f5-572b-4ce8-bfa9-9a63056888da", + "description": "Add numbers with real and imaginary part", + "property": "add", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [4, 6] + } + ] + }, + { + "description": "Subtraction", + "cases": [ + { + "uuid": "1155dc45-e4f7-44b8-af34-a91aa431475d", + "description": "Subtract purely real numbers", + "property": "sub", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [-1, 0] + }, + { + "uuid": "f95e9da8-acd5-4da4-ac7c-c861b02f774b", + "description": "Subtract purely imaginary numbers", + "property": "sub", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0, -1] + }, + { + "uuid": "f876feb1-f9d1-4d34-b067-b599a8746400", + "description": "Subtract numbers with real and imaginary part", + "property": "sub", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-2, -2] + } + ] + }, + { + "description": "Multiplication", + "cases": [ + { + "uuid": "8a0366c0-9e16-431f-9fd7-40ac46ff4ec4", + "description": "Multiply purely real numbers", + "property": "mul", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [2, 0] + }, + { + "uuid": "e560ed2b-0b80-4b4f-90f2-63cefc911aaf", + "description": "Multiply purely imaginary numbers", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [-2, 0] + }, + { + "uuid": "4d1d10f0-f8d4-48a0-b1d0-f284ada567e6", + "description": "Multiply numbers with real and imaginary part", + "property": "mul", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-5, 10] + } + ] + }, + { + "description": "Division", + "cases": [ + { + "uuid": "b0571ddb-9045-412b-9c15-cd1d816d36c1", + "description": "Divide purely real numbers", + "property": "div", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [0.5, 0] + }, + { + "uuid": "5bb4c7e4-9934-4237-93cc-5780764fdbdd", + "description": "Divide purely imaginary numbers", + "property": "div", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0.5, 0] + }, + { + "uuid": "c4e7fef5-64ac-4537-91c2-c6529707701f", + "description": "Divide numbers with real and imaginary part", + "property": "div", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [0.44, 0.08] + } + ] + } + ] + }, + { + "description": "Absolute value", + "cases": [ + { + "uuid": "c56a7332-aad2-4437-83a0-b3580ecee843", + "description": "Absolute value of a positive purely real number", + "property": "abs", + "input": { + "z": [5, 0] + }, + "expected": 5 + }, + { + "uuid": "cf88d7d3-ee74-4f4e-8a88-a1b0090ecb0c", + "description": "Absolute value of a negative purely real number", + "property": "abs", + "input": { + "z": [-5, 0] + }, + "expected": 5 + }, + { + "uuid": "bbe26568-86c1-4bb4-ba7a-da5697e2b994", + "description": "Absolute value of a purely imaginary number with positive imaginary part", + "property": "abs", + "input": { + "z": [0, 5] + }, + "expected": 5 + }, + { + "uuid": "3b48233d-468e-4276-9f59-70f4ca1f26f3", + "description": "Absolute value of a purely imaginary number with negative imaginary part", + "property": "abs", + "input": { + "z": [0, -5] + }, + "expected": 5 + }, + { + "uuid": "fe400a9f-aa22-4b49-af92-51e0f5a2a6d3", + "description": "Absolute value of a number with real and imaginary part", + "property": "abs", + "input": { + "z": [3, 4] + }, + "expected": 5 + } + ] + }, + { + "description": "Complex conjugate", + "cases": [ + { + "uuid": "fb2d0792-e55a-4484-9443-df1eddfc84a2", + "description": "Conjugate a purely real number", + "property": "conjugate", + "input": { + "z": [5, 0] + }, + "expected": [5, 0] + }, + { + "uuid": "e37fe7ac-a968-4694-a460-66cb605f8691", + "description": "Conjugate a purely imaginary number", + "property": "conjugate", + "input": { + "z": [0, 5] + }, + "expected": [0, -5] + }, + { + "uuid": "f7704498-d0be-4192-aaf5-a1f3a7f43e68", + "description": "Conjugate a number with real and imaginary part", + "property": "conjugate", + "input": { + "z": [1, 1] + }, + "expected": [1, -1] + } + ] + }, + { + "description": "Complex exponential function", + "comments": [ + " Defining the exponential function can be optional. ", + " If the language used does not have sine and cosine ", + " functions in the standard library, this will be ", + " significantly more difficult than the rest of the exer- ", + " cise and should probably not be part of the problem. ", + " The recommended implementation uses Euler's formula ", + " exp(ix) = cos(x) + i * sin(x). This is not an ideal sol- ", + " ution but works for the purpose of teaching complex ", + " numbers. " + ], + "cases": [ + { + "uuid": "6d96d4c6-2edb-445b-94a2-7de6d4caaf60", + "description": "Euler's identity/formula", + "property": "exp", + "input": { + "z": [0, "pi"] + }, + "expected": [-1, 0] + }, + { + "uuid": "2d2c05a0-4038-4427-a24d-72f6624aa45f", + "description": "Exponential of 0", + "property": "exp", + "input": { + "z": [0, 0] + }, + "expected": [1, 0] + }, + { + "uuid": "ed87f1bd-b187-45d6-8ece-7e331232c809", + "description": "Exponential of a purely real number", + "property": "exp", + "input": { + "z": [1, 0] + }, + "expected": ["e", 0] + }, + { + "uuid": "08eedacc-5a95-44fc-8789-1547b27a8702", + "description": "Exponential of a number with real and imaginary part", + "property": "exp", + "input": { + "z": ["ln(2)", "pi"] + }, + "expected": [-2, 0] + } + ] + } + ] +} diff --git a/.github/workflow-tests/immutability-check/canonical-data-mutated.json b/.github/workflow-tests/immutability-check/canonical-data-mutated.json new file mode 100644 index 0000000000..f6d695512d --- /dev/null +++ b/.github/workflow-tests/immutability-check/canonical-data-mutated.json @@ -0,0 +1,368 @@ +{ + "exercise": "complex-numbers", + "comments": [ + " The canonical data assumes mathematically correct real ", + " numbers. The testsuites should consider rounding errors ", + " instead of testing for exact values for any non-integer ", + " tests. ", + " Complex numbers z are represented as arrays [x, y] so ", + " that z = x + i * y. ", + " Pi is represented as a string \"pi\", euler's number is ", + " represented as \"e\". " + ], + "cases": [ + { + "description": "Real part", + "cases": [ + { + "uuid": "9f98e133-eb7f-45b0-9676-cce001cd6f7a", + "description": "Real part of a purely real number", + "property": "real", + "input": { + "z": [2, 0] + }, + "expected": 2 + }, + { + "uuid": "07988e20-f287-4bb7-90cf-b32c4bffe0f3", + "description": "Real part of a purely imaginary number", + "property": "real", + "input": { + "z": [0, 2] + }, + "expected": 0 + }, + { + "uuid": "4a370e86-939e-43de-a895-a00ca32da60a", + "description": "Real part of a number with real and imaginary part", + "property": "real", + "input": { + "z": [1, 2] + }, + "expected": 1 + } + ] + }, + { + "description": "Imaginary part", + "cases": [ + { + "uuid": "9b3fddef-4c12-4a99-b8f8-e3a42c7ccef6", + "description": "Imaginary part of a purely real number", + "property": "imaginary", + "input": { + "z": [1, 0] + }, + "expected": 0 + }, + { + "uuid": "a8dafedd-535a-4ed3-8a39-fda103a2b01e", + "description": "Imaginary part of a purely imaginary number", + "property": "imaginary", + "input": { + "z": [0, 1] + }, + "expected": 1 + }, + { + "uuid": "0f998f19-69ee-4c64-80ef-01b086feab80", + "description": "Imaginary part of a number with real and imaginary part", + "property": "imaginary", + "input": { + "z": [1, 2] + }, + "expected": 2 + } + ] + }, + { + "uuid": "a39b7fd6-6527-492f-8c34-609d2c913879", + "description": "Imaginary unit", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 1] + }, + "expected": [-1, 0] + }, + { + "description": "Arithmetic", + "cases": [ + { + "description": "Addition", + "cases": [ + { + "uuid": "9a2c8de9-f068-4f6f-b41c-82232cc6c33e", + "description": "Add purely real numbers", + "property": "add", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [3, 0] + }, + { + "uuid": "657c55e1-b14b-4ba7-bd5c-19db22b7d659", + "description": "Add purely imaginary numbers", + "property": "add", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0, 3] + }, + { + "uuid": "4e1395f5-572b-4ce8-bfa9-9a63056888da", + "description": "Add numbers with real and imaginary part", + "property": "add", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [4, 6] + } + ] + }, + { + "description": "Subtraction", + "cases": [ + { + "uuid": "1155dc45-e4f7-44b8-af34-a91aa431475d", + "description": "Subtract purely real numbers", + "property": "sub", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [-1, 0] + }, + { + "uuid": "f95e9da8-acd5-4da4-ac7c-c861b02f774b", + "description": "Subtract purely imaginary numbers", + "property": "sub", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0, -1] + }, + { + "uuid": "f876feb1-f9d1-4d34-b067-b599a8746400", + "description": "Subtract numbers with real and imaginary part", + "property": "sub", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-2, -2] + } + ] + }, + { + "description": "Multiplication", + "cases": [ + { + "uuid": "8a0366c0-9e16-431f-9fd7-40ac46ff4ec4", + "description": "Multiply purely real numbers", + "property": "mul", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [2, 0] + }, + { + "uuid": "e560ed2b-0b80-4b4f-90f2-63cefc911aaf", + "description": "Multiply purely imaginary numbers", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [-2, 0] + }, + { + "uuid": "4d1d10f0-f8d4-48a0-b1d0-f284ada567e6", + "description": "Multiply numbers with real and imaginary part", + "property": "mul", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-5, 10] + } + ] + }, + { + "description": "Division", + "cases": [ + { + "uuid": "b0571ddb-9045-412b-9c15-cd1d816d36c1", + "description": "Divide purely real numbers", + "property": "div", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [0.5, 0] + }, + { + "uuid": "5bb4c7e4-9934-4237-93cc-5780764fdbdd", + "description": "Divide purely imaginary numbers", + "property": "div", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0.5, 0] + }, + { + "uuid": "c4e7fef5-64ac-4537-91c2-c6529707701f", + "description": "Divide numbers with real and imaginary part", + "property": "div", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [0.44, 0.08] + } + ] + } + ] + }, + { + "description": "Absolute value", + "cases": [ + { + "uuid": "c56a7332-aad2-4437-83a0-b3580ecee843", + "description": "Absolute value of a positive purely real number", + "property": "abs", + "input": { + "z": [5, 0] + }, + "expected": 5 + }, + { + "uuid": "cf88d7d3-ee74-4f4e-8a88-a1b0090ecb0c", + "description": "Absolute value of a negative purely real number", + "property": "abs", + "input": { + "z": [-5, 0] + }, + "expected": 5 + }, + { + "uuid": "bbe26568-86c1-4bb4-ba7a-da5697e2b994", + "description": "Absolute value of a purely imaginary number with positive imaginary part", + "property": "abs", + "input": { + "z": [0, 5] + }, + "expected": 5 + }, + { + "uuid": "3b48233d-468e-4276-9f59-70f4ca1f26f3", + "description": "Absolute value of a purely imaginary number with negative imaginary part", + "property": "abs", + "input": { + "z": [0, -5] + }, + "expected": 5 + }, + { + "uuid": "fe400a9f-aa22-4b49-af92-51e0f5a2a6d3", + "description": "Absolute value of a number with real and imaginary part", + "property": "abs", + "input": { + "z": [3, 4] + }, + "expected": 5 + } + ] + }, + { + "description": "Complex conjugate", + "cases": [ + { + "uuid": "fb2d0792-e55a-4484-9443-df1eddfc84a2", + "description": "Conjugate a purely real number", + "property": "conjugate", + "input": { + "z": [5, 0] + }, + "expected": [5, 0] + }, + { + "uuid": "e37fe7ac-a968-4694-a460-66cb605f8691", + "description": "Conjugate a purely imaginary number", + "property": "conjugate", + "input": { + "z": [0, 5] + }, + "expected": [0, -5] + }, + { + "uuid": "f7704498-d0be-4192-aaf5-a1f3a7f43e68", + "description": "Conjugate a number with real and imaginary part", + "property": "conjugate", + "input": { + "z": [1, 1] + }, + "expected": [1, -1] + } + ] + }, + { + "description": "Complex exponential function", + "comments": [ + " Defining the exponential function can be optional. ", + " If the language used does not have sine and cosine ", + " functions in the standard library, this will be ", + " significantly more difficult than the rest of the exer- ", + " cise and should probably not be part of the problem. ", + " The recommended implementation uses Euler's formula ", + " exp(ix) = cos(x) + i * sin(x). This is not an ideal sol- ", + " ution but works for the purpose of teaching complex ", + " numbers. " + ], + "cases": [ + { + "uuid": "6d96d4c6-2edb-445b-94a2-7de6d4caaf60", + "description": "Euler's identity/formula", + "property": "exp", + "input": { + "z": [0, "pi"] + }, + "expected": [-1, 0] + }, + { + "uuid": "2d2c05a0-4038-4427-a24d-72f6624aa45f", + "description": "Exponential of 0", + "property": "exp", + "input": { + "z": [0, 0] + }, + "expected": [1, 0] + }, + { + "uuid": "ed87f1bd-b187-45d6-8ece-7e331232c809", + "description": "Exponential of a purely real number", + "property": "exp", + "input": { + "z": [1, 0] + }, + "expected": ["e", 0] + }, + { + "uuid": "08eedacc-5a95-44fc-8789-1547b27a8702", + "description": "Exponential of a number with real and imaginary part", + "property": "exp", + "input": { + "z": ["ln(2)", "pi"] + }, + "expected": [-2, 0] + } + ] + } + ] +} diff --git a/.github/workflow-tests/immutability-check/canonical-data-new-test.json b/.github/workflow-tests/immutability-check/canonical-data-new-test.json new file mode 100644 index 0000000000..96f8cfc6a6 --- /dev/null +++ b/.github/workflow-tests/immutability-check/canonical-data-new-test.json @@ -0,0 +1,377 @@ +{ + "exercise": "complex-numbers", + "comments": [ + " The canonical data assumes mathematically correct real ", + " numbers. The testsuites should consider rounding errors ", + " instead of testing for exact values for any non-integer ", + " tests. ", + " Complex numbers z are represented as arrays [x, y] so ", + " that z = x + i * y. ", + " Pi is represented as a string \"pi\", euler's number is ", + " represented as \"e\". " + ], + "cases": [ + { + "description": "Real part", + "cases": [ + { + "uuid": "9f98e133-eb7f-45b0-9676-cce001cd6f7a", + "description": "Real part of a purely real number", + "property": "real", + "input": { + "z": [1, 0] + }, + "expected": 1 + }, + { + "uuid": "9f98e133-eb7f-45b0-9676-cce001cd6f7x", + "description": "Real part of a number", + "property": "real", + "input": { + "z": [5, 3] + }, + "expected": 5 + }, + { + "uuid": "07988e20-f287-4bb7-90cf-b32c4bffe0f3", + "description": "Real part of a purely imaginary number", + "property": "real", + "input": { + "z": [0, 1] + }, + "expected": 0 + }, + { + "uuid": "4a370e86-939e-43de-a895-a00ca32da60a", + "description": "Real part of a number with real and imaginary part", + "property": "real", + "input": { + "z": [1, 2] + }, + "expected": 1 + } + ] + }, + { + "description": "Imaginary part", + "cases": [ + { + "uuid": "9b3fddef-4c12-4a99-b8f8-e3a42c7ccef6", + "description": "Imaginary part of a purely real number", + "property": "imaginary", + "input": { + "z": [1, 0] + }, + "expected": 0 + }, + { + "uuid": "a8dafedd-535a-4ed3-8a39-fda103a2b01e", + "description": "Imaginary part of a purely imaginary number", + "property": "imaginary", + "input": { + "z": [0, 1] + }, + "expected": 1 + }, + { + "uuid": "0f998f19-69ee-4c64-80ef-01b086feab80", + "description": "Imaginary part of a number with real and imaginary part", + "property": "imaginary", + "input": { + "z": [1, 2] + }, + "expected": 2 + } + ] + }, + { + "uuid": "a39b7fd6-6527-492f-8c34-609d2c913879", + "description": "Imaginary unit", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 1] + }, + "expected": [-1, 0] + }, + { + "description": "Arithmetic", + "cases": [ + { + "description": "Addition", + "cases": [ + { + "uuid": "9a2c8de9-f068-4f6f-b41c-82232cc6c33e", + "description": "Add purely real numbers", + "property": "add", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [3, 0] + }, + { + "uuid": "657c55e1-b14b-4ba7-bd5c-19db22b7d659", + "description": "Add purely imaginary numbers", + "property": "add", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0, 3] + }, + { + "uuid": "4e1395f5-572b-4ce8-bfa9-9a63056888da", + "description": "Add numbers with real and imaginary part", + "property": "add", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [4, 6] + } + ] + }, + { + "description": "Subtraction", + "cases": [ + { + "uuid": "1155dc45-e4f7-44b8-af34-a91aa431475d", + "description": "Subtract purely real numbers", + "property": "sub", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [-1, 0] + }, + { + "uuid": "f95e9da8-acd5-4da4-ac7c-c861b02f774b", + "description": "Subtract purely imaginary numbers", + "property": "sub", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0, -1] + }, + { + "uuid": "f876feb1-f9d1-4d34-b067-b599a8746400", + "description": "Subtract numbers with real and imaginary part", + "property": "sub", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-2, -2] + } + ] + }, + { + "description": "Multiplication", + "cases": [ + { + "uuid": "8a0366c0-9e16-431f-9fd7-40ac46ff4ec4", + "description": "Multiply purely real numbers", + "property": "mul", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [2, 0] + }, + { + "uuid": "e560ed2b-0b80-4b4f-90f2-63cefc911aaf", + "description": "Multiply purely imaginary numbers", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [-2, 0] + }, + { + "uuid": "4d1d10f0-f8d4-48a0-b1d0-f284ada567e6", + "description": "Multiply numbers with real and imaginary part", + "property": "mul", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-5, 10] + } + ] + }, + { + "description": "Division", + "cases": [ + { + "uuid": "b0571ddb-9045-412b-9c15-cd1d816d36c1", + "description": "Divide purely real numbers", + "property": "div", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [0.5, 0] + }, + { + "uuid": "5bb4c7e4-9934-4237-93cc-5780764fdbdd", + "description": "Divide purely imaginary numbers", + "property": "div", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0.5, 0] + }, + { + "uuid": "c4e7fef5-64ac-4537-91c2-c6529707701f", + "description": "Divide numbers with real and imaginary part", + "property": "div", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [0.44, 0.08] + } + ] + } + ] + }, + { + "description": "Absolute value", + "cases": [ + { + "uuid": "c56a7332-aad2-4437-83a0-b3580ecee843", + "description": "Absolute value of a positive purely real number", + "property": "abs", + "input": { + "z": [5, 0] + }, + "expected": 5 + }, + { + "uuid": "cf88d7d3-ee74-4f4e-8a88-a1b0090ecb0c", + "description": "Absolute value of a negative purely real number", + "property": "abs", + "input": { + "z": [-5, 0] + }, + "expected": 5 + }, + { + "uuid": "bbe26568-86c1-4bb4-ba7a-da5697e2b994", + "description": "Absolute value of a purely imaginary number with positive imaginary part", + "property": "abs", + "input": { + "z": [0, 5] + }, + "expected": 5 + }, + { + "uuid": "3b48233d-468e-4276-9f59-70f4ca1f26f3", + "description": "Absolute value of a purely imaginary number with negative imaginary part", + "property": "abs", + "input": { + "z": [0, -5] + }, + "expected": 5 + }, + { + "uuid": "fe400a9f-aa22-4b49-af92-51e0f5a2a6d3", + "description": "Absolute value of a number with real and imaginary part", + "property": "abs", + "input": { + "z": [3, 4] + }, + "expected": 5 + } + ] + }, + { + "description": "Complex conjugate", + "cases": [ + { + "uuid": "fb2d0792-e55a-4484-9443-df1eddfc84a2", + "description": "Conjugate a purely real number", + "property": "conjugate", + "input": { + "z": [5, 0] + }, + "expected": [5, 0] + }, + { + "uuid": "e37fe7ac-a968-4694-a460-66cb605f8691", + "description": "Conjugate a purely imaginary number", + "property": "conjugate", + "input": { + "z": [0, 5] + }, + "expected": [0, -5] + }, + { + "uuid": "f7704498-d0be-4192-aaf5-a1f3a7f43e68", + "description": "Conjugate a number with real and imaginary part", + "property": "conjugate", + "input": { + "z": [1, 1] + }, + "expected": [1, -1] + } + ] + }, + { + "description": "Complex exponential function", + "comments": [ + " Defining the exponential function can be optional. ", + " If the language used does not have sine and cosine ", + " functions in the standard library, this will be ", + " significantly more difficult than the rest of the exer- ", + " cise and should probably not be part of the problem. ", + " The recommended implementation uses Euler's formula ", + " exp(ix) = cos(x) + i * sin(x). This is not an ideal sol- ", + " ution but works for the purpose of teaching complex ", + " numbers. " + ], + "cases": [ + { + "uuid": "6d96d4c6-2edb-445b-94a2-7de6d4caaf60", + "description": "Euler's identity/formula", + "property": "exp", + "input": { + "z": [0, "pi"] + }, + "expected": [-1, 0] + }, + { + "uuid": "2d2c05a0-4038-4427-a24d-72f6624aa45f", + "description": "Exponential of 0", + "property": "exp", + "input": { + "z": [0, 0] + }, + "expected": [1, 0] + }, + { + "uuid": "ed87f1bd-b187-45d6-8ece-7e331232c809", + "description": "Exponential of a purely real number", + "property": "exp", + "input": { + "z": [1, 0] + }, + "expected": ["e", 0] + }, + { + "uuid": "08eedacc-5a95-44fc-8789-1547b27a8702", + "description": "Exponential of a number with real and imaginary part", + "property": "exp", + "input": { + "z": ["ln(2)", "pi"] + }, + "expected": [-2, 0] + } + ] + } + ] +} diff --git a/.github/workflow-tests/immutability-check/canonical-data.json b/.github/workflow-tests/immutability-check/canonical-data.json new file mode 100644 index 0000000000..8233b1d2e7 --- /dev/null +++ b/.github/workflow-tests/immutability-check/canonical-data.json @@ -0,0 +1,368 @@ +{ + "exercise": "complex-numbers", + "comments": [ + " The canonical data assumes mathematically correct real ", + " numbers. The testsuites should consider rounding errors ", + " instead of testing for exact values for any non-integer ", + " tests. ", + " Complex numbers z are represented as arrays [x, y] so ", + " that z = x + i * y. ", + " Pi is represented as a string \"pi\", euler's number is ", + " represented as \"e\". " + ], + "cases": [ + { + "description": "Real part", + "cases": [ + { + "uuid": "9f98e133-eb7f-45b0-9676-cce001cd6f7a", + "description": "Real part of a purely real number", + "property": "real", + "input": { + "z": [1, 0] + }, + "expected": 1 + }, + { + "uuid": "07988e20-f287-4bb7-90cf-b32c4bffe0f3", + "description": "Real part of a purely imaginary number", + "property": "real", + "input": { + "z": [0, 1] + }, + "expected": 0 + }, + { + "uuid": "4a370e86-939e-43de-a895-a00ca32da60a", + "description": "Real part of a number with real and imaginary part", + "property": "real", + "input": { + "z": [1, 2] + }, + "expected": 1 + } + ] + }, + { + "description": "Imaginary part", + "cases": [ + { + "uuid": "9b3fddef-4c12-4a99-b8f8-e3a42c7ccef6", + "description": "Imaginary part of a purely real number", + "property": "imaginary", + "input": { + "z": [1, 0] + }, + "expected": 0 + }, + { + "uuid": "a8dafedd-535a-4ed3-8a39-fda103a2b01e", + "description": "Imaginary part of a purely imaginary number", + "property": "imaginary", + "input": { + "z": [0, 1] + }, + "expected": 1 + }, + { + "uuid": "0f998f19-69ee-4c64-80ef-01b086feab80", + "description": "Imaginary part of a number with real and imaginary part", + "property": "imaginary", + "input": { + "z": [1, 2] + }, + "expected": 2 + } + ] + }, + { + "uuid": "a39b7fd6-6527-492f-8c34-609d2c913879", + "description": "Imaginary unit", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 1] + }, + "expected": [-1, 0] + }, + { + "description": "Arithmetic", + "cases": [ + { + "description": "Addition", + "cases": [ + { + "uuid": "9a2c8de9-f068-4f6f-b41c-82232cc6c33e", + "description": "Add purely real numbers", + "property": "add", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [3, 0] + }, + { + "uuid": "657c55e1-b14b-4ba7-bd5c-19db22b7d659", + "description": "Add purely imaginary numbers", + "property": "add", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0, 3] + }, + { + "uuid": "4e1395f5-572b-4ce8-bfa9-9a63056888da", + "description": "Add numbers with real and imaginary part", + "property": "add", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [4, 6] + } + ] + }, + { + "description": "Subtraction", + "cases": [ + { + "uuid": "1155dc45-e4f7-44b8-af34-a91aa431475d", + "description": "Subtract purely real numbers", + "property": "sub", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [-1, 0] + }, + { + "uuid": "f95e9da8-acd5-4da4-ac7c-c861b02f774b", + "description": "Subtract purely imaginary numbers", + "property": "sub", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0, -1] + }, + { + "uuid": "f876feb1-f9d1-4d34-b067-b599a8746400", + "description": "Subtract numbers with real and imaginary part", + "property": "sub", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-2, -2] + } + ] + }, + { + "description": "Multiplication", + "cases": [ + { + "uuid": "8a0366c0-9e16-431f-9fd7-40ac46ff4ec4", + "description": "Multiply purely real numbers", + "property": "mul", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [2, 0] + }, + { + "uuid": "e560ed2b-0b80-4b4f-90f2-63cefc911aaf", + "description": "Multiply purely imaginary numbers", + "property": "mul", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [-2, 0] + }, + { + "uuid": "4d1d10f0-f8d4-48a0-b1d0-f284ada567e6", + "description": "Multiply numbers with real and imaginary part", + "property": "mul", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [-5, 10] + } + ] + }, + { + "description": "Division", + "cases": [ + { + "uuid": "b0571ddb-9045-412b-9c15-cd1d816d36c1", + "description": "Divide purely real numbers", + "property": "div", + "input": { + "z1": [1, 0], + "z2": [2, 0] + }, + "expected": [0.5, 0] + }, + { + "uuid": "5bb4c7e4-9934-4237-93cc-5780764fdbdd", + "description": "Divide purely imaginary numbers", + "property": "div", + "input": { + "z1": [0, 1], + "z2": [0, 2] + }, + "expected": [0.5, 0] + }, + { + "uuid": "c4e7fef5-64ac-4537-91c2-c6529707701f", + "description": "Divide numbers with real and imaginary part", + "property": "div", + "input": { + "z1": [1, 2], + "z2": [3, 4] + }, + "expected": [0.44, 0.08] + } + ] + } + ] + }, + { + "description": "Absolute value", + "cases": [ + { + "uuid": "c56a7332-aad2-4437-83a0-b3580ecee843", + "description": "Absolute value of a positive purely real number", + "property": "abs", + "input": { + "z": [5, 0] + }, + "expected": 5 + }, + { + "uuid": "cf88d7d3-ee74-4f4e-8a88-a1b0090ecb0c", + "description": "Absolute value of a negative purely real number", + "property": "abs", + "input": { + "z": [-5, 0] + }, + "expected": 5 + }, + { + "uuid": "bbe26568-86c1-4bb4-ba7a-da5697e2b994", + "description": "Absolute value of a purely imaginary number with positive imaginary part", + "property": "abs", + "input": { + "z": [0, 5] + }, + "expected": 5 + }, + { + "uuid": "3b48233d-468e-4276-9f59-70f4ca1f26f3", + "description": "Absolute value of a purely imaginary number with negative imaginary part", + "property": "abs", + "input": { + "z": [0, -5] + }, + "expected": 5 + }, + { + "uuid": "fe400a9f-aa22-4b49-af92-51e0f5a2a6d3", + "description": "Absolute value of a number with real and imaginary part", + "property": "abs", + "input": { + "z": [3, 4] + }, + "expected": 5 + } + ] + }, + { + "description": "Complex conjugate", + "cases": [ + { + "uuid": "fb2d0792-e55a-4484-9443-df1eddfc84a2", + "description": "Conjugate a purely real number", + "property": "conjugate", + "input": { + "z": [5, 0] + }, + "expected": [5, 0] + }, + { + "uuid": "e37fe7ac-a968-4694-a460-66cb605f8691", + "description": "Conjugate a purely imaginary number", + "property": "conjugate", + "input": { + "z": [0, 5] + }, + "expected": [0, -5] + }, + { + "uuid": "f7704498-d0be-4192-aaf5-a1f3a7f43e68", + "description": "Conjugate a number with real and imaginary part", + "property": "conjugate", + "input": { + "z": [1, 1] + }, + "expected": [1, -1] + } + ] + }, + { + "description": "Complex exponential function", + "comments": [ + " Defining the exponential function can be optional. ", + " If the language used does not have sine and cosine ", + " functions in the standard library, this will be ", + " significantly more difficult than the rest of the exer- ", + " cise and should probably not be part of the problem. ", + " The recommended implementation uses Euler's formula ", + " exp(ix) = cos(x) + i * sin(x). This is not an ideal sol- ", + " ution but works for the purpose of teaching complex ", + " numbers. " + ], + "cases": [ + { + "uuid": "6d96d4c6-2edb-445b-94a2-7de6d4caaf60", + "description": "Euler's identity/formula", + "property": "exp", + "input": { + "z": [0, "pi"] + }, + "expected": [-1, 0] + }, + { + "uuid": "2d2c05a0-4038-4427-a24d-72f6624aa45f", + "description": "Exponential of 0", + "property": "exp", + "input": { + "z": [0, 0] + }, + "expected": [1, 0] + }, + { + "uuid": "ed87f1bd-b187-45d6-8ece-7e331232c809", + "description": "Exponential of a purely real number", + "property": "exp", + "input": { + "z": [1, 0] + }, + "expected": ["e", 0] + }, + { + "uuid": "08eedacc-5a95-44fc-8789-1547b27a8702", + "description": "Exponential of a number with real and imaginary part", + "property": "exp", + "input": { + "z": ["ln(2)", "pi"] + }, + "expected": [-2, 0] + } + ] + } + ] +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..f8b251cf87 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,117 @@ +name: CI + +on: + pull_request: + +jobs: + required-files: + name: All required files are present + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: All required files are present + run: bin/check_required_files_present + + immutability: + name: No test has been mutated + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + with: + path: "new" + + # Pull Requests + - name: Checkout the target branch + uses: actions/checkout@v2 + with: + ref: "${{ github.base_ref }}" + path: "old" + + - name: Check that no test has been mutated + run: | + for oldf in old/exercises/*/canonical-data.json; do + newf=${oldf//old/new} + ./new/bin/check-immutability.py "$oldf" "$newf" + done + + schema-validation: + name: Schema validation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-node@v1 + with: + node-version: "12" + + # https://github.com/actions/cache/blob/master/examples.md#node---yarn + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "::set-output name=dir::$(yarn cache dir)" + + - name: Cache yarn + uses: actions/cache@v2 + id: yarn-cache + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Install dependencies + run: yarn install + + - name: Verify that canonical-data.json files adhere to canonical-schema.json + run: yarn test + + - name: Verify that all UUIDs are indeed unique + run: | + duplicate_uuids=$(cat exercises/*/canonical-data.json | + jq -r '.. |."uuid"? | select(. != null)' | # select all UUIDs + sort | uniq -d) # check for repeated UUIDs + if [ -n "$duplicate_uuids" ]; then + echo "The following UUIDs are not unique:" + echo "$duplicate_uuids" + exit 1 + fi + + - name: Verify that reimplements-values refer to existing UUID + run: | + fail=0 + + for f in exercises/*/canonical-data.json; do + # Search for reimplemented test cases + reimplements=$(jq -r '.. |."reimplements"? | select(. != null)' "$f") + + # Abort early if the exercise doesn't have reimplemented test cases + [[ -e $reimplements ]] && continue + + uuids=$(jq -r '.. |."uuid"? | select(. != null)' "$f") + for reimplemented_uuid in $reimplements; do + if [[ $uuids != *"$reimplemented_uuid"* ]]; then + echo "$f: reimplemented value refers to a test case with UUID $reimplemented_uuid, but the file does not contain any test cases with that UUID." + fail=1 + fi + done + done + + exit "$fail" + + - name: Verify that all scenarios are defined in the schema + run: | + canonical_schema_file="canonical-schema.json" + scenarios_file="SCENARIOS.txt" + + fail=0 + + while read -r scenario; do + jq -e ".definitions.scenario.enum | index(\"$scenario\")" $canonical_schema_file > /dev/null + + if [ $? -eq 1 ]; then + echo "$canonical_schema_file: scenario '$scenario' is missing from the '.definitions.scenario.enum' field." + fail=1 + fi + done < $scenarios_file + + exit "$fail" diff --git a/.github/workflows/rebase.yml b/.github/workflows/rebase.yml new file mode 100644 index 0000000000..3533cc7b7c --- /dev/null +++ b/.github/workflows/rebase.yml @@ -0,0 +1,21 @@ +name: Rebase command + +on: + issue_comment: + types: [created] + +jobs: + rebase: + name: Rebase + if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase') + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@master + with: + fetch-depth: 0 + + - name: Automatic Rebase + uses: cirrus-actions/rebase@7cea12ac34ab078fa37e87798d8986185afa7bf2 # 1.4 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 3c3629e647..b91eaeb78c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,20 @@ +# OS specific auto-generated folders and files +*.swp +.DS_Store + +# Platform specific tools (use fetch-configlet) +bin/configlet +bin/configlet.exe + +# IDE folders and files +.idea + +# package.json generated content node_modules + +# Ignore npm error/log +npm-debug.log + +# Ignore yarn lockfile and error, in case someone accidentally runs yarn +yarn.lock +yarn-error.log diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 79db16f5b9..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: node_js -node_js: - - "6" - -cache: yarn - -script: - - bin/check_required_files_present - - sh bin/check_versions - - bin/check_optional - - yarn test diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 77d2cc4196..a5e09a05b2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,7 +17,7 @@ This guide covers several common scenarios pertaining to **improving the languag themselves. There are other guides about contributing to other parts of the Exercism ecosystem. * [The Command-Line Client](https://github.com/exercism/cli/blob/master/README.md) -* [The Website](https://github.com/exercism/exercism.io/blob/master/CONTRIBUTING.md) +* [The Website](https://github.com/exercism/website/blob/master/CONTRIBUTING.md) * [The Exercises API](https://github.com/exercism/x-api/blob/master/CONTRIBUTING.md) (used by both the command-line client and the website) ## Table of Contents @@ -33,7 +33,6 @@ themselves. There are other guides about contributing to other parts of the Exer * [Beta-Testing a Language Track](#beta-testing-a-language-track) * [Useful Tidbits](#useful-tidbits) * [Pull Request Guidelines](#pull-request-guidelines) - * [Exercise Versioning](#exercise-versioning) * [Anatomy of an Exercise](#anatomy-of-an-exercise) * [Track configuration file (config.json)](#track-configuration-file) * [Track-Level Linting With Configlet](#track-level-linting-with-configlet) @@ -147,14 +146,11 @@ If you're unsure where to make the change, ask us, and we'll help you figure it Once you've updated the test suite, there are a few things you'll want to check. -- Make sure the [reference solution](#reference-solution) is still passing. -- If the exercise is [versioned](#exercise-versioning), and the change will - mean that existing solutions on the site will not pass the new tests, then - increment the version number, both in the test and in the reference solution. +- Make sure the reference solution is still passing. - Run the full, track-level test suite, if available. If the track has a way to automatically run all the tests against their reference solutions, it will be documented in the README. -- Run [configlet](#track-level-linting-with-configlet), the track-level linter. +- Run configlet, the track-level linter. You can also take a look at the `.travis.yml` file to see what the continuous integration system will do to verify the track. @@ -187,10 +183,7 @@ needs to be made in the [exercism/problem-specifications repository](https://git not directly to the test suite itself. Find the JSON file for the problem in question. For example, if you want to change -the Clock problem, then look for `exercises/clock/canonical-data.json`. Each -change should also bump the version of the test data. For more information, -see the [test data versioning](README.md#test-data-versioning) section of the -README. +the Clock problem, then look for `exercises/clock/canonical-data.json`. Submit a pull request with the change. @@ -261,6 +254,8 @@ Each track should have the following structure: │   └── TESTS.md └── exercises └── hello-world + └── .meta + │ └── tests.toml (only if the exercise is based on canonical data) ├── hello-world_example.file ├── hello-world.file └── hello-world_test.file @@ -284,7 +279,7 @@ The example template for a track can be found in the [request-new-language-track - `LEARNING.md` - a few notes about where people might want to go to learn the track's language from scratch. These are the the resources you need only when first getting up to speed with a language (tutorials, blog posts, etc.). - `RESOURCES.md` - references and other useful resources. These resources are those that would commonly be used by a developer on an ongoing basis (core language docs, api docs, etc.). -* `exercises` - all exercises for the track should live in subdirectories of this directory. Each exercise should have a test file, an example file that should pass all tests, and a template file that is a stub to help the user get started with the exercise. The example file should be used for the CI build. +* `exercises` - all exercises for the track should live in subdirectories of this directory. Each exercise should have a test file, an example file that should pass all tests, and a template file that is a stub to help the user get started with the exercise. The example file should be used for the CI build. If the exercise is based on canonical data, a `tests.toml` file should be created which contains a mapping from a canonical test case's UUID to a boolean value that indicates if the test case was implemented by the exercise ## Starting a New Track @@ -322,32 +317,6 @@ scenarios in this guide. See the [pull request guidelines](https://github.com/exercism/docs/blob/master/contributing/pull-request-guidelines.md) in the docs repository. -### Exercise Versioning - -It's only when we get a bunch of people having conversations about the -solutions that we really discover what makes a problem interesting, and -in what way it can be improved. - -Some changes to the test suites will invalidate existing solutions that people -have submitted. - -We think this is totally fine, however sometimes people start leaving feedback -saying _this doesn't pass the tests_. This is technically true, but since the -solution passed the tests at the time it was written, it's generally more -useful to just discuss the code as it is, rather than enforce strict -adherence to the most recent version of the tests. - -Some language tracks have implemented a simple, manual versioning system to -help avoid unnecessary discussions about failing the current test suites. - -If the exercise is versioned, then the test suite will probably have a -_book-keeping_ type test at the very bottom that asserts against a value in -the reference solution. If the change you're making is backwards-incompatible, -then please increment the version in both the test suite and the reference -solution. - -Please review the details in [README.md](https://github.com/exercism/problem-specifications#test-data-versioning) and bump the version number accordingly. - ### Anatomy of an Exercise See the [anatomy of an exercise](https://github.com/exercism/docs/tree/master/language-tracks/exercises/anatomy) in the docs repository. diff --git a/README.md b/README.md index 84d5b7f5fc..c44a009bd5 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@ Shared metadata for Exercism exercises. ## Contributing Guide -Please see the [contributing guide](https://github.com/exercism/problem-specifications/blob/master/CONTRIBUTING.md) +Please see the [contributing guide](./CONTRIBUTING.md). -## Problem metadata +## Exercise Metadata -Each problem's data lives in a directory under `exercises/` +Each exercise's metadata lives in a directory under `exercises/`. ```text exercises/ @@ -26,183 +26,216 @@ exercises/ └── metadata.yml ``` -There are three metadata files: +There are three metadata files per exercise: -* `description.md` - the basic problem description -* `metadata.yml` - additional information about the problem, such as where it came from -* `canonical-data.json` - standardized test inputs and outputs that can be used to implement the problem +- `description.md` - the basic problem description +- `metadata.yml` - additional information about the exercise, such as where it came from +- `canonical-data.json` (optional) - standardized test inputs and outputs that can be used to implement the exercise -## Test Data Format (canonical-data.json) +## Test Data (canonical-data.json) -This data can be incorporated into test programs manually or extracted by a -program. The file format is described in [canonical-schema.json](https://github.com/exercism/problem-specifications/blob/master/canonical-schema.json), but it -is easier to understand with an example: +Test data can be incorporated into a track's test suites manually or extracted by a program (a.k.a. a _test generator_). + +- Exercises _must_ contain tests that cover the public interface of the exercise (also thought of as "application tests"). +- Exercises _may_ contain tests that cover the private or lower-level interface of the exercise (sometimes refered to as "library tests"). + +- Test cases are immutable, which means that once a test case has been added, it never changes. There are two exceptions: + - The `comments` field _can_ be mutated and thus does not require adding a new test case when changing its value. + - The `scenarios` field _can_ be mutated additively, by adding new scenarios. Existing scenarios must not be changed or removed. Adding new scenarios thus does not require adding a new test case. +- Test cases _must_ all be considered optional, insomuch that a track should determine per test case whether to implement it or not. +- Each test case has a [UUID (v4)](https://en.wikipedia.org/wiki/Universally_unique_identifier) to uniquely identify it. +- If tracks automatically generate test suites from test data, they _must_ do that based on an explicit list of test cases to include/exclude. Test cases must be identified by their UUID, and we'll provide tooling to help keep track of which test cases to include/exclude. + +## Test Data Format + +The file format is described in [canonical-schema.json](./canonical-schema.json), but it is easier to understand with an example: ```json -{ "exercise": "foobar" -, "version" : "1.1.0" -, "comments": - [ " Comments are always optional and can be used almost anywhere. " - , " " - , " They usually document how the exercise's readme ('description.md') " - , " is generally interpreted in test programs across different " - , " languages. " - , " " - , " In addition to a mainstream implementation path, this information " - , " can also document significant variations. " - ] -, "cases": - [ { "comments": - [ " A test case must have a 'description' and a 'property'. " - , " Anything else is optional. " - , " " - , " The 'property' is a string in lowerCamelCase identifying " - , " the type of test, but most of the times it is just the " - , " name of a function being tested. " - , " " - , " Test cases can have any number of additional keys, and " - , " most of them also have an 'expected' one, defining the " - , " value a test should return. " - ] - , "description": "Foo'ing a word returns it reversed" - , "property" : "foo" - , "input" : { - "word" : "lion" +{ + "exercise": "foobar", + "comments": [ + " Comments are always optional and can be used almost anywhere. ", + " ", + " They usually document how the exercise's readme ('description.md') ", + " is generally interpreted in test programs across different ", + " languages. ", + " ", + " In addition to a mainstream implementation path, this information ", + " can also document significant variations. " + ], + "cases": [ + { + "comments": [ + " A test case must have 'uuid', 'description', 'property', ", + " 'input' and 'expected' properties. The rest is optional. ", + " ", + " The 'property' is a string in lowerCamelCase identifying ", + " the type of test, but most of the times it is just the ", + " name of a function being tested. ", + " ", + " Test cases can have any number of additional keys, and ", + " most of them also have an 'expected' one, defining the ", + " value a test should return. " + ], + "uuid": "31e9db74-86b9-4b14-a320-9ea910337289", + "description": "Foo'ing a word returns it reversed", + "property": "foo", + "input": { + "word": "lion" + }, + "expected": "noil" + }, + { + "uuid": "09113ce5-b008-45d0-98af-c0378b64966b", + "description": "Bar'ing a name returns its parts combined", + "property": "bar", + "input": { + "firstName": "Alan", + "lastName": "Smithee" + }, + "expected": "ASlmainthee" + }, + { + "comments": [ + " Test cases can be arbitrarily grouped with a description ", + " to make organization easier. " + ], + "description": "Abnormal inputs: numbers", + "cases": [ + { + "uuid": "f22d7a03-e752-4f14-9231-4eae9f128cef", + "description": "Foo'ing a number returns nothing", + "property": "foo", + "input": { + "word": "42" + }, + "expected": null + }, + { + "uuid": "8790a635-e8a8-4343-a29f-7da2929b9378", + "description": "Foo'ing a very big number returns nothing", + "optional": "big-ints", + "comments": ["Making this test case pass requires using BigInts."], + "property": "foo", + "input": { + "word": "28948022309329048855892746252171976962977213799489202546401021394546514198529" + }, + "expected": null, + "scenarios": ["big-integers"] + }, + { + "uuid": "c7b6f24a-553f-475a-8a40-dba854fe1bff", + "description": "Bar'ing a name with numbers gives an error", + "property": "bar", + "input": { + "firstName": "HAL", + "lastName": "9000" + }, + "expected": { "error": "You should never bar a number" } } - , "expected" : "noil" - } - , { "description": "Bar'ing a name returns its parts combined" - , "property" : "bar" - , "input" : { - "firstName" : "Alan", - "lastName" : "Smithee" - } - , "expected" : "ASlmainthee" - } - , { "comments": - [ " Test cases can be arbitrarily grouped with a description " - , " to make organization easier. " - ] - , "description": "Abnormal inputs: numbers" - , "cases": - [ { "description": "Foo'ing a number returns nothing" - , "property" : "foo" - , "input" : { - "word" : "42" - } - , "expected" : null - } - , { "description": "Foo'ing a very big number returns nothing" - , "optional" : "big-ints" - , "comments" : [ "Making this test case pass requires using BigInts." ] - , "property" : "foo" - , "input" : { - "word" : "28948022309329048855892746252171976962977213799489202546401021394546514198529" - } - , "expected" : null - } - , { "description": "Bar'ing a name with numbers gives an error" - , "property" : "bar" - , "input" : { - "firstName" : "HAL", - "lastName" : "9000" - } - , "expected" : { "error": "You should never bar a number" } - } - ] - } + ] + } ] } - ``` -Keep in mind that the description should not simply explain **what** each case -is (that is redundant information) but also **why** each case is there. For -example, what kinds of implementation mistakes might this case help us find? +## Scenarios -There are also some conventions that must be followed: - - - All keys should follow the [lowerCamelCase](http://wiki.c2.com/?LowerCamelCase) convention. - - If the input is valid but there is no result for the input, the value at `"expected"` should be `null`. - - If an error is expected (because the input is invalid, or any other reason), the value at `"expected"` should be an object containing exactly one property, `"error"`, whose value is a string. - - The string should explain why the error would occur. - - A particular track's implementation of the exercise **need not** necessarily check that the error includes that exact string as the cause, depending on what is idiomatic in the language (it may not be idiomatic to check strings for error messages). - - Test cases that only some tracks should implement, for example because it would unnecessarily increase the complexity of the exercise in some but not all languages, mark it with an `optional`-key. Multiple cases related to the same reason for optionality should have the same key. The decision that a test case is optional will often be made in the PR discussion, so don't worry about it too much while creating a PR. +An optional field to allow for selectively including/excluding test cases based on a property of the test case (such as using big integers). -The `canonical.json` file can be validated against its schema prior to commiting using https://www.jsonschemavalidator.net/ with... -``` -{ - "$schema": "https://github.com/exercism/problem-specifications/blob/master/canonical-schema.json" -} -``` +- The `scenarios` field can use one or more of a predefined set of values, which are defined in a [`SCENARIOS.txt`](./SCENARIOS.txt) file. +- The `scenarios` field can be mutated additively, by adding new scenarios. Existing scenarios must not be changed or removed. Adding new scenarios does therefore does not mean adding a new test case. +- Library tests should have a `library-test` scenario added to allow for easy including/excluding of library tests. Application tests won't have their own scenario, as they must be included and should not be filtered on. +## Changing Tests -### Test Data Versioning +As test cases are immutable, a "bug fix" requires adding a new test case. We'll add metadata to test cases to link a re-implementation of a test case to the re-implemented test case. -Test data should be versioned according to [Semantic Version 2.0](http://semver.org/), which is defined as follows: +- Re-implemented test cases _must_ have a `reimplements` field which contains the UUID of the test case that was re-implemented. +- Re-implemented test cases _must_ use the `comments` field to explain why a test case was re-implemented (e.g. "Expected value is changed to 2"). +- Track generators _should not_ automatically select the "latest" version of a test case by looking at the "reimplements" hierarchy. We recommend each track to make this a manual action, as the re-implemented test case might actually make less sense for a track. -> Given a version number MAJOR.MINOR.PATCH, increment the: -> -> MAJOR version when you make incompatible API changes, -> MINOR version when you add functionality in a backwards-compatible manner, and -> PATCH version when you make backwards-compatible bug fixes. -> Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format. +This is an example of what a re-implementation looks like: -#### MAJOR version changes +```json +[ + { + "uuid": "e46c542b-31fc-4506-bcae-6b62b3268537", + "description": "two times one is two", + "property": "twice", + "input": { + "number": 1 + }, + "expected": 3 + }, + { + "uuid": "82d32c2e-07b5-42d9-9b1c-19af72bae860", + "description": "two times one is two", + "comments": ["Expected value is changed to 2"], + "reimplements": "e46c542b-31fc-4506-bcae-6b62b3268537", + "property": "twice", + "input": { + "number": 1 + }, + "expected": 2 + } +] +``` -The MAJOR version should be changed when the test suite is modified in a -fundamentally incompatible way. +## Track Test Data -There are examples of changes requiring a MAJOR version change: +If a track implements an exercise for which test data exists, the exercise _must_ contain a `.meta/tests.toml` file. The goal of this file is to keep track of which tests are implemented by the exercise. Tests in this file are identified by their UUID and each test has a boolean value that indicates if it is implemented by that exercise. -- A new "property" (test type). -- Renaming a "property". -- Insertion, deletion or renaming of keys in the test data object. -- Changing the type of one of the test data keys. +A `tests.toml` file for a track's `two-fer` exercise looks like this: -MAJOR changes should be expected to break even well-behaved test generators. +```toml +[canonical-tests] -#### MINOR version changes +# no name given +"19709124-b82e-4e86-a722-9e5c5ebf3952" = true -The MINOR version should change when you add functionality in a backwards-compatible manner, make -non-breaking changes that alter the meaning of the test suite, make previously -passing solutions possibly fail, or failing solutions fail at a different spot. +# a name given +"3451eebd-123f-4256-b667-7b109affce32" = true -There are examples of changes requiring a MINOR version change: +# another name given +"653611c6-be9f-4935-ab42-978e25fe9a10" = false +``` -- Adding or deleting test cases. -- Changing the test cases inputs and/or outputs. -- Changing the test cases ordering. +In this case, the track has chosen to implement two of the three available tests. -MINOR changes would never break well-designed test generators, because the test-generation logic remains exactly the same. +If a track uses a _test generator_ to generate an exercise's test suite, it _must_ use the contents of the `tests.toml` file to determine which tests to include in the generated test suite. -#### PATCH version changes +### Track Test Data Tooling -The PATCH version should change when you make backwards-compatible bug fixes or - whenever the meaning of the tests does not change. +To make it easy to keep the `tests.toml` up to date, tracks can use the [`canonical_data_syncer` application](https://github.com/exercism/canonical-data-syncer). This application is a small, standalone binary that will compare the tests specified in the `tests.toml` files against the tests that are defined in the exercise's canonical data. It then interactively gives the maintainer the option to include or exclude test cases that are currently missing, updating the `tests.toml` file accordingly. -There are examples of changes requiring a PATCH version change: +To use the canonical data syncer tool, tracks should copying the [`fetch-canonical_data_syncer`](https://github.com/exercism/canonical-data-syncer/blob/master/scripts/fetch-canonical_data_syncer) and/or [`fetch-canonical_data_syncer.ps1`](https://github.com/exercism/canonical-data-syncer/blob/master/scripts/fetch-canonical_data_syncer.ps1) scripts into their repository. Then, running either of these scripts will download the latest version of the tool to the track's `bin` directory. The tool can be run using `./bin/canonical_data_syncer` or `.\bin\canonical_data_syncer.exe`, depending on your operating system. -- Regrouping/"Renesting" test cases without changing test case ordering. -- Changing descriptions or comments. -- Changing keys' ordering or formatting (would result in an equivalent JSON file). +## Conventions -PATCH changes would never break well-designed test generators, because the test data remains exactly the same. +There are also some conventions that must be followed: -#### Automatic verification of versioning changes +- Descriptions should not simply explain **what** each case is (that is redundant information) but also **why** each case is there. For example, what kinds of implementation mistakes might this case help us find? +- All keys should follow the [lowerCamelCase](http://wiki.c2.com/?LowerCamelCase) convention. +- If the input is valid but there is no result for the input, the value at `"expected"` should be `null`. +- If an error is expected (because the input is invalid, or any other reason), the value at `"expected"` should be an object containing exactly one property, `"error"`, whose value is a string. + - The string should explain why the error would occur. + - A particular track's implementation of the exercise **need not** necessarily check that the error includes that exact string as the cause, depending on what is idiomatic in the language (it may not be idiomatic to check strings for error messages). -Travis CI will automatically verify that all changed JSON files have their version changed, via [bin/check_versions](https://github.com/exercism/problem-specifications/blob/master/bin/check_versions). +## Validation -This helps avoid the mistake of forgetting to change the version when a change is made to the tests. +`canonical.json` files can be validated against its schema using https://www.jsonschemavalidator.net/ with... -Although this is desired most of the time, there are instances (e.g. formatting change) where no version change is desired. -In such instances, see [bin/check_versions](https://github.com/exercism/problem-specifications/blob/master/bin/check_versions) for the override string. -Place the string inside a commit message to skip the version check. -Note that as the override applies to the entire PR, it's highly advised that changes that do not require a version change should not be in the same PR as changes that do require a version change. +``` +{ +"$schema": "https://github.com/exercism/problem-specifications/blob/master/canonical-schema.json" +} +``` ## New Exercises Require a Glyph When creating a new exercise the design team needs to be informed so that a new glyph can be created. + - An issue should be opened in [exercism/website-icons](https://github.com/exercism/website-icons/issues) after a PR has been opened in problem-specifications. - This issue should reference the PR in problem-specifications. @@ -231,3 +264,7 @@ yarn run test-one exercises//canonical-data.json ``` Replace `` by the name of exercise which you want to check. + +## Github Action Workflows + +See [`workflows/README.md`](./workflows/README.md) diff --git a/OPTIONAL-KEYS.txt b/SCENARIOS.txt similarity index 72% rename from OPTIONAL-KEYS.txt rename to SCENARIOS.txt index a063b289f1..892d821e96 100644 --- a/OPTIONAL-KEYS.txt +++ b/SCENARIOS.txt @@ -1,3 +1,4 @@ -floating-point big-integer +floating-point +library-test unicode diff --git a/STYLE-GUIDE.md b/STYLE-GUIDE.md new file mode 100644 index 0000000000..f7b89f0406 --- /dev/null +++ b/STYLE-GUIDE.md @@ -0,0 +1,75 @@ +# Exercism's Style Guide + +This document acts as a Style Guide for the language and wording used in exercises. + +## Application + +These rules should be followed in all exercises. +Existing descriptions and test-cases can be updated to adhere to them without requiring "replacement" test cases. + +### Consistency within an exercise. + +There are some terms that have multiple valid spellings (e.g. "lower case" vs "lowercase"). +Where a consistent style has not been agreed within this document, these must be consistent within an exercise. + +### Exceptions + +Exercises may vary from these rules if there is general consensus across maintainers that this is reasonable. +For example, an exercise about converting between different units might choose not to use SI measurements. + +## Language + +All content should be written in US English. In the future other translations may occur, but the "official" Exercism language is US English. + +### Measurements +All units of measurement must be [SI](https://en.wikipedia.org/wiki/International_System_of_Units) or [SI-derived](https://en.wikipedia.org/wiki/SI_derived_unit) units. + +### Abbreviations, acronyms and initialisms + +Abbreviations, acronyms and initialisms are often more difficult to understand than other phrasing options, and can alienate people trying to learn. + +Many abbreviations are jargon. Avoid jargon where possible by using alternative language. Don't use abbreviations unless either: +- The abbreviated term is better known than the unabbreviated term +- The text will be excessively verbose without abbreviation + +When using abbreviations always explain what the term means on its first use. This will often, but not always, include expanding the abbreviation. It will rarely be sufficient to only expand the abbreviation. + +Here are some example rules: +- Prefer "if I recall correctly" to "IIRC" +- Prefer "as far as I know" to "AFAIK" +- Prefer "queue" to "FIFO" and "stack" to "FILO" +- Instead of describing an interface as "RESTful", describe it's specific properties +- If you must use "CRUD", explain that it stands for Create, Read, Update, Delete and that these are the basic actions in standard databases + +An some examples of good usage: +- "HyperText Markup Language (HTML) is the language used to describe document structure and content on the web" _(expanded and explained)_ +- "DNA, a set of chemical instructions that influence how our bodies are constructed" _(DNA is not expanded because "deoxyribonucleic acid" is unlikely to help explain what DNA is to our audience)_ +- "NASA, the United States' space agency, launched the Mariner 2 space probe in..." _(NASA is not expanded because the "National Aerospace and Space Administration" is much better known by its acronym than by its expanded name)_ +- "The Department of Motor Vehicles (DMV) is filled with sloths. That's why everything takes forever at the DMV" _(Define DMV the first time it is used)_ + +#### Exceptions + +Some abbreviations are considered common, useful, and non-technical enough that we have decided to permit them: +- `e.g.` or `eg` +- `i.e.` or `ie` +- `etc.` or `etc` +- `docs` + +Contractions (e.g. "won't", "I'm", "that's") should be used sparingly if at all in exercise descriptions, but are not restricted in other language around the site (e.g. website copy, mentoring). + +## Choice of words + +### Mathematical and jargon terms. + +In any place that mathematical terms are used they should be explained or substituted out for terms that require less domain knowledge. + +Examples: +- Rather than using "natural numbers", we should use "positive whole numbers". +- If we want to use the phrase "rational numbers", it must be explained in the introduction to the exercise. +- Rather than using the word range (which can have different meanings in different contexts) use "x < ? < y (greater than x and less than y)". +- Rather than using "esoteric terms", use the phrase "terms not understood by the majority of people". + +## Use consistency within an exercise. + +There are some terms that have multiple valid spellings (e.g. "lower case" vs "lowercase"). +Where a consistent style has not been agreed within this document, these must be consistent within an exercise. diff --git a/TOPICS.txt b/TOPICS.txt index df74455e66..38b48819ee 100644 --- a/TOPICS.txt +++ b/TOPICS.txt @@ -33,6 +33,7 @@ lists maps matrices optional_values +pointers queues records sequences @@ -50,6 +51,7 @@ algorithms bitwise_operations concurrency cryptography +data_structures domain_specific_languages files filtering diff --git a/bin/check-immutability.py b/bin/check-immutability.py new file mode 100755 index 0000000000..6f01366ad5 --- /dev/null +++ b/bin/check-immutability.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python + +import json +import subprocess +import sys + +oldf = sys.argv[1] +newf = sys.argv[2] + +immutable_keys = ('property', 'input', 'expected') + +# Use jq to flatten the test data, and parse it +old = json.loads(subprocess.run([f"jq -r '[.. | objects | select(.uuid != null)]' {oldf}"], stdout=subprocess.PIPE, shell=True).stdout.decode('utf-8')) +new = json.loads(subprocess.run([f"jq -r '[.. | objects | select(.uuid != null)]' {newf}"], stdout=subprocess.PIPE, shell=True).stdout.decode('utf-8')) + +# Convert new to dict uuid => case +new = {case['uuid']: case for case in new} + +fails = set() +deleted = set() + +# Iterate through old cases as only those could potentially be mutated +for case in old: + uuid = case['uuid'] + + # Check if the case has been deleted + if uuid not in new: + deleted.add(uuid) + continue + + # Check that scenarios are only updated additively + if 'scenarios' in case and not set(case['scenarios']).issubset(set(new[uuid]['scenarios'])): + fails.add(uuid) + continue + # Check for changes to immutable keys + for key in immutable_keys: + if case[key] != new[uuid][key]: + fails.add(uuid) + break + +if len(fails) == 0 and len(deleted) == 0: + sys.exit(0) + +if len(fails) > 0: + print('The following tests contain illegal mutations:') + for failure in fails: + print(f" - {failure} ({new[failure]['description']})") + +if len(deleted) > 0: + print('The following tests have been deleted illegally:') + for deletion in deleted: + print(f" - {deletion}") + +sys.exit(1) diff --git a/bin/check_optional b/bin/check_optional deleted file mode 100755 index 7d9aaf272d..0000000000 --- a/bin/check_optional +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh - -# This script checks that 'optional' fields in canonical-data.json are listed. - -optional_keys_file=OPTIONAL-KEYS.txt -allowed_optional=$(jq -nR '[inputs]' $optional_keys_file) - -failed=0 - -check_optional_for_file() { - json_file=$1 - echo "Checking 'optional' fields in $json_file" - - present_optional=$(jq '[ .cases[] | recurse(.cases[]?) | .optional | select(. != null) ]' $json_file) - invalid_optional=$(jq --null-input \ - --argjson allowed "$allowed_optional" \ - --argjson present "$present_optional" \ - --raw-output '$present - $allowed | join("\n")') - - if [ ! -z "$invalid_optional" ]; then - echo "Invalid optional fields:" - echo "$invalid_optional" | perl -pe 's/^/ - /' - echo - - failed=1 - fi -} - -for json_file in $(git diff --name-only master HEAD | grep '^exercises/.*/canonical-data\.json$'); do - check_optional_for_file $json_file -done - -if [ $failed -gt 0 ]; then - echo "Allowed optional fields (see $optional_keys_file) are:" - cat $optional_keys_file | perl -pe 's/^/ - /' - exit 1 -fi - -exit 0 diff --git a/bin/check_required_files_present b/bin/check_required_files_present index a1908815ea..4114176f24 100755 --- a/bin/check_required_files_present +++ b/bin/check_required_files_present @@ -31,7 +31,7 @@ function check_directory { } -while : +while : do case "$1" in -p | --progress) @@ -41,7 +41,7 @@ do *) check_directory 'exercises' if [ $SHOW_PROGRESS == 'true' ]; then - echo + echo echo Done: $MISSING_FILES files missing. fi if (( $MISSING_FILES > 0 )); then diff --git a/bin/check_versions b/bin/check_versions deleted file mode 100644 index 5f93ddede0..0000000000 --- a/bin/check_versions +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh - -override_message="I have confirmed that no JSON version change is needed" - -# If *any* commit message contains the override message: -# (Note that TRAVIS_COMMIT_MESSAGE for PRs is usually "merge commit abc123 into def456" -# which is not useful. Just search all commit messages between master and HEAD) - -if git log master..HEAD | grep -q "$override_message"; then - echo "WARNING: You've overridden the JSON version check, which applies to ALL commits in this PR." - echo "No JSON file in this PR will be checked for changes." - exit 0 -fi - -need_version=0 - -for json_file in $(git diff --name-only master HEAD | grep '^exercises/.*\.json$'); do - old_version=$(git show master:$json_file | jq .version) - new_version=$(jq .version $json_file) - - if [ "$old_version" = "$new_version" ]; then - echo "ERR This PR changed $json_file, so you should change the version as well." - need_version=1 - else - echo "OK This PR changed $json_file and changed the version." - fi -done - -if [ $need_version -ne 0 ]; then - echo 'You can see the versioning policy at https://github.com/exercism/problem-specifications#test-data-versioning' - exit 1 -fi diff --git a/bin/fetch-configlet b/bin/fetch-configlet new file mode 100755 index 0000000000..1db608054c --- /dev/null +++ b/bin/fetch-configlet @@ -0,0 +1,52 @@ +#!/usr/bin/env bash + +set -eo pipefail + +readonly LATEST='https://api.github.com/repos/exercism/configlet/releases/latest' + +case "$(uname)" in + (Darwin*) OS='mac' ;; + (Linux*) OS='linux' ;; + (Windows*) OS='windows' ;; + (MINGW*) OS='windows' ;; + (MSYS_NT-*) OS='windows' ;; + (*) OS='linux' ;; +esac + +case "$OS" in + (windows*) EXT='zip' ;; + (*) EXT='tgz' ;; +esac + +case "$(uname -m)" in + (*64*) ARCH='64bit' ;; + (*686*) ARCH='32bit' ;; + (*386*) ARCH='32bit' ;; + (*) ARCH='64bit' ;; +esac + +if [ -z "${GITHUB_TOKEN}" ] +then + HEADER='' +else + HEADER="authorization: Bearer ${GITHUB_TOKEN}" +fi + +FILENAME="configlet-${OS}-${ARCH}.${EXT}" + +get_url () { + curl --header "$HEADER" -s "$LATEST" | + awk -v filename=$FILENAME '$1 ~ /browser_download_url/ && $2 ~ filename { print $2 }' | + tr -d '"' +} + +URL=$(get_url) + +case "$EXT" in + (*zip) + curl --header "$HEADER" -s --location "$URL" -o bin/latest-configlet.zip + unzip bin/latest-configlet.zip -d bin/ + rm bin/latest-configlet.zip + ;; + (*) curl --header "$HEADER" -s --location "$URL" | tar xz -C bin/ ;; +esac diff --git a/bin/fetch-configlet.ps1 b/bin/fetch-configlet.ps1 new file mode 100755 index 0000000000..f89ed4ecb6 --- /dev/null +++ b/bin/fetch-configlet.ps1 @@ -0,0 +1,24 @@ +Function DownloadUrl ([string] $FileName, $Headers) { + $latestUrl = "https://api.github.com/repos/exercism/configlet/releases/latest" + $json = Invoke-RestMethod -Headers $Headers -Uri $latestUrl + $json.assets | Where-Object { $_.browser_download_url -match $FileName } | Select-Object -ExpandProperty browser_download_url +} + +Function Headers { + If ($GITHUB_TOKEN) { @{ Authorization = "Bearer ${GITHUB_TOKEN}" } } Else { @{ } } +} + +Function Arch { + If ([Environment]::Is64BitOperatingSystem) { "64bit" } Else { "32bit" } +} + +$arch = Arch +$headers = Headers +$fileName = "configlet-windows-$arch.zip" +$outputDirectory = "bin" +$outputFile = Join-Path -Path $outputDirectory -ChildPath $fileName +$zipUrl = DownloadUrl -FileName $fileName -Headers $headers + +Invoke-WebRequest -Headers $headers -Uri $zipUrl -OutFile $outputFile +Expand-Archive $outputFile -DestinationPath $outputDirectory -Force +Remove-Item -Path $outputFile diff --git a/canonical-schema.json b/canonical-schema.json index bc8bca3381..ba96cd733b 100644 --- a/canonical-schema.json +++ b/canonical-schema.json @@ -37,10 +37,9 @@ "canonicalData": { "description": "This is the top-level file structure" , "type" : "object" - , "required" : ["exercise" , "version", "cases"] + , "required" : ["exercise", "cases"] , "properties" : { "exercise" : { "$ref": "#/definitions/exercise" } - , "version" : { "$ref": "#/definitions/version" } , "comments" : { "$ref": "#/definitions/comments" } , "cases" : { "$ref": "#/definitions/testGroup" } } @@ -53,12 +52,6 @@ , "pattern" : "^[a-z]+(-[a-z]+)*$" }, - "version" : - { "description" : "Semantic versioning: MAJOR.MINOR.PATCH" - , "type" : "string" - , "pattern" : "^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*)){2}$" - }, - "comments": { "description": "An array of strings to fake multi-line comments" , "type" : "array" @@ -83,14 +76,16 @@ "labeledTest": { "description": "A single test with a description" , "type" : "object" - , "required" : ["description", "property", "input", "expected"] + , "required" : ["uuid", "description", "property", "input", "expected"] , "properties" : - { "description": { "$ref": "#/definitions/description" } - , "optional" : { "$ref": "#/definitions/optional" } - , "comments" : { "$ref": "#/definitions/comments" } - , "property" : { "$ref": "#/definitions/property" } - , "input" : { "$ref": "#/definitions/input" } - , "expected" : { "$ref": "#/definitions/expected" } + { "uuid" : { "$ref": "#/definitions/uuid" } + , "reimplements": { "$ref": "#/definitions/uuid" } + , "description" : { "$ref": "#/definitions/description" } + , "scenarios" : { "$ref": "#/definitions/scenarios" } + , "comments" : { "$ref": "#/definitions/comments" } + , "property" : { "$ref": "#/definitions/property" } + , "input" : { "$ref": "#/definitions/input" } + , "expected" : { "$ref": "#/definitions/expected" } } , "additionalProperties": false }, @@ -101,7 +96,7 @@ , "required" : ["description", "cases"] , "properties" : { "description": { "$ref": "#/definitions/description" } - , "optional" : { "$ref": "#/definitions/optional" } + , "scenarios" : { "$ref": "#/definitions/scenarios" } , "comments" : { "$ref": "#/definitions/comments" } , "cases" : { "$ref": "#/definitions/testGroup" } } @@ -113,10 +108,23 @@ , "type" : "string" }, - "optional": - { "description": "An identifier for similar optional test cases (kebab-case)" + "uuid": + { "description": "A version 4 UUID (compliant with RFC 4122) in the canonical textual representation" , "type" : "string" - , "pattern" : "^[a-z]+(-[a-z]+)*$" + , "pattern" : "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$" + }, + + "scenario": + { "description": "An identifier for a specific scenario (kebab-case)" + , "type": "string" + , "enum": ["big-integer", "floating-point", "library-test", "unicode"] + }, + + "scenarios": + { "description": "An array of scenarios that can be used to include/exclude test cases" + , "type" : "array" + , "items" : { "$ref": "#/definitions/scenario" } + , "minItems" : 0 }, "property": diff --git a/exercises/acronym/canonical-data.json b/exercises/acronym/canonical-data.json index b71c50c743..ea52235067 100644 --- a/exercises/acronym/canonical-data.json +++ b/exercises/acronym/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "acronym", - "version": "1.7.0", "cases": [ { "description": "Abbreviate a phrase", "cases": [ { + "uuid": "1e22cceb-c5e4-4562-9afe-aef07ad1eaf4", "description": "basic", "property": "abbreviate", "input": { @@ -14,6 +14,7 @@ "expected": "PNG" }, { + "uuid": "79ae3889-a5c0-4b01-baf0-232d31180c08", "description": "lowercase words", "property": "abbreviate", "input": { @@ -22,6 +23,7 @@ "expected": "ROR" }, { + "uuid": "ec7000a7-3931-4a17-890e-33ca2073a548", "description": "punctuation", "property": "abbreviate", "input": { @@ -30,6 +32,7 @@ "expected": "FIFO" }, { + "uuid": "32dd261c-0c92-469a-9c5c-b192e94a63b0", "description": "all caps word", "property": "abbreviate", "input": { @@ -38,6 +41,7 @@ "expected": "GIMP" }, { + "uuid": "ae2ac9fa-a606-4d05-8244-3bcc4659c1d4", "description": "punctuation without whitespace", "property": "abbreviate", "input": { @@ -46,6 +50,7 @@ "expected": "CMOS" }, { + "uuid": "0e4b1e7c-1a6d-48fb-81a7-bf65eb9e69f9", "description": "very long abbreviation", "property": "abbreviate", "input": { @@ -54,6 +59,7 @@ "expected": "ROTFLSHTMDCOALM" }, { + "uuid": "6a078f49-c68d-4b7b-89af-33a1a98c28cc", "description": "consecutive delimiters", "property": "abbreviate", "input": { @@ -62,6 +68,7 @@ "expected": "SIMUFTA" }, { + "uuid": "5118b4b1-4572-434c-8d57-5b762e57973e", "description": "apostrophes", "property": "abbreviate", "input": { @@ -70,6 +77,7 @@ "expected": "HC" }, { + "uuid": "adc12eab-ec2d-414f-b48c-66a4fc06cdef", "description": "underscore emphasis", "property": "abbreviate", "input": { diff --git a/exercises/affine-cipher/canonical-data.json b/exercises/affine-cipher/canonical-data.json index 0c17044d98..1f8b0ec17a 100644 --- a/exercises/affine-cipher/canonical-data.json +++ b/exercises/affine-cipher/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "affine-cipher", - "version": "2.0.0", "comments": [ "The test are divided into two groups: ", "* Encoding from English to affine cipher", @@ -12,6 +11,7 @@ "comments": [ "Test encoding from English to ciphertext with keys" ], "cases": [ { + "uuid": "2ee1d9af-1c43-416c-b41b-cefd7d4d2b2a", "description": "encode yes", "property": "encode", "input": { @@ -24,6 +24,7 @@ "expected": "xbt" }, { + "uuid": "785bade9-e98b-4d4f-a5b0-087ba3d7de4b", "description": "encode no", "property": "encode", "input": { @@ -36,6 +37,7 @@ "expected": "fu" }, { + "uuid": "2854851c-48fb-40d8-9bf6-8f192ed25054", "description": "encode OMG", "property": "encode", "input": { @@ -48,6 +50,7 @@ "expected": "lvz" }, { + "uuid": "bc0c1244-b544-49dd-9777-13a770be1bad", "description": "encode O M G", "property": "encode", "input": { @@ -60,6 +63,7 @@ "expected": "hjp" }, { + "uuid": "381a1a20-b74a-46ce-9277-3778625c9e27", "description": "encode mindblowingly", "property": "encode", "input": { @@ -72,6 +76,7 @@ "expected": "rzcwa gnxzc dgt" }, { + "uuid": "6686f4e2-753b-47d4-9715-876fdc59029d", "description": "encode numbers", "property": "encode", "input": { @@ -84,6 +89,7 @@ "expected": "jqgjc rw123 jqgjc rw" }, { + "uuid": "ae23d5bd-30a8-44b6-afbe-23c8c0c7faa3", "description": "encode deep thought", "property": "encode", "input": { @@ -96,6 +102,7 @@ "expected": "iynia fdqfb ifje" }, { + "uuid": "c93a8a4d-426c-42ef-9610-76ded6f7ef57", "description": "encode all the letters", "property": "encode", "input": { @@ -108,6 +115,7 @@ "expected": "swxtj npvyk lruol iejdc blaxk swxmh qzglf" }, { + "uuid": "0673638a-4375-40bd-871c-fb6a2c28effb", "description": "encode with a not coprime to m", "property": "encode", "input": { @@ -126,6 +134,7 @@ "comments": [ "Test decoding from ciphertext to English with keys" ], "cases": [ { + "uuid": "3f0ac7e2-ec0e-4a79-949e-95e414953438", "description": "decode exercism", "property": "decode", "input": { @@ -138,6 +147,7 @@ "expected": "exercism" }, { + "uuid": "241ee64d-5a47-4092-a5d7-7939d259e077", "description": "decode a sentence", "property": "decode", "input": { @@ -150,6 +160,7 @@ "expected": "anobstacleisoftenasteppingstone" }, { + "uuid": "33fb16a1-765a-496f-907f-12e644837f5e", "description": "decode numbers", "property": "decode", "input": { @@ -162,6 +173,7 @@ "expected": "testing123testing" }, { + "uuid": "20bc9dce-c5ec-4db6-a3f1-845c776bcbf7", "description": "decode all the letters", "property": "decode", "input": { @@ -174,6 +186,7 @@ "expected": "thequickbrownfoxjumpsoverthelazydog" }, { + "uuid": "623e78c0-922d-49c5-8702-227a3e8eaf81", "description": "decode with no spaces in input", "property": "decode", "input": { @@ -186,6 +199,7 @@ "expected": "thequickbrownfoxjumpsoverthelazydog" }, { + "uuid": "58fd5c2a-1fd9-4563-a80a-71cff200f26f", "description": "decode with too many spaces", "property": "decode", "input": { @@ -198,6 +212,7 @@ "expected": "jollygreengiant" }, { + "uuid": "b004626f-c186-4af9-a3f4-58f74cdb86d5", "description": "decode with a not coprime to m", "property": "decode", "input": { diff --git a/exercises/affine-cipher/description.md b/exercises/affine-cipher/description.md index 05639e9f51..650706d5c0 100644 --- a/exercises/affine-cipher/description.md +++ b/exercises/affine-cipher/description.md @@ -1,42 +1,42 @@ Create an implementation of the affine cipher, an ancient encryption system created in the Middle East. - + The affine cipher is a type of monoalphabetic substitution cipher. Each character is mapped to its numeric equivalent, encrypted with a mathematical function and then converted to the letter relating to its new numeric value. Although all monoalphabetic ciphers are weak, the affine cypher is much stronger than the atbash cipher, because it has many more keys. - + the encryption function is: - + `E(x) = (ax + b) mod m` - where `x` is the letter's index from 0 - length of alphabet - 1 - `m` is the length of the alphabet. For the roman alphabet `m == 26`. - and `a` and `b` make the key - + the decryption function is: - + `D(y) = a^-1(y - b) mod m` - where `y` is the numeric value of an encrypted letter, ie. `y = E(x)` - it is important to note that `a^-1` is the modular multiplicative inverse of `a mod m` - the modular multiplicative inverse of `a` only exists if `a` and `m` are coprime. - + To find the MMI of `a`: `an mod m = 1` - where `n` is the modular multiplicative inverse of `a mod m` More information regarding how to find a Modular Multiplicative Inverse -and what it means can be found [here.](https://en.wikipedia.org/wiki/Modular_multiplicative_inverse) +and what it means can be found [here.](https://en.wikipedia.org/wiki/Modular_multiplicative_inverse) Because automatic decryption fails if `a` is not coprime to `m` your program should return status 1 and `"Error: a and m must be coprime."` if they are not. Otherwise it should encode or decode with the provided key. - + The Caesar (shift) cipher is a simple affine cipher where `a` is 1 and `b` as the magnitude results in a static displacement of the letters. This is much less secure than a full implementation of the affine cipher. @@ -46,7 +46,7 @@ size being 5 letters, and punctuation is excluded. This is to make it harder to guess things based on word boundaries. ## Examples - + - Encoding `test` gives `ybty` with the key a=5 b=7 - Decoding `ybty` gives `test` with the key a=5 b=7 - Decoding `ybty` gives `lqul` with the wrong key a=11 b=7 diff --git a/exercises/all-your-base/canonical-data.json b/exercises/all-your-base/canonical-data.json index b998618d35..86ea0015b8 100644 --- a/exercises/all-your-base/canonical-data.json +++ b/exercises/all-your-base/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "all-your-base", - "version": "2.3.0", "comments": [ "This canonical data makes the following choices:", "1. Zero is always represented in outputs as [0] instead of [].", @@ -14,6 +13,7 @@ ], "cases": [ { + "uuid": "5ce422f9-7a4b-4f44-ad29-49c67cb32d2c", "description": "single bit one to decimal", "property": "rebase", "input": { @@ -24,6 +24,7 @@ "expected": [1] }, { + "uuid": "0cc3fea8-bb79-46ac-a2ab-5a2c93051033", "description": "binary to single decimal", "property": "rebase", "input": { @@ -34,6 +35,7 @@ "expected": [5] }, { + "uuid": "f12db0f9-0d3d-42c2-b3ba-e38cb375a2b8", "description": "single decimal to binary", "property": "rebase", "input": { @@ -44,6 +46,7 @@ "expected": [1, 0, 1] }, { + "uuid": "2c45cf54-6da3-4748-9733-5a3c765d925b", "description": "binary to multiple decimal", "property": "rebase", "input": { @@ -54,6 +57,7 @@ "expected": [4, 2] }, { + "uuid": "65ddb8b4-8899-4fcc-8618-181b2cf0002d", "description": "decimal to binary", "property": "rebase", "input": { @@ -64,6 +68,7 @@ "expected": [1, 0, 1, 0, 1, 0] }, { + "uuid": "8d418419-02a7-4824-8b7a-352d33c6987e", "description": "trinary to hexadecimal", "property": "rebase", "input": { @@ -74,6 +79,7 @@ "expected": [2, 10] }, { + "uuid": "d3901c80-8190-41b9-bd86-38d988efa956", "description": "hexadecimal to trinary", "property": "rebase", "input": { @@ -84,6 +90,7 @@ "expected": [1, 1, 2, 0] }, { + "uuid": "5d42f85e-21ad-41bd-b9be-a3e8e4258bbf", "description": "15-bit integer", "property": "rebase", "input": { @@ -94,6 +101,7 @@ "expected": [6, 10, 45] }, { + "uuid": "d68788f7-66dd-43f8-a543-f15b6d233f83", "description": "empty list", "property": "rebase", "input": { @@ -104,6 +112,7 @@ "expected": [0] }, { + "uuid": "5e27e8da-5862-4c5f-b2a9-26c0382b6be7", "description": "single zero", "property": "rebase", "input": { @@ -114,6 +123,7 @@ "expected": [0] }, { + "uuid": "2e1c2573-77e4-4b9c-8517-6c56c5bcfdf2", "description": "multiple zeros", "property": "rebase", "input": { @@ -124,6 +134,7 @@ "expected": [0] }, { + "uuid": "3530cd9f-8d6d-43f5-bc6e-b30b1db9629b", "description": "leading zeros", "property": "rebase", "input": { @@ -134,6 +145,7 @@ "expected": [4, 2] }, { + "uuid": "a6b476a1-1901-4f2a-92c4-4d91917ae023", "description": "input base is one", "property": "rebase", "input": { @@ -144,6 +156,7 @@ "expected": {"error": "input base must be >= 2"} }, { + "uuid": "e21a693a-7a69-450b-b393-27415c26a016", "description": "input base is zero", "property": "rebase", "input": { @@ -154,6 +167,7 @@ "expected": {"error": "input base must be >= 2"} }, { + "uuid": "54a23be5-d99e-41cc-88e0-a650ffe5fcc2", "description": "input base is negative", "property": "rebase", "input": { @@ -164,6 +178,7 @@ "expected": {"error": "input base must be >= 2"} }, { + "uuid": "9eccf60c-dcc9-407b-95d8-c37b8be56bb6", "description": "negative digit", "property": "rebase", "input": { @@ -174,6 +189,7 @@ "expected": {"error": "all digits must satisfy 0 <= d < input base"} }, { + "uuid": "232fa4a5-e761-4939-ba0c-ed046cd0676a", "description": "invalid positive digit", "property": "rebase", "input": { @@ -184,6 +200,7 @@ "expected": {"error": "all digits must satisfy 0 <= d < input base"} }, { + "uuid": "14238f95-45da-41dc-95ce-18f860b30ad3", "description": "output base is one", "property": "rebase", "input": { @@ -194,6 +211,7 @@ "expected": {"error": "output base must be >= 2"} }, { + "uuid": "73dac367-da5c-4a37-95fe-c87fad0a4047", "description": "output base is zero", "property": "rebase", "input": { @@ -204,6 +222,7 @@ "expected": {"error": "output base must be >= 2"} }, { + "uuid": "13f81f42-ff53-4e24-89d9-37603a48ebd9", "description": "output base is negative", "property": "rebase", "input": { @@ -214,6 +233,7 @@ "expected": {"error": "output base must be >= 2"} }, { + "uuid": "0e6c895d-8a5d-4868-a345-309d094cfe8d", "description": "both bases are negative", "property": "rebase", "input": { diff --git a/exercises/allergies/canonical-data.json b/exercises/allergies/canonical-data.json index 16e600b483..86d2fea765 100644 --- a/exercises/allergies/canonical-data.json +++ b/exercises/allergies/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "allergies", - "version": "2.0.0", "comments": [ "Given a number and a substance, indicate whether Tom is allergic ", "to that substance." @@ -10,6 +9,7 @@ "description": "testing for eggs allergy", "cases": [ { + "uuid": "17fc7296-2440-4ac4-ad7b-d07c321bc5a0", "description": "not allergic to anything", "property": "allergicTo", "input": { @@ -19,6 +19,7 @@ "expected": false }, { + "uuid": "07ced27b-1da5-4c2e-8ae2-cb2791437546", "description": "allergic only to eggs", "property": "allergicTo", "input": { @@ -28,6 +29,7 @@ "expected": true }, { + "uuid": "5035b954-b6fa-4b9b-a487-dae69d8c5f96", "description": "allergic to eggs and something else", "property": "allergicTo", "input": { @@ -37,6 +39,7 @@ "expected": true }, { + "uuid": "64a6a83a-5723-4b5b-a896-663307403310", "description": "allergic to something, but not eggs", "property": "allergicTo", "input": { @@ -46,6 +49,7 @@ "expected": false }, { + "uuid": "90c8f484-456b-41c4-82ba-2d08d93231c6", "description": "allergic to everything", "property": "allergicTo", "input": { @@ -60,6 +64,7 @@ "description": "testing for peanuts allergy", "cases": [ { + "uuid": "d266a59a-fccc-413b-ac53-d57cb1f0db9d", "description": "not allergic to anything", "property": "allergicTo", "input": { @@ -69,6 +74,7 @@ "expected": false }, { + "uuid": "ea210a98-860d-46b2-a5bf-50d8995b3f2a", "description": "allergic only to peanuts", "property": "allergicTo", "input": { @@ -78,6 +84,7 @@ "expected": true }, { + "uuid": "eac69ae9-8d14-4291-ac4b-7fd2c73d3a5b", "description": "allergic to peanuts and something else", "property": "allergicTo", "input": { @@ -87,6 +94,7 @@ "expected": true }, { + "uuid": "9152058c-ce39-4b16-9b1d-283ec6d25085", "description": "allergic to something, but not peanuts", "property": "allergicTo", "input": { @@ -96,6 +104,7 @@ "expected": false }, { + "uuid": "d2d71fd8-63d5-40f9-a627-fbdaf88caeab", "description": "allergic to everything", "property": "allergicTo", "input": { @@ -110,6 +119,7 @@ "description": "testing for shellfish allergy", "cases": [ { + "uuid": "b948b0a1-cbf7-4b28-a244-73ff56687c80", "description": "not allergic to anything", "property": "allergicTo", "input": { @@ -119,6 +129,7 @@ "expected": false }, { + "uuid": "9ce9a6f3-53e9-4923-85e0-73019047c567", "description": "allergic only to shellfish", "property": "allergicTo", "input": { @@ -128,6 +139,7 @@ "expected": true }, { + "uuid": "b272fca5-57ba-4b00-bd0c-43a737ab2131", "description": "allergic to shellfish and something else", "property": "allergicTo", "input": { @@ -137,6 +149,7 @@ "expected": true }, { + "uuid": "21ef8e17-c227-494e-8e78-470a1c59c3d8", "description": "allergic to something, but not shellfish", "property": "allergicTo", "input": { @@ -146,6 +159,7 @@ "expected": false }, { + "uuid": "cc789c19-2b5e-4c67-b146-625dc8cfa34e", "description": "allergic to everything", "property": "allergicTo", "input": { @@ -160,6 +174,7 @@ "description": "testing for strawberries allergy", "cases": [ { + "uuid": "651bde0a-2a74-46c4-ab55-02a0906ca2f5", "description": "not allergic to anything", "property": "allergicTo", "input": { @@ -169,6 +184,7 @@ "expected": false }, { + "uuid": "b649a750-9703-4f5f-b7f7-91da2c160ece", "description": "allergic only to strawberries", "property": "allergicTo", "input": { @@ -178,6 +194,7 @@ "expected": true }, { + "uuid": "50f5f8f3-3bac-47e6-8dba-2d94470a4bc6", "description": "allergic to strawberries and something else", "property": "allergicTo", "input": { @@ -187,6 +204,7 @@ "expected": true }, { + "uuid": "23dd6952-88c9-48d7-a7d5-5d0343deb18d", "description": "allergic to something, but not strawberries", "property": "allergicTo", "input": { @@ -196,6 +214,7 @@ "expected": false }, { + "uuid": "74afaae2-13b6-43a2-837a-286cd42e7d7e", "description": "allergic to everything", "property": "allergicTo", "input": { @@ -210,6 +229,7 @@ "description": "testing for tomatoes allergy", "cases": [ { + "uuid": "c49a91ef-6252-415e-907e-a9d26ef61723", "description": "not allergic to anything", "property": "allergicTo", "input": { @@ -219,6 +239,7 @@ "expected": false }, { + "uuid": "b69c5131-b7d0-41ad-a32c-e1b2cc632df8", "description": "allergic only to tomatoes", "property": "allergicTo", "input": { @@ -228,6 +249,7 @@ "expected": true }, { + "uuid": "1ca50eb1-f042-4ccf-9050-341521b929ec", "description": "allergic to tomatoes and something else", "property": "allergicTo", "input": { @@ -237,6 +259,7 @@ "expected": true }, { + "uuid": "e9846baa-456b-4eff-8025-034b9f77bd8e", "description": "allergic to something, but not tomatoes", "property": "allergicTo", "input": { @@ -246,6 +269,7 @@ "expected": false }, { + "uuid": "b2414f01-f3ad-4965-8391-e65f54dad35f", "description": "allergic to everything", "property": "allergicTo", "input": { @@ -260,6 +284,7 @@ "description": "testing for chocolate allergy", "cases": [ { + "uuid": "978467ab-bda4-49f7-b004-1d011ead947c", "description": "not allergic to anything", "property": "allergicTo", "input": { @@ -269,6 +294,7 @@ "expected": false }, { + "uuid": "59cf4e49-06ea-4139-a2c1-d7aad28f8cbc", "description": "allergic only to chocolate", "property": "allergicTo", "input": { @@ -278,6 +304,7 @@ "expected": true }, { + "uuid": "b0a7c07b-2db7-4f73-a180-565e07040ef1", "description": "allergic to chocolate and something else", "property": "allergicTo", "input": { @@ -287,6 +314,7 @@ "expected": true }, { + "uuid": "f5506893-f1ae-482a-b516-7532ba5ca9d2", "description": "allergic to something, but not chocolate", "property": "allergicTo", "input": { @@ -296,6 +324,7 @@ "expected": false }, { + "uuid": "02debb3d-d7e2-4376-a26b-3c974b6595c6", "description": "allergic to everything", "property": "allergicTo", "input": { @@ -310,6 +339,7 @@ "description": "testing for pollen allergy", "cases": [ { + "uuid": "17f4a42b-c91e-41b8-8a76-4797886c2d96", "description": "not allergic to anything", "property": "allergicTo", "input": { @@ -319,6 +349,7 @@ "expected": false }, { + "uuid": "7696eba7-1837-4488-882a-14b7b4e3e399", "description": "allergic only to pollen", "property": "allergicTo", "input": { @@ -328,6 +359,7 @@ "expected": true }, { + "uuid": "9a49aec5-fa1f-405d-889e-4dfc420db2b6", "description": "allergic to pollen and something else", "property": "allergicTo", "input": { @@ -337,6 +369,7 @@ "expected": true }, { + "uuid": "3cb8e79f-d108-4712-b620-aa146b1954a9", "description": "allergic to something, but not pollen", "property": "allergicTo", "input": { @@ -346,6 +379,7 @@ "expected": false }, { + "uuid": "1dc3fe57-7c68-4043-9d51-5457128744b2", "description": "allergic to everything", "property": "allergicTo", "input": { @@ -360,6 +394,7 @@ "description": "testing for cats allergy", "cases": [ { + "uuid": "d3f523d6-3d50-419b-a222-d4dfd62ce314", "description": "not allergic to anything", "property": "allergicTo", "input": { @@ -369,6 +404,7 @@ "expected": false }, { + "uuid": "eba541c3-c886-42d3-baef-c048cb7fcd8f", "description": "allergic only to cats", "property": "allergicTo", "input": { @@ -378,6 +414,7 @@ "expected": true }, { + "uuid": "ba718376-26e0-40b7-bbbe-060287637ea5", "description": "allergic to cats and something else", "property": "allergicTo", "input": { @@ -387,6 +424,7 @@ "expected": true }, { + "uuid": "3c6dbf4a-5277-436f-8b88-15a206f2d6c4", "description": "allergic to something, but not cats", "property": "allergicTo", "input": { @@ -396,6 +434,7 @@ "expected": false }, { + "uuid": "1faabb05-2b98-4995-9046-d83e4a48a7c1", "description": "allergic to everything", "property": "allergicTo", "input": { @@ -413,6 +452,7 @@ ], "cases": [ { + "uuid": "f9c1b8e7-7dc5-4887-aa93-cebdcc29dd8f", "description": "no allergies", "property": "list", "input": { @@ -421,6 +461,7 @@ "expected": [] }, { + "uuid": "9e1a4364-09a6-4d94-990f-541a94a4c1e8", "description": "just eggs", "property": "list", "input": { @@ -431,6 +472,7 @@ ] }, { + "uuid": "8851c973-805e-4283-9e01-d0c0da0e4695", "description": "just peanuts", "property": "list", "input": { @@ -441,6 +483,7 @@ ] }, { + "uuid": "2c8943cb-005e-435f-ae11-3e8fb558ea98", "description": "just strawberries", "property": "list", "input": { @@ -451,6 +494,7 @@ ] }, { + "uuid": "6fa95d26-044c-48a9-8a7b-9ee46ec32c5c", "description": "eggs and peanuts", "property": "list", "input": { @@ -462,6 +506,7 @@ ] }, { + "uuid": "19890e22-f63f-4c5c-a9fb-fb6eacddfe8e", "description": "more than eggs but not peanuts", "property": "list", "input": { @@ -473,6 +518,7 @@ ] }, { + "uuid": "4b68f470-067c-44e4-889f-c9fe28917d2f", "description": "lots of stuff", "property": "list", "input": { @@ -487,6 +533,7 @@ ] }, { + "uuid": "0881b7c5-9efa-4530-91bd-68370d054bc7", "description": "everything", "property": "list", "input": { @@ -504,6 +551,7 @@ ] }, { + "uuid": "12ce86de-b347-42a0-ab7c-2e0570f0c65b", "description": "no allergen score parts", "property": "list", "input": { diff --git a/exercises/alphametics/canonical-data.json b/exercises/alphametics/canonical-data.json index 4ccff5cf4b..4d0c9d0126 100644 --- a/exercises/alphametics/canonical-data.json +++ b/exercises/alphametics/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "alphametics", - "version": "1.3.0", "cases": [ { "description": "Solve the alphametics puzzle", "cases": [ { + "uuid": "e0c08b07-9028-4d5f-91e1-d178fead8e1a", "description": "puzzle with three letters", "property": "solve", "input": { @@ -18,6 +18,7 @@ } }, { + "uuid": "a504ee41-cb92-4ec2-9f11-c37e95ab3f25", "description": "solution must have unique value for each letter", "property": "solve", "input": { @@ -26,6 +27,7 @@ "expected": null }, { + "uuid": "4e3b81d2-be7b-4c5c-9a80-cd72bc6d465a", "description": "leading zero solution is invalid", "property": "solve", "input": { @@ -34,6 +36,7 @@ "expected": null }, { + "uuid": "8a3e3168-d1ee-4df7-94c7-b9c54845ac3a", "description": "puzzle with two digits final carry", "property": "solve", "input": { @@ -46,6 +49,7 @@ } }, { + "uuid": "a9630645-15bd-48b6-a61e-d85c4021cc09", "description": "puzzle with four letters", "property": "solve", "input": { @@ -59,6 +63,7 @@ } }, { + "uuid": "3d905a86-5a52-4e4e-bf80-8951535791bd", "description": "puzzle with six letters", "property": "solve", "input": { @@ -74,6 +79,7 @@ } }, { + "uuid": "4febca56-e7b7-4789-97b9-530d09ba95f0", "description": "puzzle with seven letters", "property": "solve", "input": { @@ -90,6 +96,7 @@ } }, { + "uuid": "12125a75-7284-4f9a-a5fa-191471e0d44f", "description": "puzzle with eight letters", "property": "solve", "input": { @@ -107,6 +114,7 @@ } }, { + "uuid": "fb05955f-38dc-477a-a0b6-5ef78969fffa", "description": "puzzle with ten letters", "property": "solve", "input": { @@ -126,6 +134,7 @@ } }, { + "uuid": "9a101e81-9216-472b-b458-b513a7adacf7", "description": "puzzle with ten letters and 199 addends", "property": "solve", "input": { diff --git a/exercises/anagram/canonical-data.json b/exercises/anagram/canonical-data.json index 829daf9298..0165d9d157 100644 --- a/exercises/anagram/canonical-data.json +++ b/exercises/anagram/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "anagram", - "version": "1.5.0", "cases": [ { + "uuid": "dd40c4d2-3c8b-44e5-992a-f42b393ec373", "description": "no matches", "property": "findAnagrams", "input": { @@ -12,6 +12,7 @@ "expected": [] }, { + "uuid": "b3cca662-f50a-489e-ae10-ab8290a09bdc", "description": "detects two anagrams", "property": "findAnagrams", "input": { @@ -21,6 +22,7 @@ "expected": ["stream", "maters"] }, { + "uuid": "a27558ee-9ba0-4552-96b1-ecf665b06556", "description": "does not detect anagram subsets", "property": "findAnagrams", "input": { @@ -30,6 +32,7 @@ "expected": [] }, { + "uuid": "64cd4584-fc15-4781-b633-3d814c4941a4", "description": "detects anagram", "property": "findAnagrams", "input": { @@ -39,6 +42,7 @@ "expected": ["inlets"] }, { + "uuid": "99c91beb-838f-4ccd-b123-935139917283", "description": "detects three anagrams", "property": "findAnagrams", "input": { @@ -55,6 +59,7 @@ "expected": ["gallery", "regally", "largely"] }, { + "uuid": "78487770-e258-4e1f-a646-8ece10950d90", "description": "detects multiple anagrams with different case", "property": "findAnagrams", "input": { @@ -64,6 +69,7 @@ "expected": ["Eons", "ONES"] }, { + "uuid": "1d0ab8aa-362f-49b7-9902-3d0c668d557b", "description": "does not detect non-anagrams with identical checksum", "property": "findAnagrams", "input": { @@ -73,6 +79,7 @@ "expected": [] }, { + "uuid": "9e632c0b-c0b1-4804-8cc1-e295dea6d8a8", "description": "detects anagrams case-insensitively", "property": "findAnagrams", "input": { @@ -82,6 +89,7 @@ "expected": ["Carthorse"] }, { + "uuid": "b248e49f-0905-48d2-9c8d-bd02d8c3e392", "description": "detects anagrams using case-insensitive subject", "property": "findAnagrams", "input": { @@ -91,6 +99,7 @@ "expected": ["carthorse"] }, { + "uuid": "f367325c-78ec-411c-be76-e79047f4bd54", "description": "detects anagrams using case-insensitive possible matches", "property": "findAnagrams", "input": { @@ -100,6 +109,7 @@ "expected": ["Carthorse"] }, { + "uuid": "7cc195ad-e3c7-44ee-9fd2-d3c344806a2c", "description": "does not detect an anagram if the original word is repeated", "property": "findAnagrams", "input": { @@ -109,6 +119,7 @@ "expected": [] }, { + "uuid": "9878a1c9-d6ea-4235-ae51-3ea2befd6842", "description": "anagrams must use all letters exactly once", "property": "findAnagrams", "input": { @@ -118,6 +129,7 @@ "expected": [] }, { + "uuid": "85757361-4535-45fd-ac0e-3810d40debc1", "description": "words are not anagrams of themselves (case-insensitive)", "property": "findAnagrams", "input": { @@ -127,6 +139,7 @@ "expected": [] }, { + "uuid": "a0705568-628c-4b55-9798-82e4acde51ca", "description": "words other than themselves can be anagrams", "property": "findAnagrams", "input": { diff --git a/exercises/armstrong-numbers/canonical-data.json b/exercises/armstrong-numbers/canonical-data.json index ef8df7f46c..0e8c59b774 100644 --- a/exercises/armstrong-numbers/canonical-data.json +++ b/exercises/armstrong-numbers/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "armstrong-numbers", - "version": "1.1.0", "cases": [ { + "uuid": "c1ed103c-258d-45b2-be73-d8c6d9580c7b", "description": "Zero is an Armstrong number", "property": "isArmstrongNumber", "input": { @@ -11,6 +11,7 @@ "expected": true }, { + "uuid": "579e8f03-9659-4b85-a1a2-d64350f6b17a", "description": "Single digit numbers are Armstrong numbers", "property": "isArmstrongNumber", "input": { @@ -19,6 +20,7 @@ "expected": true }, { + "uuid": "2d6db9dc-5bf8-4976-a90b-b2c2b9feba60", "description": "There are no 2 digit Armstrong numbers", "property": "isArmstrongNumber", "input": { @@ -27,6 +29,7 @@ "expected": false }, { + "uuid": "509c087f-e327-4113-a7d2-26a4e9d18283", "description": "Three digit number that is an Armstrong number", "property": "isArmstrongNumber", "input": { @@ -35,6 +38,7 @@ "expected": true }, { + "uuid": "7154547d-c2ce-468d-b214-4cb953b870cf", "description": "Three digit number that is not an Armstrong number", "property": "isArmstrongNumber", "input": { @@ -43,6 +47,7 @@ "expected": false }, { + "uuid": "6bac5b7b-42e9-4ecb-a8b0-4832229aa103", "description": "Four digit number that is an Armstrong number", "property": "isArmstrongNumber", "input": { @@ -51,6 +56,7 @@ "expected": true }, { + "uuid": "eed4b331-af80-45b5-a80b-19c9ea444b2e", "description": "Four digit number that is not an Armstrong number", "property": "isArmstrongNumber", "input": { @@ -59,6 +65,7 @@ "expected": false }, { + "uuid": "f971ced7-8d68-4758-aea1-d4194900b864", "description": "Seven digit number that is an Armstrong number", "property": "isArmstrongNumber", "input": { @@ -67,6 +74,7 @@ "expected": true }, { + "uuid": "7ee45d52-5d35-4fbd-b6f1-5c8cd8a67f18", "description": "Seven digit number that is not an Armstrong number", "property": "isArmstrongNumber", "input": { diff --git a/exercises/atbash-cipher/canonical-data.json b/exercises/atbash-cipher/canonical-data.json index 399956c8d3..1663fbc2af 100644 --- a/exercises/atbash-cipher/canonical-data.json +++ b/exercises/atbash-cipher/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "atbash-cipher", - "version": "1.2.0", "comments": [ "The tests are divided into two groups: ", "* Encoding from English to atbash cipher", @@ -12,6 +11,7 @@ "comments": [ "Test encoding from English to atbash" ], "cases": [ { + "uuid": "2f47ebe1-eab9-4d6b-b3c6-627562a31c77", "description": "encode yes", "property": "encode", "input": { @@ -20,6 +20,7 @@ "expected": "bvh" }, { + "uuid": "b4ffe781-ea81-4b74-b268-cc58ba21c739", "description": "encode no", "property": "encode", "input": { @@ -28,6 +29,7 @@ "expected": "ml" }, { + "uuid": "10e48927-24ab-4c4d-9d3f-3067724ace00", "description": "encode OMG", "property": "encode", "input": { @@ -36,6 +38,7 @@ "expected": "lnt" }, { + "uuid": "d59b8bc3-509a-4a9a-834c-6f501b98750b", "description": "encode spaces", "property": "encode", "input": { @@ -44,6 +47,7 @@ "expected": "lnt" }, { + "uuid": "31d44b11-81b7-4a94-8b43-4af6a2449429", "description": "encode mindblowingly", "property": "encode", "input": { @@ -52,6 +56,7 @@ "expected": "nrmwy oldrm tob" }, { + "uuid": "d503361a-1433-48c0-aae0-d41b5baa33ff", "description": "encode numbers", "property": "encode", "input": { @@ -60,6 +65,7 @@ "expected": "gvhgr mt123 gvhgr mt" }, { + "uuid": "79c8a2d5-0772-42d4-b41b-531d0b5da926", "description": "encode deep thought", "property": "encode", "input": { @@ -68,6 +74,7 @@ "expected": "gifgs rhurx grlm" }, { + "uuid": "9ca13d23-d32a-4967-a1fd-6100b8742bab", "description": "encode all the letters", "property": "encode", "input": { @@ -82,6 +89,7 @@ "comments": [ "Test decoding from atbash to English" ], "cases": [ { + "uuid": "bb50e087-7fdf-48e7-9223-284fe7e69851", "description": "decode exercism", "property": "decode", "input": { @@ -90,6 +98,7 @@ "expected": "exercism" }, { + "uuid": "ac021097-cd5d-4717-8907-b0814b9e292c", "description": "decode a sentence", "property": "decode", "input": { @@ -98,6 +107,7 @@ "expected": "anobstacleisoftenasteppingstone" }, { + "uuid": "18729de3-de74-49b8-b68c-025eaf77f851", "description": "decode numbers", "property": "decode", "input": { @@ -106,6 +116,7 @@ "expected": "testing123testing" }, { + "uuid": "0f30325f-f53b-415d-ad3e-a7a4f63de034", "description": "decode all the letters", "property": "decode", "input": { @@ -114,6 +125,7 @@ "expected": "thequickbrownfoxjumpsoverthelazydog" }, { + "uuid": "39640287-30c6-4c8c-9bac-9d613d1a5674", "description": "decode with too many spaces", "property": "decode", "input": { @@ -122,6 +134,7 @@ "expected": "exercism" }, { + "uuid": "b34edf13-34c0-49b5-aa21-0768928000d5", "description": "decode with no spaces", "property": "decode", "input": { diff --git a/exercises/beer-song/canonical-data.json b/exercises/beer-song/canonical-data.json index ded745ed19..ce63bd1b29 100644 --- a/exercises/beer-song/canonical-data.json +++ b/exercises/beer-song/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "beer-song", - "version": "2.1.0", "cases": [ { "description": "verse", @@ -9,6 +8,7 @@ "description": "single verse", "cases": [ { + "uuid": "5a02fd08-d336-4607-8006-246fe6fa9fb0", "description": "first generic verse", "property": "recite", "input": { @@ -21,6 +21,7 @@ ] }, { + "uuid": "77299ca6-545e-4217-a9cc-606b342e0187", "description": "last generic verse", "property": "recite", "input": { @@ -33,6 +34,7 @@ ] }, { + "uuid": "102cbca0-b197-40fd-b548-e99609b06428", "description": "verse with 2 bottles", "property": "recite", "input": { @@ -45,6 +47,7 @@ ] }, { + "uuid": "b8ef9fce-960e-4d85-a0c9-980a04ec1972", "description": "verse with 1 bottle", "property": "recite", "input": { @@ -57,6 +60,7 @@ ] }, { + "uuid": "c59d4076-f671-4ee3-baaa-d4966801f90d", "description": "verse with 0 bottles", "property": "recite", "input": { @@ -79,6 +83,7 @@ "description": "multiple verses", "cases": [ { + "uuid": "7e17c794-402d-4ca6-8f96-4d8f6ee1ec7e", "description": "first two verses", "property": "recite", "input": { @@ -94,6 +99,7 @@ ] }, { + "uuid": "949868e7-67e8-43d3-9bb4-69277fe020fb", "description": "last three verses", "property": "recite", "input": { @@ -112,6 +118,7 @@ ] }, { + "uuid": "bc220626-126c-4e72-8df4-fddfc0c3e458", "description": "all verses", "property": "recite", "input": { diff --git a/exercises/binary-search-tree/canonical-data.json b/exercises/binary-search-tree/canonical-data.json index 52756c0a96..e7bfb279fd 100644 --- a/exercises/binary-search-tree/canonical-data.json +++ b/exercises/binary-search-tree/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "binary-search-tree", - "version": "1.0.0", "comments": [ "Each test case assumes an empty/new tree.", "As per exercism/problem-specifications#996 key 'treeData' counts as an input", @@ -30,6 +29,7 @@ "}" ], "cases": [{ + "uuid": "e9c93a78-c536-4750-a336-94583d23fafa", "description": "data is retained", "property": "data", "input": { @@ -44,6 +44,7 @@ { "description": "insert data at proper node", "cases": [{ + "uuid": "7a95c9e8-69f6-476a-b0c4-4170cb3f7c91", "description": "smaller number at left node", "property": "data", "input": { @@ -60,6 +61,7 @@ } }, { + "uuid": "22b89499-9805-4703-a159-1a6e434c1585", "description": "same number at left node", "property": "data", "input": { @@ -76,6 +78,7 @@ } }, { + "uuid": "2e85fdde-77b1-41ed-b6ac-26ce6b663e34", "description": "greater number at right node", "property": "data", "input": { @@ -94,6 +97,7 @@ ] }, { + "uuid": "dd898658-40ab-41d0-965e-7f145bf66e0b", "description": "can create complex tree", "property": "data", "input": { @@ -132,6 +136,7 @@ { "description": "can sort data", "cases": [{ + "uuid": "9e0c06ef-aeca-4202-b8e4-97f1ed057d56", "description": "can sort single number", "property": "sortedData", "input": { @@ -140,6 +145,7 @@ "expected": ["2"] }, { + "uuid": "425e6d07-fceb-4681-a4f4-e46920e380bb", "description": "can sort if second number is smaller than first", "property": "sortedData", "input": { @@ -148,6 +154,7 @@ "expected": ["1", "2"] }, { + "uuid": "bd7532cc-6988-4259-bac8-1d50140079ab", "description": "can sort if second number is same as first", "property": "sortedData", "input": { @@ -156,6 +163,7 @@ "expected": ["2", "2"] }, { + "uuid": "b6d1b3a5-9d79-44fd-9013-c83ca92ddd36", "description": "can sort if second number is greater than first", "property": "sortedData", "input": { @@ -164,6 +172,7 @@ "expected": ["2", "3"] }, { + "uuid": "d00ec9bd-1288-4171-b968-d44d0808c1c8", "description": "can sort complex tree", "property": "sortedData", "input": { @@ -174,4 +183,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/binary-search/canonical-data.json b/exercises/binary-search/canonical-data.json index 54c6e8a11e..cc7321f872 100644 --- a/exercises/binary-search/canonical-data.json +++ b/exercises/binary-search/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "binary-search", - "version": "1.3.0", "comments": [ "The error object is used to indicate that the value is not included in the array.", "It should be replaced with the respective expression that is idiomatic", @@ -17,6 +16,7 @@ ], "cases": [ { + "uuid": "b55c24a9-a98d-4379-a08c-2adcf8ebeee8", "description": "finds a value in an array with one element", "property": "find", "input": { @@ -26,6 +26,7 @@ "expected": 0 }, { + "uuid": "73469346-b0a0-4011-89bf-989e443d503d", "description": "finds a value in the middle of an array", "property": "find", "input": { @@ -35,6 +36,7 @@ "expected": 3 }, { + "uuid": "327bc482-ab85-424e-a724-fb4658e66ddb", "description": "finds a value at the beginning of an array", "property": "find", "input": { @@ -44,6 +46,7 @@ "expected": 0 }, { + "uuid": "f9f94b16-fe5e-472c-85ea-c513804c7d59", "description": "finds a value at the end of an array", "property": "find", "input": { @@ -53,6 +56,7 @@ "expected": 6 }, { + "uuid": "f0068905-26e3-4342-856d-ad153cadb338", "description": "finds a value in an array of odd length", "property": "find", "input": { @@ -62,6 +66,7 @@ "expected": 9 }, { + "uuid": "fc316b12-c8b3-4f5e-9e89-532b3389de8c", "description": "finds a value in an array of even length", "property": "find", "input": { @@ -71,6 +76,7 @@ "expected": 5 }, { + "uuid": "da7db20a-354f-49f7-a6a1-650a54998aa6", "description": "identifies that a value is not included in the array", "property": "find", "input": { @@ -80,6 +86,7 @@ "expected": {"error": "value not in array"} }, { + "uuid": "95d869ff-3daf-4c79-b622-6e805c675f97", "description": "a value smaller than the array's smallest value is not found", "property": "find", "input": { @@ -89,6 +96,7 @@ "expected": {"error": "value not in array"} }, { + "uuid": "8b24ef45-6e51-4a94-9eac-c2bf38fdb0ba", "description": "a value larger than the array's largest value is not found", "property": "find", "input": { @@ -98,6 +106,7 @@ "expected": {"error": "value not in array"} }, { + "uuid": "f439a0fa-cf42-4262-8ad1-64bf41ce566a", "description": "nothing is found in an empty array", "property": "find", "input": { @@ -107,6 +116,7 @@ "expected": {"error": "value not in array"} }, { + "uuid": "2c353967-b56d-40b8-acff-ce43115eed64", "description": "nothing is found when the left and right bounds cross", "property": "find", "input": { diff --git a/exercises/binary/canonical-data.json b/exercises/binary/canonical-data.json index 8b51d34383..b32835853c 100644 --- a/exercises/binary/canonical-data.json +++ b/exercises/binary/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "binary", - "version": "1.1.0", "cases": [ { + "uuid": "567fc71e-1013-4915-9285-bca0648c0844", "description": "binary 0 is decimal 0", "property": "decimal", "input": { @@ -11,6 +11,7 @@ "expected": 0 }, { + "uuid": "c0824fb1-6a0a-4e9a-a262-c6c00af99fa8", "description": "binary 1 is decimal 1", "property": "decimal", "input": { @@ -19,6 +20,7 @@ "expected": 1 }, { + "uuid": "4d2834fb-3cc3-4159-a8fd-da1098def8ed", "description": "binary 10 is decimal 2", "property": "decimal", "input": { @@ -27,6 +29,7 @@ "expected": 2 }, { + "uuid": "b7b2b649-4a7c-4808-9eb9-caf00529bac6", "description": "binary 11 is decimal 3", "property": "decimal", "input": { @@ -35,6 +38,7 @@ "expected": 3 }, { + "uuid": "de761aff-73cd-43c1-9e1f-0417f07b1e4a", "description": "binary 100 is decimal 4", "property": "decimal", "input": { @@ -43,6 +47,7 @@ "expected": 4 }, { + "uuid": "7849a8f7-f4a1-4966-963e-503282d6814c", "description": "binary 1001 is decimal 9", "property": "decimal", "input": { @@ -51,6 +56,7 @@ "expected": 9 }, { + "uuid": "836a101c-aecb-473b-ba78-962408dcda98", "description": "binary 11010 is decimal 26", "property": "decimal", "input": { @@ -59,6 +65,7 @@ "expected": 26 }, { + "uuid": "1c6822a4-8584-438b-8dd4-40f0f0b66371", "description": "binary 10001101000 is decimal 1128", "property": "decimal", "input": { @@ -67,6 +74,7 @@ "expected": 1128 }, { + "uuid": "91ffe632-8374-4016-b1d1-d8400d9f940d", "description": "binary ignores leading zeros", "property": "decimal", "input": { @@ -75,6 +83,7 @@ "expected": 31 }, { + "uuid": "44f7d8b1-ddc3-4751-8be3-700a538b421c", "description": "2 is not a valid binary digit", "property": "decimal", "input": { @@ -83,6 +92,7 @@ "expected": null }, { + "uuid": "c263a24d-6870-420f-b783-628feefd7b6e", "description": "a number containing a non-binary digit is invalid", "property": "decimal", "input": { @@ -91,6 +101,7 @@ "expected": null }, { + "uuid": "8d81305b-0502-4a07-bfba-051c5526d7f2", "description": "a number with trailing non-binary characters is invalid", "property": "decimal", "input": { @@ -99,6 +110,7 @@ "expected": null }, { + "uuid": "a7f79b6b-039a-4d42-99b4-fcee56679f03", "description": "a number with leading non-binary characters is invalid", "property": "decimal", "input": { @@ -107,6 +119,7 @@ "expected": null }, { + "uuid": "9e0ece9d-b8aa-46a0-a22b-3bed2e3f741e", "description": "a number with internal non-binary characters is invalid", "property": "decimal", "input": { @@ -115,6 +128,7 @@ "expected": null }, { + "uuid": "46c8dd65-0c32-4273-bb0d-f2b111bccfbd", "description": "a number and a word whitespace separated is invalid", "property": "decimal", "input": { diff --git a/exercises/bob/canonical-data.json b/exercises/bob/canonical-data.json index 1061e273a5..a6cc254a73 100644 --- a/exercises/bob/canonical-data.json +++ b/exercises/bob/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "bob", - "version": "1.4.0", "cases": [ { + "uuid": "e162fead-606f-437a-a166-d051915cea8e", "description": "stating something", "property": "response", "input": { @@ -11,6 +11,7 @@ "expected": "Whatever." }, { + "uuid": "73a966dc-8017-47d6-bb32-cf07d1a5fcd9", "description": "shouting", "property": "response", "input": { @@ -19,6 +20,7 @@ "expected": "Whoa, chill out!" }, { + "uuid": "d6c98afd-df35-4806-b55e-2c457c3ab748", "description": "shouting gibberish", "property": "response", "input": { @@ -27,6 +29,7 @@ "expected": "Whoa, chill out!" }, { + "uuid": "8a2e771d-d6f1-4e3f-b6c6-b41495556e37", "description": "asking a question", "property": "response", "input": { @@ -35,6 +38,7 @@ "expected": "Sure." }, { + "uuid": "81080c62-4e4d-4066-b30a-48d8d76920d9", "description": "asking a numeric question", "property": "response", "input": { @@ -43,6 +47,7 @@ "expected": "Sure." }, { + "uuid": "2a02716d-685b-4e2e-a804-2adaf281c01e", "description": "asking gibberish", "property": "response", "input": { @@ -51,30 +56,34 @@ "expected": "Sure." }, { + "uuid": "c02f9179-ab16-4aa7-a8dc-940145c385f7", "description": "talking forcefully", "property": "response", "input": { - "heyBob": "Let's go make out behind the gym!" + "heyBob": "Hi there!" }, "expected": "Whatever." }, { + "uuid": "153c0e25-9bb5-4ec5-966e-598463658bcd", "description": "using acronyms in regular speech", "property": "response", "input": { - "heyBob": "It's OK if you don't want to go to the DMV." + "heyBob": "It's OK if you don't want to go work for NASA." }, "expected": "Whatever." }, { + "uuid": "a5193c61-4a92-4f68-93e2-f554eb385ec6", "description": "forceful question", "property": "response", "input": { - "heyBob": "WHAT THE HELL WERE YOU THINKING?" + "heyBob": "WHAT'S GOING ON?" }, "expected": "Calm down, I know what I'm doing!" }, { + "uuid": "a20e0c54-2224-4dde-8b10-bd2cdd4f61bc", "description": "shouting numbers", "property": "response", "input": { @@ -83,6 +92,7 @@ "expected": "Whoa, chill out!" }, { + "uuid": "f7bc4b92-bdff-421e-a238-ae97f230ccac", "description": "no letters", "property": "response", "input": { @@ -91,6 +101,7 @@ "expected": "Whatever." }, { + "uuid": "bb0011c5-cd52-4a5b-8bfb-a87b6283b0e2", "description": "question with no letters", "property": "response", "input": { @@ -99,6 +110,7 @@ "expected": "Sure." }, { + "uuid": "496143c8-1c31-4c01-8a08-88427af85c66", "description": "shouting with special characters", "property": "response", "input": { @@ -107,14 +119,16 @@ "expected": "Whoa, chill out!" }, { + "uuid": "e6793c1c-43bd-4b8d-bc11-499aea73925f", "description": "shouting with no exclamation mark", "property": "response", "input": { - "heyBob": "I HATE THE DMV" + "heyBob": "I HATE THE DENTIST" }, "expected": "Whoa, chill out!" }, { + "uuid": "aa8097cc-c548-4951-8856-14a404dd236a", "description": "statement containing question mark", "property": "response", "input": { @@ -123,6 +137,7 @@ "expected": "Whatever." }, { + "uuid": "9bfc677d-ea3a-45f2-be44-35bc8fa3753e", "description": "non-letters with question", "property": "response", "input": { @@ -131,6 +146,7 @@ "expected": "Sure." }, { + "uuid": "8608c508-f7de-4b17-985b-811878b3cf45", "description": "prattling on", "property": "response", "input": { @@ -139,6 +155,7 @@ "expected": "Sure." }, { + "uuid": "bc39f7c6-f543-41be-9a43-fd1c2f753fc0", "description": "silence", "property": "response", "input": { @@ -147,6 +164,7 @@ "expected": "Fine. Be that way!" }, { + "uuid": "d6c47565-372b-4b09-b1dd-c40552b8378b", "description": "prolonged silence", "property": "response", "input": { @@ -155,6 +173,7 @@ "expected": "Fine. Be that way!" }, { + "uuid": "4428f28d-4100-4d85-a902-e5a78cb0ecd3", "description": "alternate silence", "property": "response", "input": { @@ -163,6 +182,7 @@ "expected": "Fine. Be that way!" }, { + "uuid": "66953780-165b-4e7e-8ce3-4bcb80b6385a", "description": "multiple line question", "property": "response", "input": { @@ -171,6 +191,7 @@ "expected": "Whatever." }, { + "uuid": "5371ef75-d9ea-4103-bcfa-2da973ddec1b", "description": "starting with whitespace", "property": "response", "input": { @@ -179,6 +200,7 @@ "expected": "Whatever." }, { + "uuid": "05b304d6-f83b-46e7-81e0-4cd3ca647900", "description": "ending with whitespace", "property": "response", "input": { @@ -187,6 +209,7 @@ "expected": "Sure." }, { + "uuid": "72bd5ad3-9b2f-4931-a988-dce1f5771de2", "description": "other whitespace", "property": "response", "input": { @@ -195,6 +218,7 @@ "expected": "Fine. Be that way!" }, { + "uuid": "12983553-8601-46a8-92fa-fcaa3bc4a2a0", "description": "non-question ending with whitespace", "property": "response", "input": { diff --git a/exercises/book-store/canonical-data.json b/exercises/book-store/canonical-data.json index 72dd54b26a..1a15a04c93 100644 --- a/exercises/book-store/canonical-data.json +++ b/exercises/book-store/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "book-store", - "version": "1.4.0", "cases": [ { "description": "Return the total basket price after applying the best discount.", @@ -14,6 +13,7 @@ ], "cases": [ { + "uuid": "17146bd5-2e80-4557-ab4c-05632b6b0d01", "property": "total", "description": "Only a single book", "comments": ["Suggested grouping, [[1]]."], @@ -23,6 +23,7 @@ "expected": 800 }, { + "uuid": "cc2de9ac-ff2a-4efd-b7c7-bfe0f43271ce", "property": "total", "description": "Two of the same book", "comments": ["Suggested grouping, [[2],[2]]."], @@ -32,6 +33,7 @@ "expected": 1600 }, { + "uuid": "5a86eac0-45d2-46aa-bbf0-266b94393a1a", "property": "total", "description": "Empty basket", "comments": ["Suggested grouping, []."], @@ -41,6 +43,7 @@ "expected": 0 }, { + "uuid": "158bd19a-3db4-4468-ae85-e0638a688990", "property": "total", "description": "Two different books", "comments": ["Suggested grouping, [[1,2]]."], @@ -50,6 +53,7 @@ "expected": 1520 }, { + "uuid": "f3833f6b-9332-4a1f-ad98-6c3f8e30e163", "property": "total", "description": "Three different books", "comments": ["Suggested grouping, [[1,2,3]]."], @@ -59,6 +63,7 @@ "expected": 2160 }, { + "uuid": "1951a1db-2fb6-4cd1-a69a-f691b6dd30a2", "property": "total", "description": "Four different books", "comments": ["Suggested grouping, [[1,2,3,4]]."], @@ -68,6 +73,7 @@ "expected": 2560 }, { + "uuid": "d70f6682-3019-4c3f-aede-83c6a8c647a3", "property": "total", "description": "Five different books", "comments": ["Suggested grouping, [[1,2,3,4,5]]."], @@ -77,6 +83,7 @@ "expected": 3000 }, { + "uuid": "78cacb57-911a-45f1-be52-2a5bd428c634", "property": "total", "description": "Two groups of four is cheaper than group of five plus group of three", "comments": ["Suggested grouping, [[1,2,3,4],[1,2,3,5]]."], @@ -86,6 +93,7 @@ "expected": 5120 }, { + "uuid": "f808b5a4-e01f-4c0d-881f-f7b90d9739da", "property": "total", "description": "Two groups of four is cheaper than groups of five and three", "comments": ["Suggested grouping, [[1,2,4,5],[1,3,4,5]]. This differs from the other 'two groups of four' test in that it will fail for solutions that add books to groups in the order in which they appear in the list."], @@ -95,6 +103,7 @@ "expected": 5120 }, { + "uuid": "fe96401c-5268-4be2-9d9e-19b76478007c", "property": "total", "description": "Group of four plus group of two is cheaper than two groups of three", "comments": ["Suggested grouping, [[1,2,3,4],[1,2]]."], @@ -104,6 +113,7 @@ "expected": 4080 }, { + "uuid": "68ea9b78-10ad-420e-a766-836a501d3633", "property": "total", "description": "Two each of first 4 books and 1 copy each of rest", "comments": ["Suggested grouping, [[1,2,3,4,5],[1,2,3,4]]."], @@ -113,6 +123,7 @@ "expected": 5560 }, { + "uuid": "c0a779d5-a40c-47ae-9828-a340e936b866", "property": "total", "description": "Two copies of each book", "comments": ["Suggested grouping, [[1,2,3,4,5],[1,2,3,4,5]]."], @@ -122,6 +133,7 @@ "expected": 6000 }, { + "uuid": "18fd86fe-08f1-4b68-969b-392b8af20513", "property": "total", "description": "Three copies of first book and 2 each of remaining", "comments": ["Suggested grouping, [[1,2,3,4,5],[1,2,3,4,5],[1]]."], @@ -131,6 +143,7 @@ "expected": 6800 }, { + "uuid": "0b19a24d-e4cf-4ec8-9db2-8899a41af0da", "property": "total", "description": "Three each of first 2 books and 2 each of remaining books", "comments": ["Suggested grouping, [[1,2,3,4,5],[1,2,3,4,5],[1,2]]."], @@ -140,6 +153,7 @@ "expected": 7520 }, { + "uuid": "bb376344-4fb2-49ab-ab85-e38d8354a58d", "property": "total", "description": "Four groups of four are cheaper than two groups each of five and three", "comments": ["Suggested grouping, [[1,2,3,4],[1,2,3,5],[1,2,3,4],[1,2,3,5]]."], diff --git a/exercises/bowling/canonical-data.json b/exercises/bowling/canonical-data.json index 4de708f8f9..5a96921e05 100644 --- a/exercises/bowling/canonical-data.json +++ b/exercises/bowling/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "bowling", - "version": "1.2.0", "comments": [ "Students should implement roll and score methods.", "Roll should accept a single integer.", @@ -21,6 +20,7 @@ "whether that be via exceptions, optional values, or otherwise." ], "cases": [{ + "uuid": "656ae006-25c2-438c-a549-f338e7ec7441", "description": "should be able to score a game with all zeros", "property": "score", "input": { @@ -28,6 +28,7 @@ }, "expected": 0 }, { + "uuid": "f85dcc56-cd6b-4875-81b3-e50921e3597b", "description": "should be able to score a game with no strikes or spares", "property": "score", "input": { @@ -35,6 +36,7 @@ }, "expected": 90 }, { + "uuid": "d1f56305-3ac2-4fe0-8645-0b37e3073e20", "description": "a spare followed by zeros is worth ten points", "property": "score", "input": { @@ -42,6 +44,7 @@ }, "expected": 10 }, { + "uuid": "0b8c8bb7-764a-4287-801a-f9e9012f8be4", "description": "points scored in the roll after a spare are counted twice", "property": "score", "input": { @@ -49,6 +52,7 @@ }, "expected": 16 }, { + "uuid": "4d54d502-1565-4691-84cd-f29a09c65bea", "description": "consecutive spares each get a one roll bonus", "property": "score", "input": { @@ -56,6 +60,7 @@ }, "expected": 31 }, { + "uuid": "e5c9cf3d-abbe-4b74-ad48-34051b2b08c0", "description": "a spare in the last frame gets a one roll bonus that is counted once", "property": "score", "input": { @@ -63,6 +68,7 @@ }, "expected": 17 }, { + "uuid": "75269642-2b34-4b72-95a4-9be28ab16902", "description": "a strike earns ten points in a frame with a single roll", "property": "score", "input": { @@ -70,6 +76,7 @@ }, "expected": 10 }, { + "uuid": "037f978c-5d01-4e49-bdeb-9e20a2e6f9a6", "description": "points scored in the two rolls after a strike are counted twice as a bonus", "property": "score", "input": { @@ -77,6 +84,7 @@ }, "expected": 26 }, { + "uuid": "1635e82b-14ec-4cd1-bce4-4ea14bd13a49", "description": "consecutive strikes each get the two roll bonus", "property": "score", "input": { @@ -84,6 +92,7 @@ }, "expected": 81 }, { + "uuid": "e483e8b6-cb4b-4959-b310-e3982030d766", "description": "a strike in the last frame gets a two roll bonus that is counted once", "property": "score", "input": { @@ -91,6 +100,7 @@ }, "expected": 18 }, { + "uuid": "9d5c87db-84bc-4e01-8e95-53350c8af1f8", "description": "rolling a spare with the two roll bonus does not get a bonus roll", "property": "score", "input": { @@ -98,6 +108,7 @@ }, "expected": 20 }, { + "uuid": "576faac1-7cff-4029-ad72-c16bcada79b5", "description": "strikes with the two roll bonus do not get bonus rolls", "property": "score", "input": { @@ -105,6 +116,7 @@ }, "expected": 30 }, { + "uuid": "72e24404-b6c6-46af-b188-875514c0377b", "description": "a strike with the one roll bonus after a spare in the last frame does not get a bonus", "property": "score", "input": { @@ -112,6 +124,7 @@ }, "expected": 20 }, { + "uuid": "62ee4c72-8ee8-4250-b794-234f1fec17b1", "description": "all strikes is a perfect game", "property": "score", "input": { @@ -119,6 +132,7 @@ }, "expected": 300 }, { + "uuid": "1245216b-19c6-422c-b34b-6e4012d7459f", "description": "rolls cannot score negative points", "property": "roll", "input": { @@ -127,6 +141,7 @@ }, "expected": {"error": "Negative roll is invalid"} }, { + "uuid": "5fcbd206-782c-4faa-8f3a-be5c538ba841", "description": "a roll cannot score more than 10 points", "property": "roll", "input": { @@ -135,6 +150,7 @@ }, "expected": {"error": "Pin count exceeds pins on the lane"} }, { + "uuid": "fb023c31-d842-422d-ad7e-79ce1db23c21", "description": "two rolls in a frame cannot score more than 10 points", "property": "roll", "input": { @@ -143,6 +159,7 @@ }, "expected": {"error": "Pin count exceeds pins on the lane"} }, { + "uuid": "6082d689-d677-4214-80d7-99940189381b", "description": "bonus roll after a strike in the last frame cannot score more than 10 points", "property": "roll", "input": { @@ -151,6 +168,7 @@ }, "expected": {"error": "Pin count exceeds pins on the lane"} }, { + "uuid": "e9565fe6-510a-4675-ba6b-733a56767a45", "description": "two bonus rolls after a strike in the last frame cannot score more than 10 points", "property": "roll", "input": { @@ -159,6 +177,7 @@ }, "expected": {"error": "Pin count exceeds pins on the lane"} }, { + "uuid": "2f6acf99-448e-4282-8103-0b9c7df99c3d", "description": "two bonus rolls after a strike in the last frame can score more than 10 points if one is a strike", "property": "score", "input": { @@ -166,6 +185,7 @@ }, "expected": 26 }, { + "uuid": "6380495a-8bc4-4cdb-a59f-5f0212dbed01", "description": "the second bonus rolls after a strike in the last frame cannot be a strike if the first one is not a strike", "property": "roll", "input": { @@ -174,6 +194,7 @@ }, "expected": {"error": "Pin count exceeds pins on the lane"} }, { + "uuid": "2b2976ea-446c-47a3-9817-42777f09fe7e", "description": "second bonus roll after a strike in the last frame cannot score more than 10 points", "property": "roll", "input": { @@ -182,6 +203,7 @@ }, "expected": {"error": "Pin count exceeds pins on the lane"} }, { + "uuid": "29220245-ac8d-463d-bc19-98a94cfada8a", "description": "an unstarted game cannot be scored", "property": "score", "input": { @@ -189,6 +211,7 @@ }, "expected": {"error": "Score cannot be taken until the end of the game"} }, { + "uuid": "4473dc5d-1f86-486f-bf79-426a52ddc955", "description": "an incomplete game cannot be scored", "property": "score", "input": { @@ -196,6 +219,7 @@ }, "expected": {"error": "Score cannot be taken until the end of the game"} }, { + "uuid": "2ccb8980-1b37-4988-b7d1-e5701c317df3", "description": "cannot roll if game already has ten frames", "property": "roll", "input": { @@ -204,6 +228,7 @@ }, "expected": {"error": "Cannot roll after game is over"} }, { + "uuid": "4864f09b-9df3-4b65-9924-c595ed236f1b", "description": "bonus rolls for a strike in the last frame must be rolled before score can be calculated", "property": "score", "input": { @@ -211,6 +236,7 @@ }, "expected": {"error": "Score cannot be taken until the end of the game"} }, { + "uuid": "537f4e37-4b51-4d1c-97e2-986eb37b2ac1", "description": "both bonus rolls for a strike in the last frame must be rolled before score can be calculated", "property": "score", "input": { @@ -218,6 +244,7 @@ }, "expected": {"error": "Score cannot be taken until the end of the game"} }, { + "uuid": "8134e8c1-4201-4197-bf9f-1431afcde4b9", "description": "bonus roll for a spare in the last frame must be rolled before score can be calculated", "property": "score", "input": { @@ -225,6 +252,7 @@ }, "expected": {"error": "Score cannot be taken until the end of the game"} }, { + "uuid": "9d4a9a55-134a-4bad-bae8-3babf84bd570", "description": "cannot roll after bonus roll for spare", "property": "roll", "input": { @@ -233,6 +261,7 @@ }, "expected": {"error": "Cannot roll after game is over"} }, { + "uuid": "d3e02652-a799-4ae3-b53b-68582cc604be", "description": "cannot roll after bonus rolls for strike", "property": "roll", "input": { diff --git a/exercises/change/canonical-data.json b/exercises/change/canonical-data.json index 31ce6f7100..bea6b1041b 100644 --- a/exercises/change/canonical-data.json +++ b/exercises/change/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "change", - "version": "1.3.0", "comments": [ "Given an infinite supply of coins with different values, ", "find the smallest number of coins needed to make a desired ", @@ -8,105 +7,236 @@ ], "cases": [ { + "uuid": "d0ebd0e1-9d27-4609-a654-df5c0ba1d83a", + "description": "change for 1 cent", + "property": "findFewestCoins", + "input": { + "coins": [ + 1, + 5, + 10, + 25 + ], + "target": 1 + }, + "expected": [ + 1 + ] + }, + { + "uuid": "36887bea-7f92-4a9c-b0cc-c0e886b3ecc8", "description": "single coin change", "property": "findFewestCoins", "input": { - "coins": [1, 5, 10, 25, 100], + "coins": [ + 1, + 5, + 10, + 25, + 100 + ], "target": 25 }, - "expected": [25] + "expected": [ + 25 + ] }, { + "uuid": "cef21ccc-0811-4e6e-af44-f011e7eab6c6", "description": "multiple coin change", "property": "findFewestCoins", "input": { - "coins": [1, 5, 10, 25, 100], + "coins": [ + 1, + 5, + 10, + 25, + 100 + ], "target": 15 }, - "expected": [5, 10] + "expected": [ + 5, + 10 + ] }, { + "uuid": "d60952bc-0c1a-4571-bf0c-41be72690cb3", "description": "change with Lilliputian Coins", "property": "findFewestCoins", "input": { - "coins": [1, 4, 15, 20, 50], + "coins": [ + 1, + 4, + 15, + 20, + 50 + ], "target": 23 }, - "expected": [4, 4, 15] + "expected": [ + 4, + 4, + 15 + ] }, { + "uuid": "408390b9-fafa-4bb9-b608-ffe6036edb6c", "description": "change with Lower Elbonia Coins", "property": "findFewestCoins", "input": { - "coins": [1, 5, 10, 21, 25], + "coins": [ + 1, + 5, + 10, + 21, + 25 + ], "target": 63 }, - "expected": [21, 21, 21] + "expected": [ + 21, + 21, + 21 + ] }, { + "uuid": "7421a4cb-1c48-4bf9-99c7-7f049689132f", "description": "large target values", "property": "findFewestCoins", "input": { - "coins": [1, 2, 5, 10, 20, 50, 100], + "coins": [ + 1, + 2, + 5, + 10, + 20, + 50, + 100 + ], "target": 999 }, - "expected": [ 2, 2, 5, 20, 20 - , 50, 100, 100, 100, 100 - , 100, 100, 100, 100, 100 ] + "expected": [ + 2, + 2, + 5, + 20, + 20, + 50, + 100, + 100, + 100, + 100, + 100, + 100, + 100, + 100, + 100 + ] }, { + "uuid": "f79d2e9b-0ae3-4d6a-bb58-dc978b0dba28", "description": "possible change without unit coins available", "property": "findFewestCoins", "input": { - "coins": [2, 5, 10, 20, 50], + "coins": [ + 2, + 5, + 10, + 20, + 50 + ], "target": 21 }, - "expected": [2, 2, 2, 5, 10] + "expected": [ + 2, + 2, + 2, + 5, + 10 + ] }, { + "uuid": "9a166411-d35d-4f7f-a007-6724ac266178", "description": "another possible change without unit coins available", "property": "findFewestCoins", "input": { - "coins": [4, 5], + "coins": [ + 4, + 5 + ], "target": 27 }, - "expected": [4, 4, 4, 5, 5, 5] + "expected": [ + 4, + 4, + 4, + 5, + 5, + 5 + ] }, { + "uuid": "bbbcc154-e9e9-4209-a4db-dd6d81ec26bb", "description": "no coins make 0 change", "property": "findFewestCoins", "input": { - "coins": [1, 5, 10, 21, 25], + "coins": [ + 1, + 5, + 10, + 21, + 25 + ], "target": 0 }, "expected": [] }, { + "uuid": "c8b81d5a-49bd-4b61-af73-8ee5383a2ce1", "description": "error testing for change smaller than the smallest of coins", "property": "findFewestCoins", "input": { - "coins": [5, 10], + "coins": [ + 5, + 10 + ], "target": 3 }, - "expected": {"error": "can't make target with given coins"} + "expected": { + "error": "can't make target with given coins" + } }, { + "uuid": "3c43e3e4-63f9-46ac-9476-a67516e98f68", "description": "error if no combination can add up to target", "property": "findFewestCoins", "input": { - "coins": [5, 10], + "coins": [ + 5, + 10 + ], "target": 94 }, - "expected": {"error": "can't make target with given coins"} + "expected": { + "error": "can't make target with given coins" + } }, { + "uuid": "8fe1f076-9b2d-4f44-89fe-8a6ccd63c8f3", "description": "cannot find negative change values", "property": "findFewestCoins", "input": { - "coins": [1, 2, 5], + "coins": [ + 1, + 2, + 5 + ], "target": -5 }, - "expected": {"error": "target can't be negative"} + "expected": { + "error": "target can't be negative" + } } ] -} \ No newline at end of file +} diff --git a/exercises/circular-buffer/canonical-data.json b/exercises/circular-buffer/canonical-data.json index ed474a46b4..241d2e4d10 100644 --- a/exercises/circular-buffer/canonical-data.json +++ b/exercises/circular-buffer/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "circular-buffer", - "version": "1.2.0", "comments": [ "In general, these circular buffers are expected to be stateful,", "and each language will operate on them differently.", @@ -26,6 +25,7 @@ ], "cases": [ { + "uuid": "28268ed4-4ff3-45f3-820e-895b44d53dfa", "description": "reading empty buffer should fail", "property": "run", "input": { @@ -40,6 +40,7 @@ "expected": {} }, { + "uuid": "2e6db04a-58a1-425d-ade8-ac30b5f318f3", "description": "can read an item just written", "property": "run", "input": { @@ -60,6 +61,7 @@ "expected": {} }, { + "uuid": "90741fe8-a448-45ce-be2b-de009a24c144", "description": "each item may only be read once", "property": "run", "input": { @@ -84,6 +86,7 @@ "expected": {} }, { + "uuid": "be0e62d5-da9c-47a8-b037-5db21827baa7", "description": "items are read in the order they are written", "property": "run", "input": { @@ -114,6 +117,7 @@ "expected": {} }, { + "uuid": "2af22046-3e44-4235-bfe6-05ba60439d38", "description": "full buffer can't be written to", "property": "run", "input": { @@ -134,6 +138,7 @@ "expected": {} }, { + "uuid": "547d192c-bbf0-4369-b8fa-fc37e71f2393", "description": "a read frees up capacity for another write", "property": "run", "input": { @@ -164,6 +169,7 @@ "expected": {} }, { + "uuid": "04a56659-3a81-4113-816b-6ecb659b4471", "description": "read position is maintained even across multiple writes", "property": "run", "input": { @@ -204,6 +210,7 @@ "expected": {} }, { + "uuid": "60c3a19a-81a7-43d7-bb0a-f07242b1111f", "description": "items cleared out of buffer can't be read", "property": "run", "input": { @@ -226,6 +233,7 @@ "expected": {} }, { + "uuid": "45f3ae89-3470-49f3-b50e-362e4b330a59", "description": "clear frees up capacity for another write", "property": "run", "input": { @@ -254,6 +262,7 @@ "expected": {} }, { + "uuid": "e1ac5170-a026-4725-bfbe-0cf332eddecd", "description": "clear does nothing on empty buffer", "property": "run", "input": { @@ -277,6 +286,7 @@ "expected": {} }, { + "uuid": "9c2d4f26-3ec7-453f-a895-7e7ff8ae7b5b", "description": "overwrite acts like write on non-full buffer", "property": "run", "input": { @@ -306,6 +316,7 @@ "expected": {} }, { + "uuid": "880f916b-5039-475c-bd5c-83463c36a147", "description": "overwrite replaces the oldest item on full buffer", "property": "run", "input": { @@ -340,6 +351,7 @@ "expected": {} }, { + "uuid": "bfecab5b-aca1-4fab-a2b0-cd4af2b053c3", "description": "overwrite replaces the oldest item remaining in buffer following a read", "property": "run", "input": { @@ -394,6 +406,7 @@ "expected": {} }, { + "uuid": "9cebe63a-c405-437b-8b62-e3fdc1ecec5a", "description": "initial clear does not affect wrapping around", "property": "run", "input": { diff --git a/exercises/clock/canonical-data.json b/exercises/clock/canonical-data.json index e7cee71a1b..76f5f86798 100644 --- a/exercises/clock/canonical-data.json +++ b/exercises/clock/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "clock", - "version": "2.4.0", "comments": [ "Most languages require constructing a clock with initial values,", "adding or subtracting some number of minutes, and testing equality", @@ -12,6 +11,7 @@ "description": "Create a new clock with an initial time", "cases": [ { + "uuid": "a577bacc-106b-496e-9792-b3083ea8705e", "description": "on the hour", "property": "create", "input": { @@ -21,6 +21,7 @@ "expected": "08:00" }, { + "uuid": "b5d0c360-3b88-489b-8e84-68a1c7a4fa23", "description": "past the hour", "property": "create", "input": { @@ -30,6 +31,7 @@ "expected": "11:09" }, { + "uuid": "473223f4-65f3-46ff-a9f7-7663c7e59440", "description": "midnight is zero hours", "property": "create", "input": { @@ -39,6 +41,7 @@ "expected": "00:00" }, { + "uuid": "ca95d24a-5924-447d-9a96-b91c8334725c", "description": "hour rolls over", "property": "create", "input": { @@ -48,6 +51,7 @@ "expected": "01:00" }, { + "uuid": "f3826de0-0925-4d69-8ac8-89aea7e52b78", "description": "hour rolls over continuously", "property": "create", "input": { @@ -57,6 +61,7 @@ "expected": "04:00" }, { + "uuid": "a02f7edf-dfd4-4b11-b21a-86de3cc6a95c", "description": "sixty minutes is next hour", "property": "create", "input": { @@ -66,6 +71,7 @@ "expected": "02:00" }, { + "uuid": "8f520df6-b816-444d-b90f-8a477789beb5", "description": "minutes roll over", "property": "create", "input": { @@ -75,6 +81,7 @@ "expected": "02:40" }, { + "uuid": "c75c091b-47ac-4655-8d40-643767fc4eed", "description": "minutes roll over continuously", "property": "create", "input": { @@ -84,6 +91,7 @@ "expected": "04:43" }, { + "uuid": "06343ecb-cf39-419d-a3f5-dcbae0cc4c57", "description": "hour and minutes roll over", "property": "create", "input": { @@ -93,6 +101,7 @@ "expected": "03:40" }, { + "uuid": "be60810e-f5d9-4b58-9351-a9d1e90e660c", "description": "hour and minutes roll over continuously", "property": "create", "input": { @@ -102,6 +111,7 @@ "expected": "11:01" }, { + "uuid": "1689107b-0b5c-4bea-aad3-65ec9859368a", "description": "hour and minutes roll over to exactly midnight", "property": "create", "input": { @@ -111,6 +121,7 @@ "expected": "00:00" }, { + "uuid": "d3088ee8-91b7-4446-9e9d-5e2ad6219d91", "description": "negative hour", "property": "create", "input": { @@ -120,6 +131,7 @@ "expected": "23:15" }, { + "uuid": "77ef6921-f120-4d29-bade-80d54aa43b54", "description": "negative hour rolls over", "property": "create", "input": { @@ -129,6 +141,7 @@ "expected": "23:00" }, { + "uuid": "359294b5-972f-4546-bb9a-a85559065234", "description": "negative hour rolls over continuously", "property": "create", "input": { @@ -138,6 +151,7 @@ "expected": "05:00" }, { + "uuid": "509db8b7-ac19-47cc-bd3a-a9d2f30b03c0", "description": "negative minutes", "property": "create", "input": { @@ -147,6 +161,7 @@ "expected": "00:20" }, { + "uuid": "5d6bb225-130f-4084-84fd-9e0df8996f2a", "description": "negative minutes roll over", "property": "create", "input": { @@ -156,6 +171,7 @@ "expected": "22:20" }, { + "uuid": "d483ceef-b520-4f0c-b94a-8d2d58cf0484", "description": "negative minutes roll over continuously", "property": "create", "input": { @@ -165,6 +181,7 @@ "expected": "16:40" }, { + "uuid": "1cd19447-19c6-44bf-9d04-9f8305ccb9ea", "description": "negative sixty minutes is previous hour", "property": "create", "input": { @@ -174,6 +191,7 @@ "expected": "01:00" }, { + "uuid": "9d3053aa-4f47-4afc-bd45-d67a72cef4dc", "description": "negative hour and minutes both roll over", "property": "create", "input": { @@ -183,6 +201,7 @@ "expected": "20:20" }, { + "uuid": "51d41fcf-491e-4ca0-9cae-2aa4f0163ad4", "description": "negative hour and minutes both roll over continuously", "property": "create", "input": { @@ -197,6 +216,7 @@ "description": "Add minutes", "cases": [ { + "uuid": "d098e723-ad29-4ef9-997a-2693c4c9d89a", "description": "add minutes", "property": "add", "input": { @@ -207,6 +227,7 @@ "expected": "10:03" }, { + "uuid": "b6ec8f38-e53e-4b22-92a7-60dab1f485f4", "description": "add no minutes", "property": "add", "input": { @@ -217,6 +238,7 @@ "expected": "06:41" }, { + "uuid": "efd349dd-0785-453e-9ff8-d7452a8e7269", "description": "add to next hour", "property": "add", "input": { @@ -227,6 +249,7 @@ "expected": "01:25" }, { + "uuid": "749890f7-aba9-4702-acce-87becf4ef9fe", "description": "add more than one hour", "property": "add", "input": { @@ -237,6 +260,7 @@ "expected": "11:01" }, { + "uuid": "da63e4c1-1584-46e3-8d18-c9dc802c1713", "description": "add more than two hours with carry", "property": "add", "input": { @@ -247,6 +271,7 @@ "expected": "03:25" }, { + "uuid": "be167a32-3d33-4cec-a8bc-accd47ddbb71", "description": "add across midnight", "property": "add", "input": { @@ -257,6 +282,7 @@ "expected": "00:01" }, { + "uuid": "6672541e-cdae-46e4-8be7-a820cc3be2a8", "description": "add more than one day (1500 min = 25 hrs)", "property": "add", "input": { @@ -267,6 +293,7 @@ "expected": "06:32" }, { + "uuid": "1918050d-c79b-4cb7-b707-b607e2745c7e", "description": "add more than two days", "property": "add", "input": { @@ -282,6 +309,7 @@ "description": "Subtract minutes", "cases": [ { + "uuid": "37336cac-5ede-43a5-9026-d426cbe40354", "description": "subtract minutes", "property": "subtract", "input": { @@ -292,6 +320,7 @@ "expected": "10:00" }, { + "uuid": "0aafa4d0-3b5f-4b12-b3af-e3a9e09c047b", "description": "subtract to previous hour", "property": "subtract", "input": { @@ -302,6 +331,7 @@ "expected": "09:33" }, { + "uuid": "9b4e809c-612f-4b15-aae0-1df0acb801b9", "description": "subtract more than an hour", "property": "subtract", "input": { @@ -312,6 +342,7 @@ "expected": "08:53" }, { + "uuid": "8b04bb6a-3d33-4e6c-8de9-f5de6d2c70d6", "description": "subtract across midnight", "property": "subtract", "input": { @@ -322,6 +353,7 @@ "expected": "23:59" }, { + "uuid": "07c3bbf7-ce4d-4658-86e8-4a77b7a5ccd9", "description": "subtract more than two hours", "property": "subtract", "input": { @@ -332,6 +364,7 @@ "expected": "21:20" }, { + "uuid": "90ac8a1b-761c-4342-9c9c-cdc3ed5db097", "description": "subtract more than two hours with borrow", "property": "subtract", "input": { @@ -342,6 +375,7 @@ "expected": "03:35" }, { + "uuid": "2149f985-7136-44ad-9b29-ec023a97a2b7", "description": "subtract more than one day (1500 min = 25 hrs)", "property": "subtract", "input": { @@ -352,6 +386,7 @@ "expected": "04:32" }, { + "uuid": "ba11dbf0-ac27-4acb-ada9-3b853ec08c97", "description": "subtract more than two days", "property": "subtract", "input": { @@ -367,6 +402,7 @@ "description": "Compare two clocks for equality", "cases": [ { + "uuid": "f2fdad51-499f-4c9b-a791-b28c9282e311", "description": "clocks with same time", "property": "equal", "input": { @@ -382,6 +418,7 @@ "expected": true }, { + "uuid": "5d409d4b-f862-4960-901e-ec430160b768", "description": "clocks a minute apart", "property": "equal", "input": { @@ -397,6 +434,7 @@ "expected": false }, { + "uuid": "a6045fcf-2b52-4a47-8bb2-ef10a064cba5", "description": "clocks an hour apart", "property": "equal", "input": { @@ -412,6 +450,7 @@ "expected": false }, { + "uuid": "66b12758-0be5-448b-a13c-6a44bce83527", "description": "clocks with hour overflow", "property": "equal", "input": { @@ -427,6 +466,7 @@ "expected": true }, { + "uuid": "2b19960c-212e-4a71-9aac-c581592f8111", "description": "clocks with hour overflow by several days", "property": "equal", "input": { @@ -442,6 +482,7 @@ "expected": true }, { + "uuid": "6f8c6541-afac-4a92-b0c2-b10d4e50269f", "description": "clocks with negative hour", "property": "equal", "input": { @@ -457,6 +498,7 @@ "expected": true }, { + "uuid": "bb9d5a68-e324-4bf5-a75e-0e9b1f97a90d", "description": "clocks with negative hour that wraps", "property": "equal", "input": { @@ -472,6 +514,7 @@ "expected": true }, { + "uuid": "56c0326d-565b-4d19-a26f-63b3205778b7", "description": "clocks with negative hour that wraps multiple times", "property": "equal", "input": { @@ -487,6 +530,7 @@ "expected": true }, { + "uuid": "c90b9de8-ddff-4ffe-9858-da44a40fdbc2", "description": "clocks with minute overflow", "property": "equal", "input": { @@ -502,6 +546,7 @@ "expected": true }, { + "uuid": "533a3dc5-59a7-491b-b728-a7a34fe325de", "description": "clocks with minute overflow by several days", "property": "equal", "input": { @@ -517,6 +562,7 @@ "expected": true }, { + "uuid": "fff49e15-f7b7-4692-a204-0f6052d62636", "description": "clocks with negative minute", "property": "equal", "input": { @@ -532,6 +578,7 @@ "expected": true }, { + "uuid": "605c65bb-21bd-43eb-8f04-878edf508366", "description": "clocks with negative minute that wraps", "property": "equal", "input": { @@ -547,6 +594,7 @@ "expected": true }, { + "uuid": "b87e64ed-212a-4335-91fd-56da8421d077", "description": "clocks with negative minute that wraps multiple times", "property": "equal", "input": { @@ -562,6 +610,7 @@ "expected": true }, { + "uuid": "822fbf26-1f3b-4b13-b9bf-c914816b53dd", "description": "clocks with negative hours and minutes", "property": "equal", "input": { @@ -577,6 +626,7 @@ "expected": true }, { + "uuid": "e787bccd-cf58-4a1d-841c-ff80eaaccfaa", "description": "clocks with negative hours and minutes that wrap", "property": "equal", "input": { @@ -592,6 +642,7 @@ "expected": true }, { + "uuid": "96969ca8-875a-48a1-86ae-257a528c44f5", "description": "full clock and zeroed clock", "property": "equal", "input": { diff --git a/exercises/collatz-conjecture/canonical-data.json b/exercises/collatz-conjecture/canonical-data.json index 7bdb593473..545c66e07d 100644 --- a/exercises/collatz-conjecture/canonical-data.json +++ b/exercises/collatz-conjecture/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "collatz-conjecture", - "version": "1.2.1", "cases": [ { + "uuid": "540a3d51-e7a6-47a5-92a3-4ad1838f0bfd", "description": "zero steps for one", "property": "steps", "input": { @@ -11,6 +11,7 @@ "expected": 0 }, { + "uuid": "3d76a0a6-ea84-444a-821a-f7857c2c1859", "description": "divide if even", "property": "steps", "input": { @@ -19,6 +20,7 @@ "expected": 4 }, { + "uuid": "754dea81-123c-429e-b8bc-db20b05a87b9", "description": "even and odd steps", "property": "steps", "input": { @@ -27,6 +29,7 @@ "expected": 9 }, { + "uuid": "ecfd0210-6f85-44f6-8280-f65534892ff6", "description": "large number of even and odd steps", "property": "steps", "input": { @@ -35,6 +38,7 @@ "expected": 152 }, { + "uuid": "7d4750e6-def9-4b86-aec7-9f7eb44f95a3", "description": "zero is an error", "property": "steps", "input": { @@ -43,6 +47,7 @@ "expected": { "error": "Only positive numbers are allowed" } }, { + "uuid": "c6c795bf-a288-45e9-86a1-841359ad426d", "description": "negative value is an error", "property": "steps", "input": { diff --git a/exercises/complex-numbers/canonical-data.json b/exercises/complex-numbers/canonical-data.json index 6838bef68a..8233b1d2e7 100644 --- a/exercises/complex-numbers/canonical-data.json +++ b/exercises/complex-numbers/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "complex-numbers", - "version": "1.3.0", "comments": [ " The canonical data assumes mathematically correct real ", " numbers. The testsuites should consider rounding errors ", @@ -16,6 +15,7 @@ "description": "Real part", "cases": [ { + "uuid": "9f98e133-eb7f-45b0-9676-cce001cd6f7a", "description": "Real part of a purely real number", "property": "real", "input": { @@ -24,6 +24,7 @@ "expected": 1 }, { + "uuid": "07988e20-f287-4bb7-90cf-b32c4bffe0f3", "description": "Real part of a purely imaginary number", "property": "real", "input": { @@ -32,6 +33,7 @@ "expected": 0 }, { + "uuid": "4a370e86-939e-43de-a895-a00ca32da60a", "description": "Real part of a number with real and imaginary part", "property": "real", "input": { @@ -45,6 +47,7 @@ "description": "Imaginary part", "cases": [ { + "uuid": "9b3fddef-4c12-4a99-b8f8-e3a42c7ccef6", "description": "Imaginary part of a purely real number", "property": "imaginary", "input": { @@ -53,6 +56,7 @@ "expected": 0 }, { + "uuid": "a8dafedd-535a-4ed3-8a39-fda103a2b01e", "description": "Imaginary part of a purely imaginary number", "property": "imaginary", "input": { @@ -61,6 +65,7 @@ "expected": 1 }, { + "uuid": "0f998f19-69ee-4c64-80ef-01b086feab80", "description": "Imaginary part of a number with real and imaginary part", "property": "imaginary", "input": { @@ -71,6 +76,7 @@ ] }, { + "uuid": "a39b7fd6-6527-492f-8c34-609d2c913879", "description": "Imaginary unit", "property": "mul", "input": { @@ -86,6 +92,7 @@ "description": "Addition", "cases": [ { + "uuid": "9a2c8de9-f068-4f6f-b41c-82232cc6c33e", "description": "Add purely real numbers", "property": "add", "input": { @@ -95,6 +102,7 @@ "expected": [3, 0] }, { + "uuid": "657c55e1-b14b-4ba7-bd5c-19db22b7d659", "description": "Add purely imaginary numbers", "property": "add", "input": { @@ -104,6 +112,7 @@ "expected": [0, 3] }, { + "uuid": "4e1395f5-572b-4ce8-bfa9-9a63056888da", "description": "Add numbers with real and imaginary part", "property": "add", "input": { @@ -118,6 +127,7 @@ "description": "Subtraction", "cases": [ { + "uuid": "1155dc45-e4f7-44b8-af34-a91aa431475d", "description": "Subtract purely real numbers", "property": "sub", "input": { @@ -127,6 +137,7 @@ "expected": [-1, 0] }, { + "uuid": "f95e9da8-acd5-4da4-ac7c-c861b02f774b", "description": "Subtract purely imaginary numbers", "property": "sub", "input": { @@ -136,6 +147,7 @@ "expected": [0, -1] }, { + "uuid": "f876feb1-f9d1-4d34-b067-b599a8746400", "description": "Subtract numbers with real and imaginary part", "property": "sub", "input": { @@ -150,6 +162,7 @@ "description": "Multiplication", "cases": [ { + "uuid": "8a0366c0-9e16-431f-9fd7-40ac46ff4ec4", "description": "Multiply purely real numbers", "property": "mul", "input": { @@ -159,6 +172,7 @@ "expected": [2, 0] }, { + "uuid": "e560ed2b-0b80-4b4f-90f2-63cefc911aaf", "description": "Multiply purely imaginary numbers", "property": "mul", "input": { @@ -168,6 +182,7 @@ "expected": [-2, 0] }, { + "uuid": "4d1d10f0-f8d4-48a0-b1d0-f284ada567e6", "description": "Multiply numbers with real and imaginary part", "property": "mul", "input": { @@ -182,6 +197,7 @@ "description": "Division", "cases": [ { + "uuid": "b0571ddb-9045-412b-9c15-cd1d816d36c1", "description": "Divide purely real numbers", "property": "div", "input": { @@ -191,6 +207,7 @@ "expected": [0.5, 0] }, { + "uuid": "5bb4c7e4-9934-4237-93cc-5780764fdbdd", "description": "Divide purely imaginary numbers", "property": "div", "input": { @@ -200,6 +217,7 @@ "expected": [0.5, 0] }, { + "uuid": "c4e7fef5-64ac-4537-91c2-c6529707701f", "description": "Divide numbers with real and imaginary part", "property": "div", "input": { @@ -216,6 +234,7 @@ "description": "Absolute value", "cases": [ { + "uuid": "c56a7332-aad2-4437-83a0-b3580ecee843", "description": "Absolute value of a positive purely real number", "property": "abs", "input": { @@ -224,6 +243,7 @@ "expected": 5 }, { + "uuid": "cf88d7d3-ee74-4f4e-8a88-a1b0090ecb0c", "description": "Absolute value of a negative purely real number", "property": "abs", "input": { @@ -232,6 +252,7 @@ "expected": 5 }, { + "uuid": "bbe26568-86c1-4bb4-ba7a-da5697e2b994", "description": "Absolute value of a purely imaginary number with positive imaginary part", "property": "abs", "input": { @@ -240,6 +261,7 @@ "expected": 5 }, { + "uuid": "3b48233d-468e-4276-9f59-70f4ca1f26f3", "description": "Absolute value of a purely imaginary number with negative imaginary part", "property": "abs", "input": { @@ -248,6 +270,7 @@ "expected": 5 }, { + "uuid": "fe400a9f-aa22-4b49-af92-51e0f5a2a6d3", "description": "Absolute value of a number with real and imaginary part", "property": "abs", "input": { @@ -261,6 +284,7 @@ "description": "Complex conjugate", "cases": [ { + "uuid": "fb2d0792-e55a-4484-9443-df1eddfc84a2", "description": "Conjugate a purely real number", "property": "conjugate", "input": { @@ -269,6 +293,7 @@ "expected": [5, 0] }, { + "uuid": "e37fe7ac-a968-4694-a460-66cb605f8691", "description": "Conjugate a purely imaginary number", "property": "conjugate", "input": { @@ -277,6 +302,7 @@ "expected": [0, -5] }, { + "uuid": "f7704498-d0be-4192-aaf5-a1f3a7f43e68", "description": "Conjugate a number with real and imaginary part", "property": "conjugate", "input": { @@ -301,6 +327,7 @@ ], "cases": [ { + "uuid": "6d96d4c6-2edb-445b-94a2-7de6d4caaf60", "description": "Euler's identity/formula", "property": "exp", "input": { @@ -309,6 +336,7 @@ "expected": [-1, 0] }, { + "uuid": "2d2c05a0-4038-4427-a24d-72f6624aa45f", "description": "Exponential of 0", "property": "exp", "input": { @@ -317,6 +345,7 @@ "expected": [1, 0] }, { + "uuid": "ed87f1bd-b187-45d6-8ece-7e331232c809", "description": "Exponential of a purely real number", "property": "exp", "input": { @@ -325,6 +354,7 @@ "expected": ["e", 0] }, { + "uuid": "08eedacc-5a95-44fc-8789-1547b27a8702", "description": "Exponential of a number with real and imaginary part", "property": "exp", "input": { diff --git a/exercises/connect/canonical-data.json b/exercises/connect/canonical-data.json index 61d0beccb4..f722b8b56c 100644 --- a/exercises/connect/canonical-data.json +++ b/exercises/connect/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "connect", - "version": "1.1.0", "cases": [ { + "uuid": "6eff0df4-3e92-478d-9b54-d3e8b354db56", "description": "an empty board has no winner", "property": "winner", "input": { @@ -17,6 +17,7 @@ "expected": "" }, { + "uuid": "298b94c0-b46d-45d8-b34b-0fa2ea71f0a4", "description": "X can win on a 1x1 board", "property": "winner", "input": { @@ -27,6 +28,7 @@ "expected": "X" }, { + "uuid": "763bbae0-cb8f-4f28-bc21-5be16a5722dc", "description": "O can win on a 1x1 board", "property": "winner", "input": { @@ -37,6 +39,7 @@ "expected": "O" }, { + "uuid": "819fde60-9ae2-485e-a024-cbb8ea68751b", "description": "only edges does not make a winner", "property": "winner", "input": { @@ -50,6 +53,7 @@ "expected": "" }, { + "uuid": "2c56a0d5-9528-41e5-b92b-499dfe08506c", "description": "illegal diagonal does not make a winner", "property": "winner", "input": { @@ -64,6 +68,7 @@ "expected": "" }, { + "uuid": "41cce3ef-43ca-4963-970a-c05d39aa1cc1", "description": "nobody wins crossing adjacent angles", "property": "winner", "input": { @@ -78,6 +83,7 @@ "expected": "" }, { + "uuid": "cd61c143-92f6-4a8d-84d9-cb2b359e226b", "description": "X wins crossing from left to right", "property": "winner", "input": { @@ -92,6 +98,7 @@ "expected": "X" }, { + "uuid": "73d1eda6-16ab-4460-9904-b5f5dd401d0b", "description": "O wins crossing from top to bottom", "property": "winner", "input": { @@ -106,6 +113,7 @@ "expected": "O" }, { + "uuid": "c3a2a550-944a-4637-8b3f-1e1bf1340a3d", "description": "X wins using a convoluted path", "property": "winner", "input": { @@ -120,6 +128,7 @@ "expected": "X" }, { + "uuid": "17e76fa8-f731-4db7-92ad-ed2a285d31f3", "description": "X wins using a spiral path", "property": "winner", "input": { @@ -138,4 +147,4 @@ "expected": "X" } ] -} \ No newline at end of file +} diff --git a/exercises/connect/description.md b/exercises/connect/description.md index 5cba2ab773..c1a70c1992 100644 --- a/exercises/connect/description.md +++ b/exercises/connect/description.md @@ -3,15 +3,16 @@ Compute the result for a game of Hex / Polygon. The abstract boardgame known as [Hex](https://en.wikipedia.org/wiki/Hex_%28board_game%29) / Polygon / CON-TAC-TIX is quite simple in rules, though complex in practice. Two players -place stones on a rhombus with hexagonal fields. The player to connect his/her -stones to the opposite side first wins. The four sides of the rhombus are +place stones on a parallelogram with hexagonal fields. The player to connect his/her +stones to the opposite side first wins. The four sides of the parallelogram are divided between the two players (i.e. one player gets assigned a side and the side directly opposite it and the other player gets assigned the two other sides). Your goal is to build a program that given a simple representation of a board computes the winner (or lack thereof). Note that all games need not be "fair". -(For example, players may have mismatched piece counts.) +(For example, players may have mismatched piece counts or the game's board might +have a different width and height.) The boards look like this: diff --git a/exercises/crypto-square/canonical-data.json b/exercises/crypto-square/canonical-data.json index b2814e2e52..63d805dc95 100644 --- a/exercises/crypto-square/canonical-data.json +++ b/exercises/crypto-square/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "crypto-square", - "version": "3.2.0", "cases": [ { + "uuid": "407c3837-9aa7-4111-ab63-ec54b58e8e9f", "description": "empty plaintext results in an empty ciphertext", "property": "ciphertext", "input": { @@ -11,6 +11,7 @@ "expected": "" }, { + "uuid": "64131d65-6fd9-4f58-bdd8-4a2370fb481d", "description": "Lowercase", "property": "ciphertext", "input": { @@ -19,6 +20,7 @@ "expected": "a" }, { + "uuid": "63a4b0ed-1e3c-41ea-a999-f6f26ba447d6", "description": "Remove spaces", "property": "ciphertext", "input": { @@ -27,6 +29,7 @@ "expected": "b" }, { + "uuid": "1b5348a1-7893-44c1-8197-42d48d18756c", "description": "Remove punctuation", "property": "ciphertext", "input": { @@ -35,6 +38,7 @@ "expected": "1" }, { + "uuid": "8574a1d3-4a08-4cec-a7c7-de93a164f41a", "description": "9 character plaintext results in 3 chunks of 3 characters", "property": "ciphertext", "input": { @@ -43,6 +47,7 @@ "expected": "tsf hiu isn" }, { + "uuid": "a65d3fa1-9e09-43f9-bcec-7a672aec3eae", "description": "8 character plaintext results in 3 chunks, the last one with a trailing space", "property": "ciphertext", "input": { @@ -51,6 +56,7 @@ "expected": "clu hlt io " }, { + "uuid": "fbcb0c6d-4c39-4a31-83f6-c473baa6af80", "description": "54 character plaintext results in 7 chunks, the last two with trailing spaces", "property": "ciphertext", "input": { @@ -59,4 +65,4 @@ "expected": "imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau " } ] -} \ No newline at end of file +} diff --git a/exercises/custom-set/canonical-data.json b/exercises/custom-set/canonical-data.json index 7666506198..827eab57f8 100644 --- a/exercises/custom-set/canonical-data.json +++ b/exercises/custom-set/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "custom-set", - "version": "1.3.0", "comments": [ "These tests cover the core components of a set data structure: checking", "presence, adding, comparing and basic set operations. Other features", @@ -16,6 +15,7 @@ "description": "Returns true if the set contains no elements", "cases": [ { + "uuid": "20c5f855-f83a-44a7-abdd-fe75c6cf022b", "description": "sets with no elements are empty", "property": "empty", "input": { @@ -24,6 +24,7 @@ "expected": true }, { + "uuid": "d506485d-5706-40db-b7d8-5ceb5acf88d2", "description": "sets with elements are not empty", "property": "empty", "input": { @@ -37,6 +38,7 @@ "description": "Sets can report if they contain an element", "cases": [ { + "uuid": "759b9740-3417-44c3-8ca3-262b3c281043", "description": "nothing is contained in an empty set", "property": "contains", "input": { @@ -46,6 +48,7 @@ "expected": false }, { + "uuid": "f83cd2d1-2a85-41bc-b6be-80adbff4be49", "description": "when the element is in the set", "property": "contains", "input": { @@ -55,6 +58,7 @@ "expected": true }, { + "uuid": "93423fc0-44d0-4bc0-a2ac-376de8d7af34", "description": "when the element is not in the set", "property": "contains", "input": { @@ -69,6 +73,7 @@ "description": "A set is a subset if all of its elements are contained in the other set", "cases": [ { + "uuid": "c392923a-637b-4495-b28e-34742cd6157a", "description": "empty set is a subset of another empty set", "property": "subset", "input": { @@ -78,6 +83,7 @@ "expected": true }, { + "uuid": "5635b113-be8c-4c6f-b9a9-23c485193917", "description": "empty set is a subset of non-empty set", "property": "subset", "input": { @@ -87,6 +93,7 @@ "expected": true }, { + "uuid": "832eda58-6d6e-44e2-92c2-be8cf0173cee", "description": "non-empty set is not a subset of empty set", "property": "subset", "input": { @@ -96,6 +103,7 @@ "expected": false }, { + "uuid": "c830c578-8f97-4036-b082-89feda876131", "description": "set is a subset of set with exact same elements", "property": "subset", "input": { @@ -105,6 +113,7 @@ "expected": true }, { + "uuid": "476a4a1c-0fd1-430f-aa65-5b70cbc810c5", "description": "set is a subset of larger set with same elements", "property": "subset", "input": { @@ -114,6 +123,7 @@ "expected": true }, { + "uuid": "d2498999-3e46-48e4-9660-1e20c3329d3d", "description": "set is not a subset of set that does not contain its elements", "property": "subset", "input": { @@ -128,6 +138,7 @@ "description": "Sets are disjoint if they share no elements", "cases": [ { + "uuid": "7d38155e-f472-4a7e-9ad8-5c1f8f95e4cc", "description": "the empty set is disjoint with itself", "property": "disjoint", "input": { @@ -137,6 +148,7 @@ "expected": true }, { + "uuid": "7a2b3938-64b6-4b32-901a-fe16891998a6", "description": "empty set is disjoint with non-empty set", "property": "disjoint", "input": { @@ -146,6 +158,7 @@ "expected": true }, { + "uuid": "589574a0-8b48-48ea-88b0-b652c5fe476f", "description": "non-empty set is disjoint with empty set", "property": "disjoint", "input": { @@ -155,6 +168,7 @@ "expected": true }, { + "uuid": "febeaf4f-f180-4499-91fa-59165955a523", "description": "sets are not disjoint if they share an element", "property": "disjoint", "input": { @@ -164,6 +178,7 @@ "expected": false }, { + "uuid": "0de20d2f-c952-468a-88c8-5e056740f020", "description": "sets are disjoint if they share no elements", "property": "disjoint", "input": { @@ -178,6 +193,7 @@ "description": "Sets with the same elements are equal", "cases": [ { + "uuid": "4bd24adb-45da-4320-9ff6-38c044e9dff8", "description": "empty sets are equal", "property": "equal", "input": { @@ -187,6 +203,7 @@ "expected": true }, { + "uuid": "f65c0a0e-6632-4b2d-b82c-b7c6da2ec224", "description": "empty set is not equal to non-empty set", "property": "equal", "input": { @@ -196,6 +213,7 @@ "expected": false }, { + "uuid": "81e53307-7683-4b1e-a30c-7e49155fe3ca", "description": "non-empty set is not equal to empty set", "property": "equal", "input": { @@ -205,6 +223,7 @@ "expected": false }, { + "uuid": "d57c5d7c-a7f3-48cc-a162-6b488c0fbbd0", "description": "sets with the same elements are equal", "property": "equal", "input": { @@ -214,6 +233,7 @@ "expected": true }, { + "uuid": "dd61bafc-6653-42cc-961a-ab071ee0ee85", "description": "sets with different elements are not equal", "property": "equal", "input": { @@ -223,6 +243,7 @@ "expected": false }, { + "uuid": "06059caf-9bf4-425e-aaff-88966cb3ea14", "description": "set is not equal to larger set with same elements", "property": "equal", "input": { @@ -237,6 +258,7 @@ "description": "Unique elements can be added to a set", "cases": [ { + "uuid": "8a677c3c-a658-4d39-bb88-5b5b1a9659f4", "description": "add to empty set", "property": "add", "input": { @@ -246,6 +268,7 @@ "expected": [3] }, { + "uuid": "0903dd45-904d-4cf2-bddd-0905e1a8d125", "description": "add to non-empty set", "property": "add", "input": { @@ -255,6 +278,7 @@ "expected": [1, 2, 3, 4] }, { + "uuid": "b0eb7bb7-5e5d-4733-b582-af771476cb99", "description": "adding an existing element does not change the set", "property": "add", "input": { @@ -269,6 +293,7 @@ "description": "Intersection returns a set of all shared elements", "cases": [ { + "uuid": "893d5333-33b8-4151-a3d4-8f273358208a", "description": "intersection of two empty sets is an empty set", "property": "intersection", "input": { @@ -278,6 +303,7 @@ "expected": [] }, { + "uuid": "d739940e-def2-41ab-a7bb-aaf60f7d782c", "description": "intersection of an empty set and non-empty set is an empty set", "property": "intersection", "input": { @@ -287,6 +313,7 @@ "expected": [] }, { + "uuid": "3607d9d8-c895-4d6f-ac16-a14956e0a4b7", "description": "intersection of a non-empty set and an empty set is an empty set", "property": "intersection", "input": { @@ -296,6 +323,7 @@ "expected": [] }, { + "uuid": "b5120abf-5b5e-41ab-aede-4de2ad85c34e", "description": "intersection of two sets with no shared elements is an empty set", "property": "intersection", "input": { @@ -305,6 +333,7 @@ "expected": [] }, { + "uuid": "af21ca1b-fac9-499c-81c0-92a591653d49", "description": "intersection of two sets with shared elements is a set of the shared elements", "property": "intersection", "input": { @@ -319,6 +348,7 @@ "description": "Difference (or Complement) of a set is a set of all elements that are only in the first set", "cases": [ { + "uuid": "c5e6e2e4-50e9-4bc2-b89f-c518f015b57e", "description": "difference of two empty sets is an empty set", "property": "difference", "input": { @@ -328,6 +358,7 @@ "expected": [] }, { + "uuid": "2024cc92-5c26-44ed-aafd-e6ca27d6fcd2", "description": "difference of empty set and non-empty set is an empty set", "property": "difference", "input": { @@ -337,6 +368,7 @@ "expected": [] }, { + "uuid": "e79edee7-08aa-4c19-9382-f6820974b43e", "description": "difference of a non-empty set and an empty set is the non-empty set", "property": "difference", "input": { @@ -346,6 +378,7 @@ "expected": [1, 2, 3, 4] }, { + "uuid": "c5ac673e-d707-4db5-8d69-7082c3a5437e", "description": "difference of two non-empty sets is a set of elements that are only in the first set", "property": "difference", "input": { @@ -360,6 +393,7 @@ "description": "Union returns a set of all elements in either set", "cases": [ { + "uuid": "c45aed16-5494-455a-9033-5d4c93589dc6", "description": "union of empty sets is an empty set", "property": "union", "input": { @@ -369,6 +403,7 @@ "expected": [] }, { + "uuid": "9d258545-33c2-4fcb-a340-9f8aa69e7a41", "description": "union of an empty set and non-empty set is the non-empty set", "property": "union", "input": { @@ -378,6 +413,7 @@ "expected": [2] }, { + "uuid": "3aade50c-80c7-4db8-853d-75bac5818b83", "description": "union of a non-empty set and empty set is the non-empty set", "property": "union", "input": { @@ -387,6 +423,7 @@ "expected": [1, 3] }, { + "uuid": "a00bb91f-c4b4-4844-8f77-c73e2e9df77c", "description": "union of non-empty sets contains all unique elements", "property": "union", "input": { diff --git a/exercises/darts/canonical-data.json b/exercises/darts/canonical-data.json index e03af88558..a3d9f5ad54 100644 --- a/exercises/darts/canonical-data.json +++ b/exercises/darts/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "darts", - "version": "2.2.0", "comments": [ "Return the correct amount earned by a dart's landing position." ], "cases": [ { + "uuid": "9033f731-0a3a-4d9c-b1c0-34a1c8362afb", "property": "score", "description": "Missed target", "input": { @@ -15,6 +15,7 @@ "expected": 0 }, { + "uuid": "4c9f6ff4-c489-45fd-be8a-1fcb08b4d0ba", "property": "score", "description": "On the outer circle", "input": { @@ -24,6 +25,7 @@ "expected": 1 }, { + "uuid": "14378687-ee58-4c9b-a323-b089d5274be8", "property": "score", "description": "On the middle circle", "input": { @@ -33,6 +35,7 @@ "expected": 5 }, { + "uuid": "849e2e63-85bd-4fed-bc3b-781ae962e2c9", "property": "score", "description": "On the inner circle", "input": { @@ -42,6 +45,7 @@ "expected": 10 }, { + "uuid": "1c5ffd9f-ea66-462f-9f06-a1303de5a226", "property": "score", "description": "Exactly on centre", "input": { @@ -51,6 +55,7 @@ "expected": 10 }, { + "uuid": "b65abce3-a679-4550-8115-4b74bda06088", "property": "score", "description": "Near the centre", "input": { @@ -60,6 +65,7 @@ "expected": 10 }, { + "uuid": "66c29c1d-44f5-40cf-9927-e09a1305b399", "property": "score", "description": "Just within the inner circle", "input": { @@ -69,6 +75,7 @@ "expected": 10 }, { + "uuid": "d1012f63-c97c-4394-b944-7beb3d0b141a", "property": "score", "description": "Just outside the inner circle", "input": { @@ -78,6 +85,7 @@ "expected": 5 }, { + "uuid": "ab2b5666-b0b4-49c3-9b27-205e790ed945", "property": "score", "description": "Just within the middle circle", "input": { @@ -85,8 +93,9 @@ "y": 3.5 }, "expected": 5 - }, + }, { + "uuid": "70f1424e-d690-4860-8caf-9740a52c0161", "property": "score", "description": "Just outside the middle circle", "input": { @@ -94,8 +103,9 @@ "y": -3.6 }, "expected": 1 - }, + }, { + "uuid": "a7dbf8db-419c-4712-8a7f-67602b69b293", "property": "score", "description": "Just within the outer circle", "input": { @@ -103,8 +113,9 @@ "y": 7.0 }, "expected": 1 - }, + }, { + "uuid": "e0f39315-9f9a-4546-96e4-a9475b885aa7", "property": "score", "description": "Just outside the outer circle", "input": { @@ -112,8 +123,9 @@ "y": -7.1 }, "expected": 0 - }, + }, { + "uuid": "045d7d18-d863-4229-818e-b50828c75d19", "property": "score", "description": "Asymmetric position between the inner and middle circles", "input": { diff --git a/exercises/darts/description.md b/exercises/darts/description.md index d691e41cdb..f129ea318d 100644 --- a/exercises/darts/description.md +++ b/exercises/darts/description.md @@ -12,4 +12,4 @@ In our particular instance of the game, the target rewards with 4 different amou The outer circle has a radius of 10 units (This is equivalent to the total radius for the entire target), the middle circle a radius of 5 units, and the inner circle a radius of 1. Of course, they are all centered to the same point (That is, the circles are [concentric](http://mathworld.wolfram.com/ConcentricCircles.html)) defined by the coordinates (0, 0). -Write a function that given a point in the target (defined by its `real` cartesian coordinates `x` and `y`), returns the correct amount earned by a dart landing in that point. \ No newline at end of file +Write a function that given a point in the target (defined by its `real` cartesian coordinates `x` and `y`), returns the correct amount earned by a dart landing in that point. diff --git a/exercises/diamond/canonical-data.json b/exercises/diamond/canonical-data.json index 12d794cc92..e642569259 100644 --- a/exercises/diamond/canonical-data.json +++ b/exercises/diamond/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "diamond", - "version": "1.1.0", "comments": [ " The tests contained within this canonical data file are suitable ", " for value-based testing, in which each test case checks that the ", @@ -20,6 +19,7 @@ ], "cases": [ { + "uuid": "202fb4cc-6a38-4883-9193-a29d5cb92076", "description": "Degenerate case with a single 'A' row", "property": "rows", "input": { @@ -30,6 +30,7 @@ ] }, { + "uuid": "bd6a6d78-9302-42e9-8f60-ac1461e9abae", "description": "Degenerate case with no row containing 3 distinct groups of spaces", "property": "rows", "input": { @@ -42,6 +43,7 @@ ] }, { + "uuid": "af8efb49-14ed-447f-8944-4cc59ce3fd76", "description": "Smallest non-degenerate case with odd diamond side length", "property": "rows", "input": { @@ -56,6 +58,7 @@ ] }, { + "uuid": "e0c19a95-9888-4d05-86a0-fa81b9e70d1d", "description": "Smallest non-degenerate case with even diamond side length", "property": "rows", "input": { @@ -72,6 +75,7 @@ ] }, { + "uuid": "82ea9aa9-4c0e-442a-b07e-40204e925944", "description": "Largest possible diamond", "property": "rows", "input": { @@ -132,4 +136,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/difference-of-squares/canonical-data.json b/exercises/difference-of-squares/canonical-data.json index ec7f78e2b6..f0325621ea 100644 --- a/exercises/difference-of-squares/canonical-data.json +++ b/exercises/difference-of-squares/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "difference-of-squares", - "version": "1.2.0", "cases": [ { "description": "Square the sum of the numbers up to the given number", "cases": [ { + "uuid": "e46c542b-31fc-4506-bcae-6b62b3268537", "description": "square of sum 1", "property": "squareOfSum", "input": { @@ -14,6 +14,7 @@ "expected": 1 }, { + "uuid": "9b3f96cb-638d-41ee-99b7-b4f9c0622948", "description": "square of sum 5", "property": "squareOfSum", "input": { @@ -22,6 +23,7 @@ "expected": 225 }, { + "uuid": "54ba043f-3c35-4d43-86ff-3a41625d5e86", "description": "square of sum 100", "property": "squareOfSum", "input": { @@ -35,6 +37,7 @@ "description": "Sum the squares of the numbers up to the given number", "cases": [ { + "uuid": "01d84507-b03e-4238-9395-dd61d03074b5", "description": "sum of squares 1", "property": "sumOfSquares", "input": { @@ -43,6 +46,7 @@ "expected": 1 }, { + "uuid": "c93900cd-8cc2-4ca4-917b-dd3027023499", "description": "sum of squares 5", "property": "sumOfSquares", "input": { @@ -51,6 +55,7 @@ "expected": 55 }, { + "uuid": "94807386-73e4-4d9e-8dec-69eb135b19e4", "description": "sum of squares 100", "property": "sumOfSquares", "input": { @@ -64,6 +69,7 @@ "description": "Subtract sum of squares from square of sums", "cases": [ { + "uuid": "44f72ae6-31a7-437f-858d-2c0837adabb6", "description": "difference of squares 1", "property": "differenceOfSquares", "input": { @@ -72,6 +78,7 @@ "expected": 0 }, { + "uuid": "005cb2bf-a0c8-46f3-ae25-924029f8b00b", "description": "difference of squares 5", "property": "differenceOfSquares", "input": { @@ -80,6 +87,7 @@ "expected": 170 }, { + "uuid": "b1bf19de-9a16-41c0-a62b-1f02ecc0b036", "description": "difference of squares 100", "property": "differenceOfSquares", "input": { @@ -90,4 +98,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/diffie-hellman/canonical-data.json b/exercises/diffie-hellman/canonical-data.json index 806c3523c3..7b56e4566d 100644 --- a/exercises/diffie-hellman/canonical-data.json +++ b/exercises/diffie-hellman/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "diffie-hellman", - "version": "1.0.0", "comments": [ "Optional tests to consider:", "* Validation of parameters:", @@ -17,7 +16,8 @@ ], "cases": [ { - "description": "private key is in range 1 .. p", + "uuid": "1b97bf38-4307-418e-bfd2-446ffc77588d", + "description": "private key is greater than 1 and less than p", "property": "privateKeyIsInRange", "input": {}, "expected": { @@ -26,6 +26,7 @@ } }, { + "uuid": "68b2a5f7-7755-44c3-97b2-d28d21f014a9", "description": "private key is random", "property": "privateKeyIsRandom", "input": {}, @@ -34,6 +35,7 @@ } }, { + "uuid": "b4161d8e-53a1-4241-ae8f-48cc86527f22", "description": "can calculate public key using private key", "property": "publicKey", "input": { @@ -44,6 +46,7 @@ "expected": 8 }, { + "uuid": "cd02ad45-3f52-4510-99cc-5161dad948a8", "description": "can calculate secret using other party's public key", "property": "secret", "input": { @@ -54,6 +57,7 @@ "expected": 2 }, { + "uuid": "17f13c61-a111-4075-9a1f-c2d4636dfa60", "description": "key exchange", "property": "keyExchange", "input": { diff --git a/exercises/dnd-character/canonical-data.json b/exercises/dnd-character/canonical-data.json index 3eccb04711..ef538074e5 100644 --- a/exercises/dnd-character/canonical-data.json +++ b/exercises/dnd-character/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "dnd-character", - "version": "1.1.0", "comments": [ "The random generator 'ability' can be property-tested.", "The pure function 'modifier' can be tested totally.", @@ -23,6 +22,7 @@ "description": "ability modifier", "cases": [ { + "uuid": "1e9ae1dc-35bd-43ba-aa08-e4b94c20fa37", "description": "ability modifier for score 3 is -4", "property": "modifier", "input": { @@ -31,6 +31,7 @@ "expected": -4 }, { + "uuid": "cc9bb24e-56b8-4e9e-989d-a0d1a29ebb9c", "description": "ability modifier for score 4 is -3", "property": "modifier", "input": { @@ -39,6 +40,7 @@ "expected": -3 }, { + "uuid": "5b519fcd-6946-41ee-91fe-34b4f9808326", "description": "ability modifier for score 5 is -3", "property": "modifier", "input": { @@ -47,6 +49,7 @@ "expected": -3 }, { + "uuid": "dc2913bd-6d7a-402e-b1e2-6d568b1cbe21", "description": "ability modifier for score 6 is -2", "property": "modifier", "input": { @@ -55,6 +58,7 @@ "expected": -2 }, { + "uuid": "099440f5-0d66-4b1a-8a10-8f3a03cc499f", "description": "ability modifier for score 7 is -2", "property": "modifier", "input": { @@ -63,6 +67,7 @@ "expected": -2 }, { + "uuid": "cfda6e5c-3489-42f0-b22b-4acb47084df0", "description": "ability modifier for score 8 is -1", "property": "modifier", "input": { @@ -71,6 +76,7 @@ "expected": -1 }, { + "uuid": "c70f0507-fa7e-4228-8463-858bfbba1754", "description": "ability modifier for score 9 is -1", "property": "modifier", "input": { @@ -79,6 +85,7 @@ "expected": -1 }, { + "uuid": "6f4e6c88-1cd9-46a0-92b8-db4a99b372f7", "description": "ability modifier for score 10 is 0", "property": "modifier", "input": { @@ -87,6 +94,7 @@ "expected": 0 }, { + "uuid": "e00d9e5c-63c8-413f-879d-cd9be9697097", "description": "ability modifier for score 11 is 0", "property": "modifier", "input": { @@ -95,6 +103,7 @@ "expected": 0 }, { + "uuid": "eea06f3c-8de0-45e7-9d9d-b8cab4179715", "description": "ability modifier for score 12 is +1", "property": "modifier", "input": { @@ -103,6 +112,7 @@ "expected": 1 }, { + "uuid": "9c51f6be-db72-4af7-92ac-b293a02c0dcd", "description": "ability modifier for score 13 is +1", "property": "modifier", "input": { @@ -111,6 +121,7 @@ "expected": 1 }, { + "uuid": "94053a5d-53b6-4efc-b669-a8b5098f7762", "description": "ability modifier for score 14 is +2", "property": "modifier", "input": { @@ -119,6 +130,7 @@ "expected": 2 }, { + "uuid": "8c33e7ca-3f9f-4820-8ab3-65f2c9e2f0e2", "description": "ability modifier for score 15 is +2", "property": "modifier", "input": { @@ -127,6 +139,7 @@ "expected": 2 }, { + "uuid": "c3ec871e-1791-44d0-b3cc-77e5fb4cd33d", "description": "ability modifier for score 16 is +3", "property": "modifier", "input": { @@ -135,6 +148,7 @@ "expected": 3 }, { + "uuid": "3d053cee-2888-4616-b9fd-602a3b1efff4", "description": "ability modifier for score 17 is +3", "property": "modifier", "input": { @@ -143,6 +157,7 @@ "expected": 3 }, { + "uuid": "bafd997a-e852-4e56-9f65-14b60261faee", "description": "ability modifier for score 18 is +4", "property": "modifier", "input": { @@ -153,12 +168,14 @@ ] }, { + "uuid": "4f28f19c-2e47-4453-a46a-c0d365259c14", "description": "random ability is within range", "property": "ability", "input": {}, "expected": "score >= 3 && score <= 18" }, { + "uuid": "385d7e72-864f-4e88-8279-81a7d75b04ad", "description": "random character is valid", "property": "character", "input": {}, @@ -173,6 +190,7 @@ } }, { + "uuid": "2ca77b9b-c099-46c3-a02c-0d0f68ffa0fe", "description": "each ability is only calculated once", "property": "strength", "input": {}, diff --git a/exercises/dominoes/canonical-data.json b/exercises/dominoes/canonical-data.json index 6943084a68..3b9b74d70e 100644 --- a/exercises/dominoes/canonical-data.json +++ b/exercises/dominoes/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "dominoes", - "version": "2.1.0", "comments": [ "Inputs are given as lists of two-element lists.", "Feel free to convert the input to a sensible type in the specific language", @@ -38,54 +37,61 @@ ], "cases": [ { + "uuid": "31a673f2-5e54-49fe-bd79-1c1dae476c9c", "description": "empty input = empty output", "property": "canChain", - "input": { + "input": { "dominoes": [] }, "expected": true }, { + "uuid": "4f99b933-367b-404b-8c6d-36d5923ee476", "description": "singleton input = singleton output", "property": "canChain", - "input": { + "input": { "dominoes": [[1, 1]] }, "expected": true }, { + "uuid": "91122d10-5ec7-47cb-b759-033756375869", "description": "singleton that can't be chained", "property": "canChain", - "input": { + "input": { "dominoes": [[1, 2]] }, "expected": false }, { + "uuid": "be8bc26b-fd3d-440b-8e9f-d698a0623be3", "description": "three elements", "property": "canChain", - "input": { + "input": { "dominoes": [[1, 2], [3, 1], [2, 3]] }, "expected": true }, { + "uuid": "99e615c6-c059-401c-9e87-ad7af11fea5c", "description": "can reverse dominoes", "property": "canChain", - "input": { + "input": { "dominoes": [[1, 2], [1, 3], [2, 3]] }, "expected": true }, { + "uuid": "51f0c291-5d43-40c5-b316-0429069528c9", "description": "can't be chained", "property": "canChain", - "input": { + "input": { "dominoes": [[1, 2], [4, 1], [2, 3]] }, "expected": false }, { + "uuid": "9a75e078-a025-4c23-8c3a-238553657f39", "description": "disconnected - simple", "comments": [ "This meets the requirement of being possibly-Euclidean.", @@ -95,28 +101,31 @@ "as that is not a sufficient condition." ], "property": "canChain", - "input": { + "input": { "dominoes": [[1, 1], [2, 2]] }, "expected": false }, { + "uuid": "0da0c7fe-d492-445d-b9ef-1f111f07a301", "description": "disconnected - double loop", "property": "canChain", - "input": { + "input": { "dominoes": [[1, 2], [2, 1], [3, 4], [4, 3]] }, "expected": false }, { + "uuid": "b6087ff0-f555-4ea0-a71c-f9d707c5994a", "description": "disconnected - single isolated", "property": "canChain", - "input": { + "input": { "dominoes": [[1, 2], [2, 3], [3, 1], [4, 4]] }, "expected": false }, { + "uuid": "2174fbdc-8b48-4bac-9914-8090d06ef978", "description": "need backtrack", "comments": [ "Some solutions may make a chain out of (1, 2), (2, 3), (3, 1)", @@ -132,6 +141,7 @@ "expected": true }, { + "uuid": "167bb480-dfd1-4318-a20d-4f90adb4a09f", "description": "separate loops", "property": "canChain", "input": { @@ -140,6 +150,7 @@ "expected": true }, { + "uuid": "cd061538-6046-45a7-ace9-6708fe8f6504", "description": "nine elements", "property": "canChain", "input": { diff --git a/exercises/dot-dsl/description.md b/exercises/dot-dsl/description.md index ee9eb66cfb..2b05590bab 100644 --- a/exercises/dot-dsl/description.md +++ b/exercises/dot-dsl/description.md @@ -1,7 +1,7 @@ A [Domain Specific Language (DSL)](https://en.wikipedia.org/wiki/Domain-specific_language) is a -small language optimized for a specific domain. Since a DSL is -targeted, it can greatly impact productivity/understanding by allowing the +small language optimized for a specific domain. Since a DSL is +targeted, it can greatly impact productivity/understanding by allowing the writer to declare *what* they want rather than *how*. One problem area where they are applied are complex customizations/configurations. @@ -25,7 +25,7 @@ Write a Domain Specific Language similar to the Graphviz dot language. Our DSL is similar to the Graphviz dot language in that our DSL will be used to create graph data structures. However, unlike the DOT Language, our DSL will -be an internal DSL for use only in our language. +be an internal DSL for use only in our language. More information about the difference between internal and external DSLs can be found [here](https://martinfowler.com/bliki/DomainSpecificLanguage.html). diff --git a/exercises/etl/canonical-data.json b/exercises/etl/canonical-data.json index 66f96b1a60..4931fa1f79 100644 --- a/exercises/etl/canonical-data.json +++ b/exercises/etl/canonical-data.json @@ -1,10 +1,9 @@ { "exercise": "etl", - "version": "2.0.0", "cases": [ { "comments": [ - "Transforms a set of legacy scrabble data stored as letters per score", + "Transforms a set of legacy Scrabble data stored as letters per score", "to a set of data stored score per letter.", "Note: The expected input data for these tests should have", "integer keys (not stringified numbers as shown in the JSON below", @@ -15,11 +14,12 @@ "description": "Transform legacy to new", "cases": [ { + "uuid": "78a7a9f9-4490-4a47-8ee9-5a38bb47d28f", "description": "single letter", "property": "transform", "input": { - "legacy": { - "1": ["A"] + "legacy": { + "1": ["A"] } }, "expected": { @@ -27,10 +27,11 @@ } }, { + "uuid": "60dbd000-451d-44c7-bdbb-97c73ac1f497", "description": "single score with multiple letters", "property": "transform", "input": { - "legacy": { + "legacy": { "1": ["A", "E", "I", "O", "U"] } }, @@ -43,10 +44,11 @@ } }, { + "uuid": "f5c5de0c-301f-4fdd-a0e5-df97d4214f54", "description": "multiple scores with multiple letters", "property": "transform", "input": { - "legacy": { + "legacy": { "1": ["A", "E"], "2": ["D", "G"] } @@ -59,10 +61,11 @@ } }, { + "uuid": "5db8ea89-ecb4-4dcd-902f-2b418cc87b9d", "description": "multiple scores with differing numbers of letters", "property": "transform", "input": { - "legacy": { + "legacy": { "1": ["A", "E", "I", "O", "U", "L", "N", "R", "S", "T"], "2": ["D", "G"], "3": ["B", "C", "M", "P"], diff --git a/exercises/etl/description.md b/exercises/etl/description.md index d210b9251b..a4a3098b00 100644 --- a/exercises/etl/description.md +++ b/exercises/etl/description.md @@ -11,7 +11,7 @@ moaning about how stupid we could possibly be.) ### The goal -We're going to extract some scrabble scores from a legacy system. +We're going to extract some Scrabble scores from a legacy system. The old system stored a list of letters per score: @@ -23,7 +23,7 @@ The old system stored a list of letters per score: - 8 points: "J", "X", - 10 points: "Q", "Z", -The shiny new scrabble system instead stores the score per letter, which +The shiny new Scrabble system instead stores the score per letter, which makes it much faster and easier to calculate the score for a word. It also stores the letters in lower-case regardless of the case of the input letters: diff --git a/exercises/flatten-array/canonical-data.json b/exercises/flatten-array/canonical-data.json index a7a625073d..4c94067adb 100644 --- a/exercises/flatten-array/canonical-data.json +++ b/exercises/flatten-array/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "flatten-array", - "version": "1.2.0", "cases": [ { + "uuid": "d268b919-963c-442d-9f07-82b93f1b518c", "description": "no nesting", "property": "flatten", "input": { @@ -11,6 +11,7 @@ "expected": [0, 1, 2] }, { + "uuid": "c84440cc-bb3a-48a6-862c-94cf23f2815d", "description": "flattens array with just integers present", "property": "flatten", "input": { @@ -19,6 +20,7 @@ "expected": [1, 2, 3, 4, 5, 6, 7, 8] }, { + "uuid": "d3d99d39-6be5-44f5-a31d-6037d92ba34f", "description": "5 level nesting", "property": "flatten", "input": { @@ -27,6 +29,7 @@ "expected": [0, 2, 2, 3, 8, 100, 4, 50, -2] }, { + "uuid": "d572bdba-c127-43ed-bdcd-6222ac83d9f7", "description": "6 level nesting", "property": "flatten", "input": { @@ -35,6 +38,7 @@ "expected": [1, 2, 3, 4, 5, 6, 7, 8] }, { + "uuid": "ef1d4790-1b1e-4939-a179-51ace0829dbd", "description": "6 level nest list with null values", "property": "flatten", "input": { @@ -43,6 +47,7 @@ "expected": [0, 2, 2, 3, 8, 100, -2] }, { + "uuid": "85721643-705a-4150-93ab-7ae398e2942d", "description": "all values in nested list are null", "property": "flatten", "input": { diff --git a/exercises/food-chain/canonical-data.json b/exercises/food-chain/canonical-data.json index e9a4a31ef2..0b923fa6e8 100644 --- a/exercises/food-chain/canonical-data.json +++ b/exercises/food-chain/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "food-chain", - "version": "2.1.0", "comments": [ "JSON doesn't allow for multi-line strings, so all verses are presented ", "here as arrays of strings. It's up to the test generator to join the ", @@ -16,6 +15,7 @@ "description": "Return specified verse or series of verses", "cases": [ { + "uuid": "751dce68-9412-496e-b6e8-855998c56166", "description": "fly", "property": "recite", "input": { @@ -28,6 +28,7 @@ ] }, { + "uuid": "6c56f861-0c5e-4907-9a9d-b2efae389379", "description": "spider", "property": "recite", "input": { @@ -42,6 +43,7 @@ ] }, { + "uuid": "3edf5f33-bef1-4e39-ae67-ca5eb79203fa", "description": "bird", "property": "recite", "input": { @@ -57,6 +59,7 @@ ] }, { + "uuid": "e866a758-e1ff-400e-9f35-f27f28cc288f", "description": "cat", "property": "recite", "input": { @@ -73,6 +76,7 @@ ] }, { + "uuid": "3f02c30e-496b-4b2a-8491-bc7e2953cafb", "description": "dog", "property": "recite", "input": { @@ -90,6 +94,7 @@ ] }, { + "uuid": "4b3fd221-01ea-46e0-825b-5734634fbc59", "description": "goat", "property": "recite", "input": { @@ -108,6 +113,7 @@ ] }, { + "uuid": "1b707da9-7001-4fac-941f-22ad9c7a65d4", "description": "cow", "property": "recite", "input": { @@ -127,6 +133,7 @@ ] }, { + "uuid": "3cb10d46-ae4e-4d2c-9296-83c9ffc04cdc", "description": "horse", "property": "recite", "input": { @@ -139,6 +146,7 @@ ] }, { + "uuid": "22b863d5-17e4-4d1e-93e4-617329a5c050", "description": "multiple verses", "property": "recite", "input": { @@ -162,6 +170,7 @@ ] }, { + "uuid": "e626b32b-745c-4101-bcbd-3b13456893db", "description": "full song", "property": "recite", "input": { @@ -224,4 +233,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/forth/canonical-data.json b/exercises/forth/canonical-data.json index 985ec286b6..a9f1c3c3ce 100644 --- a/exercises/forth/canonical-data.json +++ b/exercises/forth/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "forth", - "version": "1.7.1", "comments": [ "The cases are split into multiple sections, all with the same structure.", "In all cases, the `expected` key is the resulting stack", @@ -11,6 +10,7 @@ "description": "parsing and numbers", "cases": [ { + "uuid": "9962203f-f00a-4a85-b404-8a8ecbcec09d", "description": "numbers just get pushed onto the stack", "property": "evaluate", "input": { @@ -24,6 +24,7 @@ "description": "addition", "cases": [ { + "uuid": "9e69588e-a3d8-41a3-a371-ea02206c1e6e", "description": "can add two numbers", "property": "evaluate", "input": { @@ -32,6 +33,7 @@ "expected": [3] }, { + "uuid": "52336dd3-30da-4e5c-8523-bdf9a3427657", "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { @@ -40,6 +42,7 @@ "expected": {"error": "empty stack"} }, { + "uuid": "06efb9a4-817a-435e-b509-06166993c1b8", "description": "errors if there is only one value on the stack", "property": "evaluate", "input": { @@ -53,6 +56,7 @@ "description": "subtraction", "cases": [ { + "uuid": "09687c99-7bbc-44af-8526-e402f997ccbf", "description": "can subtract two numbers", "property": "evaluate", "input": { @@ -61,6 +65,7 @@ "expected": [-1] }, { + "uuid": "5d63eee2-1f7d-4538-b475-e27682ab8032", "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { @@ -69,6 +74,7 @@ "expected": {"error": "empty stack"} }, { + "uuid": "b3cee1b2-9159-418a-b00d-a1bb3765c23b", "description": "errors if there is only one value on the stack", "property": "evaluate", "input": { @@ -82,6 +88,7 @@ "description": "multiplication", "cases": [ { + "uuid": "5df0ceb5-922e-401f-974d-8287427dbf21", "description": "can multiply two numbers", "property": "evaluate", "input": { @@ -90,6 +97,7 @@ "expected": [8] }, { + "uuid": "9e004339-15ac-4063-8ec1-5720f4e75046", "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { @@ -98,6 +106,7 @@ "expected": {"error": "empty stack"} }, { + "uuid": "8ba4b432-9f94-41e0-8fae-3b3712bd51b3", "description": "errors if there is only one value on the stack", "property": "evaluate", "input": { @@ -111,6 +120,7 @@ "description": "division", "cases": [ { + "uuid": "e74c2204-b057-4cff-9aa9-31c7c97a93f5", "description": "can divide two numbers", "property": "evaluate", "input": { @@ -119,6 +129,7 @@ "expected": [4] }, { + "uuid": "54f6711c-4b14-4bb0-98ad-d974a22c4620", "description": "performs integer division", "property": "evaluate", "input": { @@ -127,6 +138,7 @@ "expected": [2] }, { + "uuid": "a5df3219-29b4-4d2f-b427-81f82f42a3f1", "description": "errors if dividing by zero", "property": "evaluate", "input": { @@ -135,6 +147,7 @@ "expected": {"error": "divide by zero"} }, { + "uuid": "1d5bb6b3-6749-4e02-8a79-b5d4d334cb8a", "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { @@ -143,6 +156,7 @@ "expected": {"error": "empty stack"} }, { + "uuid": "d5547f43-c2ff-4d5c-9cb0-2a4f6684c20d", "description": "errors if there is only one value on the stack", "property": "evaluate", "input": { @@ -156,6 +170,7 @@ "description": "combined arithmetic", "cases": [ { + "uuid": "ee28d729-6692-4a30-b9be-0d830c52a68c", "description": "addition and subtraction", "property": "evaluate", "input": { @@ -164,6 +179,7 @@ "expected": [-1] }, { + "uuid": "40b197da-fa4b-4aca-a50b-f000d19422c1", "description": "multiplication and division", "property": "evaluate", "input": { @@ -177,6 +193,7 @@ "description": "dup", "cases": [ { + "uuid": "c5758235-6eef-4bf6-ab62-c878e50b9957", "description": "copies a value on the stack", "property": "evaluate", "input": { @@ -185,6 +202,7 @@ "expected": [1, 1] }, { + "uuid": "f6889006-5a40-41e7-beb3-43b09e5a22f4", "description": "copies the top value on the stack", "property": "evaluate", "input": { @@ -193,6 +211,7 @@ "expected": [1, 2, 2] }, { + "uuid": "40b7569c-8401-4bd4-a30d-9adf70d11bc4", "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { @@ -206,6 +225,7 @@ "description": "drop", "cases": [ { + "uuid": "1971da68-1df2-4569-927a-72bf5bb7263c", "description": "removes the top value on the stack if it is the only one", "property": "evaluate", "input": { @@ -214,6 +234,7 @@ "expected": [] }, { + "uuid": "8929d9f2-4a78-4e0f-90ad-be1a0f313fd9", "description": "removes the top value on the stack if it is not the only one", "property": "evaluate", "input": { @@ -222,6 +243,7 @@ "expected": [1] }, { + "uuid": "6dd31873-6dd7-4cb8-9e90-7daa33ba045c", "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { @@ -235,6 +257,7 @@ "description": "swap", "cases": [ { + "uuid": "3ee68e62-f98a-4cce-9e6c-8aae6c65a4e3", "description": "swaps the top two values on the stack if they are the only ones", "property": "evaluate", "input": { @@ -243,6 +266,7 @@ "expected": [2, 1] }, { + "uuid": "8ce869d5-a503-44e4-ab55-1da36816ff1c", "description": "swaps the top two values on the stack if they are not the only ones", "property": "evaluate", "input": { @@ -251,6 +275,7 @@ "expected": [1, 3, 2] }, { + "uuid": "74ba5b2a-b028-4759-9176-c5c0e7b2b154", "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { @@ -259,6 +284,7 @@ "expected": {"error": "empty stack"} }, { + "uuid": "dd52e154-5d0d-4a5c-9e5d-73eb36052bc8", "description": "errors if there is only one value on the stack", "property": "evaluate", "input": { @@ -272,6 +298,7 @@ "description": "over", "cases": [ { + "uuid": "a2654074-ba68-4f93-b014-6b12693a8b50", "description": "copies the second element if there are only two", "property": "evaluate", "input": { @@ -280,6 +307,7 @@ "expected": [1, 2, 1] }, { + "uuid": "c5b51097-741a-4da7-8736-5c93fa856339", "description": "copies the second element if there are more than two", "property": "evaluate", "input": { @@ -288,6 +316,7 @@ "expected": [1, 2, 3, 2] }, { + "uuid": "6e1703a6-5963-4a03-abba-02e77e3181fd", "description": "errors if there is nothing on the stack", "property": "evaluate", "input": { @@ -296,6 +325,7 @@ "expected": {"error": "empty stack"} }, { + "uuid": "ee574dc4-ef71-46f6-8c6a-b4af3a10c45f", "description": "errors if there is only one value on the stack", "property": "evaluate", "input": { @@ -309,6 +339,7 @@ "description": "user-defined words", "cases": [ { + "uuid": "ed45cbbf-4dbf-4901-825b-54b20dbee53b", "description": "can consist of built-in words", "property": "evaluate", "input": { @@ -320,6 +351,7 @@ "expected": [1, 1, 1] }, { + "uuid": "2726ea44-73e4-436b-bc2b-5ff0c6aa014b", "description": "execute in the right order", "property": "evaluate", "input": { @@ -331,6 +363,7 @@ "expected": [1, 2, 3] }, { + "uuid": "9e53c2d0-b8ef-4ad8-b2c9-a559b421eb33", "description": "can override other user-defined words", "property": "evaluate", "input": { @@ -343,6 +376,7 @@ "expected": [1, 1, 1] }, { + "uuid": "669db3f3-5bd6-4be0-83d1-618cd6e4984b", "description": "can override built-in words", "property": "evaluate", "input": { @@ -354,6 +388,7 @@ "expected": [1, 1] }, { + "uuid": "588de2f0-c56e-4c68-be0b-0bb1e603c500", "description": "can override built-in operators", "property": "evaluate", "input": { @@ -365,6 +400,7 @@ "expected": [12] }, { + "uuid": "ac12aaaf-26c6-4a10-8b3c-1c958fa2914c", "description": "can use different words with the same name", "property": "evaluate", "input": { @@ -378,6 +414,7 @@ "expected": [5, 6] }, { + "uuid": "53f82ef0-2750-4ccb-ac04-5d8c1aefabb1", "description": "can define word that uses word with the same name", "property": "evaluate", "input": { @@ -390,6 +427,7 @@ "expected": [11] }, { + "uuid": "35958cee-a976-4a0f-9378-f678518fa322", "description": "cannot redefine numbers", "property": "evaluate", "input": { @@ -398,6 +436,7 @@ "expected": {"error": "illegal operation"} }, { + "uuid": "5180f261-89dd-491e-b230-62737e09806f", "description": "errors if executing a non-existent word", "property": "evaluate", "input": { @@ -411,6 +450,7 @@ "description": "case-insensitivity", "cases": [ { + "uuid": "7b83bb2e-b0e8-461f-ad3b-96ee2e111ed6", "description": "DUP is case-insensitive", "property": "evaluate", "input": { @@ -419,6 +459,7 @@ "expected": [1, 1, 1, 1] }, { + "uuid": "339ed30b-f5b4-47ff-ab1c-67591a9cd336", "description": "DROP is case-insensitive", "property": "evaluate", "input": { @@ -427,6 +468,7 @@ "expected": [1] }, { + "uuid": "ee1af31e-1355-4b1b-bb95-f9d0b2961b87", "description": "SWAP is case-insensitive", "property": "evaluate", "input": { @@ -435,6 +477,7 @@ "expected": [2, 3, 4, 1] }, { + "uuid": "acdc3a49-14c8-4cc2-945d-11edee6408fa", "description": "OVER is case-insensitive", "property": "evaluate", "input": { @@ -443,6 +486,7 @@ "expected": [1, 2, 1, 2, 1] }, { + "uuid": "5934454f-a24f-4efc-9fdd-5794e5f0c23c", "description": "user-defined words are case-insensitive", "property": "evaluate", "input": { @@ -454,6 +498,7 @@ "expected": [1, 1, 1, 1] }, { + "uuid": "037d4299-195f-4be7-a46d-f07ca6280a06", "description": "definitions are case-insensitive", "property": "evaluate", "input": { diff --git a/exercises/gigasecond/canonical-data.json b/exercises/gigasecond/canonical-data.json index 86691953c6..341aa36cac 100644 --- a/exercises/gigasecond/canonical-data.json +++ b/exercises/gigasecond/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "gigasecond", - "version": "2.0.0", "comments": [ "The basic test is to add one gigasecond to a few ordinary dates.", "Most test programs currently check only the date and ignore the time.", @@ -20,6 +19,7 @@ "description": "Add one gigasecond to the input.", "cases": [ { + "uuid": "92fbe71c-ea52-4fac-bd77-be38023cacf7", "description": "date only specification of time", "property": "add", "input": { @@ -28,6 +28,7 @@ "expected": "2043-01-01T01:46:40" }, { + "uuid": "6d86dd16-6f7a-47be-9e58-bb9fb2ae1433", "description": "second test for date only specification of time", "property": "add", "input": { @@ -36,6 +37,7 @@ "expected": "2009-02-19T01:46:40" }, { + "uuid": "77eb8502-2bca-4d92-89d9-7b39ace28dd5", "description": "third test for date only specification of time", "property": "add", "input": { @@ -44,6 +46,7 @@ "expected": "1991-03-27T01:46:40" }, { + "uuid": "c9d89a7d-06f8-4e28-a305-64f1b2abc693", "description": "full time specified", "property": "add", "input": { @@ -52,6 +55,7 @@ "expected": "2046-10-02T23:46:40" }, { + "uuid": "09d4e30e-728a-4b52-9005-be44a58d9eba", "description": "full time with day roll-over", "property": "add", "input": { @@ -62,4 +66,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/gigasecond/metadata.yml b/exercises/gigasecond/metadata.yml index 7be1db3161..8a78096965 100644 --- a/exercises/gigasecond/metadata.yml +++ b/exercises/gigasecond/metadata.yml @@ -1,4 +1,4 @@ ---- -blurb: "Given a moment, determine the moment that would be after a gigasecond has passed." -source: "Chapter 9 in Chris Pine's online Learn to Program tutorial." -source_url: "http://pine.fm/LearnToProgram/?Chapter=09" +--- +blurb: "Given a moment, determine the moment that would be after a gigasecond has passed." +source: "Chapter 9 in Chris Pine's online Learn to Program tutorial." +source_url: "http://pine.fm/LearnToProgram/?Chapter=09" diff --git a/exercises/go-counting/canonical-data.json b/exercises/go-counting/canonical-data.json index a2e0efd7c0..87fb4ada90 100644 --- a/exercises/go-counting/canonical-data.json +++ b/exercises/go-counting/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "go-counting", - "version": "1.0.0", "comments": [ "Territory consists of [x, y] coordinate pairs." ], "cases": [ { + "uuid": "94d0c01a-17d0-424c-aab5-2736d0da3939", "description": "Black corner territory on 5x5 board", "property": "territory", "input": { @@ -25,6 +25,7 @@ } }, { + "uuid": "b33bec54-356a-485c-9c71-1142a9403213", "description": "White center territory on 5x5 board", "property": "territory", "input": { @@ -44,6 +45,7 @@ } }, { + "uuid": "def7d124-422e-44ae-90e5-ceda09399bda", "description": "Open corner territory on 5x5 board", "property": "territory", "input": { @@ -63,6 +65,7 @@ } }, { + "uuid": "57d79036-2618-47f4-aa87-56c06d362e3d", "description": "A stone and not a territory on 5x5 board", "property": "territory", "input": { @@ -82,6 +85,7 @@ } }, { + "uuid": "0c84f852-e032-4762-9010-99f6a001da96", "description": "Invalid because X is too low for 5x5 board", "property": "territory", "input": { @@ -100,6 +104,7 @@ } }, { + "uuid": "6f867945-9b2c-4bdd-b23e-b55fe2069a68", "description": "Invalid because X is too high for 5x5 board", "property": "territory", "input": { @@ -118,6 +123,7 @@ } }, { + "uuid": "d67aaffd-fdf1-4e7f-b9e9-79897402b64a", "description": "Invalid because Y is too low for 5x5 board", "property": "territory", "input": { @@ -136,6 +142,7 @@ } }, { + "uuid": "14f23c25-799e-4371-b3e5-777a2c30357a", "description": "Invalid because Y is too high for 5x5 board", "property": "territory", "input": { @@ -154,6 +161,7 @@ } }, { + "uuid": "37fb04b5-98c1-4b96-8c16-af2d13624afd", "description": "One territory is the whole board", "property": "territories", "input": { @@ -168,6 +176,7 @@ } }, { + "uuid": "9a1c59b7-234b-495a-8d60-638489f0fc0a", "description": "Two territory rectangular board", "property": "territories", "input": { @@ -183,6 +192,7 @@ } }, { + "uuid": "d1645953-1cd5-4221-af6f-8164f96249e1", "description": "Two region rectangular board", "property": "territories", "input": { diff --git a/exercises/grade-school/canonical-data.json b/exercises/grade-school/canonical-data.json index 6c0544abf5..51210d8330 100644 --- a/exercises/grade-school/canonical-data.json +++ b/exercises/grade-school/canonical-data.json @@ -1,12 +1,12 @@ { "exercise": "grade-school", - "version": "1.0.0", "comments": [ "Given students' names along with the grade that they are in, ", "create a roster for the school." ], "cases": [ { + "uuid": "6d0a30e4-1b4e-472e-8e20-c41702125667", "description": "Adding a student adds them to the sorted roster", "property": "roster", "input": { @@ -15,7 +15,21 @@ "expected": ["Aimee"] }, { - "description": "Adding more student adds them to the sorted roster", + "uuid": "c125dab7-2a53-492f-a99a-56ad511940d8", + "description": "A student can't be in two different grades", + "property": "roster", + "input": { + "students": [ + ["Aimee", 2], + ["Aimee", 1] + ], + "desiredGrade": 2 + }, + "expected": [] + }, + { + "uuid": "233be705-dd58-4968-889d-fb3c7954c9cc", + "description": "Adding more students adds them to the sorted roster", "property": "roster", "input": { "students": [["Blair", 2], ["James", 2], ["Paul", 2]] @@ -23,6 +37,7 @@ "expected": ["Blair", "James", "Paul"] }, { + "uuid": "75a51579-d1d7-407c-a2f8-2166e984e8ab", "description": "Adding students to different grades adds them to the same sorted roster", "property": "roster", "input": { @@ -31,6 +46,7 @@ "expected": ["Chelsea", "Logan"] }, { + "uuid": "a3f0fb58-f240-4723-8ddc-e644666b85cc", "description": "Roster returns an empty list if there are no students enrolled", "property": "roster", "input": { @@ -39,6 +55,7 @@ "expected": [] }, { + "uuid": "180a8ff9-5b94-43fc-9db1-d46b4a8c93b6", "description": "Student names with grades are displayed in the same sorted roster", "property": "roster", "input": { @@ -47,6 +64,7 @@ "expected": ["Anna", "Barb", "Charlie", "Alex", "Peter", "Zoe", "Jim"] }, { + "uuid": "1bfbcef1-e4a3-49e8-8d22-f6f9f386187e", "description": "Grade returns the students in that grade in alphabetical order", "property": "grade", "input": { @@ -56,6 +74,7 @@ "expected": ["Bradley", "Franklin"] }, { + "uuid": "5e67aa3c-a3c6-4407-a183-d8fe59cd1630", "description": "Grade returns an empty list if there are no students in that grade", "property": "grade", "input": { diff --git a/exercises/grade-school/description.md b/exercises/grade-school/description.md index 497eadb154..42f345ce70 100644 --- a/exercises/grade-school/description.md +++ b/exercises/grade-school/description.md @@ -13,8 +13,11 @@ In the end, you should be able to: as 1, 2, 3, etc., and students within a grade should be sorted alphabetically by name. - "Who all is enrolled in school right now?" - - "Grade 1: Anna, Barb, and Charlie. Grade 2: Alex, Peter, and Zoe. - Grade 3…" + - "Let me think. We have + Anna, Barb, and Charlie in grade 1, + Alex, Peter, and Zoe in grade 2 + and Jim in grade 5. + So the answer is: Anna, Barb, Charlie, Alex, Peter, Zoe and Jim" Note that all our students only have one name. (It's a small town, what do you want?) diff --git a/exercises/grains/canonical-data.json b/exercises/grains/canonical-data.json index d78a303e50..3ed6de75a2 100644 --- a/exercises/grains/canonical-data.json +++ b/exercises/grains/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "grains", - "version": "1.2.0", "comments": [ "The final tests of square test error conditions", "In these cases you should expect an error as is idiomatic for your language" @@ -10,7 +9,8 @@ "description": "returns the number of grains on the square", "cases": [ { - "description": "1", + "uuid": "9fbde8de-36b2-49de-baf2-cd42d6f28405", + "description": "grains on square 1", "property": "square", "input": { "square": 1 @@ -18,7 +18,8 @@ "expected": 1 }, { - "description": "2", + "uuid": "ee1f30c2-01d8-4298-b25d-c677331b5e6d", + "description": "grains on square 2", "property": "square", "input": { "square": 2 @@ -26,7 +27,8 @@ "expected": 2 }, { - "description": "3", + "uuid": "10f45584-2fc3-4875-8ec6-666065d1163b", + "description": "grains on square 3", "property": "square", "input": { "square": 3 @@ -34,7 +36,8 @@ "expected": 4 }, { - "description": "4", + "uuid": "a7cbe01b-36f4-4601-b053-c5f6ae055170", + "description": "grains on square 4", "property": "square", "input": { "square": 4 @@ -42,7 +45,8 @@ "expected": 8 }, { - "description": "16", + "uuid": "c50acc89-8535-44e4-918f-b848ad2817d4", + "description": "grains on square 16", "property": "square", "input": { "square": 16 @@ -50,7 +54,8 @@ "expected": 32768 }, { - "description": "32", + "uuid": "acd81b46-c2ad-4951-b848-80d15ed5a04f", + "description": "grains on square 32", "property": "square", "input": { "square": 32 @@ -58,7 +63,8 @@ "expected": 2147483648 }, { - "description": "64", + "uuid": "c73b470a-5efb-4d53-9ac6-c5f6487f227b", + "description": "grains on square 64", "property": "square", "input": { "square": 64 @@ -66,6 +72,7 @@ "expected": 9223372036854775808 }, { + "uuid": "1d47d832-3e85-4974-9466-5bd35af484e3", "description": "square 0 raises an exception", "property": "square", "input": { @@ -74,6 +81,7 @@ "expected": {"error": "square must be between 1 and 64"} }, { + "uuid": "61974483-eeb2-465e-be54-ca5dde366453", "description": "negative square raises an exception", "property": "square", "input": { @@ -82,6 +90,7 @@ "expected": {"error": "square must be between 1 and 64"} }, { + "uuid": "a95e4374-f32c-45a7-a10d-ffec475c012f", "description": "square greater than 64 raises an exception", "property": "square", "input": { @@ -92,6 +101,7 @@ ] }, { + "uuid": "6eb07385-3659-4b45-a6be-9dc474222750", "description": "returns the total number of grains on the board", "property": "total", "input": {}, diff --git a/exercises/grep/canonical-data.json b/exercises/grep/canonical-data.json index 3baaff19fd..dfa1a21dd7 100644 --- a/exercises/grep/canonical-data.json +++ b/exercises/grep/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "grep", - "version": "1.2.0", "comments": [ " JSON doesn't allow for multi-line strings, so all ", " outputs are presented here as arrays of strings. ", @@ -57,6 +56,7 @@ "description": "Test grepping a single file", "cases": [ { + "uuid": "9049fdfd-53a7-4480-a390-375203837d09", "description": "One file, one match, no flags", "property": "grep", "input": { @@ -69,6 +69,7 @@ ] }, { + "uuid": "76519cce-98e3-46cd-b287-aac31b1d77d6", "description": "One file, one match, print line numbers flag", "property": "grep", "input": { @@ -81,6 +82,7 @@ ] }, { + "uuid": "af0b6d3c-e0e8-475e-a112-c0fc10a1eb30", "description": "One file, one match, case-insensitive flag", "property": "grep", "input": { @@ -93,6 +95,7 @@ ] }, { + "uuid": "ff7af839-d1b8-4856-a53e-99283579b672", "description": "One file, one match, print file names flag", "property": "grep", "input": { @@ -105,6 +108,7 @@ ] }, { + "uuid": "8625238a-720c-4a16-81f2-924ec8e222cb", "description": "One file, one match, match entire lines flag", "property": "grep", "input": { @@ -117,6 +121,7 @@ ] }, { + "uuid": "2a6266b3-a60f-475c-a5f5-f5008a717d3e", "description": "One file, one match, multiple flags", "property": "grep", "input": { @@ -129,6 +134,7 @@ ] }, { + "uuid": "842222da-32e8-4646-89df-0d38220f77a1", "description": "One file, several matches, no flags", "property": "grep", "input": { @@ -143,6 +149,7 @@ ] }, { + "uuid": "4d84f45f-a1d8-4c2e-a00e-0b292233828c", "description": "One file, several matches, print line numbers flag", "property": "grep", "input": { @@ -157,6 +164,7 @@ ] }, { + "uuid": "0a483b66-315b-45f5-bc85-3ce353a22539", "description": "One file, several matches, match entire lines flag", "property": "grep", "input": { @@ -167,6 +175,7 @@ "expected": [] }, { + "uuid": "3d2ca86a-edd7-494c-8938-8eeed1c61cfa", "description": "One file, several matches, case-insensitive flag", "property": "grep", "input": { @@ -180,6 +189,7 @@ ] }, { + "uuid": "1f52001f-f224-4521-9456-11120cad4432", "description": "One file, several matches, inverted flag", "property": "grep", "input": { @@ -196,6 +206,7 @@ ] }, { + "uuid": "7a6ede7f-7dd5-4364-8bf8-0697c53a09fe", "description": "One file, no matches, various flags", "property": "grep", "input": { @@ -206,6 +217,7 @@ "expected": [] }, { + "uuid": "3d3dfc23-8f2a-4e34-abd6-7b7d140291dc", "description": "One file, one match, file flag takes precedence over line flag", "property": "grep", "input": { @@ -218,6 +230,7 @@ ] }, { + "uuid": "87b21b24-b788-4d6e-a68b-7afe9ca141fe", "description": "One file, several matches, inverted and match entire lines flags", "property": "grep", "input": { @@ -242,6 +255,7 @@ "description": "Test grepping multiples files at once", "cases": [ { + "uuid": "ba496a23-6149-41c6-a027-28064ed533e5", "description": "Multiple files, one match, no flags", "property": "grep", "input": { @@ -254,6 +268,7 @@ ] }, { + "uuid": "4539bd36-6daa-4bc3-8e45-051f69f5aa95", "description": "Multiple files, several matches, no flags", "property": "grep", "input": { @@ -268,6 +283,7 @@ ] }, { + "uuid": "9fb4cc67-78e2-4761-8e6b-a4b57aba1938", "description": "Multiple files, several matches, print line numbers flag", "property": "grep", "input": { @@ -283,6 +299,7 @@ ] }, { + "uuid": "aeee1ef3-93c7-4cd5-af10-876f8c9ccc73", "description": "Multiple files, one match, print file names flag", "property": "grep", "input": { @@ -296,6 +313,7 @@ ] }, { + "uuid": "d69f3606-7d15-4ddf-89ae-01df198e6b6c", "description": "Multiple files, several matches, case-insensitive flag", "property": "grep", "input": { @@ -317,6 +335,7 @@ ] }, { + "uuid": "82ef739d-6701-4086-b911-007d1a3deb21", "description": "Multiple files, several matches, inverted flag", "property": "grep", "input": { @@ -331,6 +350,7 @@ ] }, { + "uuid": "77b2eb07-2921-4ea0-8971-7636b44f5d29", "description": "Multiple files, one match, match entire lines flag", "property": "grep", "input": { @@ -343,6 +363,7 @@ ] }, { + "uuid": "e53a2842-55bb-4078-9bb5-04ac38929989", "description": "Multiple files, one match, multiple flags", "property": "grep", "input": { @@ -355,6 +376,7 @@ ] }, { + "uuid": "9c4f7f9a-a555-4e32-bb06-4b8f8869b2cb", "description": "Multiple files, no matches, various flags", "property": "grep", "input": { @@ -365,6 +387,7 @@ "expected": [] }, { + "uuid": "ba5a540d-bffd-481b-bd0c-d9a30f225e01", "description": "Multiple files, several matches, file flag takes precedence over line number flag", "property": "grep", "input": { @@ -378,6 +401,7 @@ ] }, { + "uuid": "ff406330-2f0b-4b17-9ee4-4b71c31dd6d2", "description": "Multiple files, several matches, inverted and match entire lines flags", "property": "grep", "input": { diff --git a/exercises/hamming/canonical-data.json b/exercises/hamming/canonical-data.json index 3e78807457..b5c09b1f13 100644 --- a/exercises/hamming/canonical-data.json +++ b/exercises/hamming/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "hamming", -"version": "2.3.0", "comments": [ "Language implementations vary on the issue of unequal length strands.", "A language may elect to simplify this task by only presenting equal", @@ -12,6 +11,7 @@ ], "cases": [ { + "uuid": "f6dcb64f-03b0-4b60-81b1-3c9dbf47e887", "description": "empty strands", "property": "distance", "input": { @@ -21,6 +21,7 @@ "expected": 0 }, { + "uuid": "54681314-eee2-439a-9db0-b0636c656156", "description": "single letter identical strands", "property": "distance", "input": { @@ -30,6 +31,7 @@ "expected": 0 }, { + "uuid": "294479a3-a4c8-478f-8d63-6209815a827b", "description": "single letter different strands", "property": "distance", "input": { @@ -39,6 +41,7 @@ "expected": 1 }, { + "uuid": "9aed5f34-5693-4344-9b31-40c692fb5592", "description": "long identical strands", "property": "distance", "input": { @@ -48,6 +51,7 @@ "expected": 0 }, { + "uuid": "cd2273a5-c576-46c8-a52b-dee251c3e6e5", "description": "long different strands", "property": "distance", "input": { @@ -57,6 +61,7 @@ "expected": 9 }, { + "uuid": "919f8ef0-b767-4d1b-8516-6379d07fcb28", "description": "disallow first strand longer", "property": "distance", "input": { @@ -66,6 +71,7 @@ "expected": {"error": "left and right strands must be of equal length"} }, { + "uuid": "8a2d4ed0-ead5-4fdd-924d-27c4cf56e60e", "description": "disallow second strand longer", "property": "distance", "input": { @@ -75,6 +81,7 @@ "expected": {"error": "left and right strands must be of equal length"} }, { + "uuid": "5dce058b-28d4-4ca7-aa64-adfe4e17784c", "description": "disallow left empty strand", "property": "distance", "input": { @@ -84,6 +91,19 @@ "expected": {"error": "left strand must not be empty"} }, { + "uuid": "db92e77e-7c72-499d-8fe6-9354d2bfd504", + "description": "disallow left empty strand", + "comments": ["Normalises error messages"], + "reimplements": "5dce058b-28d4-4ca7-aa64-adfe4e17784c", + "property": "distance", + "input": { + "strand1": "", + "strand2": "G" + }, + "expected": {"error": "left and right strands must be of equal length"} + }, + { + "uuid": "38826d4b-16fb-4639-ac3e-ba027dec8b5f", "description": "disallow right empty strand", "property": "distance", "input": { @@ -91,6 +111,18 @@ "strand2": "" }, "expected": {"error": "right strand must not be empty"} + }, + { + "uuid": "920cd6e3-18f4-4143-b6b8-74270bb8f8a3", + "description": "disallow right empty strand", + "comments": ["Normalises error messages"], + "reimplements": "38826d4b-16fb-4639-ac3e-ba027dec8b5f", + "property": "distance", + "input": { + "strand1": "G", + "strand2": "" + }, + "expected": {"error": "left and right strands must be of equal length"} } ] } diff --git a/exercises/hello-world/canonical-data.json b/exercises/hello-world/canonical-data.json index 7e639b49d3..79ee3d76b6 100644 --- a/exercises/hello-world/canonical-data.json +++ b/exercises/hello-world/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "hello-world", - "version": "1.1.0", "cases": [ { + "uuid": "af9ffe10-dc13-42d8-a742-e7bdafac449d", "description": "Say Hi!", "property": "hello", "input": {}, diff --git a/exercises/high-scores/canonical-data.json b/exercises/high-scores/canonical-data.json index b90579582b..27b3446724 100644 --- a/exercises/high-scores/canonical-data.json +++ b/exercises/high-scores/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "high-scores", - "version": "4.0.0", "comments": [ "This is meant to be an easy exercise to practise: ", "* arrays as simple lists", @@ -11,6 +10,7 @@ ], "cases": [ { + "uuid": "1035eb93-2208-4c22-bab8-fef06769a73c", "description": "List of scores", "property": "scores", "input": { @@ -19,6 +19,7 @@ "expected": [30, 50, 20, 70] }, { + "uuid": "6aa5dbf5-78fa-4375-b22c-ffaa989732d2", "description": "Latest score", "property": "latest", "input": { @@ -27,6 +28,7 @@ "expected": 30 }, { + "uuid": "b661a2e1-aebf-4f50-9139-0fb817dd12c6", "description": "Personal best", "property": "personalBest", "input": { @@ -38,6 +40,7 @@ "description": "Top 3 scores", "cases": [ { + "uuid": "3d996a97-c81c-4642-9afc-80b80dc14015", "description": "Personal top three from a list of scores", "property": "personalTopThree", "input": { @@ -46,6 +49,7 @@ "expected": [100, 90, 70] }, { + "uuid": "1084ecb5-3eb4-46fe-a816-e40331a4e83a", "description": "Personal top highest to lowest", "property": "personalTopThree", "input": { @@ -54,6 +58,7 @@ "expected": [30, 20, 10] }, { + "uuid": "e6465b6b-5a11-4936-bfe3-35241c4f4f16", "description": "Personal top when there is a tie", "property": "personalTopThree", "input": { @@ -62,6 +67,7 @@ "expected": [40, 40, 30] }, { + "uuid": "f73b02af-c8fd-41c9-91b9-c86eaa86bce2", "description": "Personal top when there are less than 3", "property": "personalTopThree", "input": { @@ -70,6 +76,7 @@ "expected": [70, 30] }, { + "uuid": "16608eae-f60f-4a88-800e-aabce5df2865", "description": "Personal top when there is only one", "property": "personalTopThree", "input": { diff --git a/exercises/house/canonical-data.json b/exercises/house/canonical-data.json index dc54ca23f4..889b800514 100644 --- a/exercises/house/canonical-data.json +++ b/exercises/house/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "house", - "version": "2.2.0", "comments": [ "JSON doesn't allow for multi-line strings, so all verses are presented ", "here as arrays of strings. It's up to the test generator to join the ", @@ -16,6 +15,7 @@ "description": "Return specified verse or series of verses", "cases": [ { + "uuid": "28a540ff-f765-4348-9d57-ae33f25f41f2", "description": "verse one - the house that jack built", "property": "recite", "input": { @@ -27,6 +27,7 @@ ] }, { + "uuid": "ebc825ac-6e2b-4a5e-9afd-95732191c8da", "description": "verse two - the malt that lay", "property": "recite", "input": { @@ -38,6 +39,7 @@ ] }, { + "uuid": "1ed8bb0f-edb8-4bd1-b6d4-b64754fe4a60", "description": "verse three - the rat that ate", "property": "recite", "input": { @@ -49,6 +51,7 @@ ] }, { + "uuid": "64b0954e-8b7d-4d14-aad0-d3f6ce297a30", "description": "verse four - the cat that killed", "property": "recite", "input": { @@ -60,6 +63,7 @@ ] }, { + "uuid": "1e8d56bc-fe31-424d-9084-61e6111d2c82", "description": "verse five - the dog that worried", "property": "recite", "input": { @@ -71,6 +75,7 @@ ] }, { + "uuid": "6312dc6f-ab0a-40c9-8a55-8d4e582beac4", "description": "verse six - the cow with the crumpled horn", "property": "recite", "input": { @@ -82,6 +87,7 @@ ] }, { + "uuid": "68f76d18-6e19-4692-819c-5ff6a7f92feb", "description": "verse seven - the maiden all forlorn", "property": "recite", "input": { @@ -93,6 +99,7 @@ ] }, { + "uuid": "73872564-2004-4071-b51d-2e4326096747", "description": "verse eight - the man all tattered and torn", "property": "recite", "input": { @@ -104,6 +111,7 @@ ] }, { + "uuid": "0d53d743-66cb-4351-a173-82702f3338c9", "description": "verse nine - the priest all shaven and shorn", "property": "recite", "input": { @@ -115,6 +123,7 @@ ] }, { + "uuid": "452f24dc-8fd7-4a82-be1a-3b4839cfeb41", "description": "verse 10 - the rooster that crowed in the morn", "property": "recite", "input": { @@ -126,6 +135,7 @@ ] }, { + "uuid": "97176f20-2dd3-4646-ac72-cffced91ea26", "description": "verse 11 - the farmer sowing his corn", "property": "recite", "input": { @@ -137,6 +147,7 @@ ] }, { + "uuid": "09824c29-6aad-4dcd-ac98-f61374a6a8b7", "description": "verse 12 - the horse and the hound and the horn", "property": "recite", "input": { @@ -148,6 +159,7 @@ ] }, { + "uuid": "d2b980d3-7851-49e1-97ab-1524515ec200", "description": "multiple verses", "property": "recite", "input": { @@ -163,6 +175,7 @@ ] }, { + "uuid": "0311d1d0-e085-4f23-8ae7-92406fb3e803", "description": "full rhyme", "property": "recite", "input": { diff --git a/exercises/isbn-verifier/canonical-data.json b/exercises/isbn-verifier/canonical-data.json index 1c35e51142..b98fb1bf14 100644 --- a/exercises/isbn-verifier/canonical-data.json +++ b/exercises/isbn-verifier/canonical-data.json @@ -1,13 +1,13 @@ { "exercise": "isbn-verifier", - "version": "2.7.0", "comments": [ "An expected value of true indicates a valid ISBN-10, ", "whereas false means the ISBN-10 is invalid." ], "cases": [ { - "description": "valid isbn number", + "uuid": "0caa3eac-d2e3-4c29-8df8-b188bc8c9292", + "description": "valid isbn", "property": "isValid", "input": { "isbn": "3-598-21508-8" @@ -15,6 +15,7 @@ "expected": true }, { + "uuid": "19f76b53-7c24-45f8-87b8-4604d0ccd248", "description": "invalid isbn check digit", "property": "isValid", "input": { @@ -23,7 +24,8 @@ "expected": false }, { - "description": "valid isbn number with a check digit of 10", + "uuid": "4164bfee-fb0a-4a1c-9f70-64c6a1903dcd", + "description": "valid isbn with a check digit of 10", "property": "isValid", "input": { "isbn": "3-598-21507-X" @@ -31,6 +33,7 @@ "expected": true }, { + "uuid": "3ed50db1-8982-4423-a993-93174a20825c", "description": "check digit is a character other than X", "property": "isValid", "input": { @@ -39,6 +42,7 @@ "expected": false }, { + "uuid": "c19ba0c4-014f-4dc3-a63f-ff9aefc9b5ec", "description": "invalid character in isbn", "property": "isValid", "input": { @@ -47,6 +51,7 @@ "expected": false }, { + "uuid": "28025280-2c39-4092-9719-f3234b89c627", "description": "X is only valid as a check digit", "property": "isValid", "input": { @@ -55,6 +60,7 @@ "expected": false }, { + "uuid": "f6294e61-7e79-46b3-977b-f48789a4945b", "description": "valid isbn without separating dashes", "property": "isValid", "input": { @@ -63,6 +69,7 @@ "expected": true }, { + "uuid": "185ab99b-3a1b-45f3-aeec-b80d80b07f0b", "description": "isbn without separating dashes and X as check digit", "property": "isValid", "input": { @@ -71,6 +78,7 @@ "expected": true }, { + "uuid": "7725a837-ec8e-4528-a92a-d981dd8cf3e2", "description": "isbn without check digit and dashes", "property": "isValid", "input": { @@ -79,6 +87,7 @@ "expected": false }, { + "uuid": "47e4dfba-9c20-46ed-9958-4d3190630bdf", "description": "too long isbn and no dashes", "property": "isValid", "input": { @@ -87,6 +96,7 @@ "expected": false }, { + "uuid": "737f4e91-cbba-4175-95bf-ae630b41fb60", "description": "too short isbn", "property": "isValid", "input": { @@ -95,6 +105,7 @@ "expected": false }, { + "uuid": "5458a128-a9b6-4ff8-8afb-674e74567cef", "description": "isbn without check digit", "property": "isValid", "input": { @@ -103,6 +114,7 @@ "expected": false }, { + "uuid": "70b6ad83-d0a2-4ca7-a4d5-a9ab731800f7", "description": "check digit of X should not be used for 0", "property": "isValid", "input": { @@ -111,6 +123,7 @@ "expected": false }, { + "uuid": "94610459-55ab-4c35-9b93-ff6ea1a8e562", "description": "empty isbn", "property": "isValid", "input": { @@ -119,6 +132,7 @@ "expected": false }, { + "uuid": "7bff28d4-d770-48cc-80d6-b20b3a0fb46c", "description": "input is 9 characters", "property": "isValid", "input": { @@ -127,6 +141,7 @@ "expected": false }, { + "uuid": "ed6e8d1b-382c-4081-8326-8b772c581fec", "description": "invalid characters are not ignored", "property": "isValid", "input": { @@ -135,6 +150,7 @@ "expected": false }, { + "uuid": "fb5e48d8-7c03-4bfb-a088-b101df16fdc3", "description": "input is too long but contains a valid isbn", "property": "isValid", "input": { diff --git a/exercises/isbn-verifier/description.md b/exercises/isbn-verifier/description.md index d07fd942f8..d639f8eac1 100644 --- a/exercises/isbn-verifier/description.md +++ b/exercises/isbn-verifier/description.md @@ -37,4 +37,4 @@ Now, it's even trickier since the check digit of an ISBN-10 may be 'X' (represen * Generate a valid ISBN-13 from the input ISBN-10 (and maybe verify it again with a derived verifier). -* Generate valid ISBN, maybe even from a given starting ISBN. \ No newline at end of file +* Generate valid ISBN, maybe even from a given starting ISBN. diff --git a/exercises/isogram/canonical-data.json b/exercises/isogram/canonical-data.json index 843cb16604..e2d9818cc7 100644 --- a/exercises/isogram/canonical-data.json +++ b/exercises/isogram/canonical-data.json @@ -3,7 +3,6 @@ "comments": [ "An isogram is a word or phrase without a repeating letter." ], - "version": "1.7.0", "cases": [ { "description": "Check if the given string is an isogram", @@ -12,6 +11,7 @@ ], "cases": [ { + "uuid": "a0e97d2d-669e-47c7-8134-518a1e2c4555", "description": "empty string", "property": "isIsogram", "input": { @@ -20,6 +20,7 @@ "expected": true }, { + "uuid": "9a001b50-f194-4143-bc29-2af5ec1ef652", "description": "isogram with only lower case characters", "property": "isIsogram", "input": { @@ -28,6 +29,7 @@ "expected": true }, { + "uuid": "8ddb0ca3-276e-4f8b-89da-d95d5bae78a4", "description": "word with one duplicated character", "property": "isIsogram", "input": { @@ -36,6 +38,7 @@ "expected": false }, { + "uuid": "6450b333-cbc2-4b24-a723-0b459b34fe18", "description": "word with one duplicated character from the end of the alphabet", "property": "isIsogram", "input": { @@ -44,6 +47,7 @@ "expected": false }, { + "uuid": "a15ff557-dd04-4764-99e7-02cc1a385863", "description": "longest reported english isogram", "property": "isIsogram", "input": { @@ -52,6 +56,7 @@ "expected": true }, { + "uuid": "f1a7f6c7-a42f-4915-91d7-35b2ea11c92e", "description": "word with duplicated character in mixed case", "property": "isIsogram", "input": { @@ -60,6 +65,7 @@ "expected": false }, { + "uuid": "14a4f3c1-3b47-4695-b645-53d328298942", "description": "word with duplicated character in mixed case, lowercase first", "property": "isIsogram", "input": { @@ -68,6 +74,7 @@ "expected": false }, { + "uuid": "423b850c-7090-4a8a-b057-97f1cadd7c42", "description": "hypothetical isogrammic word with hyphen", "property": "isIsogram", "input": { @@ -76,6 +83,7 @@ "expected": true }, { + "uuid": "93dbeaa0-3c5a-45c2-8b25-428b8eacd4f2", "description": "hypothetical word with duplicated character following hyphen", "property": "isIsogram", "input": { @@ -84,6 +92,7 @@ "expected": false }, { + "uuid": "36b30e5c-173f-49c6-a515-93a3e825553f", "description": "isogram with duplicated hyphen", "property": "isIsogram", "input": { @@ -92,6 +101,7 @@ "expected": true }, { + "uuid": "cdabafa0-c9f4-4c1f-b142-689c6ee17d93", "description": "made-up name that is an isogram", "property": "isIsogram", "input": { @@ -100,6 +110,7 @@ "expected": true }, { + "uuid": "5fc61048-d74e-48fd-bc34-abfc21552d4d", "description": "duplicated character in the middle", "property": "isIsogram", "input": { @@ -108,6 +119,7 @@ "expected": false }, { + "uuid": "310ac53d-8932-47bc-bbb4-b2b94f25a83e", "description": "same first and last characters", "property": "isIsogram", "input": { diff --git a/exercises/kindergarten-garden/canonical-data.json b/exercises/kindergarten-garden/canonical-data.json index 53cf06b464..e76089ed9e 100644 --- a/exercises/kindergarten-garden/canonical-data.json +++ b/exercises/kindergarten-garden/canonical-data.json @@ -1,57 +1,86 @@ { "exercise": "kindergarten-garden", - "version": "1.1.1", "cases": [ { "description": "partial garden", "cases": [ { + "uuid": "1fc316ed-17ab-4fba-88ef-3ae78296b692", "description": "garden with single student", "property": "plants", "input": { "diagram": "RC\nGG", "student": "Alice" }, - "expected": ["radishes", "clover", "grass", "grass"] + "expected": [ + "radishes", + "clover", + "grass", + "grass" + ] }, { + "uuid": "acd19dc1-2200-4317-bc2a-08f021276b40", "description": "different garden with single student", "property": "plants", "input": { "diagram": "VC\nRC", "student": "Alice" }, - "expected": ["violets", "clover", "radishes", "clover"] + "expected": [ + "violets", + "clover", + "radishes", + "clover" + ] }, { + "uuid": "c376fcc8-349c-446c-94b0-903947315757", "description": "garden with two students", "property": "plants", "input": { "diagram": "VVCG\nVVRC", "student": "Bob" }, - "expected": ["clover", "grass", "radishes", "clover"] + "expected": [ + "clover", + "grass", + "radishes", + "clover" + ] }, { "description": "multiple students for the same garden with three students", "cases": [ { + "uuid": "2d620f45-9617-4924-9d27-751c80d17db9", "description": "second student's garden", "property": "plants", "input": { "diagram": "VVCCGG\nVVCCGG", "student": "Bob" }, - "expected": ["clover", "clover", "clover", "clover"] + "expected": [ + "clover", + "clover", + "clover", + "clover" + ] }, { + "uuid": "57712331-4896-4364-89f8-576421d69c44", "description": "third student's garden", "property": "plants", "input": { "diagram": "VVCCGG\nVVCCGG", "student": "Charlie" }, - "expected": ["grass", "grass", "grass", "grass"] + "expected": [ + "grass", + "grass", + "grass", + "grass" + ] } ] } @@ -61,40 +90,184 @@ "description": "full garden", "cases": [ { - "description": "first student's garden", + "uuid": "149b4290-58e1-40f2-8ae4-8b87c46e765b", + "description": "for Alice, first student's garden", "property": "plants", "input": { "diagram": "VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV", "student": "Alice" }, - "expected": ["violets", "radishes", "violets", "radishes"] + "expected": [ + "violets", + "radishes", + "violets", + "radishes" + ] }, { - "description": "second student's garden", + "uuid": "ba25dbbc-10bd-4a37-b18e-f89ecd098a5e", + "description": "for Bob, second student's garden", "property": "plants", "input": { "diagram": "VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV", "student": "Bob" }, - "expected": ["clover", "grass", "clover", "clover"] + "expected": [ + "clover", + "grass", + "clover", + "clover" + ] + }, + { + "uuid": "566b621b-f18e-4c5f-873e-be30544b838c", + "description": "for Charlie", + "property": "plants", + "input": { + "diagram": "VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV", + "student": "Charlie" + }, + "expected": [ + "violets", + "violets", + "clover", + "grass" + ] + }, + { + "uuid": "3ad3df57-dd98-46fc-9269-1877abf612aa", + "description": "for David", + "property": "plants", + "input": { + "diagram": "VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV", + "student": "David" + }, + "expected": [ + "radishes", + "violets", + "clover", + "radishes" + ] + }, + { + "uuid": "0f0a55d1-9710-46ed-a0eb-399ba8c72db2", + "description": "for Eve", + "property": "plants", + "input": { + "diagram": "VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV", + "student": "Eve" + }, + "expected": [ + "clover", + "grass", + "radishes", + "grass" + ] }, { - "description": "second to last student's garden", + "uuid": "a7e80c90-b140-4ea1-aee3-f4625365c9a4", + "description": "for Fred", + "property": "plants", + "input": { + "diagram": "VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV", + "student": "Fred" + }, + "expected": [ + "grass", + "clover", + "violets", + "clover" + ] + }, + { + "uuid": "9d94b273-2933-471b-86e8-dba68694c615", + "description": "for Ginny", + "property": "plants", + "input": { + "diagram": "VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV", + "student": "Ginny" + }, + "expected": [ + "clover", + "grass", + "grass", + "clover" + ] + }, + { + "uuid": "f55bc6c2-ade8-4844-87c4-87196f1b7258", + "description": "for Harriet", + "property": "plants", + "input": { + "diagram": "VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV", + "student": "Harriet" + }, + "expected": [ + "violets", + "radishes", + "radishes", + "violets" + ] + }, + { + "uuid": "759070a3-1bb1-4dd4-be2c-7cce1d7679ae", + "description": "for Ileana", + "property": "plants", + "input": { + "diagram": "VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV", + "student": "Ileana" + }, + "expected": [ + "grass", + "clover", + "violets", + "clover" + ] + }, + { + "uuid": "78578123-2755-4d4a-9c7d-e985b8dda1c6", + "description": "for Joseph", + "property": "plants", + "input": { + "diagram": "VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV", + "student": "Joseph" + }, + "expected": [ + "violets", + "clover", + "violets", + "grass" + ] + }, + { + "uuid": "6bb66df7-f433-41ab-aec2-3ead6e99f65b", + "description": "for Kincaid, second to last student's garden", "property": "plants", "input": { "diagram": "VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV", "student": "Kincaid" }, - "expected": ["grass", "clover", "clover", "grass"] + "expected": [ + "grass", + "clover", + "clover", + "grass" + ] }, { - "description": "last student's garden", + "uuid": "d7edec11-6488-418a-94e6-ed509e0fa7eb", + "description": "for Larry, last student's garden", "property": "plants", "input": { "diagram": "VRCGVVRVCGGCCGVRGCVCGCGV\nVRCCCGCRRGVCGCRVVCVGCGCV", "student": "Larry" }, - "expected": ["grass", "violets", "clover", "violets"] + "expected": [ + "grass", + "violets", + "clover", + "violets" + ] } ] } diff --git a/exercises/knapsack/canonical-data.json b/exercises/knapsack/canonical-data.json index e2263d3a49..892abcfbd0 100644 --- a/exercises/knapsack/canonical-data.json +++ b/exercises/knapsack/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "knapsack", - "version": "1.0.0", "comments": [ "Depending on the language, the input type can be modified" ], "cases": [ { + "uuid": "a4d7d2f0-ad8a-460c-86f3-88ba709d41a7", "description": "no items", "property": "maximumValue", "input": { @@ -15,6 +15,7 @@ "expected": 0 }, { + "uuid": "1d39e98c-6249-4a8b-912f-87cb12e506b0", "description": "one item, too heavy", "property": "maximumValue", "input": { @@ -26,6 +27,7 @@ "expected": 0 }, { + "uuid": "833ea310-6323-44f2-9d27-a278740ffbd8", "description": "five items (cannot be greedy by weight)", "property": "maximumValue", "input": { @@ -41,6 +43,7 @@ "expected": 21 }, { + "uuid": "277cdc52-f835-4c7d-872b-bff17bab2456", "description": "five items (cannot be greedy by value)", "property": "maximumValue", "input": { @@ -56,6 +59,7 @@ "expected": 80 }, { + "uuid": "81d8e679-442b-4f7a-8a59-7278083916c9", "description": "example knapsack", "property": "maximumValue", "input": { @@ -70,6 +74,7 @@ "expected": 90 }, { + "uuid": "f23a2449-d67c-4c26-bf3e-cde020f27ecc", "description": "8 items", "property": "maximumValue", "input": { @@ -88,6 +93,7 @@ "expected": 900 }, { + "uuid": "7c682ae9-c385-4241-a197-d2fa02c81a11", "description": "15 items", "property": "maximumValue", "input": { diff --git a/exercises/largest-series-product/canonical-data.json b/exercises/largest-series-product/canonical-data.json index 27623d5bd0..4468fd6ce2 100644 --- a/exercises/largest-series-product/canonical-data.json +++ b/exercises/largest-series-product/canonical-data.json @@ -1,10 +1,8 @@ { "exercise": "largest-series-product", - "version": "1.2.0", "comments": [ "Different languages may handle errors differently.", "e.g. raise exceptions, return (int, error), return Option, etc.", - "Some languages specifically test the string->digits conversion", "and the 'slices of size N' operation.", "These cases *deliberately* do not cover those two operations.", "Those are implementation details.", @@ -14,6 +12,7 @@ ], "cases": [ { + "uuid": "7c82f8b7-e347-48ee-8a22-f672323324d4", "description": "finds the largest product if span equals length", "property": "largestProduct", "input": { @@ -23,6 +22,7 @@ "expected": 18 }, { + "uuid": "88523f65-21ba-4458-a76a-b4aaf6e4cb5e", "description": "can find the largest product of 2 with numbers in order", "property": "largestProduct", "input": { @@ -32,6 +32,7 @@ "expected": 72 }, { + "uuid": "f1376b48-1157-419d-92c2-1d7e36a70b8a", "description": "can find the largest product of 2", "property": "largestProduct", "input": { @@ -41,6 +42,7 @@ "expected": 48 }, { + "uuid": "46356a67-7e02-489e-8fea-321c2fa7b4a4", "description": "can find the largest product of 3 with numbers in order", "property": "largestProduct", "input": { @@ -50,6 +52,7 @@ "expected": 504 }, { + "uuid": "a2dcb54b-2b8f-4993-92dd-5ce56dece64a", "description": "can find the largest product of 3", "property": "largestProduct", "input": { @@ -59,6 +62,7 @@ "expected": 270 }, { + "uuid": "673210a3-33cd-4708-940b-c482d7a88f9d", "description": "can find the largest product of 5 with numbers in order", "property": "largestProduct", "input": { @@ -68,6 +72,7 @@ "expected": 15120 }, { + "uuid": "02acd5a6-3bbf-46df-8282-8b313a80a7c9", "description": "can get the largest product of a big number", "property": "largestProduct", "input": { @@ -77,6 +82,7 @@ "expected": 23520 }, { + "uuid": "76dcc407-21e9-424c-a98e-609f269622b5", "description": "reports zero if the only digits are zero", "property": "largestProduct", "input": { @@ -86,6 +92,7 @@ "expected": 0 }, { + "uuid": "6ef0df9f-52d4-4a5d-b210-f6fae5f20e19", "description": "reports zero if all spans include zero", "property": "largestProduct", "input": { @@ -95,6 +102,7 @@ "expected": 0 }, { + "uuid": "5d81aaf7-4f67-4125-bf33-11493cc7eab7", "description": "rejects span longer than string length", "property": "largestProduct", "input": { @@ -118,6 +126,7 @@ "So LSP('123', 4) really DOES take the max of an empty list.", "So LSP('123', 4) errors and LSP('', 0) does NOT." ], + "uuid": "06bc8b90-0c51-4c54-ac22-3ec3893a079e", "description": "reports 1 for empty string and empty product (0 span)", "property": "largestProduct", "input": { @@ -131,6 +140,7 @@ "As above, there is one 0-character string in '123'.", "So again no error. It's the empty product, 1." ], + "uuid": "3ec0d92e-f2e2-4090-a380-70afee02f4c0", "description": "reports 1 for nonempty string and empty product (0 span)", "property": "largestProduct", "input": { @@ -140,6 +150,7 @@ "expected": 1 }, { + "uuid": "6d96c691-4374-4404-80ee-2ea8f3613dd4", "description": "rejects empty string and nonzero span", "property": "largestProduct", "input": { @@ -149,6 +160,7 @@ "expected": {"error": "span must be smaller than string length"} }, { + "uuid": "7a38f2d6-3c35-45f6-8d6f-12e6e32d4d74", "description": "rejects invalid character in digits", "property": "largestProduct", "input": { @@ -158,6 +170,7 @@ "expected": {"error": "digits input must only contain digits"} }, { + "uuid": "5fe3c0e5-a945-49f2-b584-f0814b4dd1ef", "description": "rejects negative span", "property": "largestProduct", "input": { @@ -167,4 +180,4 @@ "expected": {"error": "span must be greater than zero"} } ] -} \ No newline at end of file +} diff --git a/exercises/leap/canonical-data.json b/exercises/leap/canonical-data.json index 4c32ba1cf3..2a1de9d8c8 100644 --- a/exercises/leap/canonical-data.json +++ b/exercises/leap/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "leap", - "version": "1.5.1", "cases": [ { + "uuid": "6466b30d-519c-438e-935d-388224ab5223", "description": "year not divisible by 4 in common year", "property": "leapYear", "input": { @@ -11,6 +11,7 @@ "expected": false }, { + "uuid": "ac227e82-ee82-4a09-9eb6-4f84331ffdb0", "description": "year divisible by 2, not divisible by 4 in common year", "property": "leapYear", "input": { @@ -19,6 +20,7 @@ "expected": false }, { + "uuid": "4fe9b84c-8e65-489e-970b-856d60b8b78e", "description": "year divisible by 4, not divisible by 100 in leap year", "property": "leapYear", "input": { @@ -27,6 +29,16 @@ "expected": true }, { + "uuid": "7fc6aed7-e63c-48f5-ae05-5fe182f60a5d", + "description": "year divisible by 4 and 5 is still a leap year", + "property": "leapYear", + "input": { + "year": 1960 + }, + "expected": true + }, + { + "uuid": "78a7848f-9667-4192-ae53-87b30c9a02dd", "description": "year divisible by 100, not divisible by 400 in common year", "property": "leapYear", "input": { @@ -35,7 +47,17 @@ "expected": false }, { - "description": "year divisible by 400 in leap year", + "uuid": "9d70f938-537c-40a6-ba19-f50739ce8bac", + "description": "year divisible by 100 but not by 3 is still not a leap year", + "property": "leapYear", + "input": { + "year": 1900 + }, + "expected": false + }, + { + "uuid": "42ee56ad-d3e6-48f1-8e3f-c84078d916fc", + "description": "year divisible by 400 is leap year", "property": "leapYear", "input": { "year": 2000 @@ -43,6 +65,16 @@ "expected": true }, { + "uuid": "57902c77-6fe9-40de-8302-587b5c27121e", + "description": "year divisible by 400 but not by 125 is still a leap year", + "property": "leapYear", + "input": { + "year": 2400 + }, + "expected": true + }, + { + "uuid": "c30331f6-f9f6-4881-ad38-8ca8c12520c1", "description": "year divisible by 200, not divisible by 400 in common year", "property": "leapYear", "input": { diff --git a/exercises/list-ops/canonical-data.json b/exercises/list-ops/canonical-data.json index bd59f53a18..da3c0fd430 100644 --- a/exercises/list-ops/canonical-data.json +++ b/exercises/list-ops/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "list-ops", - "version": "2.4.0", "comments": [ "Though there are no specifications here for dealing with large lists,", "implementers may add tests for handling large lists to ensure that the", @@ -11,6 +10,7 @@ "description": "append entries to a list and return the new list", "cases": [ { + "uuid": "485b9452-bf94-40f7-a3db-c3cf4850066a", "description": "empty lists", "property": "append", "input": { @@ -20,7 +20,8 @@ "expected": [] }, { - "description": "empty list to list", + "uuid": "2c894696-b609-4569-b149-8672134d340a", + "description": "list to empty list", "property": "append", "input": { "list1": [], @@ -29,6 +30,17 @@ "expected": [1, 2, 3, 4] }, { + "uuid": "e842efed-3bf6-4295-b371-4d67a4fdf19c", + "description": "empty list to list", + "property": "append", + "input": { + "list1": [1, 2, 3, 4], + "list2": [] + }, + "expected": [1, 2, 3, 4] + }, + { + "uuid": "71dcf5eb-73ae-4a0e-b744-a52ee387922f", "description": "non-empty lists", "property": "append", "input": { @@ -43,6 +55,7 @@ "description": "concatenate a list of lists", "cases": [ { + "uuid": "28444355-201b-4af2-a2f6-5550227bde21", "description": "empty list", "property": "concat", "input": { @@ -51,6 +64,7 @@ "expected": [] }, { + "uuid": "331451c1-9573-42a1-9869-2d06e3b389a9", "description": "list of lists", "property": "concat", "input": { @@ -59,6 +73,7 @@ "expected": [1, 2, 3, 4, 5, 6] }, { + "uuid": "d6ecd72c-197f-40c3-89a4-aa1f45827e09", "description": "list of nested lists", "property": "concat", "input": { @@ -72,6 +87,7 @@ "description": "filter list returning only values that satisfy the filter function", "cases": [ { + "uuid": "0524fba8-3e0f-4531-ad2b-f7a43da86a16", "description": "empty list", "property": "filter", "input": { @@ -81,6 +97,7 @@ "expected": [] }, { + "uuid": "88494bd5-f520-4edb-8631-88e415b62d24", "description": "non-empty list", "property": "filter", "input": { @@ -95,6 +112,7 @@ "description": "returns the length of a list", "cases": [ { + "uuid": "1cf0b92d-8d96-41d5-9c21-7b3c37cb6aad", "description": "empty list", "property": "length", "input": { @@ -103,6 +121,7 @@ "expected": 0 }, { + "uuid": "d7b8d2d9-2d16-44c4-9a19-6e5f237cb71e", "description": "non-empty list", "property": "length", "input": { @@ -116,6 +135,7 @@ "description": "return a list of elements whose values equal the list value transformed by the mapping function", "cases": [ { + "uuid": "c0bc8962-30e2-4bec-9ae4-668b8ecd75aa", "description": "empty list", "property": "map", "input": { @@ -125,6 +145,7 @@ "expected": [] }, { + "uuid": "11e71a95-e78b-4909-b8e4-60cdcaec0e91", "description": "non-empty list", "property": "map", "input": { @@ -137,8 +158,15 @@ }, { "description": "folds (reduces) the given list from the left with a function", + "comments": [ + "For function: acc is the accumulator and el is the current element. ", + "The order of the arguments (ie. acc, el or el, acc) should match the ", + "conventions common to the language of the track implementing this. ", + "See https://github.com/exercism/problem-specifications/pull/1746#discussion_r548303995 for further advice." + ], "cases": [ { + "uuid": "613b20b7-1873-4070-a3a6-70ae5f50d7cc", "description": "empty list", "property": "foldl", "input": { @@ -149,6 +177,7 @@ "expected": 2 }, { + "uuid": "e56df3eb-9405-416a-b13a-aabb4c3b5194", "description": "direction independent function applied to non-empty list", "property": "foldl", "input": { @@ -159,7 +188,11 @@ "expected": 15 }, { + "uuid": "d2cf5644-aee1-4dfc-9b88-06896676fe27", "description": "direction dependent function applied to non-empty list", + "comments": [ + "Expects integer division (expects / to discard fractions). " + ], "property": "foldl", "input": { "list": [2, 5], @@ -167,13 +200,71 @@ "function": "(x, y) -> x / y" }, "expected": 0 + }, + { + "uuid": "36549237-f765-4a4c-bfd9-5d3a8f7b07d2", + "reimplements": "613b20b7-1873-4070-a3a6-70ae5f50d7cc", + "comments": [ + "Reimplemented to remove ambiguity about the parameters of the ", + "function input." + ], + "description": "empty list", + "property": "foldl", + "input": { + "list": [], + "initial": 2, + "function": "(acc, el) -> el * acc" + }, + "expected": 2 + }, + { + "uuid": "7a626a3c-03ec-42bc-9840-53f280e13067", + "reimplements": "e56df3eb-9405-416a-b13a-aabb4c3b5194", + "comments": [ + "Reimplemented to remove ambiguity about the parameters of the ", + "function input." + ], + "description": "direction independent function applied to non-empty list", + "property": "foldl", + "input": { + "list": [1, 2, 3, 4], + "initial": 5, + "function": "(acc, el) -> el + acc" + }, + "expected": 15 + }, + { + "uuid": "d7fcad99-e88e-40e1-a539-4c519681f390", + "reimplements": "d2cf5644-aee1-4dfc-9b88-06896676fe27", + "comments": [ + "Reimplemented to remove ambiguity about the parameters of the ", + "function input. Expects / to preserve fractions. Integer division", + "will not work here, since it would compute 1 / 24 = 0. Use the ", + "original test values (d2cf5644-aee1-4dfc-9b88-06896676fe27) if ", + "integer division is expected / required. " + ], + "description": "direction dependent function applied to non-empty list", + "property": "foldl", + "input": { + "list": [1, 2, 3, 4], + "initial": 24, + "function": "(acc, el) -> el / acc" + }, + "expected": 64 } ] }, { "description": "folds (reduces) the given list from the right with a function", + "comments": [ + "For function: acc is the accumulator and el is the current element ", + "The order of the arguments (ie. acc, el or el, acc) should match the ", + "conventions common to the language of the track implementing this. ", + "See https://github.com/exercism/problem-specifications/pull/1746#discussion_r548303995 for further advice." + ], "cases": [ { + "uuid": "aeb576b9-118e-4a57-a451-db49fac20fdc", "description": "empty list", "property": "foldr", "input": { @@ -184,6 +275,7 @@ "expected": 2 }, { + "uuid": "c4b64e58-313e-4c47-9c68-7764964efb8e", "description": "direction independent function applied to non-empty list", "property": "foldr", "input": { @@ -194,7 +286,11 @@ "expected": 15 }, { + "uuid": "be396a53-c074-4db3-8dd6-f7ed003cce7c", "description": "direction dependent function applied to non-empty list", + "comments": [ + "Expects integer division (expects / to discard fractions). " + ], "property": "foldr", "input": { "list": [2, 5], @@ -202,6 +298,57 @@ "function": "(x, y) -> x / y" }, "expected": 2 + }, + { + "uuid": "17214edb-20ba-42fc-bda8-000a5ab525b0", + "reimplements": "aeb576b9-118e-4a57-a451-db49fac20fdc", + "comments": [ + "Reimplemented to remove ambiguity about the parameters of the ", + "function input." + ], + "description": "empty list", + "property": "foldr", + "input": { + "list": [], + "initial": 2, + "function": "(acc, el) -> el * acc" + }, + "expected": 2 + }, + { + "uuid": "e1c64db7-9253-4a3d-a7c4-5273b9e2a1bd", + "reimplements": "c4b64e58-313e-4c47-9c68-7764964efb8e", + "comments": [ + "Reimplemented to remove ambiguity about the parameters of the ", + "function input." + ], + "description": "direction independent function applied to non-empty list", + "property": "foldr", + "input": { + "list": [1, 2, 3, 4], + "initial": 5, + "function": "(acc, el) -> el + acc" + }, + "expected": 15 + }, + { + "uuid": "8066003b-f2ff-437e-9103-66e6df474844", + "reimplements": "be396a53-c074-4db3-8dd6-f7ed003cce7c", + "comments": [ + "Reimplemented to remove ambiguity about the parameters of the ", + "function input. Expects / to preserve fractions. Integer division", + "will not work here, since it would compute 4 / 24 = 1 / 6. Use ", + "the original test values (be396a53-c074-4db3-8dd6-f7ed003cce7c) ", + "if integer division is expected / required." + ], + "description": "direction dependent function applied to non-empty list", + "property": "foldr", + "input": { + "list": [1, 2, 3, 4], + "initial": 24, + "function": "(acc, el) -> el / acc" + }, + "expected": 9 } ] }, @@ -209,6 +356,7 @@ "description": "reverse the elements of the list", "cases": [ { + "uuid": "94231515-050e-4841-943d-d4488ab4ee30", "description": "empty list", "property": "reverse", "input": { @@ -217,6 +365,7 @@ "expected": [] }, { + "uuid": "fcc03d1e-42e0-4712-b689-d54ad761f360", "description": "non-empty list", "property": "reverse", "input": { @@ -225,6 +374,7 @@ "expected": [7, 5, 3, 1] }, { + "uuid": "40872990-b5b8-4cb8-9085-d91fc0d05d26", "description": "list of lists is not flattened", "property": "reverse", "input": { diff --git a/exercises/list-ops/description.md b/exercises/list-ops/description.md index 54917fd76b..c546be65e9 100644 --- a/exercises/list-ops/description.md +++ b/exercises/list-ops/description.md @@ -4,7 +4,7 @@ In functional languages list operations like `length`, `map`, and `reduce` are very common. Implement a series of basic list operations, without using existing functions. -The precise number and names of the operations to be implemented will be +The precise number and names of the operations to be implemented will be track dependent to avoid conflicts with existing names, but the general operations you will implement include: diff --git a/exercises/luhn/canonical-data.json b/exercises/luhn/canonical-data.json index f6e3ebe590..c3e1f30d28 100644 --- a/exercises/luhn/canonical-data.json +++ b/exercises/luhn/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "luhn", - "version": "1.6.1", "cases": [ { + "uuid": "792a7082-feb7-48c7-b88b-bbfec160865e", "description": "single digit strings can not be valid", "property": "valid", "input": { @@ -11,6 +11,7 @@ "expected": false }, { + "uuid": "698a7924-64d4-4d89-8daa-32e1aadc271e", "description": "a single zero is invalid", "property": "valid", "input": { @@ -19,6 +20,7 @@ "expected": false }, { + "uuid": "73c2f62b-9b10-4c9f-9a04-83cee7367965", "description": "a simple valid SIN that remains valid if reversed", "property": "valid", "input": { @@ -27,6 +29,7 @@ "expected": true }, { + "uuid": "9369092e-b095-439f-948d-498bd076be11", "description": "a simple valid SIN that becomes invalid if reversed", "property": "valid", "input": { @@ -35,6 +38,7 @@ "expected": true }, { + "uuid": "8f9f2350-1faf-4008-ba84-85cbb93ffeca", "description": "a valid Canadian SIN", "property": "valid", "input": { @@ -43,6 +47,7 @@ "expected": true }, { + "uuid": "1cdcf269-6560-44fc-91f6-5819a7548737", "description": "invalid Canadian SIN", "property": "valid", "input": { @@ -51,6 +56,7 @@ "expected": false }, { + "uuid": "656c48c1-34e8-4e60-9a5a-aad8a367810a", "description": "invalid credit card", "property": "valid", "input": { @@ -59,6 +65,16 @@ "expected": false }, { + "uuid": "20e67fad-2121-43ed-99a8-14b5b856adb9", + "description": "invalid long number with an even remainder", + "property": "valid", + "input": { + "value": "1 2345 6789 1234 5678 9012" + }, + "expected": false + }, + { + "uuid": "ad2a0c5f-84ed-4e5b-95da-6011d6f4f0aa", "description": "valid number with an even number of digits", "property": "valid", "input": { @@ -67,6 +83,7 @@ "expected": true }, { + "uuid": "ef081c06-a41f-4761-8492-385e13c8202d", "description": "valid number with an odd number of spaces", "property": "valid", "input": { @@ -75,6 +92,7 @@ "expected": true }, { + "uuid": "bef66f64-6100-4cbb-8f94-4c9713c5e5b2", "description": "valid strings with a non-digit added at the end become invalid", "property": "valid", "input": { @@ -83,6 +101,7 @@ "expected": false }, { + "uuid": "2177e225-9ce7-40f6-b55d-fa420e62938e", "description": "valid strings with punctuation included become invalid", "property": "valid", "input": { @@ -91,6 +110,7 @@ "expected": false }, { + "uuid": "ebf04f27-9698-45e1-9afe-7e0851d0fe8d", "description": "valid strings with symbols included become invalid", "property": "valid", "input": { @@ -99,6 +119,7 @@ "expected": false }, { + "uuid": "08195c5e-ce7f-422c-a5eb-3e45fece68ba", "description": "single zero with space is invalid", "property": "valid", "input": { @@ -107,6 +128,7 @@ "expected": false }, { + "uuid": "12e63a3c-f866-4a79-8c14-b359fc386091", "description": "more than a single zero is valid", "property": "valid", "input": { @@ -115,6 +137,7 @@ "expected": true }, { + "uuid": "ab56fa80-5de8-4735-8a4a-14dae588663e", "description": "input digit 9 is correctly converted to output digit 9", "property": "valid", "input": { @@ -127,6 +150,7 @@ "Convert non-digits to their ascii values and then offset them by 48 sometimes accidentally declare an invalid string to be valid.", "This test is designed to avoid that solution." ], + "uuid": "39a06a5a-5bad-4e0f-b215-b042d46209b1", "description": "using ascii value for non-doubled non-digit isn't allowed", "property": "valid", "input": { @@ -139,6 +163,7 @@ "Convert non-digits to their ascii values and then offset them by 48 sometimes accidentally declare an invalid string to be valid.", "This test is designed to avoid that solution." ], + "uuid": "f94cf191-a62f-4868-bc72-7253114aa157", "description": "using ascii value for doubled non-digit isn't allowed", "property": "valid", "input": { diff --git a/exercises/luhn/description.md b/exercises/luhn/description.md index ff8fa1926f..3929910e24 100644 --- a/exercises/luhn/description.md +++ b/exercises/luhn/description.md @@ -17,27 +17,27 @@ are disallowed. ## Example 1: valid credit card number ```text -4539 1488 0343 6467 +4539 3195 0343 6467 ``` The first step of the Luhn algorithm is to double every second digit, starting from the right. We will be doubling ```text -4_3_ 1_8_ 0_4_ 6_6_ +4_3_ 3_9_ 0_4_ 6_6_ ``` If doubling the number results in a number greater than 9 then subtract 9 from the product. The results of our doubling: ```text -8569 2478 0383 3437 +8569 6195 0383 3437 ``` Then sum all of the digits: ```text -8+5+6+9+2+4+7+8+0+3+8+3+3+4+3+7 = 80 +8+5+6+9+6+1+9+5+0+3+8+3+3+4+3+7 = 80 ``` If the sum is evenly divisible by 10, then the number is valid. This number is valid! diff --git a/exercises/markdown/canonical-data.json b/exercises/markdown/canonical-data.json index 00db645110..405d3a5c7f 100644 --- a/exercises/markdown/canonical-data.json +++ b/exercises/markdown/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "markdown", - "version": "1.4.0", "comments": [ "Markdown is a shorthand for creating HTML from text strings." ], "cases": [ { + "uuid": "e75c8103-a6b8-45d9-84ad-e68520545f6e", "description": "parses normal text as a paragraph", "property": "parse", "input": { @@ -14,6 +14,7 @@ "expected": "

This will be a paragraph

" }, { + "uuid": "69a4165d-9bf8-4dd7-bfdc-536eaca80a6a", "description": "parsing italics", "property": "parse", "input": { @@ -22,6 +23,7 @@ "expected": "

This will be italic

" }, { + "uuid": "ec345a1d-db20-4569-a81a-172fe0cad8a1", "description": "parsing bold text", "property": "parse", "input": { @@ -30,6 +32,7 @@ "expected": "

This will be bold

" }, { + "uuid": "51164ed4-5641-4909-8fab-fbaa9d37d5a8", "description": "mixed normal, italics and bold text", "property": "parse", "input": { @@ -38,6 +41,7 @@ "expected": "

This will be mixed

" }, { + "uuid": "ad85f60d-0edd-4c6a-a9b1-73e1c4790d15", "description": "with h1 header level", "property": "parse", "input": { @@ -46,6 +50,7 @@ "expected": "

This will be an h1

" }, { + "uuid": "d0f7a31f-6935-44ac-8a9a-1e8ab16af77f", "description": "with h2 header level", "property": "parse", "input": { @@ -54,6 +59,7 @@ "expected": "

This will be an h2

" }, { + "uuid": "13b5f410-33f5-44f0-a6a7-cfd4ab74b5d5", "description": "with h6 header level", "property": "parse", "input": { @@ -62,6 +68,7 @@ "expected": "
This will be an h6
" }, { + "uuid": "25288a2b-8edc-45db-84cf-0b6c6ee034d6", "description": "unordered lists", "property": "parse", "input": { @@ -70,6 +77,7 @@ "expected": "
  • Item 1
  • Item 2
" }, { + "uuid": "7bf92413-df8f-4de8-9184-b724f363c3da", "description": "With a little bit of everything", "property": "parse", "input": { @@ -78,6 +86,7 @@ "expected": "

Header!

  • Bold Item
  • Italic Item
" }, { + "uuid": "0b3ed1ec-3991-4b8b-8518-5cb73d4a64fe", "description": "with markdown symbols in the header text that should not be interpreted", "property": "parse", "input": { @@ -86,6 +95,7 @@ "expected": "

This is a header with # and * in the text

" }, { + "uuid": "113a2e58-78de-4efa-90e9-20972224d759", "description": "with markdown symbols in the list item text that should not be interpreted", "property": "parse", "input": { @@ -94,6 +104,7 @@ "expected": "
  • Item 1 with a # in the text
  • Item 2 with * in the text
" }, { + "uuid": "e65e46e2-17b7-4216-b3ac-f44a1b9bcdb4", "description": "with markdown symbols in the paragraph text that should not be interpreted", "property": "parse", "input": { @@ -102,6 +113,7 @@ "expected": "

This is a paragraph with # and * in the text

" }, { + "uuid": "f0bbbbde-0f52-4c0c-99ec-be4c60126dd4", "description": "unordered lists close properly with preceding and following lines", "property": "parse", "input": { diff --git a/exercises/matching-brackets/canonical-data.json b/exercises/matching-brackets/canonical-data.json index 1a9f112dfb..323e76b591 100644 --- a/exercises/matching-brackets/canonical-data.json +++ b/exercises/matching-brackets/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "matching-brackets", - "version": "2.0.0", "cases": [ { + "uuid": "81ec11da-38dd-442a-bcf9-3de7754609a5", "description": "paired square brackets", "property": "isPaired", "input": { @@ -11,6 +11,7 @@ "expected": true }, { + "uuid": "287f0167-ac60-4b64-8452-a0aa8f4e5238", "description": "empty string", "property": "isPaired", "input": { @@ -19,6 +20,7 @@ "expected": true }, { + "uuid": "6c3615a3-df01-4130-a731-8ef5f5d78dac", "description": "unpaired brackets", "property": "isPaired", "input": { @@ -27,6 +29,7 @@ "expected": false }, { + "uuid": "9d414171-9b98-4cac-a4e5-941039a97a77", "description": "wrong ordered brackets", "property": "isPaired", "input": { @@ -35,6 +38,7 @@ "expected": false }, { + "uuid": "f0f97c94-a149-4736-bc61-f2c5148ffb85", "description": "wrong closing bracket", "property": "isPaired", "input": { @@ -43,6 +47,7 @@ "expected": false }, { + "uuid": "754468e0-4696-4582-a30e-534d47d69756", "description": "paired with whitespace", "property": "isPaired", "input": { @@ -51,6 +56,7 @@ "expected": true }, { + "uuid": "ba84f6ee-8164-434a-9c3e-b02c7f8e8545", "description": "partially paired brackets", "property": "isPaired", "input": { @@ -59,6 +65,7 @@ "expected": false }, { + "uuid": "3c86c897-5ff3-4a2b-ad9b-47ac3a30651d", "description": "simple nested brackets", "property": "isPaired", "input": { @@ -67,6 +74,7 @@ "expected": true }, { + "uuid": "2d137f2c-a19e-4993-9830-83967a2d4726", "description": "several paired brackets", "property": "isPaired", "input": { @@ -75,6 +83,7 @@ "expected": true }, { + "uuid": "2e1f7b56-c137-4c92-9781-958638885a44", "description": "paired and nested brackets", "property": "isPaired", "input": { @@ -83,6 +92,7 @@ "expected": true }, { + "uuid": "84f6233b-e0f7-4077-8966-8085d295c19b", "description": "unopened closing brackets", "property": "isPaired", "input": { @@ -91,6 +101,7 @@ "expected": false }, { + "uuid": "9b18c67d-7595-4982-b2c5-4cb949745d49", "description": "unpaired and nested brackets", "property": "isPaired", "input": { @@ -99,6 +110,7 @@ "expected": false }, { + "uuid": "a0205e34-c2ac-49e6-a88a-899508d7d68e", "description": "paired and wrong nested brackets", "property": "isPaired", "input": { @@ -107,6 +119,7 @@ "expected": false }, { + "uuid": "ef47c21b-bcfd-4998-844c-7ad5daad90a8", "description": "paired and incomplete brackets", "property": "isPaired", "input": { @@ -115,14 +128,16 @@ "expected": false }, { + "uuid": "a4675a40-a8be-4fc2-bc47-2a282ce6edbe", "description": "too many closing brackets", "property": "isPaired", "input": { "value": "[]]" }, "expected": false - }, + }, { + "uuid": "99255f93-261b-4435-a352-02bdecc9bdf2", "description": "math expression", "property": "isPaired", "input": { @@ -131,6 +146,7 @@ "expected": true }, { + "uuid": "8e357d79-f302-469a-8515-2561877256a1", "description": "complex latex expression", "property": "isPaired", "input": { @@ -139,4 +155,4 @@ "expected": true } ] -} \ No newline at end of file +} diff --git a/exercises/matrix/canonical-data.json b/exercises/matrix/canonical-data.json index aef45d4642..ba875b98f2 100644 --- a/exercises/matrix/canonical-data.json +++ b/exercises/matrix/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "matrix", - "version": "1.1.0", "cases": [ { + "uuid": "ca733dab-9d85-4065-9ef6-a880a951dafd", "description": "extract row from one number matrix", "property": "row", "input": { @@ -12,6 +12,7 @@ "expected": [1] }, { + "uuid": "5c93ec93-80e1-4268-9fc2-63bc7d23385c", "description": "can extract row", "property": "row", "input": { @@ -21,6 +22,7 @@ "expected": [3, 4] }, { + "uuid": "2f1aad89-ad0f-4bd2-9919-99a8bff0305a", "description": "extract row where numbers have different widths", "property": "row", "input": { @@ -30,15 +32,17 @@ "expected": [10, 20] }, { - "description": "can extract row from non-square matrix", + "uuid": "68f7f6ba-57e2-4e87-82d0-ad09889b5204", + "description": "can extract row from non-square matrix with no corresponding column", "property": "row", "input": { "string": "1 2 3\n4 5 6\n7 8 9\n8 7 6", - "index": 3 + "index": 4 }, - "expected": [7, 8, 9] + "expected": [8, 7, 6] }, { + "uuid": "e8c74391-c93b-4aed-8bfe-f3c9beb89ebb", "description": "extract column from one number matrix", "property": "column", "input": { @@ -48,6 +52,7 @@ "expected": [1] }, { + "uuid": "7136bdbd-b3dc-48c4-a10c-8230976d3727", "description": "can extract column", "property": "column", "input": { @@ -57,15 +62,17 @@ "expected": [3, 6, 9] }, { - "description": "can extract column from non-square matrix", + "uuid": "ad64f8d7-bba6-4182-8adf-0c14de3d0eca", + "description": "can extract column from non-square matrix with no corresponding row", "property": "column", "input": { - "string": "1 2 3\n4 5 6\n7 8 9\n8 7 6", - "index": 3 + "string": "1 2 3 4\n5 6 7 8\n9 8 7 6", + "index": 4 }, - "expected": [3, 6, 9, 6] + "expected": [4, 8, 6] }, { + "uuid": "9eddfa5c-8474-440e-ae0a-f018c2a0dd89", "description": "extract column where numbers have different widths", "property": "column", "input": { diff --git a/exercises/meetup/canonical-data.json b/exercises/meetup/canonical-data.json index 5e31a774cf..8f3c1cd86b 100644 --- a/exercises/meetup/canonical-data.json +++ b/exercises/meetup/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "meetup", - "version": "1.1.0", "cases": [ { + "uuid": "d7f8eadd-d4fc-46ee-8a20-e97bd3fd01c8", "description": "monteenth of May 2013", "property": "meetup", "input": { @@ -14,6 +14,7 @@ "expected": "2013-05-13" }, { + "uuid": "f78373d1-cd53-4a7f-9d37-e15bf8a456b4", "description": "monteenth of August 2013", "property": "meetup", "input": { @@ -25,6 +26,7 @@ "expected": "2013-08-19" }, { + "uuid": "8c78bea7-a116-425b-9c6b-c9898266d92a", "description": "monteenth of September 2013", "property": "meetup", "input": { @@ -36,6 +38,7 @@ "expected": "2013-09-16" }, { + "uuid": "cfef881b-9dc9-4d0b-8de4-82d0f39fc271", "description": "tuesteenth of March 2013", "property": "meetup", "input": { @@ -47,6 +50,7 @@ "expected": "2013-03-19" }, { + "uuid": "69048961-3b00-41f9-97ee-eb6d83a8e92b", "description": "tuesteenth of April 2013", "property": "meetup", "input": { @@ -58,6 +62,7 @@ "expected": "2013-04-16" }, { + "uuid": "d30bade8-3622-466a-b7be-587414e0caa6", "description": "tuesteenth of August 2013", "property": "meetup", "input": { @@ -69,6 +74,7 @@ "expected": "2013-08-13" }, { + "uuid": "8db4b58b-92f3-4687-867b-82ee1a04f851", "description": "wednesteenth of January 2013", "property": "meetup", "input": { @@ -80,6 +86,7 @@ "expected": "2013-01-16" }, { + "uuid": "6c27a2a2-28f8-487f-ae81-35d08c4664f7", "description": "wednesteenth of February 2013", "property": "meetup", "input": { @@ -91,6 +98,7 @@ "expected": "2013-02-13" }, { + "uuid": "008a8674-1958-45b5-b8e6-c2c9960d973a", "description": "wednesteenth of June 2013", "property": "meetup", "input": { @@ -102,6 +110,7 @@ "expected": "2013-06-19" }, { + "uuid": "e4abd5e3-57cb-4091-8420-d97e955c0dbd", "description": "thursteenth of May 2013", "property": "meetup", "input": { @@ -113,6 +122,7 @@ "expected": "2013-05-16" }, { + "uuid": "85da0b0f-eace-4297-a6dd-63588d5055b4", "description": "thursteenth of June 2013", "property": "meetup", "input": { @@ -124,6 +134,7 @@ "expected": "2013-06-13" }, { + "uuid": "ecf64f9b-8413-489b-bf6e-128045f70bcc", "description": "thursteenth of September 2013", "property": "meetup", "input": { @@ -135,6 +146,7 @@ "expected": "2013-09-19" }, { + "uuid": "ac4e180c-7d0a-4d3d-b05f-f564ebb584ca", "description": "friteenth of April 2013", "property": "meetup", "input": { @@ -146,6 +158,7 @@ "expected": "2013-04-19" }, { + "uuid": "b79101c7-83ad-4f8f-8ec8-591683296315", "description": "friteenth of August 2013", "property": "meetup", "input": { @@ -157,6 +170,7 @@ "expected": "2013-08-16" }, { + "uuid": "6ed38b9f-0072-4901-bd97-7c8b8b0ef1b8", "description": "friteenth of September 2013", "property": "meetup", "input": { @@ -168,6 +182,7 @@ "expected": "2013-09-13" }, { + "uuid": "dfae03ed-9610-47de-a632-655ab01e1e7c", "description": "saturteenth of February 2013", "property": "meetup", "input": { @@ -179,6 +194,7 @@ "expected": "2013-02-16" }, { + "uuid": "ec02e3e1-fc72-4a3c-872f-a53fa8ab358e", "description": "saturteenth of April 2013", "property": "meetup", "input": { @@ -190,6 +206,7 @@ "expected": "2013-04-13" }, { + "uuid": "d983094b-7259-4195-b84e-5d09578c89d9", "description": "saturteenth of October 2013", "property": "meetup", "input": { @@ -201,6 +218,7 @@ "expected": "2013-10-19" }, { + "uuid": "d84a2a2e-f745-443a-9368-30051be60c2e", "description": "sunteenth of May 2013", "property": "meetup", "input": { @@ -212,6 +230,7 @@ "expected": "2013-05-19" }, { + "uuid": "0e64bc53-92a3-4f61-85b2-0b7168c7ce5a", "description": "sunteenth of June 2013", "property": "meetup", "input": { @@ -223,6 +242,7 @@ "expected": "2013-06-16" }, { + "uuid": "de87652c-185e-4854-b3ae-04cf6150eead", "description": "sunteenth of October 2013", "property": "meetup", "input": { @@ -234,6 +254,7 @@ "expected": "2013-10-13" }, { + "uuid": "2cbfd0f5-ba3a-46da-a8cc-0fe4966d3411", "description": "first Monday of March 2013", "property": "meetup", "input": { @@ -245,6 +266,7 @@ "expected": "2013-03-04" }, { + "uuid": "a6168c7c-ed95-4bb3-8f92-c72575fc64b0", "description": "first Monday of April 2013", "property": "meetup", "input": { @@ -256,6 +278,7 @@ "expected": "2013-04-01" }, { + "uuid": "1bfc620f-1c54-4bbd-931f-4a1cd1036c20", "description": "first Tuesday of May 2013", "property": "meetup", "input": { @@ -267,6 +290,7 @@ "expected": "2013-05-07" }, { + "uuid": "12959c10-7362-4ca0-a048-50cf1c06e3e2", "description": "first Tuesday of June 2013", "property": "meetup", "input": { @@ -278,6 +302,7 @@ "expected": "2013-06-04" }, { + "uuid": "1033dc66-8d0b-48a1-90cb-270703d59d1d", "description": "first Wednesday of July 2013", "property": "meetup", "input": { @@ -289,6 +314,7 @@ "expected": "2013-07-03" }, { + "uuid": "b89185b9-2f32-46f4-a602-de20b09058f6", "description": "first Wednesday of August 2013", "property": "meetup", "input": { @@ -300,6 +326,7 @@ "expected": "2013-08-07" }, { + "uuid": "53aedc4d-b2c8-4dfb-abf7-a8dc9cdceed5", "description": "first Thursday of September 2013", "property": "meetup", "input": { @@ -311,6 +338,7 @@ "expected": "2013-09-05" }, { + "uuid": "b420a7e3-a94c-4226-870a-9eb3a92647f0", "description": "first Thursday of October 2013", "property": "meetup", "input": { @@ -322,6 +350,7 @@ "expected": "2013-10-03" }, { + "uuid": "61df3270-28b4-4713-bee2-566fa27302ca", "description": "first Friday of November 2013", "property": "meetup", "input": { @@ -333,6 +362,7 @@ "expected": "2013-11-01" }, { + "uuid": "cad33d4d-595c-412f-85cf-3874c6e07abf", "description": "first Friday of December 2013", "property": "meetup", "input": { @@ -344,6 +374,7 @@ "expected": "2013-12-06" }, { + "uuid": "a2869b52-5bba-44f0-a863-07bd1f67eadb", "description": "first Saturday of January 2013", "property": "meetup", "input": { @@ -355,6 +386,7 @@ "expected": "2013-01-05" }, { + "uuid": "3585315a-d0db-4ea1-822e-0f22e2a645f5", "description": "first Saturday of February 2013", "property": "meetup", "input": { @@ -366,6 +398,7 @@ "expected": "2013-02-02" }, { + "uuid": "c49e9bd9-8ccf-4cf2-947a-0ccd4e4f10b1", "description": "first Sunday of March 2013", "property": "meetup", "input": { @@ -377,6 +410,7 @@ "expected": "2013-03-03" }, { + "uuid": "1513328b-df53-4714-8677-df68c4f9366c", "description": "first Sunday of April 2013", "property": "meetup", "input": { @@ -388,6 +422,7 @@ "expected": "2013-04-07" }, { + "uuid": "49e083af-47ec-4018-b807-62ef411efed7", "description": "second Monday of March 2013", "property": "meetup", "input": { @@ -399,6 +434,7 @@ "expected": "2013-03-11" }, { + "uuid": "6cb79a73-38fe-4475-9101-9eec36cf79e5", "description": "second Monday of April 2013", "property": "meetup", "input": { @@ -410,6 +446,7 @@ "expected": "2013-04-08" }, { + "uuid": "4c39b594-af7e-4445-aa03-bf4f8effd9a1", "description": "second Tuesday of May 2013", "property": "meetup", "input": { @@ -421,6 +458,7 @@ "expected": "2013-05-14" }, { + "uuid": "41b32c34-2e39-40e3-b790-93539aaeb6dd", "description": "second Tuesday of June 2013", "property": "meetup", "input": { @@ -432,6 +470,7 @@ "expected": "2013-06-11" }, { + "uuid": "90a160c5-b5d9-4831-927f-63a78b17843d", "description": "second Wednesday of July 2013", "property": "meetup", "input": { @@ -443,6 +482,7 @@ "expected": "2013-07-10" }, { + "uuid": "23b98ce7-8dd5-41a1-9310-ef27209741cb", "description": "second Wednesday of August 2013", "property": "meetup", "input": { @@ -454,6 +494,7 @@ "expected": "2013-08-14" }, { + "uuid": "447f1960-27ca-4729-bc3f-f36043f43ed0", "description": "second Thursday of September 2013", "property": "meetup", "input": { @@ -465,6 +506,7 @@ "expected": "2013-09-12" }, { + "uuid": "c9aa2687-300c-4e79-86ca-077849a81bde", "description": "second Thursday of October 2013", "property": "meetup", "input": { @@ -476,6 +518,7 @@ "expected": "2013-10-10" }, { + "uuid": "a7e11ef3-6625-4134-acda-3e7195421c09", "description": "second Friday of November 2013", "property": "meetup", "input": { @@ -487,6 +530,7 @@ "expected": "2013-11-08" }, { + "uuid": "8b420e5f-9290-4106-b5ae-022f3e2a3e41", "description": "second Friday of December 2013", "property": "meetup", "input": { @@ -498,6 +542,7 @@ "expected": "2013-12-13" }, { + "uuid": "80631afc-fc11-4546-8b5f-c12aaeb72b4f", "description": "second Saturday of January 2013", "property": "meetup", "input": { @@ -509,6 +554,7 @@ "expected": "2013-01-12" }, { + "uuid": "e34d43ac-f470-44c2-aa5f-e97b78ecaf83", "description": "second Saturday of February 2013", "property": "meetup", "input": { @@ -520,6 +566,7 @@ "expected": "2013-02-09" }, { + "uuid": "a57d59fd-1023-47ad-b0df-a6feb21b44fc", "description": "second Sunday of March 2013", "property": "meetup", "input": { @@ -531,6 +578,7 @@ "expected": "2013-03-10" }, { + "uuid": "a829a8b0-abdd-4ad1-b66c-5560d843c91a", "description": "second Sunday of April 2013", "property": "meetup", "input": { @@ -542,6 +590,7 @@ "expected": "2013-04-14" }, { + "uuid": "501a8a77-6038-4fc0-b74c-33634906c29d", "description": "third Monday of March 2013", "property": "meetup", "input": { @@ -553,6 +602,7 @@ "expected": "2013-03-18" }, { + "uuid": "49e4516e-cf32-4a58-8bbc-494b7e851c92", "description": "third Monday of April 2013", "property": "meetup", "input": { @@ -564,6 +614,7 @@ "expected": "2013-04-15" }, { + "uuid": "4db61095-f7c7-493c-85f1-9996ad3012c7", "description": "third Tuesday of May 2013", "property": "meetup", "input": { @@ -575,6 +626,7 @@ "expected": "2013-05-21" }, { + "uuid": "714fc2e3-58d0-4b91-90fd-61eefd2892c0", "description": "third Tuesday of June 2013", "property": "meetup", "input": { @@ -586,6 +638,7 @@ "expected": "2013-06-18" }, { + "uuid": "b08a051a-2c80-445b-9b0e-524171a166d1", "description": "third Wednesday of July 2013", "property": "meetup", "input": { @@ -597,6 +650,7 @@ "expected": "2013-07-17" }, { + "uuid": "80bb9eff-3905-4c61-8dc9-bb03016d8ff8", "description": "third Wednesday of August 2013", "property": "meetup", "input": { @@ -608,6 +662,7 @@ "expected": "2013-08-21" }, { + "uuid": "fa52a299-f77f-4784-b290-ba9189fbd9c9", "description": "third Thursday of September 2013", "property": "meetup", "input": { @@ -619,6 +674,7 @@ "expected": "2013-09-19" }, { + "uuid": "f74b1bc6-cc5c-4bf1-ba69-c554a969eb38", "description": "third Thursday of October 2013", "property": "meetup", "input": { @@ -630,6 +686,7 @@ "expected": "2013-10-17" }, { + "uuid": "8900f3b0-801a-466b-a866-f42d64667abd", "description": "third Friday of November 2013", "property": "meetup", "input": { @@ -641,6 +698,7 @@ "expected": "2013-11-15" }, { + "uuid": "538ac405-a091-4314-9ccd-920c4e38e85e", "description": "third Friday of December 2013", "property": "meetup", "input": { @@ -652,6 +710,7 @@ "expected": "2013-12-20" }, { + "uuid": "244db35c-2716-4fa0-88ce-afd58e5cf910", "description": "third Saturday of January 2013", "property": "meetup", "input": { @@ -663,6 +722,7 @@ "expected": "2013-01-19" }, { + "uuid": "dd28544f-f8fa-4f06-9bcd-0ad46ce68e9e", "description": "third Saturday of February 2013", "property": "meetup", "input": { @@ -674,6 +734,7 @@ "expected": "2013-02-16" }, { + "uuid": "be71dcc6-00d2-4b53-a369-cbfae55b312f", "description": "third Sunday of March 2013", "property": "meetup", "input": { @@ -685,6 +746,7 @@ "expected": "2013-03-17" }, { + "uuid": "b7d2da84-4290-4ee6-a618-ee124ae78be7", "description": "third Sunday of April 2013", "property": "meetup", "input": { @@ -696,6 +758,7 @@ "expected": "2013-04-21" }, { + "uuid": "4276dc06-a1bd-4fc2-b6c2-625fee90bc88", "description": "fourth Monday of March 2013", "property": "meetup", "input": { @@ -707,6 +770,7 @@ "expected": "2013-03-25" }, { + "uuid": "ddbd7976-2deb-4250-8a38-925ac1a8e9a2", "description": "fourth Monday of April 2013", "property": "meetup", "input": { @@ -718,6 +782,7 @@ "expected": "2013-04-22" }, { + "uuid": "eb714ef4-1656-47cc-913c-844dba4ebddd", "description": "fourth Tuesday of May 2013", "property": "meetup", "input": { @@ -729,6 +794,7 @@ "expected": "2013-05-28" }, { + "uuid": "16648435-7937-4d2d-b118-c3e38fd084bd", "description": "fourth Tuesday of June 2013", "property": "meetup", "input": { @@ -740,6 +806,7 @@ "expected": "2013-06-25" }, { + "uuid": "de062bdc-9484-437a-a8c5-5253c6f6785a", "description": "fourth Wednesday of July 2013", "property": "meetup", "input": { @@ -751,6 +818,7 @@ "expected": "2013-07-24" }, { + "uuid": "c2ce6821-169c-4832-8d37-690ef5d9514a", "description": "fourth Wednesday of August 2013", "property": "meetup", "input": { @@ -762,6 +830,7 @@ "expected": "2013-08-28" }, { + "uuid": "d462c631-2894-4391-a8e3-dbb98b7a7303", "description": "fourth Thursday of September 2013", "property": "meetup", "input": { @@ -773,6 +842,7 @@ "expected": "2013-09-26" }, { + "uuid": "9ff1f7b6-1b72-427d-9ee9-82b5bb08b835", "description": "fourth Thursday of October 2013", "property": "meetup", "input": { @@ -784,6 +854,7 @@ "expected": "2013-10-24" }, { + "uuid": "83bae8ba-1c49-49bc-b632-b7c7e1d7e35f", "description": "fourth Friday of November 2013", "property": "meetup", "input": { @@ -795,6 +866,7 @@ "expected": "2013-11-22" }, { + "uuid": "de752d2a-a95e-48d2-835b-93363dac3710", "description": "fourth Friday of December 2013", "property": "meetup", "input": { @@ -806,6 +878,7 @@ "expected": "2013-12-27" }, { + "uuid": "eedd90ad-d581-45db-8312-4c6dcf9cf560", "description": "fourth Saturday of January 2013", "property": "meetup", "input": { @@ -817,6 +890,7 @@ "expected": "2013-01-26" }, { + "uuid": "669fedcd-912e-48c7-a0a1-228b34af91d0", "description": "fourth Saturday of February 2013", "property": "meetup", "input": { @@ -828,6 +902,7 @@ "expected": "2013-02-23" }, { + "uuid": "648e3849-ea49-44a5-a8a3-9f2a43b3bf1b", "description": "fourth Sunday of March 2013", "property": "meetup", "input": { @@ -839,6 +914,7 @@ "expected": "2013-03-24" }, { + "uuid": "f81321b3-99ab-4db6-9267-69c5da5a7823", "description": "fourth Sunday of April 2013", "property": "meetup", "input": { @@ -850,6 +926,7 @@ "expected": "2013-04-28" }, { + "uuid": "1af5e51f-5488-4548-aee8-11d7d4a730dc", "description": "last Monday of March 2013", "property": "meetup", "input": { @@ -861,6 +938,7 @@ "expected": "2013-03-25" }, { + "uuid": "f29999f2-235e-4ec7-9dab-26f137146526", "description": "last Monday of April 2013", "property": "meetup", "input": { @@ -872,6 +950,7 @@ "expected": "2013-04-29" }, { + "uuid": "31b097a0-508e-48ac-bf8a-f63cdcf6dc41", "description": "last Tuesday of May 2013", "property": "meetup", "input": { @@ -883,6 +962,7 @@ "expected": "2013-05-28" }, { + "uuid": "8c022150-0bb5-4a1f-80f9-88b2e2abcba4", "description": "last Tuesday of June 2013", "property": "meetup", "input": { @@ -894,6 +974,7 @@ "expected": "2013-06-25" }, { + "uuid": "0e762194-672a-4bdf-8a37-1e59fdacef12", "description": "last Wednesday of July 2013", "property": "meetup", "input": { @@ -905,6 +986,7 @@ "expected": "2013-07-31" }, { + "uuid": "5016386a-f24e-4bd7-b439-95358f491b66", "description": "last Wednesday of August 2013", "property": "meetup", "input": { @@ -916,6 +998,7 @@ "expected": "2013-08-28" }, { + "uuid": "12ead1a5-cdf9-4192-9a56-2229e93dd149", "description": "last Thursday of September 2013", "property": "meetup", "input": { @@ -927,6 +1010,7 @@ "expected": "2013-09-26" }, { + "uuid": "7db89e11-7fbe-4e57-ae3c-0f327fbd7cc7", "description": "last Thursday of October 2013", "property": "meetup", "input": { @@ -938,6 +1022,7 @@ "expected": "2013-10-31" }, { + "uuid": "e47a739e-b979-460d-9c8a-75c35ca2290b", "description": "last Friday of November 2013", "property": "meetup", "input": { @@ -949,6 +1034,7 @@ "expected": "2013-11-29" }, { + "uuid": "5bed5aa9-a57a-4e5d-8997-2cc796a5b0ec", "description": "last Friday of December 2013", "property": "meetup", "input": { @@ -960,6 +1046,7 @@ "expected": "2013-12-27" }, { + "uuid": "61e54cba-76f3-4772-a2b1-bf443fda2137", "description": "last Saturday of January 2013", "property": "meetup", "input": { @@ -971,6 +1058,7 @@ "expected": "2013-01-26" }, { + "uuid": "8b6a737b-2fa9-444c-b1a2-80ce7a2ec72f", "description": "last Saturday of February 2013", "property": "meetup", "input": { @@ -982,6 +1070,7 @@ "expected": "2013-02-23" }, { + "uuid": "0b63e682-f429-4d19-9809-4a45bd0242dc", "description": "last Sunday of March 2013", "property": "meetup", "input": { @@ -993,6 +1082,7 @@ "expected": "2013-03-31" }, { + "uuid": "5232307e-d3e3-4afc-8ba6-4084ad987c00", "description": "last Sunday of April 2013", "property": "meetup", "input": { @@ -1004,6 +1094,7 @@ "expected": "2013-04-28" }, { + "uuid": "0bbd48e8-9773-4e81-8e71-b9a51711e3c5", "description": "last Wednesday of February 2012", "property": "meetup", "input": { @@ -1015,6 +1106,7 @@ "expected": "2012-02-29" }, { + "uuid": "fe0936de-7eee-4a48-88dd-66c07ab1fefc", "description": "last Wednesday of December 2014", "property": "meetup", "input": { @@ -1026,6 +1118,7 @@ "expected": "2014-12-31" }, { + "uuid": "2ccf2488-aafc-4671-a24e-2b6effe1b0e2", "description": "last Sunday of February 2015", "property": "meetup", "input": { @@ -1037,6 +1130,7 @@ "expected": "2015-02-22" }, { + "uuid": "00c3ce9f-cf36-4b70-90d8-92b32be6830e", "description": "first Friday of December 2012", "property": "meetup", "input": { @@ -1048,4 +1142,4 @@ "expected": "2012-12-07" } ] -} \ No newline at end of file +} diff --git a/exercises/micro-blog/canonical-data.json b/exercises/micro-blog/canonical-data.json new file mode 100644 index 0000000000..5a3d84022a --- /dev/null +++ b/exercises/micro-blog/canonical-data.json @@ -0,0 +1,136 @@ +{ + "exercise": "micro-blog", + "comments": [ + "This exercise is only applicable to languages that use UTF-8, UTF-16", + "or other variable width Unicode compatible encoding as their internal", + "string representation.", + "", + "This exercise is probably too easy in languages that use Unicode aware", + "string slicing.", + "", + "When adding additional tests to the problem specification, consider that", + "in progress solutions might not fail due to UTF-8 and UTF-16", + "differences.", + "", + "Avoid adding tests that involve characters (graphemes) that are made up", + "of multiple characters, or introduce them as a more advanced step.", + "", + "Consider adding a track specific hint.md about if your language uses", + "UTF-8, UTF-16 or other for its internal string representation." + ], + "cases": [ + { + "description": "Truncate a micro blog post", + "cases": [ + { + "uuid": "b927b57f-7c98-42fd-8f33-fae091dc1efc", + "description": "English language short", + "property": "truncate", + "input": { + "phrase": "Hi" + }, + "expected": "Hi" + }, + { + "uuid": "a3fcdc5b-0ed4-4f49-80f5-b1a293eac2a0", + "description": "English language long", + "property": "truncate", + "input": { + "phrase": "Hello there" + }, + "expected": "Hello" + }, + { + "uuid": "01910864-8e15-4007-9c7c-ac956c686e60", + "description": "German language short (broth)", + "property": "truncate", + "input": { + "phrase": "brühe" + }, + "expected": "brühe" + }, + { + "uuid": "f263e488-aefb-478f-a671-b6ba99722543", + "description": "German language long (bear carpet → beards)", + "property": "truncate", + "input": { + "phrase": "Bärteppich" + }, + "expected": "Bärte" + }, + { + "uuid": "0916e8f1-41d7-4402-a110-b08aa000342c", + "description": "Bulgarian language short (good)", + "property": "truncate", + "input": { + "phrase": "Добър" + }, + "expected": "Добър" + }, + { + "uuid": "bed6b89c-03df-4154-98e6-a61a74f61b7d", + "description": "Greek language short (health)", + "property": "truncate", + "input": { + "phrase": "υγειά" + }, + "expected": "υγειά" + }, + { + "uuid": "485a6a70-2edb-424d-b999-5529dbc8e002", + "description": "Maths short", + "property": "truncate", + "input": { + "phrase": "a=πr²" + }, + "expected": "a=πr²" + }, + { + "uuid": "8b4b7b51-8f48-4fbe-964e-6e4e6438be28", + "description": "Maths long", + "property": "truncate", + "input": { + "phrase": "∅⊊ℕ⊊ℤ⊊ℚ⊊ℝ⊊ℂ" + }, + "expected": "∅⊊ℕ⊊ℤ" + }, + { + "uuid": "71f4a192-0566-4402-a512-fe12878be523", + "description": "English and emoji short", + "property": "truncate", + "input": { + "phrase": "Fly 🛫" + }, + "expected": "Fly 🛫" + }, + { + "uuid": "6f0f71f3-9806-4759-a844-fa182f7bc203", + "description": "Emoji short", + "property": "truncate", + "input": { + "phrase": "💇" + }, + "expected": "💇" + }, + { + "uuid": "ce71fb92-5214-46d0-a7f8-d5ba56b4cc6e", + "description": "Emoji long", + "property": "truncate", + "input": { + "phrase": "❄🌡🤧🤒🏥🕰😀" + }, + "expected": "❄🌡🤧🤒🏥" + }, + { + "uuid": "5dee98d2-d56e-468a-a1f2-121c3f7c5a0b", + "description": "Royal Flush?", + "property": "truncate", + "input": { + "phrase": "🃎🂸🃅🃋🃍🃁🃊" + }, + "expected": "🃎🂸🃅🃋🃍" + } + ] + } + ] +} diff --git a/exercises/micro-blog/description.md b/exercises/micro-blog/description.md new file mode 100644 index 0000000000..7e35d42c95 --- /dev/null +++ b/exercises/micro-blog/description.md @@ -0,0 +1,39 @@ +You have identified a gap in the social media market for very very short +posts. Now that Twitter allows 280 character posts, people wanting quick +social media updates aren't being served. You decide to create your own +social media network. + +To make your product noteworthy, you make it extreme and only allow posts +of 5 or less characters. Any posts of more than 5 characters should be +truncated to 5. + +To allow your users to express themselves fully, you allow Emoji and +other Unicode. + +The task is to truncate input strings to 5 characters. + +## Text Encodings + +Text stored digitally has to be converted to a series of bytes. +There are 3 ways to map characters to bytes in common use. +* **ASCII** can encode English language characters. All +characters are precisely 1 byte long. +* **UTF-8** is a Unicode text encoding. Characters take between 1 +and 4 bytes. +* **UTF-16** is a Unicode text encoding. Characters are either 2 or +4 bytes long. + +UTF-8 and UTF-16 are both Unicode encodings which means they're capable of +representing a massive range of characters including: +* Text in most of the world's languages and scripts +* Historic text +* Emoji + +UTF-8 and UTF-16 are both variable length encodings, which means that +different characters take up different amounts of space. + +Consider the letter 'a' and the emoji '😛'. In UTF-16 the letter takes +2 bytes but the emoji takes 4 bytes. + +The trick to this exercise is to use APIs designed around Unicode +characters (codepoints) instead of Unicode codeunits. diff --git a/exercises/micro-blog/metadata.yml b/exercises/micro-blog/metadata.yml new file mode 100644 index 0000000000..c634933f18 --- /dev/null +++ b/exercises/micro-blog/metadata.yml @@ -0,0 +1,3 @@ +--- +title: "Micro Blog" +blurb: "Given an input string, truncate it to 5 characters." diff --git a/exercises/minesweeper/canonical-data.json b/exercises/minesweeper/canonical-data.json index 0c4f8f38a2..f6a3182263 100644 --- a/exercises/minesweeper/canonical-data.json +++ b/exercises/minesweeper/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "minesweeper", - "version": "1.1.0", "comments": [ " The expected outputs are represented as arrays of strings to ", " improve readability in this JSON file. ", @@ -9,6 +8,7 @@ ], "cases": [ { + "uuid": "0c5ec4bd-dea7-4138-8651-1203e1cb9f44", "description": "no rows", "property": "annotate", "input": { @@ -17,6 +17,7 @@ "expected": [] }, { + "uuid": "650ac4c0-ad6b-4b41-acde-e4ea5852c3b8", "description": "no columns", "property": "annotate", "input": { @@ -25,6 +26,7 @@ "expected": [""] }, { + "uuid": "6fbf8f6d-a03b-42c9-9a58-b489e9235478", "description": "no mines", "property": "annotate", "input": { @@ -41,6 +43,7 @@ ] }, { + "uuid": "61aff1c4-fb31-4078-acad-cd5f1e635655", "description": "minefield with only mines", "property": "annotate", "input": { @@ -57,6 +60,7 @@ ] }, { + "uuid": "84167147-c504-4896-85d7-246b01dea7c5", "description": "mine surrounded by spaces", "property": "annotate", "input": { @@ -73,6 +77,7 @@ ] }, { + "uuid": "cb878f35-43e3-4c9d-93d9-139012cccc4a", "description": "space surrounded by mines", "property": "annotate", "input": { @@ -89,6 +94,7 @@ ] }, { + "uuid": "7037f483-ddb4-4b35-b005-0d0f4ef4606f", "description": "horizontal line", "property": "annotate", "input": { @@ -97,6 +103,7 @@ "expected": ["1*2*1"] }, { + "uuid": "e359820f-bb8b-4eda-8762-47b64dba30a6", "description": "horizontal line, mines at edges", "property": "annotate", "input": { @@ -105,6 +112,7 @@ "expected": ["*1 1*"] }, { + "uuid": "c5198b50-804f-47e9-ae02-c3b42f7ce3ab", "description": "vertical line", "property": "annotate", "input": { @@ -125,6 +133,7 @@ ] }, { + "uuid": "0c79a64d-703d-4660-9e90-5adfa5408939", "description": "vertical line, mines at edges", "property": "annotate", "input": { @@ -145,6 +154,7 @@ ] }, { + "uuid": "4b098563-b7f3-401c-97c6-79dd1b708f34", "description": "cross", "property": "annotate", "input": { @@ -165,6 +175,7 @@ ] }, { + "uuid": "04a260f1-b40a-4e89-839e-8dd8525abe0e", "description": "large minefield", "property": "annotate", "input": { diff --git a/exercises/minesweeper/description.md b/exercises/minesweeper/description.md index be4077654d..98583d4d3d 100644 --- a/exercises/minesweeper/description.md +++ b/exercises/minesweeper/description.md @@ -1,25 +1,35 @@ -Add the numbers to a minesweeper board. +Add the mine counts to a completed Minesweeper board. 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. In this exercise you have to create some code that counts the number of -mines adjacent to a square and transforms boards like this (where `*` -indicates a mine): - - +-----+ - | * * | - | * | - | * | - | | - +-----+ - -into this: - - +-----+ - |1*3*1| - |13*31| - | 2*2 | - | 111 | - +-----+ +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): + +``` +·*·*· +··*·· +··*·· +····· +``` + +And your code will transform it into this: + +``` +1*3*1 +13*31 +·2*2· +·111· +``` diff --git a/exercises/nth-prime/canonical-data.json b/exercises/nth-prime/canonical-data.json index 80546f69a4..bc1646f1aa 100644 --- a/exercises/nth-prime/canonical-data.json +++ b/exercises/nth-prime/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "nth-prime", - "version": "2.1.0", "cases": [ { + "uuid": "75c65189-8aef-471a-81de-0a90c728160c", "description": "first prime", "property": "prime", "input": { @@ -11,6 +11,7 @@ "expected": 2 }, { + "uuid": "2c38804c-295f-4701-b728-56dea34fd1a0", "description": "second prime", "property": "prime", "input": { @@ -19,6 +20,7 @@ "expected": 3 }, { + "uuid": "56692534-781e-4e8c-b1f9-3e82c1640259", "description": "sixth prime", "property": "prime", "input": { @@ -27,6 +29,7 @@ "expected": 13 }, { + "uuid": "fce1e979-0edb-412d-93aa-2c744e8f50ff", "description": "big prime", "property": "prime", "input": { @@ -35,6 +38,7 @@ "expected": 104743 }, { + "uuid": "bd0a9eae-6df7-485b-a144-80e13c7d55b2", "description": "there is no zeroth prime", "property": "prime", "input": { @@ -45,4 +49,4 @@ } } ] -} \ No newline at end of file +} diff --git a/exercises/nucleotide-count/canonical-data.json b/exercises/nucleotide-count/canonical-data.json index 597ee93ab1..d0f27a6076 100644 --- a/exercises/nucleotide-count/canonical-data.json +++ b/exercises/nucleotide-count/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "nucleotide-count", - "version": "1.3.0", "cases": [ { "description": "count all nucleotides in a strand", "cases": [ { + "uuid": "3e5c30a8-87e2-4845-a815-a49671ade970", "description": "empty strand", "property": "nucleotideCounts", "input": { @@ -19,6 +19,7 @@ } }, { + "uuid": "a0ea42a6-06d9-4ac6-828c-7ccaccf98fec", "description": "can count one nucleotide in single-character input", "property": "nucleotideCounts", "input": { @@ -32,6 +33,7 @@ } }, { + "uuid": "eca0d565-ed8c-43e7-9033-6cefbf5115b5", "description": "strand with repeated nucleotide", "property": "nucleotideCounts", "input": { @@ -45,6 +47,7 @@ } }, { + "uuid": "40a45eac-c83f-4740-901a-20b22d15a39f", "description": "strand with multiple nucleotides", "property": "nucleotideCounts", "input": { @@ -58,6 +61,7 @@ } }, { + "uuid": "b4c47851-ee9e-4b0a-be70-a86e343bd851", "description": "strand with invalid nucleotides", "property": "nucleotideCounts", "input": { @@ -70,4 +74,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/nucleotide-count/description.md b/exercises/nucleotide-count/description.md index 77854d64ee..206c0258de 100644 --- a/exercises/nucleotide-count/description.md +++ b/exercises/nucleotide-count/description.md @@ -1,11 +1,19 @@ -Given a single stranded DNA string, compute how many times each nucleotide occurs in the string. +Each of us inherits from our biological parents a set of chemical instructions known as DNA that influence how our bodies are constructed. All known life depends on DNA! -The genetic language of every living thing on the planet is DNA. -DNA is a large molecule that is built from an extremely long sequence of individual elements called nucleotides. -4 types exist in DNA and these differ only slightly and can be represented as the following symbols: 'A' for adenine, 'C' for cytosine, 'G' for guanine, and 'T' thymine. +> Note: You do not need to understand anything about nucleotides or DNA to complete this exercise. -Here is an analogy: -- twigs are to birds nests as -- nucleotides are to DNA as -- legos are to lego houses as -- words are to sentences as... +DNA is a long chain of other chemicals and the most important are the four nucleotides, adenine, cytosine, guanine and thymine. A single DNA chain can contain billions of these four nucleotides and the order in which they occur is important! +We call the order of these nucleotides in a bit of DNA a "DNA sequence". + +We represent a DNA sequence as an ordered collection of these four nucleotides and a common way to do that is with a string of characters such as "ATTACG" for a DNA sequence of 6 nucleotides. +'A' for adenine, 'C' for cytosine, 'G' for guanine, and 'T' for thymine. + +Given a string representing a DNA sequence, count how many of each nucleotide is present. +If the string contains characters that aren't A, C, G, or T then it is invalid and you should signal an error. + +For example: + +``` +"GATTACA" -> 'A': 3, 'C': 1, 'G': 1, 'T': 2 +"INVALID" -> error +``` diff --git a/exercises/ocr-numbers/canonical-data.json b/exercises/ocr-numbers/canonical-data.json index 1c63708125..8948b2eaaa 100644 --- a/exercises/ocr-numbers/canonical-data.json +++ b/exercises/ocr-numbers/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "ocr-numbers", - "version": "1.2.0", "cases": [ { "description": "Converts lines of OCR Numbers to a string of integers", "cases": [ { + "uuid": "5ee54e1a-b554-4bf3-a056-9a7976c3f7e8", "description": "Recognizes 0", "property": "convert", "input": { @@ -19,6 +19,7 @@ "expected": "0" }, { + "uuid": "027ada25-17fd-4d78-aee6-35a19623639d", "description": "Recognizes 1", "property": "convert", "input": { @@ -32,6 +33,7 @@ "expected": "1" }, { + "uuid": "3cce2dbd-01d9-4f94-8fae-419a822e89bb", "description": "Unreadable but correctly sized inputs return ?", "property": "convert", "input": { @@ -45,6 +47,7 @@ "expected": "?" }, { + "uuid": "cb19b733-4e36-4cf9-a4a1-6e6aac808b9a", "description": "Input with a number of lines that is not a multiple of four raises an error", "property": "convert", "input": { @@ -57,6 +60,7 @@ "expected": {"error": "Number of input lines is not a multiple of four"} }, { + "uuid": "235f7bd1-991b-4587-98d4-84206eec4cc6", "description": "Input with a number of columns that is not a multiple of three raises an error", "property": "convert", "input": { @@ -70,6 +74,7 @@ "expected": {"error": "Number of input columns is not a multiple of three"} }, { + "uuid": "4a841794-73c9-4da9-a779-1f9837faff66", "description": "Recognizes 110101100", "property": "convert", "input": { @@ -83,6 +88,7 @@ "expected": "110101100" }, { + "uuid": "70c338f9-85b1-4296-a3a8-122901cdfde8", "description": "Garbled numbers in a string are replaced with ?", "property": "convert", "input": { @@ -96,6 +102,7 @@ "expected": "11?10?1?0" }, { + "uuid": "ea494ff4-3610-44d7-ab7e-72fdef0e0802", "description": "Recognizes 2", "property": "convert", "input": { @@ -109,6 +116,7 @@ "expected": "2" }, { + "uuid": "1acd2c00-412b-4268-93c2-bd7ff8e05a2c", "description": "Recognizes 3", "property": "convert", "input": { @@ -122,6 +130,7 @@ "expected": "3" }, { + "uuid": "eaec6a15-be17-4b6d-b895-596fae5d1329", "description": "Recognizes 4", "property": "convert", "input": { @@ -135,6 +144,7 @@ "expected": "4" }, { + "uuid": "440f397a-f046-4243-a6ca-81ab5406c56e", "description": "Recognizes 5", "property": "convert", "input": { @@ -148,6 +158,7 @@ "expected": "5" }, { + "uuid": "f4c9cf6a-f1e2-4878-bfc3-9b85b657caa0", "description": "Recognizes 6", "property": "convert", "input": { @@ -161,6 +172,7 @@ "expected": "6" }, { + "uuid": "e24ebf80-c611-41bb-a25a-ac2c0f232df5", "description": "Recognizes 7", "property": "convert", "input": { @@ -174,6 +186,7 @@ "expected": "7" }, { + "uuid": "b79cad4f-e264-4818-9d9e-77766792e233", "description": "Recognizes 8", "property": "convert", "input": { @@ -187,6 +200,7 @@ "expected": "8" }, { + "uuid": "5efc9cfc-9227-4688-b77d-845049299e66", "description": "Recognizes 9", "property": "convert", "input": { @@ -200,6 +214,7 @@ "expected": "9" }, { + "uuid": "f60cb04a-42be-494e-a535-3451c8e097a4", "description": "Recognizes string of decimal numbers", "property": "convert", "input": { @@ -213,6 +228,7 @@ "expected": "1234567890" }, { + "uuid": "b73ecf8b-4423-4b36-860d-3710bdb8a491", "description": "Numbers separated by empty lines are recognized. Lines are joined by commas.", "property": "convert", "input": { diff --git a/exercises/paasio/metadata.yml b/exercises/paasio/metadata.yml index 5100ad66e1..d6137c6191 100644 --- a/exercises/paasio/metadata.yml +++ b/exercises/paasio/metadata.yml @@ -1,4 +1,5 @@ --- +title: "PaaS I/O" blurb: "Report network IO statistics" source: "Brian Matsuo" source_url: "https://github.com/bmatsuo" diff --git a/exercises/palindrome-products/canonical-data.json b/exercises/palindrome-products/canonical-data.json index 4a96e5712b..054624728d 100644 --- a/exercises/palindrome-products/canonical-data.json +++ b/exercises/palindrome-products/canonical-data.json @@ -1,7 +1,7 @@ { "exercise": "palindrome-products", - "version": "1.2.0", "cases": [{ + "uuid": "5cff78fe-cf02-459d-85c2-ce584679f887", "description": "finds the smallest palindrome from single digit factors", "property": "smallest", "input": { @@ -16,6 +16,7 @@ } }, { + "uuid": "0853f82c-5fc4-44ae-be38-fadb2cced92d", "description": "finds the largest palindrome from single digit factors", "property": "largest", "input": { @@ -31,6 +32,7 @@ } }, { + "uuid": "66c3b496-bdec-4103-9129-3fcb5a9063e1", "description": "find the smallest palindrome from double digit factors", "property": "smallest", "input": { @@ -45,6 +47,7 @@ } }, { + "uuid": "a10682ae-530a-4e56-b89d-69664feafe53", "description": "find the largest palindrome from double digit factors", "property": "largest", "input": { @@ -59,6 +62,7 @@ } }, { + "uuid": "cecb5a35-46d1-4666-9719-fa2c3af7499d", "description": "find smallest palindrome from triple digit factors", "property": "smallest", "input": { @@ -73,6 +77,7 @@ } }, { + "uuid": "edab43e1-c35f-4ea3-8c55-2f31dddd92e5", "description": "find the largest palindrome from triple digit factors", "property": "largest", "input": { @@ -87,6 +92,7 @@ } }, { + "uuid": "4f802b5a-9d74-4026-a70f-b53ff9234e4e", "description": "find smallest palindrome from four digit factors", "property": "smallest", "input": { @@ -101,6 +107,7 @@ } }, { + "uuid": "787525e0-a5f9-40f3-8cb2-23b52cf5d0be", "description": "find the largest palindrome from four digit factors", "property": "largest", "input": { @@ -115,6 +122,7 @@ } }, { + "uuid": "58fb1d63-fddb-4409-ab84-a7a8e58d9ea0", "description": "empty result for smallest if no palindrome in the range", "property": "smallest", "input": { @@ -127,6 +135,7 @@ } }, { + "uuid": "9de9e9da-f1d9-49a5-8bfc-3d322efbdd02", "description": "empty result for largest if no palindrome in the range", "property": "largest", "input": { @@ -139,6 +148,7 @@ } }, { + "uuid": "12e73aac-d7ee-4877-b8aa-2aa3dcdb9f8a", "description": "error result for smallest if min is more than max", "property": "smallest", "input": { @@ -150,6 +160,7 @@ } }, { + "uuid": "eeeb5bff-3f47-4b1e-892f-05829277bd74", "description": "error result for largest if min is more than max", "property": "largest", "input": { @@ -161,4 +172,4 @@ } } ] -} \ No newline at end of file +} diff --git a/exercises/palindrome-products/description.md b/exercises/palindrome-products/description.md index a4256f2519..57504a8c22 100644 --- a/exercises/palindrome-products/description.md +++ b/exercises/palindrome-products/description.md @@ -4,7 +4,7 @@ A palindromic number is a number that remains the same when its digits are reversed. For example, `121` is a palindromic number but `112` is not. Given a range of numbers, find the largest and smallest palindromes which -are products of numbers within that range. +are products of two numbers within that range. Your solution should return the largest and smallest palindromes, along with the factors of each within the range. If the largest or smallest palindrome has more diff --git a/exercises/pangram/canonical-data.json b/exercises/pangram/canonical-data.json index d940ebd103..a674b35d37 100644 --- a/exercises/pangram/canonical-data.json +++ b/exercises/pangram/canonical-data.json @@ -4,9 +4,9 @@ "A pangram is a sentence using every letter of the alphabet at least once.", "Output should be a boolean denoting if the string is a pangram or not." ], - "version": "2.0.0", "cases": [ { + "uuid": "64f61791-508e-4f5c-83ab-05de042b0149", "description": "empty sentence", "property": "isPangram", "input": { @@ -15,6 +15,7 @@ "expected": false }, { + "uuid": "74858f80-4a4d-478b-8a5e-c6477e4e4e84", "description": "perfect lower case", "property": "isPangram", "input": { @@ -23,6 +24,7 @@ "expected": true }, { + "uuid": "61288860-35ca-4abe-ba08-f5df76ecbdcd", "description": "only lower case", "property": "isPangram", "input": { @@ -31,6 +33,7 @@ "expected": true }, { + "uuid": "6564267d-8ac5-4d29-baf2-e7d2e304a743", "description": "missing the letter 'x'", "property": "isPangram", "input": { @@ -39,6 +42,7 @@ "expected": false }, { + "uuid": "c79af1be-d715-4cdb-a5f2-b2fa3e7e0de0", "description": "missing the letter 'h'", "property": "isPangram", "input": { @@ -47,6 +51,7 @@ "expected": false }, { + "uuid": "d835ec38-bc8f-48e4-9e36-eb232427b1df", "description": "with underscores", "property": "isPangram", "input": { @@ -55,6 +60,7 @@ "expected": true }, { + "uuid": "8cc1e080-a178-4494-b4b3-06982c9be2a8", "description": "with numbers", "property": "isPangram", "input": { @@ -63,6 +69,7 @@ "expected": true }, { + "uuid": "bed96b1c-ff95-45b8-9731-fdbdcb6ede9a", "description": "missing letters replaced by numbers", "property": "isPangram", "input": { @@ -71,6 +78,7 @@ "expected": false }, { + "uuid": "938bd5d8-ade5-40e2-a2d9-55a338a01030", "description": "mixed case and punctuation", "property": "isPangram", "input": { @@ -79,6 +87,7 @@ "expected": true }, { + "uuid": "2577bf54-83c8-402d-a64b-a2c0f7bb213a", "description": "case insensitive", "property": "isPangram", "input": { diff --git a/exercises/pascals-triangle/canonical-data.json b/exercises/pascals-triangle/canonical-data.json index 2d9c06e4e5..74a1962424 100644 --- a/exercises/pascals-triangle/canonical-data.json +++ b/exercises/pascals-triangle/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "pascals-triangle", - "version": "1.5.0", "comments": [ "Expectations are represented here as an array of arrays.", "How you represent this idiomatically in your language is up to you." @@ -10,6 +9,7 @@ "description": "Given a count, return a collection of that many rows of pascal's triangle", "cases": [ { + "uuid": "9920ce55-9629-46d5-85d6-4201f4a4234d", "description": "zero rows", "property": "rows", "input": { @@ -18,6 +18,7 @@ "expected": [] }, { + "uuid": "70d643ce-a46d-4e93-af58-12d88dd01f21", "description": "single row", "property": "rows", "input": { @@ -26,6 +27,7 @@ "expected": [[1]] }, { + "uuid": "a6e5a2a2-fc9a-4b47-9f4f-ed9ad9fbe4bd", "description": "two rows", "property": "rows", "input": { @@ -34,6 +36,7 @@ "expected": [[1], [1, 1]] }, { + "uuid": "97206a99-79ba-4b04-b1c5-3c0fa1e16925", "description": "three rows", "property": "rows", "input": { @@ -42,6 +45,7 @@ "expected": [[1], [1, 1], [1, 2, 1]] }, { + "uuid": "565a0431-c797-417c-a2c8-2935e01ce306", "description": "four rows", "property": "rows", "input": { @@ -50,6 +54,7 @@ "expected": [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1]] }, { + "uuid": "06f9ea50-9f51-4eb2-b9a9-c00975686c27", "description": "five rows", "property": "rows", "input": { @@ -58,6 +63,7 @@ "expected": [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]] }, { + "uuid": "c3912965-ddb4-46a9-848e-3363e6b00b13", "description": "six rows", "property": "rows", "input": { @@ -66,6 +72,7 @@ "expected": [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1], [1, 5, 10, 10, 5, 1]] }, { + "uuid": "6cb26c66-7b57-4161-962c-81ec8c99f16b", "description": "ten rows", "property": "rows", "input": { diff --git a/exercises/perfect-numbers/canonical-data.json b/exercises/perfect-numbers/canonical-data.json index 95ab0b81c9..1c462006aa 100644 --- a/exercises/perfect-numbers/canonical-data.json +++ b/exercises/perfect-numbers/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "perfect-numbers", - "version": "1.1.0", "cases": [ { "description": "Perfect numbers", "cases": [ { + "uuid": "163e8e86-7bfd-4ee2-bd68-d083dc3381a3", "description": "Smallest perfect number is classified correctly", "property": "classify", "input": { @@ -14,6 +14,7 @@ "expected": "perfect" }, { + "uuid": "169a7854-0431-4ae0-9815-c3b6d967436d", "description": "Medium perfect number is classified correctly", "property": "classify", "input": { @@ -22,6 +23,7 @@ "expected": "perfect" }, { + "uuid": "ee3627c4-7b36-4245-ba7c-8727d585f402", "description": "Large perfect number is classified correctly", "property": "classify", "input": { @@ -35,6 +37,7 @@ "description": "Abundant numbers", "cases": [ { + "uuid": "80ef7cf8-9ea8-49b9-8b2d-d9cb3db3ed7e", "description": "Smallest abundant number is classified correctly", "property": "classify", "input": { @@ -43,6 +46,7 @@ "expected": "abundant" }, { + "uuid": "3e300e0d-1a12-4f11-8c48-d1027165ab60", "description": "Medium abundant number is classified correctly", "property": "classify", "input": { @@ -51,6 +55,7 @@ "expected": "abundant" }, { + "uuid": "ec7792e6-8786-449c-b005-ce6dd89a772b", "description": "Large abundant number is classified correctly", "property": "classify", "input": { @@ -64,6 +69,7 @@ "description": "Deficient numbers", "cases": [ { + "uuid": "e610fdc7-2b6e-43c3-a51c-b70fb37413ba", "description": "Smallest prime deficient number is classified correctly", "property": "classify", "input": { @@ -72,6 +78,7 @@ "expected": "deficient" }, { + "uuid": "0beb7f66-753a-443f-8075-ad7fbd9018f3", "description": "Smallest non-prime deficient number is classified correctly", "property": "classify", "input": { @@ -80,6 +87,7 @@ "expected": "deficient" }, { + "uuid": "1c802e45-b4c6-4962-93d7-1cad245821ef", "description": "Medium deficient number is classified correctly", "property": "classify", "input": { @@ -88,6 +96,7 @@ "expected": "deficient" }, { + "uuid": "47dd569f-9e5a-4a11-9a47-a4e91c8c28aa", "description": "Large deficient number is classified correctly", "property": "classify", "input": { @@ -96,6 +105,7 @@ "expected": "deficient" }, { + "uuid": "a696dec8-6147-4d68-afad-d38de5476a56", "description": "Edge case (no factors other than itself) is classified correctly", "property": "classify", "input": { @@ -109,26 +119,28 @@ "description": "Invalid inputs", "cases": [ { - "description": "Zero is rejected (not a natural number)", + "uuid": "72445cee-660c-4d75-8506-6c40089dc302", + "description": "Zero is rejected (as it is not a positive integer)", "property": "classify", "input": { "number": 0 }, "expected": { - "error": "Classification is only possible for natural numbers." + "error": "Classification is only possible for positive integers." } }, { - "description": "Negative integer is rejected (not a natural number)", + "uuid": "2d72ce2c-6802-49ac-8ece-c790ba3dae13", + "description": "Negative integer is rejected (as it is not a positive integer)", "property": "classify", "input": { "number": -1 }, "expected": { - "error": "Classification is only possible for natural numbers." + "error": "Classification is only possible for positive integers." } } ] } ] -} \ No newline at end of file +} diff --git a/exercises/perfect-numbers/description.md b/exercises/perfect-numbers/description.md index b1b8306e71..e70f150f0f 100644 --- a/exercises/perfect-numbers/description.md +++ b/exercises/perfect-numbers/description.md @@ -1,7 +1,7 @@ Determine if a number is perfect, abundant, or deficient based on -Nicomachus' (60 - 120 CE) classification scheme for natural numbers. +Nicomachus' (60 - 120 CE) classification scheme for positive integers. -The Greek mathematician [Nicomachus](https://en.wikipedia.org/wiki/Nicomachus) devised a classification scheme for natural numbers, identifying each as belonging uniquely to the categories of **perfect**, **abundant**, or **deficient** based on their [aliquot sum](https://en.wikipedia.org/wiki/Aliquot_sum). The aliquot sum is defined as the sum of the factors of a number not including the number itself. For example, the aliquot sum of 15 is (1 + 3 + 5) = 9 +The Greek mathematician [Nicomachus](https://en.wikipedia.org/wiki/Nicomachus) devised a classification scheme for positive integers, identifying each as belonging uniquely to the categories of **perfect**, **abundant**, or **deficient** based on their [aliquot sum](https://en.wikipedia.org/wiki/Aliquot_sum). The aliquot sum is defined as the sum of the factors of a number not including the number itself. For example, the aliquot sum of 15 is (1 + 3 + 5) = 9 - **Perfect**: aliquot sum = number - 6 is a perfect number because (1 + 2 + 3) = 6 diff --git a/exercises/perfect-numbers/metadata.yml b/exercises/perfect-numbers/metadata.yml index b2514cf54d..67234e6aca 100644 --- a/exercises/perfect-numbers/metadata.yml +++ b/exercises/perfect-numbers/metadata.yml @@ -1,4 +1,4 @@ --- -blurb: "Determine if a number is perfect, abundant, or deficient based on Nicomachus' (60 - 120 CE) classification scheme for natural numbers." +blurb: "Determine if a number is perfect, abundant, or deficient based on Nicomachus' (60 - 120 CE) classification scheme for positive integers." source: "Taken from Chapter 2 of Functional Thinking by Neal Ford." source_url: "http://shop.oreilly.com/product/0636920029687.do" diff --git a/exercises/phone-number/canonical-data.json b/exercises/phone-number/canonical-data.json index 155d2589a6..4b86fb0a0b 100644 --- a/exercises/phone-number/canonical-data.json +++ b/exercises/phone-number/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "phone-number", - "version": "1.7.0", "cases": [ { "description": "Cleanup user-entered phone numbers", @@ -11,6 +10,7 @@ ], "cases": [ { + "uuid": "79666dce-e0f1-46de-95a1-563802913c35", "description": "cleans the number", "property": "clean", "input": { @@ -19,6 +19,7 @@ "expected": "2234567890" }, { + "uuid": "c360451f-549f-43e4-8aba-fdf6cb0bf83f", "description": "cleans numbers with dots", "property": "clean", "input": { @@ -27,6 +28,7 @@ "expected": "2234567890" }, { + "uuid": "08f94c34-9a37-46a2-a123-2a8e9727395d", "description": "cleans numbers with multiple spaces", "property": "clean", "input": { @@ -35,6 +37,7 @@ "expected": "2234567890" }, { + "uuid": "598d8432-0659-4019-a78b-1c6a73691d21", "description": "invalid when 9 digits", "property": "clean", "input": { @@ -43,6 +46,7 @@ "expected": {"error": "incorrect number of digits"} }, { + "uuid": "57061c72-07b5-431f-9766-d97da7c4399d", "description": "invalid when 11 digits does not start with a 1", "property": "clean", "input": { @@ -51,6 +55,7 @@ "expected": {"error": "11 digits must start with 1"} }, { + "uuid": "9962cbf3-97bb-4118-ba9b-38ff49c64430", "description": "valid when 11 digits and starting with 1", "property": "clean", "input": { @@ -59,6 +64,7 @@ "expected": "2234567890" }, { + "uuid": "fa724fbf-054c-4d91-95da-f65ab5b6dbca", "description": "valid when 11 digits and starting with 1 even with punctuation", "property": "clean", "input": { @@ -67,6 +73,7 @@ "expected": "2234567890" }, { + "uuid": "c6a5f007-895a-4fc5-90bc-a7e70f9b5cad", "description": "invalid when more than 11 digits", "property": "clean", "input": { @@ -75,6 +82,7 @@ "expected": {"error": "more than 11 digits"} }, { + "uuid": "63f38f37-53f6-4a5f-bd86-e9b404f10a60", "description": "invalid with letters", "property": "clean", "input": { @@ -83,6 +91,7 @@ "expected": {"error": "letters not permitted"} }, { + "uuid": "4bd97d90-52fd-45d3-b0db-06ab95b1244e", "description": "invalid with punctuations", "property": "clean", "input": { @@ -91,6 +100,7 @@ "expected": {"error": "punctuations not permitted"} }, { + "uuid": "d77d07f8-873c-4b17-8978-5f66139bf7d7", "description": "invalid if area code starts with 0", "property": "clean", "input": { @@ -99,6 +109,7 @@ "expected": {"error": "area code cannot start with zero"} }, { + "uuid": "c7485cfb-1e7b-4081-8e96-8cdb3b77f15e", "description": "invalid if area code starts with 1", "property": "clean", "input": { @@ -107,6 +118,7 @@ "expected": {"error": "area code cannot start with one"} }, { + "uuid": "4d622293-6976-413d-b8bf-dd8a94d4e2ac", "description": "invalid if exchange code starts with 0", "property": "clean", "input": { @@ -115,6 +127,7 @@ "expected": {"error": "exchange code cannot start with zero"} }, { + "uuid": "4cef57b4-7d8e-43aa-8328-1e1b89001262", "description": "invalid if exchange code starts with 1", "property": "clean", "input": { @@ -123,6 +136,7 @@ "expected": {"error": "exchange code cannot start with one"} }, { + "uuid": "9925b09c-1a0d-4960-a197-5d163cbe308c", "description": "invalid if area code starts with 0 on valid 11-digit number", "property": "clean", "input": { @@ -131,6 +145,7 @@ "expected": {"error": "area code cannot start with zero"} }, { + "uuid": "3f809d37-40f3-44b5-ad90-535838b1a816", "description": "invalid if area code starts with 1 on valid 11-digit number", "property": "clean", "input": { @@ -139,6 +154,7 @@ "expected": {"error": "area code cannot start with one"} }, { + "uuid": "e08e5532-d621-40d4-b0cc-96c159276b65", "description": "invalid if exchange code starts with 0 on valid 11-digit number", "property": "clean", "input": { @@ -147,6 +163,7 @@ "expected": {"error": "exchange code cannot start with zero"} }, { + "uuid": "57b32f3d-696a-455c-8bf1-137b6d171cdf", "description": "invalid if exchange code starts with 1 on valid 11-digit number", "property": "clean", "input": { diff --git a/exercises/pig-latin/canonical-data.json b/exercises/pig-latin/canonical-data.json index 4ec929fd93..9b7b11cc69 100644 --- a/exercises/pig-latin/canonical-data.json +++ b/exercises/pig-latin/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "pig-latin", - "version": "1.2.0", "cases": [ { "description": "ay is added to words that start with vowels", "cases": [ { + "uuid": "11567f84-e8c6-4918-aedb-435f0b73db57", "description": "word beginning with a", "property": "translate", "input": { @@ -14,6 +14,7 @@ "expected": "appleay" }, { + "uuid": "f623f581-bc59-4f45-9032-90c3ca9d2d90", "description": "word beginning with e", "property": "translate", "input": { @@ -22,6 +23,7 @@ "expected": "earay" }, { + "uuid": "7dcb08b3-23a6-4e8a-b9aa-d4e859450d58", "description": "word beginning with i", "property": "translate", "input": { @@ -30,6 +32,7 @@ "expected": "iglooay" }, { + "uuid": "0e5c3bff-266d-41c8-909f-364e4d16e09c", "description": "word beginning with o", "property": "translate", "input": { @@ -38,6 +41,7 @@ "expected": "objectay" }, { + "uuid": "614ba363-ca3c-4e96-ab09-c7320799723c", "description": "word beginning with u", "property": "translate", "input": { @@ -46,6 +50,7 @@ "expected": "underay" }, { + "uuid": "bf2538c6-69eb-4fa7-a494-5a3fec911326", "description": "word beginning with a vowel and followed by a qu", "property": "translate", "input": { @@ -59,6 +64,7 @@ "description": "first letter and ay are moved to the end of words that start with consonants", "cases": [ { + "uuid": "e5be8a01-2d8a-45eb-abb4-3fcc9582a303", "description": "word beginning with p", "property": "translate", "input": { @@ -67,6 +73,7 @@ "expected": "igpay" }, { + "uuid": "d36d1e13-a7ed-464d-a282-8820cb2261ce", "description": "word beginning with k", "property": "translate", "input": { @@ -75,6 +82,7 @@ "expected": "oalakay" }, { + "uuid": "d838b56f-0a89-4c90-b326-f16ff4e1dddc", "description": "word beginning with x", "property": "translate", "input": { @@ -83,6 +91,7 @@ "expected": "enonxay" }, { + "uuid": "bce94a7a-a94e-4e2b-80f4-b2bb02e40f71", "description": "word beginning with q without a following u", "property": "translate", "input": { @@ -96,6 +105,7 @@ "description": "some letter clusters are treated like a single consonant", "cases": [ { + "uuid": "c01e049a-e3e2-451c-bf8e-e2abb7e438b8", "description": "word beginning with ch", "property": "translate", "input": { @@ -104,6 +114,7 @@ "expected": "airchay" }, { + "uuid": "9ba1669e-c43f-4b93-837a-cfc731fd1425", "description": "word beginning with qu", "property": "translate", "input": { @@ -112,6 +123,7 @@ "expected": "eenquay" }, { + "uuid": "92e82277-d5e4-43d7-8dd3-3a3b316c41f7", "description": "word beginning with qu and a preceding consonant", "property": "translate", "input": { @@ -120,6 +132,7 @@ "expected": "aresquay" }, { + "uuid": "79ae4248-3499-4d5b-af46-5cb05fa073ac", "description": "word beginning with th", "property": "translate", "input": { @@ -128,6 +141,7 @@ "expected": "erapythay" }, { + "uuid": "e0b3ae65-f508-4de3-8999-19c2f8e243e1", "description": "word beginning with thr", "property": "translate", "input": { @@ -136,6 +150,7 @@ "expected": "ushthray" }, { + "uuid": "20bc19f9-5a35-4341-9d69-1627d6ee6b43", "description": "word beginning with sch", "property": "translate", "input": { @@ -149,6 +164,7 @@ "description": "some letter clusters are treated like a single vowel", "cases": [ { + "uuid": "54b796cb-613d-4509-8c82-8fbf8fc0af9e", "description": "word beginning with yt", "property": "translate", "input": { @@ -157,6 +173,7 @@ "expected": "yttriaay" }, { + "uuid": "8c37c5e1-872e-4630-ba6e-d20a959b67f6", "description": "word beginning with xr", "property": "translate", "input": { @@ -170,6 +187,7 @@ "description": "position of y in a word determines if it is a consonant or a vowel", "cases": [ { + "uuid": "a4a36d33-96f3-422c-a233-d4021460ff00", "description": "y is treated like a consonant at the beginning of a word", "property": "translate", "input": { @@ -178,6 +196,7 @@ "expected": "ellowyay" }, { + "uuid": "adc90017-1a12-4100-b595-e346105042c7", "description": "y is treated like a vowel at the end of a consonant cluster", "property": "translate", "input": { @@ -186,6 +205,7 @@ "expected": "ythmrhay" }, { + "uuid": "29b4ca3d-efe5-4a95-9a54-8467f2e5e59a", "description": "y as second letter in two letter word", "property": "translate", "input": { @@ -199,6 +219,7 @@ "description": "phrases are translated", "cases": [ { + "uuid": "44616581-5ce3-4a81-82d0-40c7ab13d2cf", "description": "a whole phrase", "property": "translate", "input": { @@ -209,4 +230,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/poker/canonical-data.json b/exercises/poker/canonical-data.json index d67a931185..df1bacb4b6 100644 --- a/exercises/poker/canonical-data.json +++ b/exercises/poker/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "poker", - "version": "1.1.0", "cases": [ { + "uuid": "161f485e-39c2-4012-84cf-bec0c755b66c", "description": "single hand always wins", "property": "bestHands", "input": { @@ -15,6 +15,7 @@ ] }, { + "uuid": "370ac23a-a00f-48a9-9965-6f3fb595cf45", "description": "highest card out of all hands wins", "property": "bestHands", "input": { @@ -29,6 +30,7 @@ ] }, { + "uuid": "d94ad5a7-17df-484b-9932-c64fc26cff52", "description": "a tie has multiple winners", "property": "bestHands", "input": { @@ -45,6 +47,7 @@ ] }, { + "uuid": "61ed83a9-cfaa-40a5-942a-51f52f0a8725", "description": "multiple hands with the same high cards, tie compares next highest ranked, down to last card", "property": "bestHands", "input": { @@ -58,6 +61,7 @@ ] }, { + "uuid": "f7175a89-34ff-44de-b3d7-f6fd97d1fca4", "description": "one pair beats high card", "property": "bestHands", "input": { @@ -71,6 +75,7 @@ ] }, { + "uuid": "e114fd41-a301-4111-a9e7-5a7f72a76561", "description": "highest pair wins", "property": "bestHands", "input": { @@ -84,6 +89,7 @@ ] }, { + "uuid": "935bb4dc-a622-4400-97fa-86e7d06b1f76", "description": "two pairs beats one pair", "property": "bestHands", "input": { @@ -97,6 +103,7 @@ ] }, { + "uuid": "c8aeafe1-6e3d-4711-a6de-5161deca91fd", "description": "both hands have two pairs, highest ranked pair wins", "property": "bestHands", "input": { @@ -110,6 +117,7 @@ ] }, { + "uuid": "88abe1ba-7ad7-40f3-847e-0a26f8e46a60", "description": "both hands have two pairs, with the same highest ranked pair, tie goes to low pair", "property": "bestHands", "input": { @@ -123,6 +131,7 @@ ] }, { + "uuid": "15a7a315-0577-47a3-9981-d6cf8e6f387b", "description": "both hands have two identically ranked pairs, tie goes to remaining card (kicker)", "property": "bestHands", "input": { @@ -136,6 +145,7 @@ ] }, { + "uuid": "21e9f1e6-2d72-49a1-a930-228e5e0195dc", "description": "three of a kind beats two pair", "property": "bestHands", "input": { @@ -149,6 +159,7 @@ ] }, { + "uuid": "c2fffd1f-c287-480f-bf2d-9628e63bbcc3", "description": "both hands have three of a kind, tie goes to highest ranked triplet", "property": "bestHands", "input": { @@ -162,6 +173,7 @@ ] }, { + "uuid": "eb856cc2-481c-4b0d-9835-4d75d07a5d9d", "description": "with multiple decks, two players can have same three of a kind, ties go to highest remaining cards", "property": "bestHands", "input": { @@ -175,6 +187,7 @@ ] }, { + "uuid": "a858c5d9-2f28-48e7-9980-b7fa04060a60", "description": "a straight beats three of a kind", "property": "bestHands", "input": { @@ -188,6 +201,7 @@ ] }, { + "uuid": "73c9c756-e63e-4b01-a88d-0d4491a7a0e3", "description": "aces can end a straight (10 J Q K A)", "property": "bestHands", "input": { @@ -201,6 +215,7 @@ ] }, { + "uuid": "76856b0d-35cd-49ce-a492-fe5db53abc02", "description": "aces can start a straight (A 2 3 4 5)", "property": "bestHands", "input": { @@ -214,6 +229,7 @@ ] }, { + "uuid": "6980c612-bbff-4914-b17a-b044e4e69ea1", "description": "both hands with a straight, tie goes to highest ranked card", "property": "bestHands", "input": { @@ -227,6 +243,7 @@ ] }, { + "uuid": "5135675c-c2fc-4e21-9ba3-af77a32e9ba4", "description": "even though an ace is usually high, a 5-high straight is the lowest-scoring straight", "property": "bestHands", "input": { @@ -240,6 +257,7 @@ ] }, { + "uuid": "c601b5e6-e1df-4ade-b444-b60ce13b2571", "description": "flush beats a straight", "property": "bestHands", "input": { @@ -253,6 +271,7 @@ ] }, { + "uuid": "4d90261d-251c-49bd-a468-896bf10133de", "description": "both hands have a flush, tie goes to high card, down to the last one if necessary", "property": "bestHands", "input": { @@ -266,6 +285,7 @@ ] }, { + "uuid": "3a19361d-8974-455c-82e5-f7152f5dba7c", "description": "full house beats a flush", "property": "bestHands", "input": { @@ -279,6 +299,7 @@ ] }, { + "uuid": "eb73d0e6-b66c-4f0f-b8ba-bf96bc0a67f0", "description": "both hands have a full house, tie goes to highest-ranked triplet", "property": "bestHands", "input": { @@ -292,6 +313,7 @@ ] }, { + "uuid": "34b51168-1e43-4c0d-9b32-e356159b4d5d", "description": "with multiple decks, both hands have a full house with the same triplet, tie goes to the pair", "property": "bestHands", "input": { @@ -305,6 +327,7 @@ ] }, { + "uuid": "d61e9e99-883b-4f99-b021-18f0ae50c5f4", "description": "four of a kind beats a full house", "property": "bestHands", "input": { @@ -318,6 +341,7 @@ ] }, { + "uuid": "2e1c8c63-e0cb-4214-a01b-91954490d2fe", "description": "both hands have four of a kind, tie goes to high quad", "property": "bestHands", "input": { @@ -331,6 +355,7 @@ ] }, { + "uuid": "892ca75d-5474-495d-9f64-a6ce2dcdb7e1", "description": "with multiple decks, both hands with identical four of a kind, tie determined by kicker" , "property": "bestHands", "input": { @@ -344,6 +369,7 @@ ] }, { + "uuid": "923bd910-dc7b-4f7d-a330-8b42ec10a3ac", "description": "straight flush beats four of a kind", "property": "bestHands", "input": { @@ -357,6 +383,7 @@ ] }, { + "uuid": "d0927f70-5aec-43db-aed8-1cbd1b6ee9ad", "description": "both hands have straight flush, tie goes to highest-ranked card", "property": "bestHands", "input": { @@ -370,4 +397,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/pov/canonical-data.json b/exercises/pov/canonical-data.json index be39ef04e1..183697c114 100644 --- a/exercises/pov/canonical-data.json +++ b/exercises/pov/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "pov", - "version": "1.3.0", "cases": [ { "description": "Reroot a tree so that its root is the specified node.", @@ -18,6 +17,7 @@ ], "cases": [ { + "uuid": "1b3cd134-49ad-4a7d-8376-7087b7e70792", "description": "Results in the same tree if the input tree is a singleton", "property": "fromPov", "input": { @@ -31,6 +31,7 @@ } }, { + "uuid": "0778c745-0636-40de-9edd-25a8f40426f6", "description": "Can reroot a tree with a parent and one sibling", "property": "fromPov", "input": { @@ -62,6 +63,7 @@ } }, { + "uuid": "fdfdef0a-4472-4248-8bcf-19cf33f9c06e", "description": "Can reroot a tree with a parent and many siblings", "property": "fromPov", "input": { @@ -105,6 +107,7 @@ } }, { + "uuid": "cbcf52db-8667-43d8-a766-5d80cb41b4bb", "description": "Can reroot a tree with new root deeply nested in tree", "property": "fromPov", "input": { @@ -158,6 +161,7 @@ } }, { + "uuid": "e27fa4fa-648d-44cd-90af-d64a13d95e06", "description": "Moves children of the new root to same level as former parent", "property": "fromPov", "input": { @@ -195,6 +199,7 @@ } }, { + "uuid": "09236c7f-7c83-42cc-87a1-25afa60454a3", "description": "Can reroot a complex tree with cousins", "property": "fromPov", "input": { @@ -278,6 +283,7 @@ } }, { + "uuid": "f41d5eeb-8973-448f-a3b0-cc1e019a4193", "description": "Errors if target does not exist in a singleton tree", "property": "fromPov", "input": { @@ -289,6 +295,7 @@ "expected": null }, { + "uuid": "9dc0a8b3-df02-4267-9a41-693b6aff75e7", "description": "Errors if target does not exist in a large tree", "property": "fromPov", "input": { @@ -329,6 +336,7 @@ ], "cases": [ { + "uuid": "02d1f1d9-428d-4395-b026-2db35ffa8f0a", "description": "Can find path to parent", "property": "pathTo", "input": { @@ -352,6 +360,7 @@ ] }, { + "uuid": "d0002674-fcfb-4cdc-9efa-bfc54e3c31b5", "description": "Can find path to sibling", "property": "pathTo", "input": { @@ -382,6 +391,7 @@ ] }, { + "uuid": "c9877cd1-0a69-40d4-b362-725763a5c38f", "description": "Can find path to cousin", "property": "pathTo", "input": { @@ -435,6 +445,7 @@ ] }, { + "uuid": "9fb17a82-2c14-4261-baa3-2f3f234ffa03", "description": "Can find path not involving root", "property": "pathTo", "input": { @@ -467,6 +478,7 @@ ] }, { + "uuid": "5124ed49-7845-46ad-bc32-97d5ac7451b2", "description": "Can find path from nodes other than x", "property": "pathTo", "input": { @@ -497,6 +509,7 @@ ] }, { + "uuid": "f52a183c-25cc-4c87-9fc9-0e7f81a5725c", "description": "Errors if destination does not exist", "property": "pathTo", "input": { @@ -528,6 +541,7 @@ "expected": null }, { + "uuid": "f4fe18b9-b4a2-4bd5-a694-e179155c2149", "description": "Errors if source does not exist", "property": "pathTo", "input": { @@ -561,4 +575,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/prime-factors/canonical-data.json b/exercises/prime-factors/canonical-data.json index d7123f5f58..454f54c136 100644 --- a/exercises/prime-factors/canonical-data.json +++ b/exercises/prime-factors/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "prime-factors", - "version": "1.1.0", "cases": [ { "description": "returns prime factors for the given input number", "cases": [ { + "uuid": "924fc966-a8f5-4288-82f2-6b9224819ccd", "description": "no factors", "property": "factors", "input": { @@ -14,52 +14,142 @@ "expected": [] }, { + "uuid": "17e30670-b105-4305-af53-ddde182cb6ad", "description": "prime number", "property": "factors", "input": { "value": 2 }, - "expected": [2] + "expected": [ + 2 + ] }, { + "uuid": "238d57c8-4c12-42ef-af34-ae4929f94789", + "description": "another prime number", + "property": "factors", + "input": { + "value": 3 + }, + "expected": [ + 3 + ] + }, + { + "uuid": "f59b8350-a180-495a-8fb1-1712fbee1158", "description": "square of a prime", "property": "factors", "input": { "value": 9 }, - "expected": [3, 3] + "expected": [ + 3, + 3 + ] }, { + "uuid": "756949d3-3158-4e3d-91f2-c4f9f043ee70", + "description": "product of first prime", + "property": "factors", + "input": { + "value": 4 + }, + "expected": [ + 2, + 2 + ] + }, + { + "uuid": "bc8c113f-9580-4516-8669-c5fc29512ceb", "description": "cube of a prime", "property": "factors", "input": { "value": 8 }, - "expected": [2, 2, 2] + "expected": [ + 2, + 2, + 2 + ] + }, + { + "uuid": "7d6a3300-a4cb-4065-bd33-0ced1de6cb44", + "description": "product of second prime", + "property": "factors", + "input": { + "value": 27 + }, + "expected": [ + 3, + 3, + 3 + ] + }, + { + "uuid": "073ac0b2-c915-4362-929d-fc45f7b9a9e4", + "description": "product of third prime", + "property": "factors", + "input": { + "value": 625 + }, + "expected": [ + 5, + 5, + 5, + 5 + ] + }, + { + "uuid": "6e0e4912-7fb6-47f3-a9ad-dbcd79340c75", + "description": "product of first and second prime", + "property": "factors", + "input": { + "value": 6 + }, + "expected": [ + 2, + 3 + ] }, { + "uuid": "00485cd3-a3fe-4fbe-a64a-a4308fc1f870", "description": "product of primes and non-primes", "property": "factors", "input": { "value": 12 }, - "expected": [2, 2, 3] + "expected": [ + 2, + 2, + 3 + ] }, { + "uuid": "02251d54-3ca1-4a9b-85e1-b38f4b0ccb91", "description": "product of primes", "property": "factors", "input": { "value": 901255 }, - "expected": [5, 17, 23, 461] + "expected": [ + 5, + 17, + 23, + 461 + ] }, { + "uuid": "070cf8dc-e202-4285-aa37-8d775c9cd473", "description": "factors include a large prime", "property": "factors", "input": { "value": 93819012551 }, - "expected": [11, 9539, 894119] + "expected": [ + 11, + 9539, + 894119 + ] } ] } diff --git a/exercises/protein-translation/canonical-data.json b/exercises/protein-translation/canonical-data.json index 3f7c81930d..54dbb85f00 100644 --- a/exercises/protein-translation/canonical-data.json +++ b/exercises/protein-translation/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "protein-translation", - "version": "1.1.1", "cases": [ { "description": "Translate input RNA sequences into proteins", "cases": [ { + "uuid": "96d3d44f-34a2-4db4-84cd-fff523e069be", "description": "Methionine RNA sequence", "property": "proteins", "input": { @@ -14,6 +14,7 @@ "expected": ["Methionine"] }, { + "uuid": "1b4c56d8-d69f-44eb-be0e-7b17546143d9", "description": "Phenylalanine RNA sequence 1", "property": "proteins", "input": { @@ -22,6 +23,7 @@ "expected": ["Phenylalanine"] }, { + "uuid": "81b53646-bd57-4732-b2cb-6b1880e36d11", "description": "Phenylalanine RNA sequence 2", "property": "proteins", "input": { @@ -30,6 +32,7 @@ "expected": ["Phenylalanine"] }, { + "uuid": "42f69d4f-19d2-4d2c-a8b0-f0ae9ee1b6b4", "description": "Leucine RNA sequence 1", "property": "proteins", "input": { @@ -38,6 +41,7 @@ "expected": ["Leucine"] }, { + "uuid": "ac5edadd-08ed-40a3-b2b9-d82bb50424c4", "description": "Leucine RNA sequence 2", "property": "proteins", "input": { @@ -46,6 +50,7 @@ "expected": ["Leucine"] }, { + "uuid": "8bc36e22-f984-44c3-9f6b-ee5d4e73f120", "description": "Serine RNA sequence 1", "property": "proteins", "input": { @@ -54,6 +59,7 @@ "expected": ["Serine"] }, { + "uuid": "5c3fa5da-4268-44e5-9f4b-f016ccf90131", "description": "Serine RNA sequence 2", "property": "proteins", "input": { @@ -62,6 +68,7 @@ "expected": ["Serine"] }, { + "uuid": "00579891-b594-42b4-96dc-7ff8bf519606", "description": "Serine RNA sequence 3", "property": "proteins", "input": { @@ -70,6 +77,7 @@ "expected": ["Serine"] }, { + "uuid": "08c61c3b-fa34-4950-8c4a-133945570ef6", "description": "Serine RNA sequence 4", "property": "proteins", "input": { @@ -78,6 +86,7 @@ "expected": ["Serine"] }, { + "uuid": "54e1e7d8-63c0-456d-91d2-062c72f8eef5", "description": "Tyrosine RNA sequence 1", "property": "proteins", "input": { @@ -86,6 +95,7 @@ "expected": ["Tyrosine"] }, { + "uuid": "47bcfba2-9d72-46ad-bbce-22f7666b7eb1", "description": "Tyrosine RNA sequence 2", "property": "proteins", "input": { @@ -94,6 +104,7 @@ "expected": ["Tyrosine"] }, { + "uuid": "3a691829-fe72-43a7-8c8e-1bd083163f72", "description": "Cysteine RNA sequence 1", "property": "proteins", "input": { @@ -102,6 +113,7 @@ "expected": ["Cysteine"] }, { + "uuid": "1b6f8a26-ca2f-43b8-8262-3ee446021767", "description": "Cysteine RNA sequence 2", "property": "proteins", "input": { @@ -110,6 +122,7 @@ "expected": ["Cysteine"] }, { + "uuid": "1e91c1eb-02c0-48a0-9e35-168ad0cb5f39", "description": "Tryptophan RNA sequence", "property": "proteins", "input": { @@ -118,6 +131,7 @@ "expected": ["Tryptophan"] }, { + "uuid": "e547af0b-aeab-49c7-9f13-801773a73557", "description": "STOP codon RNA sequence 1", "property": "proteins", "input": { @@ -126,6 +140,7 @@ "expected": [] }, { + "uuid": "67640947-ff02-4f23-a2ef-816f8a2ba72e", "description": "STOP codon RNA sequence 2", "property": "proteins", "input": { @@ -134,6 +149,7 @@ "expected": [] }, { + "uuid": "9c2ad527-ebc9-4ace-808b-2b6447cb54cb", "description": "STOP codon RNA sequence 3", "property": "proteins", "input": { @@ -142,6 +158,7 @@ "expected": [] }, { + "uuid": "d0f295df-fb70-425c-946c-ec2ec185388e", "description": "Translate RNA strand into correct protein list", "property": "proteins", "input": { @@ -150,6 +167,7 @@ "expected": ["Methionine","Phenylalanine","Tryptophan"] }, { + "uuid": "e30e8505-97ec-4e5f-a73e-5726a1faa1f4", "description": "Translation stops if STOP codon at beginning of sequence", "property": "proteins", "input": { @@ -158,6 +176,7 @@ "expected": [] }, { + "uuid": "5358a20b-6f4c-4893-bce4-f929001710f3", "description": "Translation stops if STOP codon at end of two-codon sequence", "property": "proteins", "input": { @@ -166,6 +185,7 @@ "expected": ["Tryptophan"] }, { + "uuid": "ba16703a-1a55-482f-bb07-b21eef5093a3", "description": "Translation stops if STOP codon at end of three-codon sequence", "property": "proteins", "input": { @@ -174,6 +194,7 @@ "expected": ["Methionine","Phenylalanine"] }, { + "uuid": "4089bb5a-d5b4-4e71-b79e-b8d1f14a2911", "description": "Translation stops if STOP codon in middle of three-codon sequence", "property": "proteins", "input": { @@ -182,6 +203,7 @@ "expected": ["Tryptophan"] }, { + "uuid": "2c2a2a60-401f-4a80-b977-e0715b23b93d", "description": "Translation stops if STOP codon in middle of six-codon sequence", "property": "proteins", "input": { @@ -192,4 +214,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/proverb/canonical-data.json b/exercises/proverb/canonical-data.json index f91ded092b..2cabf7192a 100644 --- a/exercises/proverb/canonical-data.json +++ b/exercises/proverb/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "proverb", - "version": "1.1.0", "comments": [ "JSON doesn't allow for multi-line strings, so all expected outputs are presented ", "here as arrays of strings. It's up to the test generator to join the ", @@ -8,6 +7,7 @@ ], "cases": [ { + "uuid": "e974b73e-7851-484f-8d6d-92e07fe742fc", "description": "zero pieces", "property": "recite", "input": { @@ -16,6 +16,7 @@ "expected": [] }, { + "uuid": "2fcd5f5e-8b82-4e74-b51d-df28a5e0faa4", "description": "one piece", "property": "recite", "input": { @@ -28,6 +29,7 @@ ] }, { + "uuid": "d9d0a8a1-d933-46e2-aa94-eecf679f4b0e", "description": "two pieces", "property": "recite", "input": { @@ -42,6 +44,7 @@ ] }, { + "uuid": "c95ef757-5e94-4f0d-a6cb-d2083f5e5a83", "description": "three pieces", "property": "recite", "input": { @@ -58,6 +61,7 @@ ] }, { + "uuid": "433fb91c-35a2-4d41-aeab-4de1e82b2126", "description": "full proverb", "property": "recite", "input": { @@ -82,6 +86,7 @@ ] }, { + "uuid": "c1eefa5a-e8d9-41c7-91d4-99fab6d6b9f7", "description": "four pieces modernized", "property": "recite", "input": { diff --git a/exercises/pythagorean-triplet/canonical-data.json b/exercises/pythagorean-triplet/canonical-data.json index 4df2dff3ee..2a6e7251c9 100644 --- a/exercises/pythagorean-triplet/canonical-data.json +++ b/exercises/pythagorean-triplet/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "pythagorean-triplet", - "version": "1.0.0", "cases": [ { + "uuid": "a19de65d-35b8-4480-b1af-371d9541e706", "description": "triplets whose sum is 12", "property": "tripletsWithSum", "input": { @@ -13,6 +13,7 @@ ] }, { + "uuid": "48b21332-0a3d-43b2-9a52-90b2a6e5c9f5", "description": "triplets whose sum is 108", "property": "tripletsWithSum", "input": { @@ -23,6 +24,7 @@ ] }, { + "uuid": "dffc1266-418e-4daa-81af-54c3e95c3bb5", "description": "triplets whose sum is 1000", "property": "tripletsWithSum", "input": { @@ -33,6 +35,7 @@ ] }, { + "uuid": "5f86a2d4-6383-4cce-93a5-e4489e79b186", "description": "no matching triplets for 1001", "property": "tripletsWithSum", "input": { @@ -41,6 +44,7 @@ "expected": [] }, { + "uuid": "bf17ba80-1596-409a-bb13-343bdb3b2904", "description": "returns all matching triplets", "property": "tripletsWithSum", "input": { @@ -52,6 +56,7 @@ ] }, { + "uuid": "9d8fb5d5-6c6f-42df-9f95-d3165963ac57", "description": "several matching triplets", "property": "tripletsWithSum", "input": { @@ -69,6 +74,7 @@ ] }, { + "uuid": "f5be5734-8aa0-4bd1-99a2-02adcc4402b4", "description": "triplets for large number", "property": "tripletsWithSum", "input": { @@ -83,4 +89,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/queen-attack/canonical-data.json b/exercises/queen-attack/canonical-data.json index ea5605267f..2e63dda857 100644 --- a/exercises/queen-attack/canonical-data.json +++ b/exercises/queen-attack/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "queen-attack", - "version": "2.3.0", "comments": [ "Testing invalid positions will vary by language. The expected", "value of 'error' is there to indicate some sort of failure should", @@ -15,6 +14,7 @@ "description": "Test creation of Queens with valid and invalid positions", "cases": [ { + "uuid": "3ac4f735-d36c-44c4-a3e2-316f79704203", "description": "queen with a valid position", "property": "create", "input": { @@ -28,6 +28,7 @@ "expected": 0 }, { + "uuid": "4e812d5d-b974-4e38-9a6b-8e0492bfa7be", "description": "queen must have positive row", "property": "create", "input": { @@ -41,6 +42,7 @@ "expected": {"error": "row not positive"} }, { + "uuid": "f07b7536-b66b-4f08-beb9-4d70d891d5c8", "description": "queen must have row on board", "property": "create", "input": { @@ -54,6 +56,7 @@ "expected": {"error": "row not on board"} }, { + "uuid": "15a10794-36d9-4907-ae6b-e5a0d4c54ebe", "description": "queen must have positive column", "property": "create", "input": { @@ -67,6 +70,7 @@ "expected": {"error": "column not positive"} }, { + "uuid": "6907762d-0e8a-4c38-87fb-12f2f65f0ce4", "description": "queen must have column on board", "property": "create", "input": { @@ -85,7 +89,8 @@ "description": "Test the ability of one queen to attack another", "cases": [ { - "description": "can not attack", + "uuid": "33ae4113-d237-42ee-bac1-e1e699c0c007", + "description": "cannot attack", "property": "canAttack", "input": { "white_queen": { @@ -104,6 +109,7 @@ "expected": false }, { + "uuid": "eaa65540-ea7c-4152-8c21-003c7a68c914", "description": "can attack on same row", "property": "canAttack", "input": { @@ -123,6 +129,7 @@ "expected": true }, { + "uuid": "bae6f609-2c0e-4154-af71-af82b7c31cea", "description": "can attack on same column", "property": "canAttack", "input": { @@ -142,6 +149,7 @@ "expected": true }, { + "uuid": "0e1b4139-b90d-4562-bd58-dfa04f1746c7", "description": "can attack on first diagonal", "property": "canAttack", "input": { @@ -161,6 +169,7 @@ "expected": true }, { + "uuid": "ff9b7ed4-e4b6-401b-8d16-bc894d6d3dcd", "description": "can attack on second diagonal", "property": "canAttack", "input": { @@ -180,6 +189,7 @@ "expected": true }, { + "uuid": "0a71e605-6e28-4cc2-aa47-d20a2e71037a", "description": "can attack on third diagonal", "property": "canAttack", "input": { @@ -199,6 +209,7 @@ "expected": true }, { + "uuid": "0790b588-ae73-4f1f-a968-dd0b34f45f86", "description": "can attack on fourth diagonal", "property": "canAttack", "input": { diff --git a/exercises/rail-fence-cipher/canonical-data.json b/exercises/rail-fence-cipher/canonical-data.json index 0d32875abe..84967226c1 100644 --- a/exercises/rail-fence-cipher/canonical-data.json +++ b/exercises/rail-fence-cipher/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "rail-fence-cipher", - "version": "1.1.0", "comments": [ "The tests do not expect any normalization or cleaning.", "That trade is tested in enough other exercises." @@ -10,6 +9,7 @@ "description": "encode", "cases": [ { + "uuid": "46dc5c50-5538-401d-93a5-41102680d068", "description": "encode with two rails", "property": "encode", "input": { @@ -19,6 +19,7 @@ "expected": "XXXXXXXXXOOOOOOOOO" }, { + "uuid": "25691697-fbd8-4278-8c38-b84068b7bc29", "description": "encode with three rails", "property": "encode", "input": { @@ -28,6 +29,7 @@ "expected": "WECRLTEERDSOEEFEAOCAIVDEN" }, { + "uuid": "384f0fea-1442-4f1a-a7c4-5cbc2044002c", "description": "encode with ending in the middle", "property": "encode", "input": { @@ -42,6 +44,7 @@ "description": "decode", "cases": [ { + "uuid": "cd525b17-ec34-45ef-8f0e-4f27c24a7127", "description": "decode with three rails", "property": "decode", "input": { @@ -51,6 +54,7 @@ "expected": "THEDEVILISINTHEDETAILS" }, { + "uuid": "dd7b4a98-1a52-4e5c-9499-cbb117833507", "description": "decode with five rails", "property": "decode", "input": { @@ -60,6 +64,7 @@ "expected": "EXERCISMISAWESOME" }, { + "uuid": "93e1ecf4-fac9-45d9-9cd2-591f47d3b8d3", "description": "decode with six rails", "property": "decode", "input": { diff --git a/exercises/raindrops/canonical-data.json b/exercises/raindrops/canonical-data.json index f41a684459..6ea758de70 100644 --- a/exercises/raindrops/canonical-data.json +++ b/exercises/raindrops/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "raindrops", - "version": "1.1.0", "cases": [ { + "uuid": "1575d549-e502-46d4-a8e1-6b7bec6123d8", "description": "the sound for 1 is 1", "property": "convert", "input": { @@ -11,6 +11,7 @@ "expected": "1" }, { + "uuid": "1f51a9f9-4895-4539-b182-d7b0a5ab2913", "description": "the sound for 3 is Pling", "property": "convert", "input": { @@ -19,6 +20,7 @@ "expected": "Pling" }, { + "uuid": "2d9bfae5-2b21-4bcd-9629-c8c0e388f3e0", "description": "the sound for 5 is Plang", "property": "convert", "input": { @@ -27,6 +29,7 @@ "expected": "Plang" }, { + "uuid": "d7e60daa-32ef-4c23-b688-2abff46c4806", "description": "the sound for 7 is Plong", "property": "convert", "input": { @@ -35,6 +38,7 @@ "expected": "Plong" }, { + "uuid": "6bb4947b-a724-430c-923f-f0dc3d62e56a", "description": "the sound for 6 is Pling as it has a factor 3", "property": "convert", "input": { @@ -43,6 +47,7 @@ "expected": "Pling" }, { + "uuid": "ce51e0e8-d9d4-446d-9949-96eac4458c2d", "description": "2 to the power 3 does not make a raindrop sound as 3 is the exponent not the base", "property": "convert", "input": { @@ -51,6 +56,7 @@ "expected": "8" }, { + "uuid": "0dd66175-e3e2-47fc-8750-d01739856671", "description": "the sound for 9 is Pling as it has a factor 3", "property": "convert", "input": { @@ -59,6 +65,7 @@ "expected": "Pling" }, { + "uuid": "022c44d3-2182-4471-95d7-c575af225c96", "description": "the sound for 10 is Plang as it has a factor 5", "property": "convert", "input": { @@ -67,6 +74,7 @@ "expected": "Plang" }, { + "uuid": "37ab74db-fed3-40ff-b7b9-04acdfea8edf", "description": "the sound for 14 is Plong as it has a factor of 7", "property": "convert", "input": { @@ -75,6 +83,7 @@ "expected": "Plong" }, { + "uuid": "31f92999-6afb-40ee-9aa4-6d15e3334d0f", "description": "the sound for 15 is PlingPlang as it has factors 3 and 5", "property": "convert", "input": { @@ -83,6 +92,7 @@ "expected": "PlingPlang" }, { + "uuid": "ff9bb95d-6361-4602-be2c-653fe5239b54", "description": "the sound for 21 is PlingPlong as it has factors 3 and 7", "property": "convert", "input": { @@ -91,6 +101,7 @@ "expected": "PlingPlong" }, { + "uuid": "d2e75317-b72e-40ab-8a64-6734a21dece1", "description": "the sound for 25 is Plang as it has a factor 5", "property": "convert", "input": { @@ -99,6 +110,7 @@ "expected": "Plang" }, { + "uuid": "a09c4c58-c662-4e32-97fe-f1501ef7125c", "description": "the sound for 27 is Pling as it has a factor 3", "property": "convert", "input": { @@ -107,6 +119,7 @@ "expected": "Pling" }, { + "uuid": "bdf061de-8564-4899-a843-14b48b722789", "description": "the sound for 35 is PlangPlong as it has factors 5 and 7", "property": "convert", "input": { @@ -115,6 +128,7 @@ "expected": "PlangPlong" }, { + "uuid": "c4680bee-69ba-439d-99b5-70c5fd1a7a83", "description": "the sound for 49 is Plong as it has a factor 7", "property": "convert", "input": { @@ -123,6 +137,7 @@ "expected": "Plong" }, { + "uuid": "17f2bc9a-b65a-4d23-8ccd-266e8c271444", "description": "the sound for 52 is 52", "property": "convert", "input": { @@ -131,6 +146,7 @@ "expected": "52" }, { + "uuid": "e46677ed-ff1a-419f-a740-5c713d2830e4", "description": "the sound for 105 is PlingPlangPlong as it has factors 3, 5 and 7", "property": "convert", "input": { @@ -139,6 +155,7 @@ "expected": "PlingPlangPlong" }, { + "uuid": "13c6837a-0fcd-4b86-a0eb-20572f7deb0b", "description": "the sound for 3125 is Plang as it has a factor 5", "property": "convert", "input": { diff --git a/exercises/rational-numbers/canonical-data.json b/exercises/rational-numbers/canonical-data.json index 26eff76b88..e19b738284 100644 --- a/exercises/rational-numbers/canonical-data.json +++ b/exercises/rational-numbers/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "rational-numbers", - "version": "1.1.0", "comments": [ " The canonical data assumes mathematically correct real ", " numbers. The testsuites should consider rounding errors ", @@ -17,6 +16,7 @@ "description": "Addition", "cases": [ { + "uuid": "0ba4d988-044c-4ed5-9215-4d0bb8d0ae9f", "description": "Add two positive rational numbers", "property": "add", "input": { @@ -26,6 +26,7 @@ "expected": [7, 6] }, { + "uuid": "88ebc342-a2ac-4812-a656-7b664f718b6a", "description": "Add a positive rational number and a negative rational number", "property": "add", "input": { @@ -35,6 +36,7 @@ "expected": [-1, 6] }, { + "uuid": "92ed09c2-991e-4082-a602-13557080205c", "description": "Add two negative rational numbers", "property": "add", "input": { @@ -44,6 +46,7 @@ "expected": [-7, 6] }, { + "uuid": "6e58999e-3350-45fb-a104-aac7f4a9dd11", "description": "Add a rational number to its additive inverse", "property": "add", "input": { @@ -58,6 +61,7 @@ "description": "Subtraction", "cases": [ { + "uuid": "47bba350-9db1-4ab9-b412-4a7e1f72a66e", "description": "Subtract two positive rational numbers", "property": "sub", "input": { @@ -67,6 +71,7 @@ "expected": [-1, 6] }, { + "uuid": "93926e2a-3e82-4aee-98a7-fc33fb328e87", "description": "Subtract a positive rational number and a negative rational number", "property": "sub", "input": { @@ -76,6 +81,7 @@ "expected": [7, 6] }, { + "uuid": "a965ba45-9b26-442b-bdc7-7728e4b8d4cc", "description": "Subtract two negative rational numbers", "property": "sub", "input": { @@ -85,6 +91,7 @@ "expected": [1, 6] }, { + "uuid": "0df0e003-f68e-4209-8c6e-6a4e76af5058", "description": "Subtract a rational number from itself", "property": "sub", "input": { @@ -99,6 +106,7 @@ "description": "Multiplication", "cases": [ { + "uuid": "34fde77a-75f4-4204-8050-8d3a937958d3", "description": "Multiply two positive rational numbers", "property": "mul", "input": { @@ -108,6 +116,7 @@ "expected": [1, 3] }, { + "uuid": "6d015cf0-0ea3-41f1-93de-0b8e38e88bae", "description": "Multiply a negative rational number by a positive rational number", "property": "mul", "input": { @@ -117,6 +126,7 @@ "expected": [-1, 3] }, { + "uuid": "d1bf1b55-954e-41b1-8c92-9fc6beeb76fa", "description": "Multiply two negative rational numbers", "property": "mul", "input": { @@ -126,6 +136,7 @@ "expected": [1, 3] }, { + "uuid": "a9b8f529-9ec7-4c79-a517-19365d779040", "description": "Multiply a rational number by its reciprocal", "property": "mul", "input": { @@ -135,6 +146,7 @@ "expected": [1, 1] }, { + "uuid": "d89d6429-22fa-4368-ab04-9e01a44d3b48", "description": "Multiply a rational number by 1", "property": "mul", "input": { @@ -144,6 +156,7 @@ "expected": [1, 2] }, { + "uuid": "0d95c8b9-1482-4ed7-bac9-b8694fa90145", "description": "Multiply a rational number by 0", "property": "mul", "input": { @@ -158,6 +171,7 @@ "description": "Division", "cases": [ { + "uuid": "1de088f4-64be-4e6e-93fd-5997ae7c9798", "description": "Divide two positive rational numbers", "property": "div", "input": { @@ -167,6 +181,7 @@ "expected": [3, 4] }, { + "uuid": "7d7983db-652a-4e66-981a-e921fb38d9a9", "description": "Divide a positive rational number by a negative rational number", "property": "div", "input": { @@ -176,6 +191,7 @@ "expected": [-3, 4] }, { + "uuid": "1b434d1b-5b38-4cee-aaf5-b9495c399e34", "description": "Divide two negative rational numbers", "property": "div", "input": { @@ -185,6 +201,7 @@ "expected": [3, 4] }, { + "uuid": "d81c2ebf-3612-45a6-b4e0-f0d47812bd59", "description": "Divide a rational number by 1", "property": "div", "input": { @@ -201,6 +218,7 @@ "description": "Absolute value", "cases": [ { + "uuid": "5fee0d8e-5955-4324-acbe-54cdca94ddaa", "description": "Absolute value of a positive rational number", "property": "abs", "input": { @@ -209,6 +227,7 @@ "expected": [1, 2] }, { + "uuid": "3cb570b6-c36a-4963-a380-c0834321bcaa", "description": "Absolute value of a positive rational number with negative numerator and denominator", "property": "abs", "input": { @@ -217,6 +236,7 @@ "expected": [1, 2] }, { + "uuid": "6a05f9a0-1f6b-470b-8ff7-41af81773f25", "description": "Absolute value of a negative rational number", "property": "abs", "input": { @@ -225,6 +245,7 @@ "expected": [1, 2] }, { + "uuid": "5d0f2336-3694-464f-8df9-f5852fda99dd", "description": "Absolute value of a negative rational number with negative denominator", "property": "abs", "input": { @@ -233,6 +254,7 @@ "expected": [1, 2] }, { + "uuid": "f8e1ed4b-9dca-47fb-a01e-5311457b3118", "description": "Absolute value of zero", "property": "abs", "input": { @@ -246,6 +268,7 @@ "description": "Exponentiation of a rational number", "cases": [ { + "uuid": "ea2ad2af-3dab-41e7-bb9f-bd6819668a84", "description": "Raise a positive rational number to a positive integer power", "property": "exprational", "input": { @@ -255,6 +278,7 @@ "expected": [1, 8] }, { + "uuid": "8168edd2-0af3-45b1-b03f-72c01332e10a", "description": "Raise a negative rational number to a positive integer power", "property": "exprational", "input": { @@ -264,6 +288,7 @@ "expected": [-1, 8] }, { + "uuid": "e2f25b1d-e4de-4102-abc3-c2bb7c4591e4", "description": "Raise zero to an integer power", "property": "exprational", "input": { @@ -273,6 +298,7 @@ "expected": [0, 1] }, { + "uuid": "431cac50-ab8b-4d58-8e73-319d5404b762", "description": "Raise one to an integer power", "property": "exprational", "input": { @@ -282,6 +308,7 @@ "expected": [1, 1] }, { + "uuid": "7d164739-d68a-4a9c-b99f-dd77ce5d55e6", "description": "Raise a positive rational number to the power of zero", "property": "exprational", "input": { @@ -291,6 +318,7 @@ "expected": [1, 1] }, { + "uuid": "eb6bd5f5-f880-4bcd-8103-e736cb6e41d1", "description": "Raise a negative rational number to the power of zero", "property": "exprational", "input": { @@ -305,6 +333,7 @@ "description": "Exponentiation of a real number to a rational number", "cases": [ { + "uuid": "30b467dd-c158-46f5-9ffb-c106de2fd6fa", "description": "Raise a real number to a positive rational number", "property": "expreal", "input": { @@ -314,6 +343,7 @@ "expected": 16.0 }, { + "uuid": "6e026bcc-be40-4b7b-ae22-eeaafc5a1789", "description": "Raise a real number to a negative rational number", "property": "expreal", "input": { @@ -323,6 +353,7 @@ "expected": 0.3333333333333333 }, { + "uuid": "9f866da7-e893-407f-8cd2-ee85d496eec5", "description": "Raise a real number to a zero rational number", "property": "expreal", "input": { @@ -337,6 +368,7 @@ "description": "Reduction to lowest terms", "cases": [ { + "uuid": "0a63fbde-b59c-4c26-8237-1e0c73354d0a", "description": "Reduce a positive rational number to lowest terms", "property": "reduce", "input": { @@ -345,6 +377,7 @@ "expected": [1, 2] }, { + "uuid": "f87c2a4e-d29c-496e-a193-318c503e4402", "description": "Reduce a negative rational number to lowest terms", "property": "reduce", "input": { @@ -353,6 +386,7 @@ "expected": [-2, 3] }, { + "uuid": "3b92ffc0-5b70-4a43-8885-8acee79cdaaf", "description": "Reduce a rational number with a negative denominator to lowest terms", "property": "reduce", "input": { @@ -361,6 +395,7 @@ "expected": [-1, 3] }, { + "uuid": "c9dbd2e6-5ac0-4a41-84c1-48b645b4f663", "description": "Reduce zero to lowest terms", "property": "reduce", "input": { @@ -369,6 +404,7 @@ "expected": [0, 1] }, { + "uuid": "297b45ad-2054-4874-84d4-0358dc1b8887", "description": "Reduce an integer to lowest terms", "property": "reduce", "input": { @@ -377,6 +413,7 @@ "expected": [-2, 1] }, { + "uuid": "a73a17fe-fe8c-4a1c-a63b-e7579e333d9e", "description": "Reduce one to lowest terms", "property": "reduce", "input": { diff --git a/exercises/rational-numbers/description.md b/exercises/rational-numbers/description.md index 91652d82a7..55ebaeb4bc 100644 --- a/exercises/rational-numbers/description.md +++ b/exercises/rational-numbers/description.md @@ -2,13 +2,13 @@ A rational number is defined as the quotient of two integers `a` and `b`, called The absolute value `|r|` of the rational number `r = a/b` is equal to `|a|/|b|`. -The sum of two rational numbers `r1 = a1/b1` and `r2 = a2/b2` is `r1 + r2 = a1/b1 + a2/b2 = (a1 * b2 + a2 * b1) / (b1 * b2)`. +The sum of two rational numbers `r₁ = a₁/b₁` and `r₂ = a₂/b₂` is `r₁ + r₂ = a₁/b₁ + a₂/b₂ = (a₁ * b₂ + a₂ * b₁) / (b₁ * b₂)`. -The difference of two rational numbers `r1 = a1/b1` and `r2 = a2/b2` is `r1 - r2 = a1/b1 - a2/b2 = (a1 * b2 - a2 * b1) / (b1 * b2)`. +The difference of two rational numbers `r₁ = a₁/b₁` and `r₂ = a₂/b₂` is `r₁ - r₂ = a₁/b₁ - a₂/b₂ = (a₁ * b₂ - a₂ * b₁) / (b₁ * b₂)`. -The product (multiplication) of two rational numbers `r1 = a1/b1` and `r2 = a2/b2` is `r1 * r2 = (a1 * a2) / (b1 * b2)`. +The product (multiplication) of two rational numbers `r₁ = a₁/b₁` and `r₂ = a₂/b₂` is `r₁ * r₂ = (a₁ * a₂) / (b₁ * b₂)`. -Dividing a rational number `r1 = a1/b1` by another `r2 = a2/b2` is `r1 / r2 = (a1 * b2) / (a2 * b1)` if `a2 * b1` is not zero. +Dividing a rational number `r₁ = a₁/b₁` by another `r₂ = a₂/b₂` is `r₁ / r₂ = (a₁ * b₂) / (a₂ * b₁)` if `a₂` is not zero. Exponentiation of a rational number `r = a/b` to a non-negative integer power `n` is `r^n = (a^n)/(b^n)`. diff --git a/exercises/react/canonical-data.json b/exercises/react/canonical-data.json index 572405955a..3216540aae 100644 --- a/exercises/react/canonical-data.json +++ b/exercises/react/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "react", - "version": "2.0.0", "comments": [ "Note that, due to the nature of this exercise,", "the tests are specified using their cells and a series of operations to perform on the cells.", @@ -45,6 +44,7 @@ ], "cases": [ { + "uuid": "c51ee736-d001-4f30-88d1-0c8e8b43cd07", "description": "input cells have a value", "property": "react", "input": { @@ -66,6 +66,7 @@ "expected": {} }, { + "uuid": "dedf0fe0-da0c-4d5d-a582-ffaf5f4d0851", "description": "an input cell's value can be set", "property": "react", "input": { @@ -92,6 +93,7 @@ "expected": {} }, { + "uuid": "5854b975-f545-4f93-8968-cc324cde746e", "description": "compute cells calculate initial value", "property": "react", "input": { @@ -119,6 +121,7 @@ "expected": {} }, { + "uuid": "25795a3d-b86c-4e91-abe7-1c340e71560c", "description": "compute cells take inputs in the right order", "property": "react", "input": { @@ -151,6 +154,7 @@ "expected": {} }, { + "uuid": "c62689bf-7be5-41bb-b9f8-65178ef3e8ba", "description": "compute cells update value when dependencies are changed", "property": "react", "input": { @@ -183,6 +187,7 @@ "expected": {} }, { + "uuid": "5ff36b09-0a88-48d4-b7f8-69dcf3feea40", "description": "compute cells can depend on other compute cells", "property": "react", "input": { @@ -232,6 +237,7 @@ "expected": {} }, { + "uuid": "abe33eaf-68ad-42a5-b728-05519ca88d2d", "description": "compute cells fire callbacks", "property": "react", "input": { @@ -267,6 +273,7 @@ "expected": {} }, { + "uuid": "9e5cb3a4-78e5-4290-80f8-a78612c52db2", "description": "callback cells only fire on change", "property": "react", "input": { @@ -308,6 +315,7 @@ "expected": {} }, { + "uuid": "ada17cb6-7332-448a-b934-e3d7495c13d3", "description": "callbacks do not report already reported values", "property": "react", "input": { @@ -351,6 +359,7 @@ "expected": {} }, { + "uuid": "ac271900-ea5c-461c-9add-eeebcb8c03e5", "description": "callbacks can fire from multiple cells", "property": "react", "input": { @@ -398,6 +407,7 @@ "expected": {} }, { + "uuid": "95a82dcc-8280-4de3-a4cd-4f19a84e3d6f", "description": "callbacks can be added and removed", "property": "react", "input": { @@ -459,6 +469,7 @@ "expected": {} }, { + "uuid": "f2a7b445-f783-4e0e-8393-469ab4915f2a", "description": "removing a callback multiple times doesn't interfere with other callbacks", "comments": [ "Some incorrect implementations store their callbacks in an array", @@ -520,6 +531,7 @@ "expected": {} }, { + "uuid": "daf6feca-09e0-4ce5-801d-770ddfe1c268", "description": "callbacks should only be called once even if multiple dependencies change", "comments": [ "Some incorrect implementations call a callback function too early,", @@ -577,6 +589,7 @@ "expected": {} }, { + "uuid": "9a5b159f-b7aa-4729-807e-f1c38a46d377", "description": "callbacks should not be called if dependencies change but output value doesn't change", "comments": [ "Some incorrect implementations simply mark a compute cell as dirty when a dependency changes,", diff --git a/exercises/rectangles/canonical-data.json b/exercises/rectangles/canonical-data.json index 3c0304b433..1d72f006e6 100644 --- a/exercises/rectangles/canonical-data.json +++ b/exercises/rectangles/canonical-data.json @@ -1,12 +1,12 @@ { "exercise": "rectangles", - "version": "1.1.0", "comments": [ "The inputs are represented as arrays of strings to improve readability in this JSON file.", "Your track may choose whether to present the input as a single string (concatenating all the lines) or as the list." ], "cases": [ { + "uuid": "485b7bab-4150-40aa-a8db-73013427d08c", "description": "no rows", "property": "rectangles", "input": { @@ -15,6 +15,7 @@ "expected": 0 }, { + "uuid": "076929ed-27e8-45dc-b14b-08279944dc49", "description": "no columns", "property": "rectangles", "input": { @@ -23,6 +24,7 @@ "expected": 0 }, { + "uuid": "0a8abbd1-a0a4-4180-aa4e-65c1b1a073fa", "description": "no rectangles", "property": "rectangles", "input": { @@ -31,6 +33,7 @@ "expected": 0 }, { + "uuid": "a4ba42e9-4e7f-4973-b7c7-4ce0760ac6cd", "description": "one rectangle", "property": "rectangles", "input": { @@ -43,6 +46,7 @@ "expected": 1 }, { + "uuid": "ced06550-83da-4d23-98b7-d24152e0db93", "description": "two rectangles without shared parts", "property": "rectangles", "input": { @@ -57,6 +61,7 @@ "expected": 2 }, { + "uuid": "5942d69a-a07c-41c8-8b93-2d13877c706a", "description": "five rectangles with shared parts", "property": "rectangles", "input": { @@ -71,6 +76,7 @@ "expected": 5 }, { + "uuid": "82d70be4-ab37-4bf2-a433-e33778d3bbf1", "description": "rectangle of height 1 is counted", "property": "rectangles", "input": { @@ -82,6 +88,7 @@ "expected": 1 }, { + "uuid": "57f1bc0e-2782-401e-ab12-7c01d8bfc2e0", "description": "rectangle of width 1 is counted", "property": "rectangles", "input": { @@ -94,6 +101,7 @@ "expected": 1 }, { + "uuid": "ef0bb65c-bd80-4561-9535-efc4067054f9", "description": "1x1 square is counted", "property": "rectangles", "input": { @@ -105,6 +113,7 @@ "expected": 1 }, { + "uuid": "e1e1d444-e926-4d30-9bf3-7d8ec9a9e330", "description": "only complete rectangles are counted", "property": "rectangles", "input": { @@ -119,6 +128,7 @@ "expected": 1 }, { + "uuid": "ca021a84-1281-4a56-9b9b-af14113933a4", "description": "rectangles can be of different sizes", "property": "rectangles", "input": { @@ -133,6 +143,7 @@ "expected": 3 }, { + "uuid": "51f689a7-ef3f-41ae-aa2f-5ea09ad897ff", "description": "corner is required for a rectangle to be complete", "property": "rectangles", "input": { @@ -147,6 +158,7 @@ "expected": 2 }, { + "uuid": "d78fe379-8c1b-4d3c-bdf7-29bfb6f6dc66", "description": "large input with many rectangles", "property": "rectangles", "input": { diff --git a/exercises/resistor-color-duo/canonical-data.json b/exercises/resistor-color-duo/canonical-data.json index 2031d75c75..7deceeddca 100644 --- a/exercises/resistor-color-duo/canonical-data.json +++ b/exercises/resistor-color-duo/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "resistor-color-duo", - "version": "2.0.0", "cases": [ { + "uuid": "ce11995a-5b93-4950-a5e9-93423693b2fc", "description": "Brown and black", "property": "value", "input": { @@ -11,6 +11,7 @@ "expected": 10 }, { + "uuid": "7bf82f7a-af23-48ba-a97d-38d59406a920", "description": "Blue and grey", "property": "value", "input": { @@ -19,6 +20,7 @@ "expected": 68 }, { + "uuid": "f1886361-fdfd-4693-acf8-46726fe24e0c", "description": "Yellow and violet", "property": "value", "input": { @@ -27,12 +29,22 @@ "expected": 47 }, { + "uuid": "77a8293d-2a83-4016-b1af-991acc12b9fe", "description": "Orange and orange", "property": "value", "input": { "colors": ["orange", "orange"] }, "expected": 33 + }, + { + "uuid": "0c4fb44f-db7c-4d03-afa8-054350f156a8", + "description": "Ignore additional colors", + "property": "value", + "input": { + "colors": ["green", "brown", "orange"] + }, + "expected": 51 } ] } diff --git a/exercises/resistor-color-duo/description.md b/exercises/resistor-color-duo/description.md index b060cd5e89..1099cbc99a 100644 --- a/exercises/resistor-color-duo/description.md +++ b/exercises/resistor-color-duo/description.md @@ -1,10 +1,17 @@ -If you want to build something using a Raspberry Pi, you'll probably use _resistors_. For this exercise, you need to know two things about them: +If you want to build something using a Raspberry Pi, you'll probably use _resistors_. +For this exercise, you need to know two things about them: * Each resistor has a resistance value. * Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read. -To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values. Each band acts as a digit of a number. For example, if they printed a brown band (value 1) followed by a green band (value 5), it would translate to the number 15. -In this exercise, you are going to create a helpful program so that you don't have to remember the values of the bands. The program will take two colors as input, and output the correct number. +To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values. +Each band has a position and a numeric value. + +The first 2 bands of a resistor have a simple encoding scheme: each color maps to a single number. +For example, if they printed a brown band (value 1) followed by a green band (value 5), it would translate to the number 15. + +In this exercise you are going to create a helpful program so that you don't have to remember the values of the bands. +The program will take color names as input and output a two digit number, even if the input is more than two colors! The band colors are encoded as follows: @@ -18,3 +25,8 @@ The band colors are encoded as follows: - Violet: 7 - Grey: 8 - White: 9 + +From the example above: +brown-green should return 15 +brown-green-violet should return 15 too, ignoring the third color. + diff --git a/exercises/resistor-color-trio/canonical-data.json b/exercises/resistor-color-trio/canonical-data.json index 9b4a60d7a6..c039354bc5 100644 --- a/exercises/resistor-color-trio/canonical-data.json +++ b/exercises/resistor-color-trio/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "resistor-color-trio", - "version": "1.0.0", "cases": [ { + "uuid": "d6863355-15b7-40bb-abe0-bfb1a25512ed", "description": "Orange and orange and black", "property": "label", "input": { @@ -14,6 +14,7 @@ } }, { + "uuid": "1224a3a9-8c8e-4032-843a-5224e04647d6", "description": "Blue and grey and brown", "property": "label", "input": { @@ -25,6 +26,7 @@ } }, { + "uuid": "b8bda7dc-6b95-4539-abb2-2ad51d66a207", "description": "Red and black and red", "property": "label", "input": { @@ -36,6 +38,7 @@ } }, { + "uuid": "5b1e74bc-d838-4eda-bbb3-eaba988e733b", "description": "Green and brown and orange", "property": "label", "input": { @@ -47,6 +50,7 @@ } }, { + "uuid": "f5d37ef9-1919-4719-a90d-a33c5a6934c9", "description": "Yellow and violet and yellow", "property": "label", "input": { diff --git a/exercises/resistor-color/canonical-data.json b/exercises/resistor-color/canonical-data.json index 1a64c58288..37624546de 100644 --- a/exercises/resistor-color/canonical-data.json +++ b/exercises/resistor-color/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "resistor-color", - "version": "1.0.0", "cases": [ { "description": "Color codes", "cases": [ { + "uuid": "49eb31c5-10a8-4180-9f7f-fea632ab87ef", "description": "Black", "property": "colorCode", "input": { @@ -14,6 +14,7 @@ "expected": 0 }, { + "uuid": "0a4df94b-92da-4579-a907-65040ce0b3fc", "description": "White", "property": "colorCode", "input": { @@ -22,6 +23,7 @@ "expected": 9 }, { + "uuid": "5f81608d-f36f-4190-8084-f45116b6f380", "description": "Orange", "property": "colorCode", "input": { @@ -32,6 +34,7 @@ ] }, { + "uuid": "581d68fa-f968-4be2-9f9d-880f2fb73cf7", "description": "Colors", "property": "colors", "input": {}, diff --git a/exercises/resistor-color/description.md b/exercises/resistor-color/description.md index 226f0f2e63..7778acd50f 100644 --- a/exercises/resistor-color/description.md +++ b/exercises/resistor-color/description.md @@ -1,4 +1,15 @@ -Resistors have color coded bands, where each color maps to a number. The first 2 bands of a resistor have a simple encoding scheme: each color maps to a single number. +If you want to build something using a Raspberry Pi, you'll probably use _resistors_. +For this exercise, you need to know two things about them: + +* Each resistor has a resistance value. +* Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read. + +To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values. +Each band has a position and a numeric value. + +The first 2 bands of a resistor have a simple encoding scheme: each color maps to a single number. + +In this exercise you are going to create a helpful program so that you don't have to remember the values of the bands. These colors are encoded as follows: @@ -13,6 +24,10 @@ These colors are encoded as follows: - Grey: 8 - White: 9 +The goal of this exercise is to create a way: +- to look up the numerical value associated with a particular color band +- to list the different band colors + Mnemonics map the colors to the numbers, that, when stored as an array, happen to map to their index in the array: Better Be Right Or Your Great Big Values Go Wrong. More information on the color encoding of resistors can be found in the [Electronic color code Wikipedia article](https://en.wikipedia.org/wiki/Electronic_color_code) diff --git a/exercises/rest-api/canonical-data.json b/exercises/rest-api/canonical-data.json index 9dc3224d7d..29e86388b5 100644 --- a/exercises/rest-api/canonical-data.json +++ b/exercises/rest-api/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "rest-api", - "version": "1.1.1", "comments": [ "The state of the API database before the request is represented", "by the input->database object. Your track may determine how this", @@ -15,6 +14,7 @@ "description": "user management", "cases": [ { + "uuid": "5be01ffb-a814-47a8-a19f-490a5622ba07", "description": "no users", "property": "get", "input": { @@ -28,6 +28,7 @@ } }, { + "uuid": "382b70cc-9f6c-486d-9bee-fda2df81c803", "description": "add user", "property": "post", "input": { @@ -47,6 +48,7 @@ } }, { + "uuid": "d624e5e5-1abb-4f18-95b3-45d55c818dc3", "description": "get single user", "property": "get", "input": { @@ -89,6 +91,7 @@ "description": "iou", "cases": [ { + "uuid": "7a81b82c-7276-433e-8fce-29ce983a7c56", "description": "both users have 0 balance", "property": "post", "input": { @@ -137,6 +140,7 @@ } }, { + "uuid": "1c61f957-cf8c-48ba-9e77-b221ab068803", "description": "borrower has negative balance", "property": "post", "input": { @@ -196,6 +200,7 @@ } }, { + "uuid": "8a8567b3-c097-468a-9541-6bb17d5afc85", "description": "lender has negative balance", "property": "post", "input": { @@ -256,6 +261,7 @@ } }, { + "uuid": "29fb7c12-7099-4a85-a7c4-9c290d2dc01a", "description": "lender owes borrower", "property": "post", "input": { @@ -308,6 +314,7 @@ } }, { + "uuid": "ce969e70-163c-4135-a4a6-2c3a5da286f5", "description": "lender owes borrower less than new loan", "property": "post", "input": { @@ -360,6 +367,7 @@ } }, { + "uuid": "7f4aafd9-ae9b-4e15-a406-87a87bdf47a4", "description": "lender owes borrower same as new loan", "property": "post", "input": { @@ -410,4 +418,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/rest-api/description.md b/exercises/rest-api/description.md index 6fb0033c4a..2b228a375d 100644 --- a/exercises/rest-api/description.md +++ b/exercises/rest-api/description.md @@ -35,4 +35,4 @@ Your task is to implement a simple [RESTful API](https://en.wikipedia.org/wiki/R - https://restfulapi.net/ - Example RESTful APIs - [GitHub](https://developer.github.com/v3/) - - [Reddit](https://www.reddit.com/dev/api/) \ No newline at end of file + - [Reddit](https://www.reddit.com/dev/api/) diff --git a/exercises/reverse-string/canonical-data.json b/exercises/reverse-string/canonical-data.json index 025d3092bd..1127970dea 100644 --- a/exercises/reverse-string/canonical-data.json +++ b/exercises/reverse-string/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "reverse-string", - "version": "1.2.0", "comments": [ "If property based testing tools are available, a good property to test is reversing a string twice: reverse(reverse(string)) == string" ], "cases": [ { + "uuid": "c3b7d806-dced-49ee-8543-933fd1719b1c", "description": "an empty string", "property": "reverse", "input": { @@ -14,6 +14,7 @@ "expected": "" }, { + "uuid": "01ebf55b-bebb-414e-9dec-06f7bb0bee3c", "description": "a word", "property": "reverse", "input": { @@ -22,6 +23,7 @@ "expected": "tobor" }, { + "uuid": "0f7c07e4-efd1-4aaa-a07a-90b49ce0b746", "description": "a capitalized word", "property": "reverse", "input": { @@ -30,14 +32,16 @@ "expected": "nemaR" }, { + "uuid": "71854b9c-f200-4469-9f5c-1e8e5eff5614", "description": "a sentence with punctuation", - "property": "reverse", + "property": "reverse", "input": { "value": "I'm hungry!" }, "expected": "!yrgnuh m'I" }, { + "uuid": "1f8ed2f3-56f3-459b-8f3e-6d8d654a1f6c", "description": "a palindrome", "property": "reverse", "input": { @@ -46,6 +50,7 @@ "expected": "racecar" }, { + "uuid": "b9e7dec1-c6df-40bd-9fa3-cd7ded010c4c", "description": "an even-sized word", "property": "reverse", "input": { diff --git a/exercises/rna-transcription/canonical-data.json b/exercises/rna-transcription/canonical-data.json index d946cd31d5..d05146ed00 100644 --- a/exercises/rna-transcription/canonical-data.json +++ b/exercises/rna-transcription/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "rna-transcription", - "version": "1.3.0", "cases": [ { + "uuid": "b4631f82-c98c-4a2f-90b3-c5c2b6c6f661", "description": "Empty RNA sequence", "property": "toRna", "input": { @@ -11,6 +11,7 @@ "expected": "" }, { + "uuid": "a9558a3c-318c-4240-9256-5d5ed47005a6", "description": "RNA complement of cytosine is guanine", "property": "toRna", "input": { @@ -19,6 +20,7 @@ "expected": "G" }, { + "uuid": "6eedbb5c-12cb-4c8b-9f51-f8320b4dc2e7", "description": "RNA complement of guanine is cytosine", "property": "toRna", "input": { @@ -27,6 +29,7 @@ "expected": "C" }, { + "uuid": "870bd3ec-8487-471d-8d9a-a25046488d3e", "description": "RNA complement of thymine is adenine", "property": "toRna", "input": { @@ -35,6 +38,7 @@ "expected": "A" }, { + "uuid": "aade8964-02e1-4073-872f-42d3ffd74c5f", "description": "RNA complement of adenine is uracil", "property": "toRna", "input": { @@ -43,6 +47,7 @@ "expected": "U" }, { + "uuid": "79ed2757-f018-4f47-a1d7-34a559392dbf", "description": "RNA complement", "property": "toRna", "input": { diff --git a/exercises/robot-name/description.md b/exercises/robot-name/description.md index e6e9a889a1..d9690087a4 100644 --- a/exercises/robot-name/description.md +++ b/exercises/robot-name/description.md @@ -1,14 +1,14 @@ Manage robot factory settings. -When robots come off the factory floor, they have no name. +When a robot comes off the factory floor, it has no name. -The first time you boot them up, a random name is generated in the format +The first time you turn on a robot, a random name is generated in the format of two uppercase letters followed by three digits, such as RX837 or BC811. Every once in a while we need to reset a robot to its factory settings, -which means that their name gets wiped. The next time you ask, it will +which means that its name gets wiped. The next time you ask, that robot will respond with a new random name. The names must be random: they should not follow a predictable sequence. -Random names means a risk of collisions. Your solution must ensure that +Using random names means a risk of collisions. Your solution must ensure that every existing robot has a unique name. diff --git a/exercises/robot-name/metadata.yml b/exercises/robot-name/metadata.yml index 73a9e9e699..bb13936eec 100644 --- a/exercises/robot-name/metadata.yml +++ b/exercises/robot-name/metadata.yml @@ -1,4 +1,3 @@ --- blurb: "Manage robot factory settings." source: "A debugging session with Paul Blackwell at gSchool." -source_url: "http://gschool.it" diff --git a/exercises/robot-simulator/canonical-data.json b/exercises/robot-simulator/canonical-data.json index fdbce2d1c2..fd013e300f 100644 --- a/exercises/robot-simulator/canonical-data.json +++ b/exercises/robot-simulator/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "robot-simulator", - "version": "3.2.0", "comments": [ "Some tests have two expectations: one for the position, one for the direction", "Optionally, you can also test", @@ -13,6 +12,7 @@ "description": "Create robot", "cases": [ { + "uuid": "c557c16d-26c1-4e06-827c-f6602cd0785c", "description": "at origin facing north", "property": "create", "input": { @@ -31,6 +31,7 @@ } }, { + "uuid": "bf0dffce-f11c-4cdb-8a5e-2c89d8a5a67d", "description": "at negative position facing south", "property": "create", "input": { @@ -54,6 +55,7 @@ "description": "Rotating clockwise", "cases": [ { + "uuid": "8cbd0086-6392-4680-b9b9-73cf491e67e5", "description": "changes north to east", "property": "move", "input": { @@ -73,6 +75,7 @@ } }, { + "uuid": "8abc87fc-eab2-4276-93b7-9c009e866ba1", "description": "changes east to south", "property": "move", "input": { @@ -92,6 +95,7 @@ } }, { + "uuid": "3cfe1b85-bbf2-4bae-b54d-d73e7e93617a", "description": "changes south to west", "property": "move", "input": { @@ -111,6 +115,7 @@ } }, { + "uuid": "5ea9fb99-3f2c-47bd-86f7-46b7d8c3c716", "description": "changes west to north", "property": "move", "input": { @@ -135,6 +140,7 @@ "description": "Rotating counter-clockwise", "cases": [ { + "uuid": "fa0c40f5-6ba3-443d-a4b3-58cbd6cb8d63", "description": "changes north to west", "property": "move", "input": { @@ -154,6 +160,7 @@ } }, { + "uuid": "da33d734-831f-445c-9907-d66d7d2a92e2", "description": "changes west to south", "property": "move", "input": { @@ -173,6 +180,7 @@ } }, { + "uuid": "bd1ca4b9-4548-45f4-b32e-900fc7c19389", "description": "changes south to east", "property": "move", "input": { @@ -192,6 +200,7 @@ } }, { + "uuid": "2de27b67-a25c-4b59-9883-bc03b1b55bba", "description": "changes east to north", "property": "move", "input": { @@ -216,6 +225,7 @@ "description": "Moving forward one", "cases": [ { + "uuid": "f0dc2388-cddc-4f83-9bed-bcf46b8fc7b8", "description": "facing north increments Y", "property": "move", "input": { @@ -235,6 +245,7 @@ } }, { + "uuid": "2786cf80-5bbf-44b0-9503-a89a9c5789da", "description": "facing south decrements Y", "property": "move", "input": { @@ -254,6 +265,7 @@ } }, { + "uuid": "84bf3c8c-241f-434d-883d-69817dbd6a48", "description": "facing east increments X", "property": "move", "input": { @@ -273,6 +285,7 @@ } }, { + "uuid": "bb69c4a7-3bbf-4f64-b415-666fa72d7b04", "description": "facing west decrements X", "property": "move", "input": { @@ -300,6 +313,7 @@ ], "cases": [ { + "uuid": "e34ac672-4ed4-4be3-a0b8-d9af259cbaa1", "description": "moving east and north from README", "property": "move", "input": { @@ -319,6 +333,7 @@ } }, { + "uuid": "f30e4955-4b47-4aa3-8b39-ae98cfbd515b", "description": "moving west and north", "property": "move", "input": { @@ -338,6 +353,7 @@ } }, { + "uuid": "3e466bf6-20ab-4d79-8b51-264165182fca", "description": "moving west and south", "property": "move", "input": { @@ -357,6 +373,7 @@ } }, { + "uuid": "41f0bb96-c617-4e6b-acff-a4b279d44514", "description": "moving east and north", "property": "move", "input": { diff --git a/exercises/roman-numerals/canonical-data.json b/exercises/roman-numerals/canonical-data.json index 115636da0e..ad9f48d9c6 100644 --- a/exercises/roman-numerals/canonical-data.json +++ b/exercises/roman-numerals/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "roman-numerals", - "version": "1.2.0", "cases": [ { + "uuid": "19828a3a-fbf7-4661-8ddd-cbaeee0e2178", "description": "1 is a single I", "property": "roman", "input": { @@ -11,6 +11,7 @@ "expected": "I" }, { + "uuid": "f088f064-2d35-4476-9a41-f576da3f7b03", "description": "2 is two I's", "property": "roman", "input": { @@ -19,6 +20,7 @@ "expected": "II" }, { + "uuid": "b374a79c-3bea-43e6-8db8-1286f79c7106", "description": "3 is three I's", "property": "roman", "input": { @@ -27,6 +29,7 @@ "expected": "III" }, { + "uuid": "05a0a1d4-a140-4db1-82e8-fcc21fdb49bb", "description": "4, being 5 - 1, is IV", "property": "roman", "input": { @@ -35,6 +38,7 @@ "expected": "IV" }, { + "uuid": "57c0f9ad-5024-46ab-975d-de18c430b290", "description": "5 is a single V", "property": "roman", "input": { @@ -43,6 +47,7 @@ "expected": "V" }, { + "uuid": "20a2b47f-e57f-4797-a541-0b3825d7f249", "description": "6, being 5 + 1, is VI", "property": "roman", "input": { @@ -51,6 +56,7 @@ "expected": "VI" }, { + "uuid": "ff3fb08c-4917-4aab-9f4e-d663491d083d", "description": "9, being 10 - 1, is IX", "property": "roman", "input": { @@ -59,6 +65,7 @@ "expected": "IX" }, { + "uuid": "2bda64ca-7d28-4c56-b08d-16ce65716cf6", "description": "20 is two X's", "property": "roman", "input": { @@ -67,6 +74,7 @@ "expected": "XXVII" }, { + "uuid": "a1f812ef-84da-4e02-b4f0-89c907d0962c", "description": "48 is not 50 - 2 but rather 40 + 8", "property": "roman", "input": { @@ -75,6 +83,7 @@ "expected": "XLVIII" }, { + "uuid": "607ead62-23d6-4c11-a396-ef821e2e5f75", "description": "49 is not 40 + 5 + 4 but rather 50 - 10 + 10 - 1", "property": "roman", "input": { @@ -83,6 +92,7 @@ "expected": "XLIX" }, { + "uuid": "d5b283d4-455d-4e68-aacf-add6c4b51915", "description": "50 is a single L", "property": "roman", "input": { @@ -91,6 +101,7 @@ "expected": "LIX" }, { + "uuid": "46b46e5b-24da-4180-bfe2-2ef30b39d0d0", "description": "90, being 100 - 10, is XC", "property": "roman", "input": { @@ -99,6 +110,7 @@ "expected": "XCIII" }, { + "uuid": "30494be1-9afb-4f84-9d71-db9df18b55e3", "description": "100 is a single C", "property": "roman", "input": { @@ -107,6 +119,7 @@ "expected": "CXLI" }, { + "uuid": "267f0207-3c55-459a-b81d-67cec7a46ed9", "description": "60, being 50 + 10, is LX", "property": "roman", "input": { @@ -115,6 +128,7 @@ "expected": "CLXIII" }, { + "uuid": "cdb06885-4485-4d71-8bfb-c9d0f496b404", "description": "400, being 500 - 100, is CD", "property": "roman", "input": { @@ -123,6 +137,7 @@ "expected": "CDII" }, { + "uuid": "6b71841d-13b2-46b4-ba97-dec28133ea80", "description": "500 is a single D", "property": "roman", "input": { @@ -131,6 +146,7 @@ "expected": "DLXXV" }, { + "uuid": "432de891-7fd6-4748-a7f6-156082eeca2f", "description": "900, being 1000 - 100, is CM", "property": "roman", "input": { @@ -139,6 +155,7 @@ "expected": "CMXI" }, { + "uuid": "e6de6d24-f668-41c0-88d7-889c0254d173", "description": "1000 is a single M", "property": "roman", "input": { @@ -147,6 +164,7 @@ "expected": "MXXIV" }, { + "uuid": "bb550038-d4eb-4be2-a9ce-f21961ac3bc6", "description": "3000 is three M's", "property": "roman", "input": { diff --git a/exercises/rotational-cipher/canonical-data.json b/exercises/rotational-cipher/canonical-data.json index eae5c1a6fc..53a298c7b1 100644 --- a/exercises/rotational-cipher/canonical-data.json +++ b/exercises/rotational-cipher/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "rotational-cipher", - "version": "1.2.0", "comments": [ "The tests are a series of rotation tests: " ], @@ -9,6 +8,7 @@ "description": "Test rotation from English to ROTn", "cases": [ { + "uuid": "74e58a38-e484-43f1-9466-877a7515e10f", "description": "rotate a by 0, same output as input", "property": "rotate", "input": { @@ -18,6 +18,7 @@ "expected": "a" }, { + "uuid": "7ee352c6-e6b0-4930-b903-d09943ecb8f5", "description": "rotate a by 1", "property": "rotate", "input": { @@ -27,6 +28,7 @@ "expected": "b" }, { + "uuid": "edf0a733-4231-4594-a5ee-46a4009ad764", "description": "rotate a by 26, same output as input", "property": "rotate", "input": { @@ -36,6 +38,7 @@ "expected": "a" }, { + "uuid": "e3e82cb9-2a5b-403f-9931-e43213879300", "description": "rotate m by 13", "property": "rotate", "input": { @@ -45,6 +48,7 @@ "expected": "z" }, { + "uuid": "19f9eb78-e2ad-4da4-8fe3-9291d47c1709", "description": "rotate n by 13 with wrap around alphabet", "property": "rotate", "input": { @@ -54,6 +58,7 @@ "expected": "a" }, { + "uuid": "a116aef4-225b-4da9-884f-e8023ca6408a", "description": "rotate capital letters", "property": "rotate", "input": { @@ -63,6 +68,7 @@ "expected": "TRL" }, { + "uuid": "71b541bb-819c-4dc6-a9c3-132ef9bb737b", "description": "rotate spaces", "property": "rotate", "input": { @@ -72,6 +78,7 @@ "expected": "T R L" }, { + "uuid": "ef32601d-e9ef-4b29-b2b5-8971392282e6", "description": "rotate numbers", "property": "rotate", "input": { @@ -81,6 +88,7 @@ "expected": "Xiwxmrk 1 2 3 xiwxmrk" }, { + "uuid": "32dd74f6-db2b-41a6-b02c-82eb4f93e549", "description": "rotate punctuation", "property": "rotate", "input": { @@ -90,6 +98,7 @@ "expected": "Gzo'n zvo, Bmviyhv!" }, { + "uuid": "9fb93fe6-42b0-46e6-9ec1-0bf0a062d8c9", "description": "rotate all letters", "property": "rotate", "input": { @@ -101,4 +110,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/run-length-encoding/canonical-data.json b/exercises/run-length-encoding/canonical-data.json index ac82810474..bb82ed9fe2 100644 --- a/exercises/run-length-encoding/canonical-data.json +++ b/exercises/run-length-encoding/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "run-length-encoding", - "version": "1.1.0", "cases": [ { "description": "run-length encode a string", "cases": [ { + "uuid": "ad53b61b-6ffc-422f-81a6-61f7df92a231", "description": "empty string", "property": "encode", "input": { @@ -14,6 +14,7 @@ "expected": "" }, { + "uuid": "52012823-b7e6-4277-893c-5b96d42f82de", "description": "single characters only are encoded without count", "property": "encode", "input": { @@ -22,6 +23,7 @@ "expected": "XYZ" }, { + "uuid": "b7868492-7e3a-415f-8da3-d88f51f80409", "description": "string with no single characters", "property": "encode", "input": { @@ -30,6 +32,7 @@ "expected": "2A3B4C" }, { + "uuid": "859b822b-6e9f-44d6-9c46-6091ee6ae358", "description": "single characters mixed with repeated characters", "property": "encode", "input": { @@ -38,6 +41,7 @@ "expected": "12WB12W3B24WB" }, { + "uuid": "1b34de62-e152-47be-bc88-469746df63b3", "description": "multiple whitespace mixed in string", "property": "encode", "input": { @@ -46,6 +50,7 @@ "expected": "2 hs2q q2w2 " }, { + "uuid": "abf176e2-3fbd-40ad-bb2f-2dd6d4df721a", "description": "lowercase characters", "property": "encode", "input": { @@ -59,6 +64,7 @@ "description": "run-length decode a string", "cases": [ { + "uuid": "7ec5c390-f03c-4acf-ac29-5f65861cdeb5", "description": "empty string", "property": "decode", "input": { @@ -67,6 +73,7 @@ "expected": "" }, { + "uuid": "ad23f455-1ac2-4b0e-87d0-b85b10696098", "description": "single characters only", "property": "decode", "input": { @@ -75,6 +82,7 @@ "expected": "XYZ" }, { + "uuid": "21e37583-5a20-4a0e-826c-3dee2c375f54", "description": "string with no single characters", "property": "decode", "input": { @@ -83,6 +91,7 @@ "expected": "AABBBCCCC" }, { + "uuid": "1389ad09-c3a8-4813-9324-99363fba429c", "description": "single characters with repeated characters", "property": "decode", "input": { @@ -91,6 +100,7 @@ "expected": "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB" }, { + "uuid": "3f8e3c51-6aca-4670-b86c-a213bf4706b0", "description": "multiple whitespace mixed in string", "property": "decode", "input": { @@ -99,7 +109,8 @@ "expected": " hsqq qww " }, { - "description": "lower case string", + "uuid": "29f721de-9aad-435f-ba37-7662df4fb551", + "description": "lowercase string", "property": "decode", "input": { "string": "2a3b4c" @@ -112,6 +123,7 @@ "description": "encode and then decode", "cases": [ { + "uuid": "2a762efd-8695-4e04-b0d6-9736899fbc16", "description": "encode followed by decode gives original string", "property": "consistency", "input": { diff --git a/exercises/saddle-points/canonical-data.json b/exercises/saddle-points/canonical-data.json index 40655befe8..a897c7203f 100644 --- a/exercises/saddle-points/canonical-data.json +++ b/exercises/saddle-points/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "saddle-points", - "version": "1.5.0", "comments": [ "Matrix rows and columns are 1-indexed." ], "cases": [ { + "uuid": "3e374e63-a2e0-4530-a39a-d53c560382bd", "description": "Can identify single saddle point", "comments": [ "This is the README example." @@ -26,6 +26,7 @@ ] }, { + "uuid": "6b501e2b-6c1f-491f-b1bb-7f278f760534", "description": "Can identify that empty matrix has no saddle points", "property": "saddlePoints", "input": { @@ -36,6 +37,7 @@ "expected": [] }, { + "uuid": "8c27cc64-e573-4fcb-a099-f0ae863fb02f", "description": "Can identify lack of saddle points when there are none", "property": "saddlePoints", "input": { @@ -48,6 +50,7 @@ "expected": [] }, { + "uuid": "6d1399bd-e105-40fd-a2c9-c6609507d7a3", "description": "Can identify multiple saddle points in a column", "property": "saddlePoints", "input": { @@ -73,6 +76,7 @@ ] }, { + "uuid": "3e81dce9-53b3-44e6-bf26-e328885fd5d1", "description": "Can identify multiple saddle points in a row", "property": "saddlePoints", "input": { @@ -98,6 +102,7 @@ ] }, { + "uuid": "88868621-b6f4-4837-bb8b-3fad8b25d46b", "description": "Can identify saddle point in bottom right corner", "comments": [ "This is a permutation of the README matrix designed to test", @@ -119,6 +124,7 @@ ] }, { + "uuid": "5b9499ca-fcea-4195-830a-9c4584a0ee79", "description": "Can identify saddle points in a non square matrix", "property": "saddlePoints", "input": { @@ -139,6 +145,7 @@ ] }, { + "uuid": "ee99ccd2-a1f1-4283-ad39-f8c70f0cf594", "description": "Can identify that saddle points in a single column matrix are those with the minimum value", "property": "saddlePoints", "input": { @@ -161,6 +168,7 @@ ] }, { + "uuid": "63abf709-a84b-407f-a1b3-456638689713", "description": "Can identify that saddle points in a single row matrix are those with the maximum value", "property": "saddlePoints", "input": { diff --git a/exercises/satellite/canonical-data.json b/exercises/satellite/canonical-data.json index 556b6fc6d2..2326463bf6 100644 --- a/exercises/satellite/canonical-data.json +++ b/exercises/satellite/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "satellite", - "version": "2.0.0", "cases": [ { + "uuid": "8df3fa26-811a-4165-9286-ff9ac0850d19", "description": "Empty tree", "property": "treeFromTraversals", "input": { @@ -12,6 +12,7 @@ "expected": {} }, { + "uuid": "f945ccfc-05e3-47d7-825b-0270559d43ad", "description": "Tree with one item", "property": "treeFromTraversals", "input": { @@ -21,6 +22,7 @@ "expected": {"v": "a", "l": {}, "r": {}} }, { + "uuid": "a0121d5f-37b0-48dd-9c64-cba4c4464135", "description": "Tree with many items", "property": "treeFromTraversals", "input": { @@ -36,6 +38,7 @@ } }, { + "uuid": "6074041f-4891-4d81-a128-401050c2a3b0", "description": "Reject traversals of different length", "property": "treeFromTraversals", "input": { @@ -45,6 +48,7 @@ "expected": {"error": "traversals must have the same length"} }, { + "uuid": "27916ce4-45f3-4d8b-8528-496fedc157ca", "description": "Reject inconsistent traversals of same length", "property": "treeFromTraversals", "input": { @@ -54,6 +58,7 @@ "expected": {"error": "traversals must have the same elements"} }, { + "uuid": "d86a3d72-76a9-43b5-9d3a-e64cb1216035", "description": "Reject traversals with repeated items", "property": "treeFromTraversals", "input": { diff --git a/exercises/say/canonical-data.json b/exercises/say/canonical-data.json index 0f46c30cda..8df626d902 100644 --- a/exercises/say/canonical-data.json +++ b/exercises/say/canonical-data.json @@ -1,12 +1,12 @@ { "exercise": "say", - "version": "1.2.0", "comments": [ "An 'error' object is used as expected value to indicate that the", "input value is out of the range described in the exercise." ], "cases": [ { + "uuid": "5d22a120-ba0c-428c-bd25-8682235d83e8", "description": "zero", "property": "say", "input": { @@ -15,6 +15,7 @@ "expected": "zero" }, { + "uuid": "9b5eed77-dbf6-439d-b920-3f7eb58928f6", "description": "one", "property": "say", "input": { @@ -23,6 +24,7 @@ "expected": "one" }, { + "uuid": "7c499be1-612e-4096-a5e1-43b2f719406d", "description": "fourteen", "property": "say", "input": { @@ -31,6 +33,7 @@ "expected": "fourteen" }, { + "uuid": "f541dd8e-f070-4329-92b4-b7ce2fcf06b4", "description": "twenty", "property": "say", "input": { @@ -39,6 +42,7 @@ "expected": "twenty" }, { + "uuid": "d78601eb-4a84-4bfa-bf0e-665aeb8abe94", "description": "twenty-two", "property": "say", "input": { @@ -47,6 +51,7 @@ "expected": "twenty-two" }, { + "uuid": "e417d452-129e-4056-bd5b-6eb1df334dce", "description": "one hundred", "property": "say", "input": { @@ -55,6 +60,7 @@ "expected": "one hundred" }, { + "uuid": "d6924f30-80ba-4597-acf6-ea3f16269da8", "description": "one hundred twenty-three", "property": "say", "input": { @@ -63,6 +69,7 @@ "expected": "one hundred twenty-three" }, { + "uuid": "3d83da89-a372-46d3-b10d-de0c792432b3", "description": "one thousand", "property": "say", "input": { @@ -71,6 +78,7 @@ "expected": "one thousand" }, { + "uuid": "865af898-1d5b-495f-8ff0-2f06d3c73709", "description": "one thousand two hundred thirty-four", "property": "say", "input": { @@ -79,6 +87,7 @@ "expected": "one thousand two hundred thirty-four" }, { + "uuid": "b6a3f442-266e-47a3-835d-7f8a35f6cf7f", "description": "one million", "property": "say", "input": { @@ -87,6 +96,7 @@ "expected": "one million" }, { + "uuid": "2cea9303-e77e-4212-b8ff-c39f1978fc70", "description": "one million two thousand three hundred forty-five", "property": "say", "input": { @@ -95,6 +105,7 @@ "expected": "one million two thousand three hundred forty-five" }, { + "uuid": "3e240eeb-f564-4b80-9421-db123f66a38f", "description": "one billion", "property": "say", "input": { @@ -103,6 +114,7 @@ "expected": "one billion" }, { + "uuid": "9a43fed1-c875-4710-8286-5065d73b8a9e", "description": "a big number", "property": "say", "input": { @@ -111,6 +123,7 @@ "expected": "nine hundred eighty-seven billion six hundred fifty-four million three hundred twenty-one thousand one hundred twenty-three" }, { + "uuid": "49a6a17b-084e-423e-994d-a87c0ecc05ef", "description": "numbers below zero are out of range", "property": "say", "input": { @@ -119,6 +132,7 @@ "expected": {"error": "input out of range"} }, { + "uuid": "4d6492eb-5853-4d16-9d34-b0f61b261fd9", "description": "numbers above 999,999,999,999 are out of range", "property": "say", "input": { @@ -127,4 +141,4 @@ "expected": {"error": "input out of range"} } ] -} \ No newline at end of file +} diff --git a/exercises/scale-generator/canonical-data.json b/exercises/scale-generator/canonical-data.json index 69e9e24815..a5c141716d 100644 --- a/exercises/scale-generator/canonical-data.json +++ b/exercises/scale-generator/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "scale-generator", - "version": "2.0.0", "cases": [ { "comments": [ @@ -10,6 +9,7 @@ "description": "Chromatic scales", "cases": [ { + "uuid": "10ea7b14-8a49-40be-ac55-7c62b55f9b47", "description": "Chromatic scale with sharps", "property": "chromatic", "input": { @@ -18,6 +18,7 @@ "expected": [ "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" ] }, { + "uuid": "af8381de-9a72-4efd-823a-48374dbfe76f", "description": "Chromatic scale with flats", "property": "chromatic", "input": { @@ -35,6 +36,7 @@ "description": "Scales with specified intervals", "cases": [ { + "uuid": "6f5b1410-1dd7-4c6c-b410-6b7e986f6f1e", "description": "Simple major scale", "comments": [ "The simplest major scale, with no sharps or flats." @@ -47,6 +49,7 @@ "expected": [ "C", "D", "E", "F", "G", "A", "B" ] }, { + "uuid": "13a92f89-a83e-40b5-b9d4-01136931ba02", "description": "Major scale with sharps", "property": "interval", "input": { @@ -56,6 +59,7 @@ "expected": [ "G", "A", "B", "C", "D", "E", "F#" ] }, { + "uuid": "aa3320f6-a761-49a1-bcf6-978e0c81080a", "description": "Major scale with flats", "property": "interval", "input": { @@ -65,6 +69,7 @@ "expected": [ "F", "G", "A", "Bb", "C", "D", "E" ] }, { + "uuid": "63daeb2f-c3f9-4c45-92be-5bf97f61ff94", "description": "Minor scale with sharps", "property": "interval", "input": { @@ -74,6 +79,7 @@ "expected": [ "F#", "G#", "A", "B", "C#", "D", "E" ] }, { + "uuid": "616594d0-9c48-4301-949e-af1d4fad16fd", "description": "Minor scale with flats", "property": "interval", "input": { @@ -83,6 +89,7 @@ "expected": [ "Bb", "C", "Db", "Eb", "F", "Gb", "Ab" ] }, { + "uuid": "390bd12c-5ac7-4ec7-bdde-4e58d5c78b0a", "description": "Dorian mode", "property": "interval", "input": { @@ -92,6 +99,7 @@ "expected": [ "D", "E", "F", "G", "A", "B", "C" ] }, { + "uuid": "846d0862-0f3e-4f3b-8a2d-9cc74f017848", "description": "Mixolydian mode", "property": "interval", "input": { @@ -101,6 +109,7 @@ "expected": [ "Eb", "F", "G", "Ab", "Bb", "C", "Db" ] }, { + "uuid": "7d49a8bb-b5f7-46ad-a207-83bd5032291a", "description": "Lydian mode", "property": "interval", "input": { @@ -110,6 +119,7 @@ "expected": [ "A", "B", "C#", "D#", "E", "F#", "G#" ] }, { + "uuid": "a4e4dac5-1891-4160-a19f-bb06d653d4d0", "description": "Phrygian mode", "property": "interval", "input": { @@ -119,6 +129,7 @@ "expected": [ "E", "F", "G", "A", "B", "C", "D" ] }, { + "uuid": "ef3650af-90f8-4ad9-9ef6-fdbeae07dcaa", "description": "Locrian mode", "property": "interval", "input": { @@ -131,6 +142,7 @@ "comments": [ "Note that this case introduces the accidental interval (A)" ], + "uuid": "70517400-12b7-4530-b861-fa940ae69ee8", "description": "Harmonic minor", "property": "interval", "input": { @@ -140,6 +152,7 @@ "expected": [ "D", "E", "F", "G", "A", "Bb", "Db" ] }, { + "uuid": "37114c0b-c54d-45da-9f4b-3848201470b0", "description": "Octatonic", "property": "interval", "input": { @@ -149,6 +162,7 @@ "expected": [ "C", "D", "D#", "F", "F#", "G#", "A", "B" ] }, { + "uuid": "496466e7-aa45-4bbd-a64d-f41030feed9c", "description": "Hexatonic", "property": "interval", "input": { @@ -158,6 +172,7 @@ "expected": [ "Db", "Eb", "F", "G", "A", "B" ] }, { + "uuid": "bee5d9ec-e226-47b6-b62b-847a9241f3cc", "description": "Pentatonic", "property": "interval", "input": { @@ -167,6 +182,7 @@ "expected": [ "A", "B", "C#", "E", "F#" ] }, { + "uuid": "dbee06a6-7535-4ab7-98e8-d8a36c8402d1", "description": "Enigmatic", "property": "interval", "input": { diff --git a/exercises/scale-generator/description.md b/exercises/scale-generator/description.md index 3114f7cc20..a758bab738 100644 --- a/exercises/scale-generator/description.md +++ b/exercises/scale-generator/description.md @@ -41,7 +41,7 @@ a "whole step" or "major second" (written as an upper-case "M"). The diatonic scales are built using only these two intervals between adjacent notes. -Non-diatonic scales can contain other intervals. An "augmented first" -interval, written "A", has two interceding notes (e.g., from A to C or -Db to E). There are also smaller and larger intervals, but they will not -figure into this exercise. +Non-diatonic scales can contain other intervals. An "augmented second" +interval, written "A", has two interceding notes (e.g., from A to C or Db to E) +or a "whole step" plus a "half step". There are also smaller and larger +intervals, but they will not figure into this exercise. diff --git a/exercises/scrabble-score/canonical-data.json b/exercises/scrabble-score/canonical-data.json index 7aa6ce7a29..f69b1964bc 100644 --- a/exercises/scrabble-score/canonical-data.json +++ b/exercises/scrabble-score/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "scrabble-score", - "version": "1.1.0", "cases": [ { + "uuid": "f46cda29-1ca5-4ef2-bd45-388a767e3db2", "description": "lowercase letter", "property": "score", "input": { @@ -11,6 +11,7 @@ "expected": 1 }, { + "uuid": "f7794b49-f13e-45d1-a933-4e48459b2201", "description": "uppercase letter", "property": "score", "input": { @@ -19,6 +20,7 @@ "expected": 1 }, { + "uuid": "eaba9c76-f9fa-49c9-a1b0-d1ba3a5b31fa", "description": "valuable letter", "property": "score", "input": { @@ -27,6 +29,7 @@ "expected": 4 }, { + "uuid": "f3c8c94e-bb48-4da2-b09f-e832e103151e", "description": "short word", "property": "score", "input": { @@ -35,6 +38,7 @@ "expected": 2 }, { + "uuid": "71e3d8fa-900d-4548-930e-68e7067c4615", "description": "short, valuable word", "property": "score", "input": { @@ -43,6 +47,7 @@ "expected": 12 }, { + "uuid": "d3088ad9-570c-4b51-8764-c75d5a430e99", "description": "medium word", "property": "score", "input": { @@ -51,6 +56,7 @@ "expected": 6 }, { + "uuid": "fa20c572-ad86-400a-8511-64512daac352", "description": "medium, valuable word", "property": "score", "input": { @@ -59,6 +65,7 @@ "expected": 22 }, { + "uuid": "9336f0ba-9c2b-4fa0-bd1c-2e2d328cf967", "description": "long, mixed-case word", "property": "score", "input": { @@ -67,6 +74,7 @@ "expected": 41 }, { + "uuid": "1e34e2c3-e444-4ea7-b598-3c2b46fd2c10", "description": "english-like word", "property": "score", "input": { @@ -75,6 +83,7 @@ "expected": 8 }, { + "uuid": "4efe3169-b3b6-4334-8bae-ff4ef24a7e4f", "description": "empty input", "property": "score", "input": { @@ -83,6 +92,7 @@ "expected": 0 }, { + "uuid": "3b305c1c-f260-4e15-a5b5-cb7d3ea7c3d7", "description": "entire alphabet available", "property": "score", "input": { @@ -91,4 +101,4 @@ "expected": 87 } ] -} \ No newline at end of file +} diff --git a/exercises/scrabble-score/description.md b/exercises/scrabble-score/description.md index 394018feef..c3c68a195d 100644 --- a/exercises/scrabble-score/description.md +++ b/exercises/scrabble-score/description.md @@ -1,4 +1,4 @@ -Given a word, compute the scrabble score for that word. +Given a word, compute the Scrabble score for that word. ## Letter Values diff --git a/exercises/scrabble-score/metadata.yml b/exercises/scrabble-score/metadata.yml index d2358ac514..f0b43e6ca3 100644 --- a/exercises/scrabble-score/metadata.yml +++ b/exercises/scrabble-score/metadata.yml @@ -1,4 +1,4 @@ --- -blurb: "Given a word, compute the scrabble score for that word." +blurb: "Given a word, compute the Scrabble score for that word." source: "Inspired by the Extreme Startup game" source_url: "https://github.com/rchatley/extreme_startup" diff --git a/exercises/secret-handshake/canonical-data.json b/exercises/secret-handshake/canonical-data.json index 50eaab3b78..aee52e8351 100644 --- a/exercises/secret-handshake/canonical-data.json +++ b/exercises/secret-handshake/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "secret-handshake", - "version": "1.2.0", "comments": [ " In a discussion in https://github.com/exercism/problem-specifications/pull/794 and ", " https://github.com/exercism/problem-specifications/issues/335 it has been decided to ", @@ -19,6 +18,7 @@ "description": "Create a handshake for a number", "cases": [ { + "uuid": "b8496fbd-6778-468c-8054-648d03c4bb23", "description": "wink for 1", "property": "commands", "input": { @@ -27,6 +27,7 @@ "expected": ["wink"] }, { + "uuid": "83ec6c58-81a9-4fd1-bfaf-0160514fc0e3", "description": "double blink for 10", "property": "commands", "input": { @@ -35,6 +36,7 @@ "expected": ["double blink"] }, { + "uuid": "0e20e466-3519-4134-8082-5639d85fef71", "description": "close your eyes for 100", "property": "commands", "input": { @@ -43,6 +45,7 @@ "expected": ["close your eyes"] }, { + "uuid": "b339ddbb-88b7-4b7d-9b19-4134030d9ac0", "description": "jump for 1000", "property": "commands", "input": { @@ -51,6 +54,7 @@ "expected": ["jump"] }, { + "uuid": "40499fb4-e60c-43d7-8b98-0de3ca44e0eb", "description": "combine two actions", "property": "commands", "input": { @@ -59,6 +63,7 @@ "expected": ["wink", "double blink"] }, { + "uuid": "9730cdd5-ef27-494b-afd3-5c91ad6c3d9d", "description": "reverse two actions", "property": "commands", "input": { @@ -67,6 +72,7 @@ "expected": ["double blink", "wink"] }, { + "uuid": "0b828205-51ca-45cd-90d5-f2506013f25f", "description": "reversing one action gives the same action", "property": "commands", "input": { @@ -75,6 +81,7 @@ "expected": ["jump"] }, { + "uuid": "9949e2ac-6c9c-4330-b685-2089ab28b05f", "description": "reversing no actions still gives no actions", "property": "commands", "input": { @@ -83,6 +90,7 @@ "expected": [] }, { + "uuid": "23fdca98-676b-4848-970d-cfed7be39f81", "description": "all possible actions", "property": "commands", "input": { @@ -91,6 +99,7 @@ "expected": ["wink", "double blink", "close your eyes", "jump"] }, { + "uuid": "ae8fe006-d910-4d6f-be00-54b7c3799e79", "description": "reverse all possible actions", "property": "commands", "input": { @@ -99,6 +108,7 @@ "expected": ["jump", "close your eyes", "double blink", "wink"] }, { + "uuid": "3d36da37-b31f-4cdb-a396-d93a2ee1c4a5", "description": "do nothing for zero", "property": "commands", "input": { diff --git a/exercises/series/canonical-data.json b/exercises/series/canonical-data.json index b97b6c6500..fcf8632080 100644 --- a/exercises/series/canonical-data.json +++ b/exercises/series/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "series", - "version": "1.0.0", "cases": [ { + "uuid": "7ae7a46a-d992-4c2a-9c15-a112d125ebad", "description": "slices of one from one", "property": "slices", "input": { @@ -12,6 +12,7 @@ "expected": ["1"] }, { + "uuid": "3143b71d-f6a5-4221-aeae-619f906244d2", "description": "slices of one from two", "property": "slices", "input": { @@ -21,6 +22,7 @@ "expected": ["1", "2"] }, { + "uuid": "dbb68ff5-76c5-4ccd-895a-93dbec6d5805", "description": "slices of two", "property": "slices", "input": { @@ -30,6 +32,7 @@ "expected": ["35"] }, { + "uuid": "19bbea47-c987-4e11-a7d1-e103442adf86", "description": "slices of two overlap", "property": "slices", "input": { @@ -39,6 +42,7 @@ "expected": ["91", "14", "42"] }, { + "uuid": "8e17148d-ba0a-4007-a07f-d7f87015d84c", "description": "slices can include duplicates", "property": "slices", "input": { @@ -48,6 +52,7 @@ "expected": ["777", "777", "777", "777"] }, { + "uuid": "bd5b085e-f612-4f81-97a8-6314258278b0", "description": "slices of a long series", "property": "slices", "input": { @@ -58,6 +63,7 @@ "93904", "39042", "90424", "04243"] }, { + "uuid": "6d235d85-46cf-4fae-9955-14b6efef27cd", "description": "slice length is too large", "property": "slices", "input": { @@ -69,6 +75,7 @@ } }, { + "uuid": "d34004ad-8765-4c09-8ba1-ada8ce776806", "description": "slice length cannot be zero", "property": "slices", "input": { @@ -80,6 +87,7 @@ } }, { + "uuid": "10ab822d-8410-470a-a85d-23fbeb549e54", "description": "slice length cannot be negative", "property": "slices", "input": { @@ -91,6 +99,7 @@ } }, { + "uuid": "c7ed0812-0e4b-4bf3-99c4-28cbbfc246a2", "description": "empty series is invalid", "property": "slices", "input": { diff --git a/exercises/sgf-parsing/canonical-data.json b/exercises/sgf-parsing/canonical-data.json index e4386ad937..b12ea74782 100644 --- a/exercises/sgf-parsing/canonical-data.json +++ b/exercises/sgf-parsing/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "sgf-parsing", - "version": "1.2.0", "cases": [ { + "uuid": "2668d5dc-109f-4f71-b9d5-8d06b1d6f1cd", "description": "empty input", "property": "parse", "input": { @@ -13,6 +13,7 @@ } }, { + "uuid": "84ded10a-94df-4a30-9457-b50ccbdca813", "description": "tree with no nodes", "property": "parse", "input": { @@ -23,6 +24,7 @@ } }, { + "uuid": "0a6311b2-c615-4fa7-800e-1b1cbb68833d", "description": "node without tree", "property": "parse", "input": { @@ -33,6 +35,7 @@ } }, { + "uuid": "8c419ed8-28c4-49f6-8f2d-433e706110ef", "description": "node without properties", "property": "parse", "input": { @@ -44,6 +47,7 @@ } }, { + "uuid": "8209645f-32da-48fe-8e8f-b9b562c26b49", "description": "single node tree", "property": "parse", "input": { @@ -57,6 +61,7 @@ } }, { + "uuid": "6c995856-b919-4c75-8fd6-c2c3c31b37dc", "description": "multiple properties", "property": "parse", "input": { @@ -71,6 +76,7 @@ } }, { + "uuid": "a771f518-ec96-48ca-83c7-f8d39975645f", "description": "properties without delimiter", "property": "parse", "input": { @@ -81,6 +87,7 @@ } }, { + "uuid": "6c02a24e-6323-4ed5-9962-187d19e36bc8", "description": "all lowercase property", "property": "parse", "input": { @@ -91,6 +98,7 @@ } }, { + "uuid": "8772d2b1-3c57-405a-93ac-0703b671adc1", "description": "upper and lowercase property", "property": "parse", "input": { @@ -101,6 +109,7 @@ } }, { + "uuid": "a759b652-240e-42ec-a6d2-3a08d834b9e2", "description": "two nodes", "property": "parse", "input": { @@ -121,6 +130,7 @@ } }, { + "uuid": "cc7c02bc-6097-42c4-ab88-a07cb1533d00", "description": "two child trees", "property": "parse", "input": { @@ -147,6 +157,7 @@ } }, { + "uuid": "724eeda6-00db-41b1-8aa9-4d5238ca0130", "description": "multiple property values", "property": "parse", "input": { @@ -160,6 +171,7 @@ } }, { + "uuid": "11c36323-93fc-495d-bb23-c88ee5844b8c", "description": "escaped property", "property": "parse", "input": { diff --git a/exercises/sieve/canonical-data.json b/exercises/sieve/canonical-data.json index 18efc4401c..27cf604d39 100644 --- a/exercises/sieve/canonical-data.json +++ b/exercises/sieve/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "sieve", - "version": "1.1.0", "cases": [ { + "uuid": "88529125-c4ce-43cc-bb36-1eb4ddd7b44f", "description": "no primes under two", "property": "primes", "input": { @@ -11,6 +11,7 @@ "expected": [] }, { + "uuid": "4afe9474-c705-4477-9923-840e1024cc2b", "description": "find first prime", "property": "primes", "input": { @@ -19,6 +20,7 @@ "expected": [2] }, { + "uuid": "974945d8-8cd9-4f00-9463-7d813c7f17b7", "description": "find primes up to 10", "property": "primes", "input": { @@ -27,6 +29,7 @@ "expected": [2, 3, 5, 7] }, { + "uuid": "2e2417b7-3f3a-452a-8594-b9af08af6d82", "description": "limit is prime", "property": "primes", "input": { @@ -35,6 +38,7 @@ "expected": [2, 3, 5, 7, 11, 13] }, { + "uuid": "92102a05-4c7c-47de-9ed0-b7d5fcd00f21", "description": "find primes up to 1000", "property": "primes", "input": { diff --git a/exercises/simple-cipher/canonical-data.json b/exercises/simple-cipher/canonical-data.json index 5fc78ad0e9..569cc3565f 100644 --- a/exercises/simple-cipher/canonical-data.json +++ b/exercises/simple-cipher/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "simple-cipher", - "version": "2.0.0", "comments": ["Some of the strings used in this file are symbolic and do not represent their literal value. They are:", "cipher.key - Represents the Cipher key", @@ -12,6 +11,7 @@ "description": "Random key cipher", "cases": [ { + "uuid": "b8bdfbe1-bea3-41bb-a999-b41403f2b15d", "description": "Can encode", "property": "encode", "input": { @@ -20,6 +20,7 @@ "expected": "cipher.key.substring(0, plaintext.length)" }, { + "uuid": "3dff7f36-75db-46b4-ab70-644b3f38b81c", "description": "Can decode", "property": "decode", "input": { @@ -28,6 +29,7 @@ "expected": "aaaaaaaaaa" }, { + "uuid": "8143c684-6df6-46ba-bd1f-dea8fcb5d265", "description": "Is reversible. I.e., if you apply decode in a encoded result, you must see the same plaintext encode parameter as a result of the decode method", "property": "decode", "input": { @@ -37,6 +39,7 @@ "expected": "abcdefghij" }, { + "uuid": "defc0050-e87d-4840-85e4-51a1ab9dd6aa", "description": "Key is made only of lowercase letters", "property": "key", "input": {}, @@ -50,6 +53,7 @@ "description": "Substitution cipher", "cases": [ { + "uuid": "565e5158-5b3b-41dd-b99d-33b9f413c39f", "description": "Can encode", "property": "encode", "input": { @@ -59,6 +63,7 @@ "expected": "abcdefghij" }, { + "uuid": "d44e4f6a-b8af-4e90-9d08-fd407e31e67b", "description": "Can decode", "property": "decode", "input": { @@ -68,6 +73,7 @@ "expected": "aaaaaaaaaa" }, { + "uuid": "70a16473-7339-43df-902d-93408c69e9d1", "description": "Is reversible. I.e., if you apply decode in a encoded result, you must see the same plaintext encode parameter as a result of the decode method", "property": "decode", "input": { @@ -78,6 +84,7 @@ "expected": "abcdefghij" }, { + "uuid": "69a1458b-92a6-433a-a02d-7beac3ea91f9", "description": "Can double shift encode", "property": "encode", "input": { @@ -87,7 +94,8 @@ "expected": "qayaeaagaciai" }, { - "description": "Can wrap on encode", + "uuid": "21d207c1-98de-40aa-994f-86197ae230fb", + "description": "Can wrap on encode", "property": "encode", "input": { "key": "abcdefghij", @@ -96,6 +104,7 @@ "expected": "zabcdefghi" }, { + "uuid": "a3d7a4d7-24a9-4de6-bdc4-a6614ced0cb3", "description": "Can wrap on decode", "property": "decode", "input": { @@ -105,6 +114,7 @@ "expected": "zzzzzzzzzz" }, { + "uuid": "e31c9b8c-8eb6-45c9-a4b5-8344a36b9641", "description": "Can encode messages longer than the key", "property": "encode", "input": { @@ -114,6 +124,7 @@ "expected": "iboaqcnecbfcr" }, { + "uuid": "93cfaae0-17da-4627-9a04-d6d1e1be52e3", "description": "Can decode messages longer than the key", "property": "decode", "input": { diff --git a/exercises/simple-cipher/description.md b/exercises/simple-cipher/description.md index dd25d8861e..b1acc8d3ed 100644 --- a/exercises/simple-cipher/description.md +++ b/exercises/simple-cipher/description.md @@ -59,7 +59,7 @@ substitution cipher a little more fault tolerant by providing a source of randomness and ensuring that the key contains only lowercase letters. If someone doesn't submit a key at all, generate a truly random key of -at least 100 alphanumeric characters in length. +at least 100 lowercase characters in length. ## Extensions diff --git a/exercises/simple-linked-list/metadata.yml b/exercises/simple-linked-list/metadata.yml index 2ec75401bc..3d71cc7de4 100644 --- a/exercises/simple-linked-list/metadata.yml +++ b/exercises/simple-linked-list/metadata.yml @@ -1,4 +1,4 @@ --- blurb: "Write a simple linked list implementation that uses Elements and a List" source: "Inspired by 'Data Structures and Algorithms with Object-Oriented Design Patterns in Ruby', singly linked-lists." -source_url: "http://www.brpreiss.com/books/opus8/html/page96.html#SECTION004300000000000000000" +source_url: "https://web.archive.org/web/20160731005714/http://brpreiss.com/books/opus8/html/page96.html" diff --git a/exercises/space-age/canonical-data.json b/exercises/space-age/canonical-data.json index 9b6b1aef4a..285c66cd94 100644 --- a/exercises/space-age/canonical-data.json +++ b/exercises/space-age/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "space-age", - "version": "1.2.0", "cases": [ { + "uuid": "84f609af-5a91-4d68-90a3-9e32d8a5cd34", "description": "age on Earth", "property": "age", "input": { @@ -12,6 +12,7 @@ "expected": 31.69 }, { + "uuid": "ca20c4e9-6054-458c-9312-79679ffab40b", "description": "age on Mercury", "property": "age", "input": { @@ -21,6 +22,7 @@ "expected": 280.88 }, { + "uuid": "502c6529-fd1b-41d3-8fab-65e03082b024", "description": "age on Venus", "property": "age", "input": { @@ -30,6 +32,7 @@ "expected": 9.78 }, { + "uuid": "9ceadf5e-a0d5-4388-9d40-2c459227ceb8", "description": "age on Mars", "property": "age", "input": { @@ -39,6 +42,7 @@ "expected": 35.88 }, { + "uuid": "42927dc3-fe5e-4f76-a5b5-f737fc19bcde", "description": "age on Jupiter", "property": "age", "input": { @@ -48,6 +52,7 @@ "expected": 2.41 }, { + "uuid": "8469b332-7837-4ada-b27c-00ee043ebcad", "description": "age on Saturn", "property": "age", "input": { @@ -57,6 +62,7 @@ "expected": 2.15 }, { + "uuid": "999354c1-76f8-4bb5-a672-f317b6436743", "description": "age on Uranus", "property": "age", "input": { @@ -66,6 +72,7 @@ "expected": 0.46 }, { + "uuid": "80096d30-a0d4-4449-903e-a381178355d8", "description": "age on Neptune", "property": "age", "input": { @@ -75,4 +82,4 @@ "expected": 0.35 } ] -} \ No newline at end of file +} diff --git a/exercises/space-age/description.md b/exercises/space-age/description.md index ca0ef9157e..1d3e69c235 100644 --- a/exercises/space-age/description.md +++ b/exercises/space-age/description.md @@ -1,8 +1,8 @@ Given an age in seconds, calculate how old someone would be on: - - Earth: orbital period 365.25 Earth days, or 31557600 seconds - Mercury: orbital period 0.2408467 Earth years - Venus: orbital period 0.61519726 Earth years + - Earth: orbital period 1.0 Earth years, 365.25 Earth days, or 31557600 seconds - Mars: orbital period 1.8808158 Earth years - Jupiter: orbital period 11.862615 Earth years - Saturn: orbital period 29.447498 Earth years diff --git a/exercises/spiral-matrix/canonical-data.json b/exercises/spiral-matrix/canonical-data.json index b6e22e9b8b..2da984622e 100644 --- a/exercises/spiral-matrix/canonical-data.json +++ b/exercises/spiral-matrix/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "spiral-matrix", - "version": "1.1.0", "cases": [ { + "uuid": "8f584201-b446-4bc9-b132-811c8edd9040", "description": "empty spiral", "property": "spiralMatrix", "input": { @@ -11,6 +11,7 @@ "expected": [] }, { + "uuid": "e40ae5f3-e2c9-4639-8116-8a119d632ab2", "description": "trivial spiral", "property": "spiralMatrix", "input": { @@ -19,6 +20,7 @@ "expected": [ [1] ] }, { + "uuid": "cf05e42d-eb78-4098-a36e-cdaf0991bc48", "description": "spiral of size 2", "property": "spiralMatrix", "input": { @@ -28,6 +30,7 @@ , [4, 3] ] }, { + "uuid": "1c475667-c896-4c23-82e2-e033929de939", "description": "spiral of size 3", "property": "spiralMatrix", "input": { @@ -38,6 +41,7 @@ , [7, 6, 5] ] }, { + "uuid": "05ccbc48-d891-44f5-9137-f4ce462a759d", "description": "spiral of size 4", "property": "spiralMatrix", "input": { @@ -49,6 +53,7 @@ , [10, 9, 8, 7] ] }, { + "uuid": "f4d2165b-1738-4e0c-bed0-c459045ae50d", "description": "spiral of size 5", "property": "spiralMatrix", "input": { diff --git a/exercises/square-root/canonical-data.json b/exercises/square-root/canonical-data.json new file mode 100644 index 0000000000..d5cddd5d8f --- /dev/null +++ b/exercises/square-root/canonical-data.json @@ -0,0 +1,59 @@ +{ + "exercise": "square-root", + "cases": [ + { + "uuid": "9b748478-7b0a-490c-b87a-609dacf631fd", + "description": "root of 1", + "property": "squareRoot", + "input": { + "radicand": 1 + }, + "expected": 1 + }, + { + "uuid": "7d3aa9ba-9ac6-4e93-a18b-2e8b477139bb", + "description": "root of 4", + "property": "squareRoot", + "input": { + "radicand": 4 + }, + "expected": 2 + }, + { + "uuid": "6624aabf-3659-4ae0-a1c8-25ae7f33c6ef", + "description": "root of 25", + "property": "squareRoot", + "input": { + "radicand": 25 + }, + "expected": 5 + }, + { + "uuid": "93beac69-265e-4429-abb1-94506b431f81", + "description": "root of 81", + "property": "squareRoot", + "input": { + "radicand": 81 + }, + "expected": 9 + }, + { + "uuid": "fbddfeda-8c4f-4bc4-87ca-6991af35360e", + "description": "root of 196", + "property": "squareRoot", + "input": { + "radicand": 196 + }, + "expected": 14 + }, + { + "uuid": "c03d0532-8368-4734-a8e0-f96a9eb7fc1d", + "description": "root of 65025", + "property": "squareRoot", + "input": { + "radicand": 65025 + }, + "expected": 255 + } + ] +} diff --git a/exercises/square-root/description.md b/exercises/square-root/description.md new file mode 100644 index 0000000000..7cc3e05944 --- /dev/null +++ b/exercises/square-root/description.md @@ -0,0 +1,7 @@ +Given a natural radicand, return its square root. + +Note that the term "radicand" refers to the number for which the root is to be determined. That is, it is the number under the root symbol. + +Check out the Wikipedia pages on [square root](https://en.wikipedia.org/wiki/Square_root) and [methods of computing square roots](https://en.wikipedia.org/wiki/Methods_of_computing_square_roots). + +Recall also that natural numbers are positive real whole numbers (i.e. 1, 2, 3 and up). diff --git a/exercises/square-root/metadata.yml b/exercises/square-root/metadata.yml new file mode 100644 index 0000000000..39f118ba9b --- /dev/null +++ b/exercises/square-root/metadata.yml @@ -0,0 +1,4 @@ +--- +blurb: "Given a natural radicand, return its square root." +source: "wolf99" +source_url: "https://github.com/exercism/problem-specifications/pull/1582" diff --git a/exercises/sublist/canonical-data.json b/exercises/sublist/canonical-data.json index ac066fe300..5acaf957e6 100644 --- a/exercises/sublist/canonical-data.json +++ b/exercises/sublist/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "sublist", - "version": "1.1.0", "comments": [ "Lists are ordered and sequential.", "https://en.wikipedia.org/wiki/List_%28abstract_data_type%29", @@ -16,6 +15,7 @@ ], "cases": [ { + "uuid": "97319c93-ebc5-47ab-a022-02a1980e1d29", "description": "empty lists", "property": "sublist", "input": { @@ -25,6 +25,7 @@ "expected": "equal" }, { + "uuid": "de27dbd4-df52-46fe-a336-30be58457382", "description": "empty list within non empty list", "property": "sublist", "input": { @@ -34,6 +35,7 @@ "expected": "sublist" }, { + "uuid": "5487cfd1-bc7d-429f-ac6f-1177b857d4fb", "description": "non empty list contains empty list", "property": "sublist", "input": { @@ -43,6 +45,7 @@ "expected": "superlist" }, { + "uuid": "1f390b47-f6b2-4a93-bc23-858ba5dda9a6", "description": "list equals itself", "property": "sublist", "input": { @@ -52,6 +55,7 @@ "expected": "equal" }, { + "uuid": "7ed2bfb2-922b-4363-ae75-f3a05e8274f5", "description": "different lists", "property": "sublist", "input": { @@ -61,6 +65,7 @@ "expected": "unequal" }, { + "uuid": "3b8a2568-6144-4f06-b0a1-9d266b365341", "description": "false start", "property": "sublist", "input": { @@ -70,6 +75,7 @@ "expected": "sublist" }, { + "uuid": "dc39ed58-6311-4814-be30-05a64bc8d9b1", "description": "consecutive", "property": "sublist", "input": { @@ -79,6 +85,7 @@ "expected": "sublist" }, { + "uuid": "d1270dab-a1ce-41aa-b29d-b3257241ac26", "description": "sublist at start", "property": "sublist", "input": { @@ -88,6 +95,7 @@ "expected": "sublist" }, { + "uuid": "81f3d3f7-4f25-4ada-bcdc-897c403de1b6", "description": "sublist in middle", "property": "sublist", "input": { @@ -97,6 +105,7 @@ "expected": "sublist" }, { + "uuid": "43bcae1e-a9cf-470e-923e-0946e04d8fdd", "description": "sublist at end", "property": "sublist", "input": { @@ -106,6 +115,7 @@ "expected": "sublist" }, { + "uuid": "76cf99ed-0ff0-4b00-94af-4dfb43fe5caa", "description": "at start of superlist", "property": "sublist", "input": { @@ -115,6 +125,7 @@ "expected": "superlist" }, { + "uuid": "b83989ec-8bdf-4655-95aa-9f38f3e357fd", "description": "in middle of superlist", "property": "sublist", "input": { @@ -124,6 +135,7 @@ "expected": "superlist" }, { + "uuid": "26f9f7c3-6cf6-4610-984a-662f71f8689b", "description": "at end of superlist", "property": "sublist", "input": { @@ -133,6 +145,7 @@ "expected": "superlist" }, { + "uuid": "0a6db763-3588-416a-8f47-76b1cedde31e", "description": "first list missing element from second list", "property": "sublist", "input": { @@ -142,6 +155,7 @@ "expected": "unequal" }, { + "uuid": "83ffe6d8-a445-4a3c-8795-1e51a95e65c3", "description": "second list missing element from first list", "property": "sublist", "input": { @@ -151,6 +165,7 @@ "expected": "unequal" }, { + "uuid": "0d7ee7c1-0347-45c8-9ef5-b88db152b30b", "description": "order matters to a list", "property": "sublist", "input": { @@ -160,6 +175,7 @@ "expected": "unequal" }, { + "uuid": "5f47ce86-944e-40f9-9f31-6368aad70aa6", "description": "same digits but different numbers", "property": "sublist", "input": { diff --git a/exercises/sum-of-multiples/canonical-data.json b/exercises/sum-of-multiples/canonical-data.json index daba19defd..f90b773e7a 100644 --- a/exercises/sum-of-multiples/canonical-data.json +++ b/exercises/sum-of-multiples/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "sum-of-multiples", - "version": "1.5.0", "cases": [ { + "uuid": "54aaab5a-ce86-4edc-8b40-d3ab2400a279", "description": "no multiples within limit", "property": "sum", "input": { @@ -12,6 +12,7 @@ "expected": 0 }, { + "uuid": "361e4e50-c89b-4f60-95ef-5bc5c595490a", "description": "one factor has multiples within limit", "property": "sum", "input": { @@ -21,6 +22,7 @@ "expected": 3 }, { + "uuid": "e644e070-040e-4ae0-9910-93c69fc3f7ce", "description": "more than one multiple within limit", "property": "sum", "input": { @@ -30,6 +32,7 @@ "expected": 9 }, { + "uuid": "607d6eb9-535c-41ce-91b5-3a61da3fa57f", "description": "more than one factor with multiples within limit", "property": "sum", "input": { @@ -39,6 +42,7 @@ "expected": 23 }, { + "uuid": "f47e8209-c0c5-4786-b07b-dc273bf86b9b", "description": "each multiple is only counted once", "property": "sum", "input": { @@ -48,6 +52,7 @@ "expected": 2318 }, { + "uuid": "28c4b267-c980-4054-93e9-07723db615ac", "description": "a much larger limit", "property": "sum", "input": { @@ -57,6 +62,7 @@ "expected": 233168 }, { + "uuid": "09c4494d-ff2d-4e0f-8421-f5532821ee12", "description": "three factors", "property": "sum", "input": { @@ -66,6 +72,7 @@ "expected": 51 }, { + "uuid": "2d0d5faa-f177-4ad6-bde9-ebb865083751", "description": "factors not relatively prime", "property": "sum", "input": { @@ -75,6 +82,7 @@ "expected": 30 }, { + "uuid": "ece8f2e8-96aa-4166-bbb7-6ce71261e354", "description": "some pairs of factors relatively prime and some not", "property": "sum", "input": { @@ -84,6 +92,7 @@ "expected": 4419 }, { + "uuid": "624fdade-6ffb-400e-8472-456a38c171c0", "description": "one factor is a multiple of another", "property": "sum", "input": { @@ -93,6 +102,7 @@ "expected": 275 }, { + "uuid": "949ee7eb-db51-479c-b5cb-4a22b40ac057", "description": "much larger factors", "property": "sum", "input": { @@ -102,6 +112,7 @@ "expected": 2203160 }, { + "uuid": "41093673-acbd-482c-ab80-d00a0cbedecd", "description": "all numbers are multiples of 1", "property": "sum", "input": { @@ -111,6 +122,7 @@ "expected": 4950 }, { + "uuid": "1730453b-baaa-438e-a9c2-d754497b2a76", "description": "no factors means an empty sum", "property": "sum", "input": { @@ -120,6 +132,7 @@ "expected": 0 }, { + "uuid": "214a01e9-f4bf-45bb-80f1-1dce9fbb0310", "description": "the only multiple of 0 is 0", "property": "sum", "input": { @@ -129,6 +142,7 @@ "expected": 0 }, { + "uuid": "c423ae21-a0cb-4ec7-aeb1-32971af5b510", "description": "the factor 0 does not affect the sum of multiples of other factors", "property": "sum", "input": { @@ -138,6 +152,7 @@ "expected": 3 }, { + "uuid": "17053ba9-112f-4ac0-aadb-0519dd836342", "description": "solutions using include-exclude must extend to cardinality greater than 3", "property": "sum", "input": { diff --git a/exercises/tournament/canonical-data.json b/exercises/tournament/canonical-data.json index f1e0386abe..fcda4b01b2 100644 --- a/exercises/tournament/canonical-data.json +++ b/exercises/tournament/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "tournament", - "version": "1.4.0", "comments": [ "The inputs and outputs are represented as arrays of strings to", "improve readability in this JSON file.", @@ -11,6 +10,7 @@ ], "cases": [ { + "uuid": "67e9fab1-07c1-49cf-9159-bc8671cc7c9c", "description": "just the header if no input", "property": "tally", "input": { @@ -19,6 +19,7 @@ "expected": [ "Team | MP | W | D | L | P" ] }, { + "uuid": "1b4a8aef-0734-4007-80a2-0626178c88f4", "description": "a win is three points, a loss is zero points", "property": "tally", "input": { @@ -33,6 +34,7 @@ ] }, { + "uuid": "5f45ac09-4efe-46e7-8ddb-75ad85f86e05", "description": "a win can also be expressed as a loss", "property": "tally", "input": { @@ -47,6 +49,7 @@ ] }, { + "uuid": "fd297368-efa0-442d-9f37-dd3f9a437239", "description": "a different team can win", "property": "tally", "input": { @@ -61,6 +64,7 @@ ] }, { + "uuid": "26c016f9-e753-4a93-94e9-842f7b4d70fc", "description": "a draw is one point each", "property": "tally", "input": { @@ -75,6 +79,7 @@ ] }, { + "uuid": "731204f6-4f34-4928-97eb-1c307ba83e62", "description": "There can be more than one match", "property": "tally", "input": { @@ -90,6 +95,7 @@ ] }, { + "uuid": "49dc2463-42af-4ea6-95dc-f06cc5776adf", "description": "There can be more than one winner", "property": "tally", "input": { @@ -105,6 +111,7 @@ ] }, { + "uuid": "6d930f33-435c-4e6f-9e2d-63fa85ce7dc7", "description": "There can be more than two teams", "property": "tally", "input": { @@ -122,6 +129,7 @@ ] }, { + "uuid": "97022974-0c8a-4a50-8fe7-e36bdd8a5945", "description": "typical input", "property": "tally", "input": { @@ -143,6 +151,7 @@ ] }, { + "uuid": "fe562f0d-ac0a-4c62-b9c9-44ee3236392b", "description": "incomplete competition (not all pairs have played)", "property": "tally", "input": { @@ -162,6 +171,7 @@ ] }, { + "uuid": "3aa0386f-150b-4f99-90bb-5195e7b7d3b8", "description": "ties broken alphabetically", "property": "tally", "input": { diff --git a/exercises/transpose/canonical-data.json b/exercises/transpose/canonical-data.json index 8ad5a4c474..8cb13cdd03 100644 --- a/exercises/transpose/canonical-data.json +++ b/exercises/transpose/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "transpose", - "version": "1.1.0", "comments": [ "JSON doesn't allow for multi-line strings, so all multi-line input is ", "presented here as arrays of strings. It's up to the test generator to join the ", @@ -8,6 +7,7 @@ ], "cases": [ { + "uuid": "404b7262-c050-4df0-a2a2-0cb06cd6a821", "description": "empty string", "property": "transpose", "input": { @@ -16,6 +16,7 @@ "expected": [] }, { + "uuid": "a89ce8a3-c940-4703-a688-3ea39412fbcb", "description": "two characters in a row", "property": "transpose", "input": { @@ -29,6 +30,7 @@ ] }, { + "uuid": "855bb6ae-4180-457c-abd0-ce489803ce98", "description": "two characters in a column", "property": "transpose", "input": { @@ -42,6 +44,7 @@ ] }, { + "uuid": "5ceda1c0-f940-441c-a244-0ced197769c8", "description": "simple", "property": "transpose", "input": { @@ -57,6 +60,7 @@ ] }, { + "uuid": "a54675dd-ae7d-4a58-a9c4-0c20e99a7c1f", "description": "single line", "property": "transpose", "input": { @@ -78,6 +82,7 @@ ] }, { + "uuid": "0dc2ec0b-549d-4047-aeeb-8029fec8d5c5", "description": "first line longer than second line", "property": "transpose", "input": { @@ -106,6 +111,7 @@ ] }, { + "uuid": "984e2ec3-b3d3-4b53-8bd6-96f5ef404102", "description": "second line longer than first line", "property": "transpose", "input": { @@ -134,6 +140,7 @@ ] }, { + "uuid": "eccd3784-45f0-4a3f-865a-360cb323d314", "description": "mixed line length", "property": "transpose", "input": { @@ -165,6 +172,7 @@ ] }, { + "uuid": "85b96b3f-d00c-4f80-8ca2-c8a5c9216c2d", "description": "square", "property": "transpose", "input": { @@ -185,6 +193,7 @@ ] }, { + "uuid": "b9257625-7a53-4748-8863-e08e9d27071d", "description": "rectangle", "property": "transpose", "input": { @@ -207,6 +216,7 @@ ] }, { + "uuid": "b80badc9-057e-4543-bd07-ce1296a1ea2c", "description": "triangle", "property": "transpose", "input": { @@ -227,6 +237,29 @@ " ER", " R" ] + }, + { + "uuid": "76acfd50-5596-4d05-89f1-5116328a7dd9", + "description": "jagged triangle", + "property": "transpose", + "input": { + "lines": [ + "11", + "2", + "3333", + "444", + "555555", + "66666" + ] + }, + "expected": [ + "123456", + "1 3456", + " 3456", + " 3 56", + " 56", + " 5" + ] } ] } diff --git a/exercises/triangle/canonical-data.json b/exercises/triangle/canonical-data.json index 420e775bab..a47380b7b4 100644 --- a/exercises/triangle/canonical-data.json +++ b/exercises/triangle/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "triangle", - "version": "1.2.1", "comments": [ " Pursuant to discussion in #202, we have decided NOT to test triangles ", " where all side lengths are positive but a + b = c. e.g: ", @@ -22,6 +21,7 @@ "description": "equilateral triangle", "cases": [ { + "uuid": "8b2c43ac-7257-43f9-b552-7631a91988af", "description": "all sides are equal", "property": "equilateral", "input": { @@ -30,6 +30,7 @@ "expected": true }, { + "uuid": "33eb6f87-0498-4ccf-9573-7f8c3ce92b7b", "description": "any side is unequal", "property": "equilateral", "input": { @@ -38,6 +39,7 @@ "expected": false }, { + "uuid": "c6585b7d-a8c0-4ad8-8a34-e21d36f7ad87", "description": "no sides are equal", "property": "equilateral", "input": { @@ -46,6 +48,7 @@ "expected": false }, { + "uuid": "16e8ceb0-eadb-46d1-b892-c50327479251", "description": "all zero sides is not a triangle", "property": "equilateral", "input": { @@ -58,6 +61,7 @@ " Your track may choose to skip this test ", " and deal only with integers if appropriate " ], + "uuid": "3022f537-b8e5-4cc1-8f12-fd775827a00c", "description": "sides may be floats", "property": "equilateral", "input": { @@ -71,6 +75,7 @@ "description": "isosceles triangle", "cases": [ { + "uuid": "cbc612dc-d75a-4c1c-87fc-e2d5edd70b71", "description": "last two sides are equal", "property": "isosceles", "input": { @@ -79,6 +84,7 @@ "expected": true }, { + "uuid": "e388ce93-f25e-4daf-b977-4b7ede992217", "description": "first two sides are equal", "property": "isosceles", "input": { @@ -87,6 +93,7 @@ "expected": true }, { + "uuid": "d2080b79-4523-4c3f-9d42-2da6e81ab30f", "description": "first and last sides are equal", "property": "isosceles", "input": { @@ -95,6 +102,7 @@ "expected": true }, { + "uuid": "8d71e185-2bd7-4841-b7e1-71689a5491d8", "description": "equilateral triangles are also isosceles", "property": "isosceles", "input": { @@ -103,6 +111,7 @@ "expected": true }, { + "uuid": "840ed5f8-366f-43c5-ac69-8f05e6f10bbb", "description": "no sides are equal", "property": "isosceles", "input": { @@ -111,6 +120,7 @@ "expected": false }, { + "uuid": "2eba0cfb-6c65-4c40-8146-30b608905eae", "description": "first triangle inequality violation", "property": "isosceles", "input": { @@ -119,6 +129,7 @@ "expected": false }, { + "uuid": "278469cb-ac6b-41f0-81d4-66d9b828f8ac", "description": "second triangle inequality violation", "property": "isosceles", "input": { @@ -127,6 +138,7 @@ "expected": false }, { + "uuid": "90efb0c7-72bb-4514-b320-3a3892e278ff", "description": "third triangle inequality violation", "property": "isosceles", "input": { @@ -135,6 +147,7 @@ "expected": false }, { + "uuid": "adb4ee20-532f-43dc-8d31-e9271b7ef2bc", "comments": [ " Your track may choose to skip this test ", " and deal only with integers if appropriate " @@ -152,6 +165,7 @@ "description": "scalene triangle", "cases": [ { + "uuid": "e8b5f09c-ec2e-47c1-abec-f35095733afb", "description": "no sides are equal", "property": "scalene", "input": { @@ -160,6 +174,7 @@ "expected": true }, { + "uuid": "2510001f-b44d-4d18-9872-2303e7977dc1", "description": "all sides are equal", "property": "scalene", "input": { @@ -168,6 +183,7 @@ "expected": false }, { + "uuid": "c6e15a92-90d9-4fb3-90a2-eef64f8d3e1e", "description": "two sides are equal", "property": "scalene", "input": { @@ -176,6 +192,7 @@ "expected": false }, { + "uuid": "70ad5154-0033-48b7-af2c-b8d739cd9fdc", "description": "may not violate triangle inequality", "property": "scalene", "input": { @@ -188,6 +205,7 @@ " Your track may choose to skip this test ", " and deal only with integers if appropriate " ], + "uuid": "26d9d59d-f8f1-40d3-ad58-ae4d54123d7d", "description": "sides may be floats", "property": "scalene", "input": { diff --git a/exercises/trinary/canonical-data.json b/exercises/trinary/canonical-data.json index 18ae38c5ba..bdf7e8c9a7 100644 --- a/exercises/trinary/canonical-data.json +++ b/exercises/trinary/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "trinary", - "version": "1.1.0", "cases": [ { "description": "returns the decimal representation of the input trinary value", "cases": [ { + "uuid": "a7a79a9e-5606-454c-9cdb-4f3c0ca46931", "description": "trinary 1 is decimal 1", "property": "toDecimal", "input": { @@ -14,6 +14,7 @@ "expected": 1 }, { + "uuid": "39240078-13e2-4eb8-87c4-aeffa7d64130", "description": "trinary 2 is decimal 2", "property": "toDecimal", "input": { @@ -22,6 +23,7 @@ "expected": 2 }, { + "uuid": "81900d67-7e07-4d41-a71e-86f1cd72ce1f", "description": "trinary 10 is decimal 3", "property": "toDecimal", "input": { @@ -30,6 +32,7 @@ "expected": 3 }, { + "uuid": "7a8d5341-f88a-4c60-9048-4d5e017fa701", "description": "trinary 11 is decimal 4", "property": "toDecimal", "input": { @@ -38,6 +41,7 @@ "expected": 4 }, { + "uuid": "6b3c37f6-d6b3-4575-85c0-19f48dd101af", "description": "trinary 100 is decimal 9", "property": "toDecimal", "input": { @@ -46,6 +50,7 @@ "expected": 9 }, { + "uuid": "a210b2b8-d333-4e19-9e59-87cabdd2a0ba", "description": "trinary 112 is decimal 14", "property": "toDecimal", "input": { @@ -54,6 +59,7 @@ "expected": 14 }, { + "uuid": "5ae03472-b942-42ce-ba00-e84a7dc86dd8", "description": "trinary 222 is decimal 26", "property": "toDecimal", "input": { @@ -62,6 +68,7 @@ "expected": 26 }, { + "uuid": "d4fabf94-6149-4d1e-b42f-b34dc3ddef8f", "description": "trinary 1122000120 is decimal 32091", "property": "toDecimal", "input": { @@ -70,6 +77,7 @@ "expected": 32091 }, { + "uuid": "34be152d-38f3-4dcf-b5ab-9e14fe2f7161", "description": "invalid trinary digits returns 0", "property": "toDecimal", "input": { @@ -78,6 +86,7 @@ "expected": 0 }, { + "uuid": "b57aa24d-3da2-4787-9429-5bc94d3112d6", "description": "invalid word as input returns 0", "property": "toDecimal", "input": { @@ -86,6 +95,7 @@ "expected": 0 }, { + "uuid": "673c2057-5d89-483c-87fa-139da6927b90", "description": "invalid numbers with letters as input returns 0", "property": "toDecimal", "input": { diff --git a/exercises/twelve-days/canonical-data.json b/exercises/twelve-days/canonical-data.json index fc7fd7a468..5e6465a924 100644 --- a/exercises/twelve-days/canonical-data.json +++ b/exercises/twelve-days/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "twelve-days", - "version": "1.2.0", "comments": [ "JSON doesn't allow for multi-line strings, so all verses are presented ", "here as arrays of strings. It's up to the test generator to join the ", @@ -11,6 +10,7 @@ "description": "verse", "cases": [ { + "uuid": "c0b5a5e6-c89d-49b1-a6b2-9f523bff33f7", "description": "first day a partridge in a pear tree", "property": "recite", "input": { @@ -22,6 +22,7 @@ ] }, { + "uuid": "1c64508a-df3d-420a-b8e1-fe408847854a", "description": "second day two turtle doves", "property": "recite", "input": { @@ -33,6 +34,7 @@ ] }, { + "uuid": "a919e09c-75b2-4e64-bb23-de4a692060a8", "description": "third day three french hens", "property": "recite", "input": { @@ -44,6 +46,7 @@ ] }, { + "uuid": "9bed8631-ec60-4894-a3bb-4f0ec9fbe68d", "description": "fourth day four calling birds", "property": "recite", "input": { @@ -55,6 +58,7 @@ ] }, { + "uuid": "cf1024f0-73b6-4545-be57-e9cea565289a", "description": "fifth day five gold rings", "property": "recite", "input": { @@ -66,6 +70,7 @@ ] }, { + "uuid": "50bd3393-868a-4f24-a618-68df3d02ff04", "description": "sixth day six geese-a-laying", "property": "recite", "input": { @@ -77,6 +82,7 @@ ] }, { + "uuid": "8f29638c-9bf1-4680-94be-e8b84e4ade83", "description": "seventh day seven swans-a-swimming", "property": "recite", "input": { @@ -88,6 +94,7 @@ ] }, { + "uuid": "7038d6e1-e377-47ad-8c37-10670a05bc05", "description": "eighth day eight maids-a-milking", "property": "recite", "input": { @@ -99,6 +106,7 @@ ] }, { + "uuid": "37a800a6-7a56-4352-8d72-0f51eb37cfe8", "description": "ninth day nine ladies dancing", "property": "recite", "input": { @@ -110,6 +118,7 @@ ] }, { + "uuid": "10b158aa-49ff-4b2d-afc3-13af9133510d", "description": "tenth day ten lords-a-leaping", "property": "recite", "input": { @@ -121,6 +130,7 @@ ] }, { + "uuid": "08d7d453-f2ba-478d-8df0-d39ea6a4f457", "description": "eleventh day eleven pipers piping", "property": "recite", "input": { @@ -132,6 +142,7 @@ ] }, { + "uuid": "0620fea7-1704-4e48-b557-c05bf43967f0", "description": "twelfth day twelve drummers drumming", "property": "recite", "input": { @@ -148,6 +159,7 @@ "description": "lyrics", "cases": [ { + "uuid": "da8b9013-b1e8-49df-b6ef-ddec0219e398", "description": "recites first three verses of the song", "property": "recite", "input": { @@ -161,6 +173,7 @@ ] }, { + "uuid": "c095af0d-3137-4653-ad32-bfb899eda24c", "description": "recites three verses from the middle of the song", "property": "recite", "input": { @@ -174,6 +187,7 @@ ] }, { + "uuid": "20921bc9-cc52-4627-80b3-198cbbfcf9b7", "description": "recites the whole song", "property": "recite", "input": { @@ -198,4 +212,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/exercises/two-bucket/canonical-data.json b/exercises/two-bucket/canonical-data.json index 44b053d5aa..2e681479e4 100644 --- a/exercises/two-bucket/canonical-data.json +++ b/exercises/two-bucket/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "two-bucket", - "version": "1.4.0", "cases": [ { + "uuid": "a6f2b4ba-065f-4dca-b6f0-e3eee51cb661", "description": "Measure using bucket one of size 3 and bucket two of size 5 - start with bucket one", "property": "measure", "input": { @@ -18,6 +18,7 @@ } }, { + "uuid": "6c4ea451-9678-4926-b9b3-68364e066d40", "description": "Measure using bucket one of size 3 and bucket two of size 5 - start with bucket two", "property": "measure", "input": { @@ -33,6 +34,7 @@ } }, { + "uuid": "3389f45e-6a56-46d5-9607-75aa930502ff", "description": "Measure using bucket one of size 7 and bucket two of size 11 - start with bucket one", "property": "measure", "input": { @@ -48,6 +50,7 @@ } }, { + "uuid": "fe0ff9a0-3ea5-4bf7-b17d-6d4243961aa1", "description": "Measure using bucket one of size 7 and bucket two of size 11 - start with bucket two", "property": "measure", "input": { @@ -63,6 +66,7 @@ } }, { + "uuid": "0ee1f57e-da84-44f7-ac91-38b878691602", "description": "Measure one step using bucket one of size 1 and bucket two of size 3 - start with bucket two", "property": "measure", "input": { @@ -78,6 +82,7 @@ } }, { + "uuid": "eb329c63-5540-4735-b30b-97f7f4df0f84", "description": "Measure using bucket one of size 2 and bucket two of size 3 - start with bucket one and end with bucket two", "property": "measure", "input": { @@ -91,6 +96,50 @@ "goalBucket": "two", "otherBucket": 2 } + }, + { + "uuid": "449be72d-b10a-4f4b-a959-ca741e333b72", + "description": "Not possible to reach the goal", + "property": "measure", + "input": { + "bucketOne": 6, + "bucketTwo": 15, + "goal": 5, + "startBucket": "one" + }, + "expected": { + "error": "impossible" + } + }, + { + "uuid": "aac38b7a-77f4-4d62-9b91-8846d533b054", + "description": "With the same buckets but a different goal, then it is possible", + "property": "measure", + "input": { + "bucketOne": 6, + "bucketTwo": 15, + "goal": 9, + "startBucket": "one" + }, + "expected": { + "moves": 10, + "goalBucket": "two", + "otherBucket": 0 + } + }, + { + "uuid": "74633132-0ccf-49de-8450-af4ab2e3b299", + "description": "Goal larger than both buckets is impossible", + "property": "measure", + "input": { + "bucketOne": 5, + "bucketTwo": 7, + "goal": 8, + "startBucket": "one" + }, + "expected": { + "error": "impossible" + } } ] -} \ No newline at end of file +} diff --git a/exercises/two-bucket/description.md b/exercises/two-bucket/description.md index 6c061a7f72..455ac2ce5a 100644 --- a/exercises/two-bucket/description.md +++ b/exercises/two-bucket/description.md @@ -21,8 +21,8 @@ Example: Bucket one can hold up to 7 liters, and bucket two can hold up to 11 liters. Let's say bucket one, at a given step, is holding 7 liters, and bucket two is holding 8 liters (7,8). If you empty bucket one and make no change to bucket two, leaving you with 0 liters and 8 liters respectively (0,8), that counts as one "move". Instead, if you had poured from bucket one into bucket two until bucket two was full, leaving you with 4 liters in bucket one and 11 liters in bucket two (4,11), that would count as only one "move" as well. To conclude, the only valid moves are: -- pouring from one bucket to another -- emptying one bucket and doing nothing to the other -- filling one bucket and doing nothing to the other +- pouring from either bucket to another +- emptying either bucket and doing nothing to the other +- filling either bucket and doing nothing to the other Written with <3 at [Fullstack Academy](http://www.fullstackacademy.com/) by Lindsay Levine. diff --git a/exercises/two-fer/canonical-data.json b/exercises/two-fer/canonical-data.json index 9b043575c1..ea6ee91d68 100644 --- a/exercises/two-fer/canonical-data.json +++ b/exercises/two-fer/canonical-data.json @@ -1,8 +1,8 @@ { "exercise": "two-fer", - "version": "1.2.0", "cases": [ { + "uuid": "1cf3e15a-a3d7-4a87-aeb3-ba1b43bc8dce", "description": "no name given", "property": "twoFer", "input": { @@ -11,6 +11,7 @@ "expected": "One for you, one for me." }, { + "uuid": "b4c6dbb8-b4fb-42c2-bafd-10785abe7709", "description": "a name given", "property": "twoFer", "input": { @@ -19,6 +20,7 @@ "expected": "One for Alice, one for me." }, { + "uuid": "3549048d-1a6e-4653-9a79-b0bda163e8d5", "description": "another name given", "property": "twoFer", "input": { @@ -27,4 +29,4 @@ "expected": "One for Bob, one for me." } ] -} \ No newline at end of file +} diff --git a/exercises/two-fer/description.md b/exercises/two-fer/description.md index 3a29112e1d..7df1a9fc99 100644 --- a/exercises/two-fer/description.md +++ b/exercises/two-fer/description.md @@ -3,10 +3,10 @@ Given a name, return a string with the message: ```text -One for X, one for me. +One for name, one for me. ``` -Where X is the given name. +Where "name" is the given name. However, if the name is missing, return the string: @@ -16,9 +16,9 @@ One for you, one for me. Here are some examples: -|Name |String to return +|Name |String to return |:-------|:------------------ -|Alice |One for Alice, one for me. +|Alice |One for Alice, one for me. |Bob |One for Bob, one for me. | |One for you, one for me. |Zaphod |One for Zaphod, one for me. diff --git a/exercises/variable-length-quantity/canonical-data.json b/exercises/variable-length-quantity/canonical-data.json index 7fdc4806e2..2cde144ead 100644 --- a/exercises/variable-length-quantity/canonical-data.json +++ b/exercises/variable-length-quantity/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "variable-length-quantity", - "version": "1.2.0", "comments": [ "JSON doesn't allow hexadecimal literals.", "All numbers are given as decimal literals instead.", @@ -12,6 +11,7 @@ "description": "Encode a series of integers, producing a series of bytes.", "cases": [ { + "uuid": "35c9db2e-f781-4c52-b73b-8e76427defd0", "description": "zero", "property": "encode", "input": { @@ -20,6 +20,7 @@ "expected": [0] }, { + "uuid": "be44d299-a151-4604-a10e-d4b867f41540", "description": "arbitrary single byte", "property": "encode", "input": { @@ -28,6 +29,7 @@ "expected": [64] }, { + "uuid": "ea399615-d274-4af6-bbef-a1c23c9e1346", "description": "largest single byte", "property": "encode", "input": { @@ -36,6 +38,7 @@ "expected": [127] }, { + "uuid": "77b07086-bd3f-4882-8476-8dcafee79b1c", "description": "smallest double byte", "property": "encode", "input": { @@ -44,6 +47,7 @@ "expected": [129,0] }, { + "uuid": "63955a49-2690-4e22-a556-0040648d6b2d", "description": "arbitrary double byte", "property": "encode", "input": { @@ -52,6 +56,7 @@ "expected": [192, 0] }, { + "uuid": "29da7031-0067-43d3-83a7-4f14b29ed97a", "description": "largest double byte", "property": "encode", "input": { @@ -60,6 +65,7 @@ "expected": [255, 127] }, { + "uuid": "3345d2e3-79a9-4999-869e-d4856e3a8e01", "description": "smallest triple byte", "property": "encode", "input": { @@ -68,6 +74,7 @@ "expected": [129, 128, 0] }, { + "uuid": "5df0bc2d-2a57-4300-a653-a75ee4bd0bee", "description": "arbitrary triple byte", "property": "encode", "input": { @@ -76,6 +83,7 @@ "expected": [192, 128, 0] }, { + "uuid": "f51d8539-312d-4db1-945c-250222c6aa22", "description": "largest triple byte", "property": "encode", "input": { @@ -84,6 +92,7 @@ "expected": [255, 255, 127] }, { + "uuid": "da78228b-544f-47b7-8bfe-d16b35bbe570", "description": "smallest quadruple byte", "property": "encode", "input": { @@ -92,6 +101,7 @@ "expected": [129, 128, 128, 0] }, { + "uuid": "11ed3469-a933-46f1-996f-2231e05d7bb6", "description": "arbitrary quadruple byte", "property": "encode", "input": { @@ -100,6 +110,7 @@ "expected": [192, 128, 128, 0] }, { + "uuid": "d5f3f3c3-e0f1-4e7f-aad0-18a44f223d1c", "description": "largest quadruple byte", "property": "encode", "input": { @@ -108,6 +119,7 @@ "expected": [255, 255, 255, 127] }, { + "uuid": "91a18b33-24e7-4bfb-bbca-eca78ff4fc47", "description": "smallest quintuple byte", "property": "encode", "input": { @@ -116,6 +128,7 @@ "expected": [129, 128, 128, 128, 0] }, { + "uuid": "5f34ff12-2952-4669-95fe-2d11b693d331", "description": "arbitrary quintuple byte", "property": "encode", "input": { @@ -124,6 +137,7 @@ "expected": [143, 248, 128, 128, 0] }, { + "uuid": "7489694b-88c3-4078-9864-6fe802411009", "description": "maximum 32-bit integer input", "property": "encode", "input": { @@ -132,6 +146,7 @@ "expected": [143, 255, 255, 255, 127] }, { + "uuid": "f9b91821-cada-4a73-9421-3c81d6ff3661", "description": "two single-byte values", "property": "encode", "input": { @@ -140,6 +155,7 @@ "expected": [64, 127] }, { + "uuid": "68694449-25d2-4974-ba75-fa7bb36db212", "description": "two multi-byte values", "property": "encode", "input": { @@ -148,6 +164,7 @@ "expected": [129, 128, 0, 200, 232, 86] }, { + "uuid": "51a06b5c-de1b-4487-9a50-9db1b8930d85", "description": "many multi-byte values", "property": "encode", "input": { @@ -161,6 +178,7 @@ "description": "Decode a series of bytes, producing a series of integers.", "cases": [ { + "uuid": "baa73993-4514-4915-bac0-f7f585e0e59a", "description": "one byte", "property": "decode", "input": { @@ -169,6 +187,7 @@ "expected": [127] }, { + "uuid": "72e94369-29f9-46f2-8c95-6c5b7a595aee", "description": "two bytes", "property": "decode", "input": { @@ -177,6 +196,7 @@ "expected": [8192] }, { + "uuid": "df5a44c4-56f7-464e-a997-1db5f63ce691", "description": "three bytes", "property": "decode", "input": { @@ -185,6 +205,7 @@ "expected": [2097151] }, { + "uuid": "1bb58684-f2dc-450a-8406-1f3452aa1947", "description": "four bytes", "property": "decode", "input": { @@ -193,6 +214,7 @@ "expected": [2097152] }, { + "uuid": "cecd5233-49f1-4dd1-a41a-9840a40f09cd", "description": "maximum 32-bit integer", "property": "decode", "input": { @@ -201,6 +223,7 @@ "expected": [4294967295] }, { + "uuid": "e7d74ba3-8b8e-4bcb-858d-d08302e15695", "description": "incomplete sequence causes error", "property": "decode", "input": { @@ -209,6 +232,7 @@ "expected": {"error": "incomplete sequence"} }, { + "uuid": "aa378291-9043-4724-bc53-aca1b4a3fcb6", "description": "incomplete sequence causes error, even if value is zero", "property": "decode", "input": { @@ -217,10 +241,11 @@ "expected": {"error": "incomplete sequence"} }, { + "uuid": "a91e6f5a-c64a-48e3-8a75-ce1a81e0ebee", "description": "multiple values", "property": "decode", "input": { - "integers": [192, 0, 200, 232, 86, 255, 255, 255, 127, 0, 255, 127, 129, 128, 0] + "integers": [192, 0, 200, 232, 86, 255, 255, 255, 127, 0, 255, 127, 129, 128, 0] }, "expected": [8192, 1193046, 268435455, 0, 16383, 16384] } diff --git a/exercises/word-count/canonical-data.json b/exercises/word-count/canonical-data.json index f991a610ff..93ae9a4737 100644 --- a/exercises/word-count/canonical-data.json +++ b/exercises/word-count/canonical-data.json @@ -1,12 +1,12 @@ { "exercise": "word-count", - "version": "1.4.0", "comments": [ "For each word in the input, count the number of times it appears in the", "entire sentence." ], "cases": [ { + "uuid": "61559d5f-2cad-48fb-af53-d3973a9ee9ef", "description": "count one word", "property": "countWords", "input": { @@ -17,6 +17,7 @@ } }, { + "uuid": "5abd53a3-1aed-43a4-a15a-29f88c09cbbd", "description": "count one of each word", "property": "countWords", "input": { @@ -29,6 +30,7 @@ } }, { + "uuid": "2a3091e5-952e-4099-9fac-8f85d9655c0e", "description": "multiple occurrences of a word", "property": "countWords", "input": { @@ -43,6 +45,7 @@ } }, { + "uuid": "e81877ae-d4da-4af4-931c-d923cd621ca6", "description": "handles cramped lists", "property": "countWords", "input": { @@ -55,6 +58,7 @@ } }, { + "uuid": "7349f682-9707-47c0-a9af-be56e1e7ff30", "description": "handles expanded lists", "property": "countWords", "input": { @@ -67,6 +71,7 @@ } }, { + "uuid": "a514a0f2-8589-4279-8892-887f76a14c82", "description": "ignore punctuation", "property": "countWords", "input": { @@ -81,6 +86,7 @@ } }, { + "uuid": "d2e5cee6-d2ec-497b-bdc9-3ebe092ce55e", "description": "include numbers", "property": "countWords", "input": { @@ -93,6 +99,7 @@ } }, { + "uuid": "dac6bc6a-21ae-4954-945d-d7f716392dbf", "description": "normalize case", "property": "countWords", "input": { @@ -104,6 +111,7 @@ } }, { + "uuid": "4185a902-bdb0-4074-864c-f416e42a0f19", "description": "with apostrophes", "property": "countWords", "input": { @@ -118,6 +126,7 @@ } }, { + "uuid": "be72af2b-8afe-4337-b151-b297202e4a7b", "description": "with quotations", "property": "countWords", "input": { @@ -133,6 +142,7 @@ } }, { + "uuid": "8d6815fe-8a51-4a65-96f9-2fb3f6dc6ed6", "description": "substrings from the beginning", "property": "countWords", "input": { @@ -150,6 +160,7 @@ } }, { + "uuid": "c5f4ef26-f3f7-4725-b314-855c04fb4c13", "description": "multiple spaces not detected as a word", "property": "countWords", "input": { @@ -161,6 +172,7 @@ } }, { + "uuid": "50176e8a-fe8e-4f4c-b6b6-aa9cf8f20360", "description": "alternating word separators not detected as a word", "property": "countWords", "input": { diff --git a/exercises/word-search/canonical-data.json b/exercises/word-search/canonical-data.json index fcd681f19e..641bc2c8f7 100644 --- a/exercises/word-search/canonical-data.json +++ b/exercises/word-search/canonical-data.json @@ -1,11 +1,11 @@ { "exercise": "word-search", - "version": "1.2.1", "comments": [ "Grid rows and columns are 1-indexed." ], "cases": [ { + "uuid": "b4057815-0d01-41f0-9119-6a91f54b2a0a", "description": "Should accept an initial game grid and a target search word", "property": "search", "input": { @@ -21,6 +21,7 @@ } }, { + "uuid": "6b22bcc5-6cbf-4674-931b-d2edbff73132", "description": "Should locate one word written left to right", "property": "search", "input": { @@ -45,6 +46,7 @@ } }, { + "uuid": "ff462410-434b-442d-9bc3-3360c75f34a8", "description": "Should locate the same word written left to right in a different position", "property": "search", "input": { @@ -69,6 +71,7 @@ } }, { + "uuid": "a02febae-6347-443e-b99c-ab0afb0b8fca", "description": "Should locate a different left to right word", "property": "search", "input": { @@ -93,6 +96,7 @@ } }, { + "uuid": "e42e9987-6304-4e13-8232-fa07d5280130", "description": "Should locate that different left to right word in a different position", "property": "search", "input": { @@ -117,6 +121,7 @@ } }, { + "uuid": "9bff3cee-49b9-4775-bdfb-d55b43a70b2f", "description": "Should locate a left to right word in two line grid", "property": "search", "input": { @@ -142,6 +147,7 @@ } }, { + "uuid": "851a35fb-f499-4ec1-9581-395a87903a22", "description": "Should locate a left to right word in three line grid", "property": "search", "input": { @@ -168,6 +174,7 @@ } }, { + "uuid": "2f3dcf84-ba7d-4b75-8b8d-a3672b32c035", "description": "Should locate a left to right word in ten line grid", "property": "search", "input": { @@ -201,6 +208,7 @@ } }, { + "uuid": "006d4856-f365-4e84-a18c-7d129ce9eefb", "description": "Should locate that left to right word in a different position in a ten line grid", "property": "search", "input": { @@ -234,6 +242,7 @@ } }, { + "uuid": "eff7ac9f-ff11-443e-9747-40850c12ab60", "description": "Should locate a different left to right word in a ten line grid", "property": "search", "input": { @@ -267,6 +276,7 @@ } }, { + "uuid": "dea39f86-8c67-4164-8884-13bfc48bd13b", "description": "Should locate multiple words", "property": "search", "input": { @@ -311,6 +321,7 @@ } }, { + "uuid": "29e6a6a5-f80c-48a6-8e68-05bbbe187a09", "description": "Should locate a single word written right to left", "property": "search", "input": { @@ -335,6 +346,7 @@ } }, { + "uuid": "3cf34428-b43f-48b6-b332-ea0b8836011d", "description": "Should locate multiple words written in different horizontal directions", "property": "search", "input": { @@ -379,6 +391,7 @@ } }, { + "uuid": "2c8cd344-a02f-464b-93b6-8bf1bd890003", "description": "Should locate words written top to bottom", "property": "search", "input": { @@ -434,6 +447,7 @@ } }, { + "uuid": "9ee1e43d-e59d-4c32-9a5f-6a22d4a1550f", "description": "Should locate words written bottom to top", "property": "search", "input": { @@ -500,6 +514,7 @@ } }, { + "uuid": "6a21a676-f59e-4238-8e88-9f81015afae9", "description": "Should locate words written top left to bottom right", "property": "search", "input": { @@ -577,6 +592,7 @@ } }, { + "uuid": "c9125189-1861-4b0d-a14e-ba5dab29ca7c", "description": "Should locate words written bottom right to top left", "property": "search", "input": { @@ -665,6 +681,7 @@ } }, { + "uuid": "b19e2149-7fc5-41ec-a8a9-9bc6c6c38c40", "description": "Should locate words written bottom left to top right", "property": "search", "input": { @@ -764,6 +781,7 @@ } }, { + "uuid": "69e1d994-a6d7-4e24-9b5a-db76751c2ef8", "description": "Should locate words written top right to bottom left", "property": "search", "input": { @@ -874,6 +892,7 @@ } }, { + "uuid": "695531db-69eb-463f-8bad-8de3bf5ef198", "description": "Should fail to locate a word that is not in the puzzle", "property": "search", "input": { @@ -986,4 +1005,4 @@ } } ] -} \ No newline at end of file +} diff --git a/exercises/wordy/canonical-data.json b/exercises/wordy/canonical-data.json index 05e667ba2f..83bc1efca9 100644 --- a/exercises/wordy/canonical-data.json +++ b/exercises/wordy/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "wordy", - "version": "1.5.0", "comments": [ "The tests that expect an 'error' should be implemented to raise", "an error, or indicate a failure. Implement this in a way that", @@ -8,6 +7,7 @@ ], "cases": [ { + "uuid": "88bf4b28-0de3-4883-93c7-db1b14aa806e", "description": "just a number", "property": "answer", "input": { @@ -16,6 +16,7 @@ "expected": 5 }, { + "uuid": "bb8c655c-cf42-4dfc-90e0-152fcfd8d4e0", "description": "addition", "property": "answer", "input": { @@ -24,6 +25,7 @@ "expected": 2 }, { + "uuid": "79e49e06-c5ae-40aa-a352-7a3a01f70015", "description": "more addition", "property": "answer", "input": { @@ -32,6 +34,7 @@ "expected": 55 }, { + "uuid": "b345dbe0-f733-44e1-863c-5ae3568f3803", "description": "addition with negative numbers", "property": "answer", "input": { @@ -40,6 +43,7 @@ "expected": -11 }, { + "uuid": "cd070f39-c4cc-45c4-97fb-1be5e5846f87", "description": "large addition", "property": "answer", "input": { @@ -48,6 +52,7 @@ "expected": 45801 }, { + "uuid": "0d86474a-cd93-4649-a4fa-f6109a011191", "description": "subtraction", "property": "answer", "input": { @@ -56,6 +61,7 @@ "expected": 16 }, { + "uuid": "30bc8395-5500-4712-a0cf-1d788a529be5", "description": "multiplication", "property": "answer", "input": { @@ -64,6 +70,7 @@ "expected": -75 }, { + "uuid": "34c36b08-8605-4217-bb57-9a01472c427f", "description": "division", "property": "answer", "input": { @@ -72,6 +79,7 @@ "expected": -11 }, { + "uuid": "da6d2ce4-fb94-4d26-8f5f-b078adad0596", "description": "multiple additions", "property": "answer", "input": { @@ -80,6 +88,7 @@ "expected": 3 }, { + "uuid": "7fd74c50-9911-4597-be09-8de7f2fea2bb", "description": "addition and subtraction", "property": "answer", "input": { @@ -88,6 +97,7 @@ "expected": 8 }, { + "uuid": "b120ffd5-bad6-4e22-81c8-5512e8faf905", "description": "multiple subtraction", "property": "answer", "input": { @@ -96,6 +106,7 @@ "expected": 3 }, { + "uuid": "4f4a5749-ef0c-4f60-841f-abcfaf05d2ae", "description": "subtraction then addition", "property": "answer", "input": { @@ -104,6 +115,7 @@ "expected": 14 }, { + "uuid": "312d908c-f68f-42c9-aa75-961623cc033f", "description": "multiple multiplication", "property": "answer", "input": { @@ -112,6 +124,7 @@ "expected": -12 }, { + "uuid": "38e33587-8940-4cc1-bc28-bfd7e3966276", "description": "addition and multiplication", "property": "answer", "input": { @@ -120,6 +133,7 @@ "expected": -8 }, { + "uuid": "3c854f97-9311-46e8-b574-92b60d17d394", "description": "multiple division", "property": "answer", "input": { @@ -128,6 +142,7 @@ "expected": 2 }, { + "uuid": "3ad3e433-8af7-41ec-aa9b-97b42ab49357", "description": "unknown operation", "property": "answer", "input": { @@ -136,6 +151,7 @@ "expected": {"error": "unknown operation"} }, { + "uuid": "8a7e85a8-9e7b-4d46-868f-6d759f4648f8", "description": "Non math question", "property": "answer", "input": { @@ -144,6 +160,7 @@ "expected": {"error": "unknown operation"} }, { + "uuid": "42d78b5f-dbd7-4cdb-8b30-00f794bb24cf", "description": "reject problem missing an operand", "property": "answer", "input": { @@ -152,6 +169,7 @@ "expected": {"error": "syntax error"} }, { + "uuid": "c2c3cbfc-1a72-42f2-b597-246e617e66f5", "description": "reject problem with no operands or operators", "property": "answer", "input": { @@ -160,6 +178,7 @@ "expected": {"error": "syntax error"} }, { + "uuid": "4b3df66d-6ed5-4c95-a0a1-d38891fbdab6", "description": "reject two operations in a row", "property": "answer", "input": { @@ -168,6 +187,7 @@ "expected": {"error": "syntax error"} }, { + "uuid": "6abd7a50-75b4-4665-aa33-2030fd08bab1", "description": "reject two numbers in a row", "property": "answer", "input": { @@ -176,6 +196,7 @@ "expected": {"error": "syntax error"} }, { + "uuid": "10a56c22-e0aa-405f-b1d2-c642d9c4c9de", "description": "reject postfix notation", "property": "answer", "input": { @@ -184,6 +205,7 @@ "expected": {"error": "syntax error"} }, { + "uuid": "0035bc63-ac43-4bb5-ad6d-e8651b7d954e", "description": "reject prefix notation", "property": "answer", "input": { diff --git a/exercises/yacht/canonical-data.json b/exercises/yacht/canonical-data.json index d88598a582..3faf79b6ac 100644 --- a/exercises/yacht/canonical-data.json +++ b/exercises/yacht/canonical-data.json @@ -1,6 +1,5 @@ { "exercise":"yacht", - "version":"1.2.0", "comments":[ "The dice are represented always as a list of exactly five integers", "with values between 1 and 6 inclusive. The category is an string.", @@ -14,6 +13,7 @@ ], "cases":[ { + "uuid": "3060e4a5-4063-4deb-a380-a630b43a84b6", "description":"Yacht", "property":"score", "input":{ @@ -23,6 +23,7 @@ "expected":50 }, { + "uuid": "15026df2-f567-482f-b4d5-5297d57769d9", "description":"Not Yacht", "property":"score", "input":{ @@ -32,6 +33,7 @@ "expected":0 }, { + "uuid": "36b6af0c-ca06-4666-97de-5d31213957a4", "description":"Ones", "property":"score", "input":{ @@ -41,6 +43,7 @@ "expected":3 }, { + "uuid": "023a07c8-6c6e-44d0-bc17-efc5e1b8205a", "description":"Ones, out of order", "property":"score", "input":{ @@ -50,6 +53,7 @@ "expected":3 }, { + "uuid": "7189afac-cccd-4a74-8182-1cb1f374e496", "description":"No ones", "property":"score", "input":{ @@ -59,6 +63,7 @@ "expected":0 }, { + "uuid": "793c4292-dd14-49c4-9707-6d9c56cee725", "description":"Twos", "property":"score", "input":{ @@ -68,6 +73,7 @@ "expected":2 }, { + "uuid": "dc41bceb-d0c5-4634-a734-c01b4233a0c6", "description":"Fours", "property":"score", "input":{ @@ -77,6 +83,7 @@ "expected":8 }, { + "uuid": "f6125417-5c8a-4bca-bc5b-b4b76d0d28c8", "description":"Yacht counted as threes", "property":"score", "input":{ @@ -86,6 +93,7 @@ "expected":15 }, { + "uuid": "464fc809-96ed-46e4-acb8-d44e302e9726", "description":"Yacht of 3s counted as fives", "property":"score", "input":{ @@ -95,6 +103,7 @@ "expected":0 }, { + "uuid": "e8a036e0-9d21-443a-8b5f-e15a9e19a761", "description":"Sixes", "property":"score", "input":{ @@ -104,6 +113,7 @@ "expected":6 }, { + "uuid": "51cb26db-6b24-49af-a9ff-12f53b252eea", "description":"Full house two small, three big", "property":"score", "input":{ @@ -113,6 +123,7 @@ "expected":16 }, { + "uuid": "1822ca9d-f235-4447-b430-2e8cfc448f0c", "description":"Full house three small, two big", "property":"score", "input":{ @@ -122,6 +133,7 @@ "expected":19 }, { + "uuid": "b208a3fc-db2e-4363-a936-9e9a71e69c07", "description":"Two pair is not a full house", "property":"score", "input":{ @@ -131,6 +143,7 @@ "expected":0 }, { + "uuid": "b90209c3-5956-445b-8a0b-0ac8b906b1c2", "description":"Four of a kind is not a full house", "property":"score", "input":{ @@ -140,6 +153,7 @@ "expected":0 }, { + "uuid": "32a3f4ee-9142-4edf-ba70-6c0f96eb4b0c", "description":"Yacht is not a full house", "property":"score", "input":{ @@ -149,6 +163,7 @@ "expected":0 }, { + "uuid": "b286084d-0568-4460-844a-ba79d71d79c6", "description":"Four of a Kind", "property":"score", "input":{ @@ -158,6 +173,7 @@ "expected":24 }, { + "uuid": "f25c0c90-5397-4732-9779-b1e9b5f612ca", "description":"Yacht can be scored as Four of a Kind", "property":"score", "input":{ @@ -167,6 +183,7 @@ "expected":12 }, { + "uuid": "9f8ef4f0-72bb-401a-a871-cbad39c9cb08", "description":"Full house is not Four of a Kind", "property":"score", "input":{ @@ -176,6 +193,7 @@ "expected":0 }, { + "uuid": "b4743c82-1eb8-4a65-98f7-33ad126905cd", "description":"Little Straight", "property":"score", "input":{ @@ -185,6 +203,7 @@ "expected":30 }, { + "uuid": "7ac08422-41bf-459c-8187-a38a12d080bc", "description":"Little Straight as Big Straight", "property":"score", "input":{ @@ -194,6 +213,7 @@ "expected":0 }, { + "uuid": "97bde8f7-9058-43ea-9de7-0bc3ed6d3002", "description":"Four in order but not a little straight", "property":"score", "input":{ @@ -203,6 +223,7 @@ "expected":0 }, { + "uuid": "cef35ff9-9c5e-4fd2-ae95-6e4af5e95a99", "description":"No pairs but not a little straight", "property":"score", "input":{ @@ -212,6 +233,7 @@ "expected":0 }, { + "uuid": "fd785ad2-c060-4e45-81c6-ea2bbb781b9d", "description":"Minimum is 1, maximum is 5, but not a little straight", "property":"score", "input":{ @@ -221,6 +243,7 @@ "expected":0 }, { + "uuid": "35bd74a6-5cf6-431a-97a3-4f713663f467", "description":"Big Straight", "property":"score", "input":{ @@ -230,6 +253,7 @@ "expected":30 }, { + "uuid": "87c67e1e-3e87-4f3a-a9b1-62927822b250", "description":"Big Straight as little straight", "property":"score", "input":{ @@ -239,6 +263,7 @@ "expected":0 }, { + "uuid": "c1fa0a3a-40ba-4153-a42d-32bc34d2521e", "description":"No pairs but not a big straight", "property":"score", "input":{ @@ -248,6 +273,7 @@ "expected":0 }, { + "uuid": "207e7300-5d10-43e5-afdd-213e3ac8827d", "description":"Choice", "property":"score", "input":{ @@ -257,6 +283,7 @@ "expected":23 }, { + "uuid": "b524c0cf-32d2-4b40-8fb3-be3500f3f135", "description":"Yacht as choice", "property":"score", "input":{ diff --git a/exercises/zebra-puzzle/canonical-data.json b/exercises/zebra-puzzle/canonical-data.json index a9d067d045..3a8c02c584 100644 --- a/exercises/zebra-puzzle/canonical-data.json +++ b/exercises/zebra-puzzle/canonical-data.json @@ -1,14 +1,15 @@ { "exercise": "zebra-puzzle", - "version": "1.1.0", "cases": [ { + "uuid": "16efb4e4-8ad7-4d5e-ba96-e5537b66fd42", "description": "resident who drinks water", "property": "drinksWater", "input": {}, "expected": "Norwegian" }, { + "uuid": "084d5b8b-24e2-40e6-b008-c800da8cd257", "description": "resident who owns zebra", "property": "ownsZebra", "input": {}, diff --git a/exercises/zipper/canonical-data.json b/exercises/zipper/canonical-data.json index 02e40f1bf5..864f88dc27 100644 --- a/exercises/zipper/canonical-data.json +++ b/exercises/zipper/canonical-data.json @@ -1,6 +1,5 @@ { "exercise": "zipper", - "version": "1.1.0", "comments": [ " The test cases for this exercise include an initial tree and a ", " series of operations to perform on the initial tree. ", @@ -18,6 +17,7 @@ ], "cases": [ { + "uuid": "771c652e-0754-4ef0-945c-0675d12ef1f5", "description": "data is retained", "property": "expectedValue", "input": { @@ -66,6 +66,7 @@ } }, { + "uuid": "d7dcbb92-47fc-4d01-b81a-df3353bc09ff", "description": "left, right and value", "property": "expectedValue", "input": { @@ -104,6 +105,7 @@ } }, { + "uuid": "613d8286-b05c-4453-b205-e6f9c5966339", "description": "dead end", "property": "expectedValue", "input": { @@ -139,6 +141,7 @@ } }, { + "uuid": "dda31af7-1c68-4e29-933a-c9d198d94284", "description": "tree from deep focus", "property": "expectedValue", "input": { @@ -193,6 +196,7 @@ } }, { + "uuid": "1e3072a6-f85b-430b-b014-cdb4087e3577", "description": "traversing up from top", "property": "expectedValue", "input": { @@ -225,6 +229,7 @@ } }, { + "uuid": "b8505f6a-aed4-4c2e-824f-a0ed8570d74b", "description": "left, right, and up", "property": "expectedValue", "input": { @@ -275,6 +280,7 @@ } }, { + "uuid": "47df1a27-b709-496e-b381-63a03b82ea5f", "description": "set_value", "property": "expectedValue", "input": { @@ -330,6 +336,7 @@ } }, { + "uuid": "16a1f1a8-dbed-456d-95ac-1cbb6093e0ab", "description": "set_value after traversing up", "property": "expectedValue", "input": { @@ -391,6 +398,7 @@ } }, { + "uuid": "535a91af-a02e-49cd-8d2c-ecb6e4647174", "description": "set_left with leaf", "property": "expectedValue", "input": { @@ -454,6 +462,7 @@ } }, { + "uuid": "b3f60c4b-a788-4ffd-be5d-1e69aee61de3", "description": "set_right with null", "property": "expectedValue", "input": { @@ -505,6 +514,7 @@ } }, { + "uuid": "e91c221d-7b90-4604-b4ec-46638a673a12", "description": "set_right with subtree", "property": "expectedValue", "input": { @@ -577,6 +587,7 @@ } }, { + "uuid": "c246be85-6648-4e9c-866f-b08cd495149a", "description": "set_value on deep focus", "property": "expectedValue", "input": { @@ -635,6 +646,7 @@ } }, { + "uuid": "47aa85a0-5240-48a4-9f42-e2ac636710ea", "description": "different paths to same zipper", "property": "sameResultFromOperations", "input": { diff --git a/package.json b/package.json index 9044ffbfe0..874717ca9b 100644 --- a/package.json +++ b/package.json @@ -7,10 +7,13 @@ "author": "Tejas Bubane ", "license": "MIT", "dependencies": { - "ajv-cli": "^2.1.0" + "ajv-cli": "^3.3.0" }, "scripts": { "test": "ajv -s canonical-schema.json -d \"exercises/*/canonical-data.json\"", "test-one": "ajv -s canonical-schema.json -d" + }, + "resolutions": { + "minimist": "^1.2.3" } } diff --git a/workflows/README.md b/workflows/README.md new file mode 100644 index 0000000000..ff60e86e89 --- /dev/null +++ b/workflows/README.md @@ -0,0 +1,320 @@ +# Workflow templates + +This document explains how to set up Continuous Integration (CI) workflows for an Exercism Language Track using GitHub Actions (GHA). It provides best practices and examples for you to use to make your own fast, reliable and robust CI workflows. The GHA workflows in this folder can be adapted to work with any CI, because the base structure will remain the same. + +It will: +- Outline the ideal CI workflow +- Discuss considerations and recommendations +- Provide you with some templates to use +- Leave you with a guide to migrating from Travis + +_Note: The content in this folder doesn't **necessarily** belong in this repository, but we don't have a great place to put it that allows for good discoverability. _ + +Example implementation of these workflow files [can be found in `exercism/javascript`][git-javascript]. + +## **HELP**: this looks like _a lot_ of work :sweat: + +The rest of the document is designed to explain how the workflows work. If you're in a hurry, and you just want to switch from Travis or Circle to GHA without optimizing the PR scripts, scroll down to the **~10 minute guide** on [**Migrating from Travis**](#migrating-from-travis). + +## Track CI actions + +The recommended actions for checking the content of your repository has integrity are as follows: + +1. [`configlet` linting][git-configlet] in order to check `config.json` +2. check for stubs +3. check for documentation (`v3` requires new files; this might move to `configlet`) +4. lint the exercises using a "maintainers" configuration +5. test the exercises using the example/examplar files (can include build step) + +There can also be track-specific actions. For example: + +1. check the [integrity][wiki-integrity] of the exercise configurations +2. check the formatting of the exercise files + +And perhaps you'd want more Quality Of Life checks, such as: + +1. ensure CONTRIBUTING exists +2. ensure there is a sane lockfile for dependencies +3. ensure links inside markdown files are valid +4. ... + +## Recommendations + +### Frequency of running checks + +For each action think about how often it should run. + +- The `configlet` linting is something that's so important (because a track can break if the `config.json` breaks) that it should probably always run, **but** only needs to run once per commit. +- The existence or integrity of files only needs to run once per commit. +- If a track is supposed to run under multiple runtime-versions or compiler-versions, building/testing exercises should be ran against each supported version +- PRs _probably_ only need to run actions on files _added_ or _changed_, but since a file can influence an exercise, it's safer to run the actions for the _exercise_, if one of its files changes. + +It can be very helpful to make the actions that should run, available locally as well. This means that the scripts that do the actual work are also manually runnable. To achieve this **do not inline** the action inside the workflow files., but create a standalone script. For example, checking for stubs can be completely bashed out inside the workflow file, but the recommendation here is to create a new executable script `scripts/ci-check` instead. + +> "But the command is very short, e.g. `eslint . --ext ts --ext tsx`". +> +> When this command needs to be updated, it now needs to update in all the places in the documentation, the workflow files, ánd in the _minds of the maintainers_. Extracting this to a script resolves all that. Reading a workflow file can also be **very** daunting. + +### Checks on PRs where exercises change + +The `scripts/pr` and `scripts/pr-check` scripts (see [templates](#templates)) are run with multiple arguments, one for each file that has been changed or added in this PR. For example, if `two-fer` has been updated, a call might look like this: + +```bash +scripts/pr exercises/two-fer/README.md exercises/two-fer/.meta/example.ext +``` + +It's recommended to run any actions against the changed _exercise_ and not the changed _file_. This is because changing a file is likely to trigger changes for the entire exercise (think: configuration, packages). + +> **Not ready?** / **Complex?** +> +> Before implementing this optimization, it may be safely ignored! The migration guide hints at adding at a later stage. If the input arguments are ignored, all the checks will run on all the exercises. **This is perfectly fine**. It will just take longer. + +### Integrity checks + +If the track has a single "top-level" dependency file and/or other configuration files, add an [integrity][wiki-integrity] step (that exists alongside a `scripts/sync` or `bin/sync`, which would copy all configuration files to all exercises), which ensures that the top-level/base files are the same as the one copied to the exercise directories. Now dependencies can be updated, synced across the repository, and we can ensure that all exercises have the same configuration. + +A common way to accomplish this is to use a checksum. Ubuntu (and various other Linux distributions) comes with a tool called `sha1sum`, but using _whichever_ method to hash or reduce the configuration file (md5, sha1, crc32) to a checksum value, would work: + +```bash +$ sha1sum README.md +cd58091c5043bf21f00d39ff1740d8b2976deeff *README.md +``` + +### Security checks + +If the track uses additional workflows that require access to the GitHub token or other secrets, it's best practice to pin **all** actions used in the workflow to a specific commit. See [GitHub's security hardening guide][github-actions-security] for details. + +For example: + +```diff +- uses: julia-actions/setup-julia@v1 ++ uses: julia-actions/setup-julia@d26d1111976eae5f00db04f0515ab744ec9cd79e # 1.3.1 +``` + +If the tooling has lockfiles for dependency management, consider checking it into the repository and use a "frozen lockfile" inside the workflow files. For example: `npm ci`, `yarn install --frozen-lockfile` and `bundle install --frozen`. This ensures that the lockfile is up-to-date when changing dependencies and prevents malicious packages to come in. + +## Templates + +In this directory at minimum there are the following templates: + +- `configlet.yml`: This workflow will do a fetch the latest configlet binary and lint this repository. Run on every commit. For PRs, runs on the actual commit and a "after merge" tree. +- `ci.yml`: This workflow **only runs on the main branch (`master` or `main` by default)**, once on each commit. + 1. Run a 'pre-check' command (check for stubs, lint, docs, etc.) for all exercises + 2. Run a 'ci' command (build and test) for multiple versions, for all exercises +- `pr.ci.yml`: This workflow **only runs on PRs**, once on each commit. + 1. Run a 'pre-check' command (check for stubs, lint, docs, etc.) for changed files + 2. Run a 'ci' command (build and test) for multiple versions, for changed exercises + +The non-pr workflows can also be triggered via [`workflow_dispatch`][github-workflow-dispatch]. + +Each file has listed at the top which "scripts" should be available. If you want these to be binaries, replace `scripts/xxx` with `bin/xxx`. Some tooling will _require_ binaries to be inside a `bin` folder. + +- `scripts/ci`: a script that should build and test all exercises using the example solutions against the tests +- `scripts/ci-check`: a script that should lint all exercises, and optionally check for stubs, configuration integrity, and more +- `scripts/pr`: same as `scripts/ci`, but should only run exercises resolved from the paths given as input +- `scripts/pr-check`: same as `scripts/ci-check`, but should only run for files or exercises resolved from the paths given as input + +## Migrating from Travis + +Here is an example `.travis.yml` (taken from the `elm` track): + +```yml +sudo: false +language: node_js +node_js: + - lts/* +script: + - bin/fetch-configlet + - bin/configlet lint . + - bin/build.sh +``` + +In order to convert this quickly to GitHub Actions, take the following steps: + +### Determine the template variables + +| variable | value | +| --------------------------- | ------------------------------------ | +| `` | `elm` | +| `` | `ubuntu-latest` | +| `` | `actions/setup-node@v1` | +| `` | `npm ci` (happens inside `build.sh`) | +| `` | `.elm` | + +> Found the setup action via [this search](https://github.com/actions/?q=setup+node&type=&language=). +> Found the image name by looking at [default distribution for Travis](https://blog.travis-ci.com/2019-04-15-xenial-default-build-environment). + +### Determine the steps + +- `bin/fetch-configlet`: don't need this anymore when using `configlet.yml` workflow +- `bin/configlet lint .`: don't need this anymore when using `configlet.yml` workflow +- `bin/build.sh`: single script that does everything + +### Prepare the "scripts" + +This track uses the `bin` folder, so inside the `bin` folder, create the following files: + +```bash +# bin/pr +bin/build.sh +``` + +```bash +# bin/pr-check +echo "No checks yet" +``` + +```bash +# bin/ci +bin/build.sh +``` + +```bash +# bin/ci-check +echo "No checks yet" +``` + +Creating these as _separate_ binaries will allow for optimisation later. No need to in-line anything right now. + +### Fill in the templates + +Here is the diff for `workflows/ci.yml`. + +```diff +# # .github/workflows/ci.yml + + # This workflow will do a clean install of node dependencies and run tests across different versions + # +- # Replace with the track name +- # Replace with an image to run the jobs on +- # Replace with a github action to setup tooling on the image +- # Replace with a cli command to install the dependencies +- # Replace with file extensions that should trigger the workflow +- # +- # Find Github Actions to setup tooling here: +- # - https://github.com/actions/?q=setup&type=&language= +- # - https://github.com/actions/starter-workflows/tree/main/ci +- # - https://github.com/marketplace?type=actions&query=setup +- # + # Requires scripts: +- # - scripts/ci-check +- # - scripts/ci ++ # - bin/ci-check ++ # - bin/ci + +- name: / master ++ name: elm / master + + on: + push: + branches: [master, main] + workflow_dispatch: + + jobs: + precheck: +- runs-on: ++ runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 +- - name: Use +- uses: ++ - name: Use Node LTS ++ uses: actions/setup-node@v1 + with: +- # here, use the LTS/stable version of the track's tooling +- # node-version: 12.x ++ node-version: 12.x + + - name: Install project dependencies +- run: ++ run: npm ci + +- - name: Run exercism/ ci pre-check (checks config, lint code) for all exercises +- run: scripts/ci-check ++ - name: Run exercism/elm ci pre-check (checks config, lint code) for all exercises ++ run: bin/ci-check + + ci: +- runs-on: ++ runs-on: ubuntu-latest + + strategy: + matrix: +- # here, add all SUPPORTED versions only +- # version: [10.x, 12.x, 14.x] ++ version: [10.x, 12.x, 14.x] + + steps: + - uses: actions/checkout@v2 +- - name: Use ${{ matrix.version }} +- uses: ++ - name: Use Node ${{ matrix.version }} ++ uses: actions/setup-node@v1 + with: +- # below: see how to inject the version +- # node-version: ${{ matrix.version }} ++ node-version: ${{ matrix.version }} + + - name: Install project dependencies +- run: ++ run: npm ci + +- - name: Run exercism/ ci (runs tests) for all exercises +- run: scripts/ci ++ - name: Run exercism/elm ci (runs tests) for all exercises ++ run: bin/ci +``` + +`workflows/pr.yml` has the same changes, with the notable exception of the bash-fu that calls the `pr-check` and `pr` scripts with each changed file as argument: + +```diff +# # .github/workflows/pr.yml + +# # ... + +- - name: Run exercism/ ci pre-check (stub files, config integrity) for changed exercises ++ - name: Run exercism/elm ci pre-check (stub files, config integrity) for changed exercises + run: | + PULL_REQUEST_URL=$(jq -r ".pull_request.url" "$GITHUB_EVENT_PATH") + curl --url $"${PULL_REQUEST_URL}/files" --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' | \ +- jq -c '.[] | select(.status == "added" or .status == "modified") | select(.filename | match("\\.(|md|json)$")) | .filename' | \ ++ jq -c '.[] | select(.status == "added" or .status == "modified") | select(.filename | match("\\.(elm|md|json)$")) | .filename' | \ +- xargs -r scripts/pr-check ++ xargs -r bin/pr-check + + # ... +``` + +### Now it should work + +This is enough to convert to GitHub Actions, with the possibility to optimise your scripts. + +1. From `build.sh`, remove steps that should run only once, and extract them to the `ci-check.sh` and `pre-check.sh` files (hint, you can create `lint.sh`, and call that from both "scripts") +2. To `pr.sh` and `pr-check.sh`, add optimisations that use the input arguments to determine which files or exercises to check. +3. Add additional checks +4. Add documentation how to run checks locally, and what each one tries to accomplish. + +## Troubleshooting + +If you run into any issues or want someone to review your workflows, please ping the `@exercism/github-actions` team. + +> **Changed a top-level file that should trigger a CI run on all exercises** + +At moment of writing, `pr.ci.yml` only allows for "extension" testing. Ideally this is updated to trigger always when certain files are changed (for example the binary to run the tests). However, these changes are often infrequent and done by maintainers, that the fact that `ci.yml` runs on master, always, for everything, is probably safe enough. + +> **Created a scripts/xxx file on Windows and now it doesn't work on {other OS}** + +By default, files created on Windows don't have metadata in the [git-index][git-index] embedded about their executability, because the model for permissions on windows is different. Git, by default, will use the git-index metadata to determine if the file should be executable on POSIX-based systems, and thus make the `scripts/xxx` file NOT executable. + +```bash +git update-index --chmod=+x scripts/xxx +git commit -m "Make scripts/xxx executable" +``` + +[git-configlet]: https://github.com/exercism/configlet#lint +[git-index]: https://www.git-scm.com/docs/git-update-index +[git-javascript]: https://github.com/exercism/javascript/tree/f49ac022d3a55cbbb48dadbc6dbf1d407de72187/.github/workflows +[github-workflow-dispatch]: https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/ +[github-actions-security]: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions +[wiki-integrity]: https://en.wikipedia.org/wiki/File_verification diff --git a/workflows/ci.yml b/workflows/ci.yml new file mode 100644 index 0000000000..a68d43213e --- /dev/null +++ b/workflows/ci.yml @@ -0,0 +1,64 @@ +# This workflow will do a clean install of the dependencies and run tests across different versions +# +# Replace with the track name +# Replace with an image to run the jobs on +# Replace with a github action to setup tooling on the image +# Replace with a cli command to install the dependencies +# Replace with file extensions that should trigger the workflow +# +# Find Github Actions to setup tooling here: +# - https://github.com/actions/?q=setup&type=&language= +# - https://github.com/actions/starter-workflows/tree/main/ci +# - https://github.com/marketplace?type=actions&query=setup +# +# Requires scripts: +# - scripts/ci-check +# - scripts/ci + +name: / main + +on: + push: + branches: [master, main] + workflow_dispatch: + +jobs: + precheck: + runs-on: + + steps: + - uses: actions/checkout@v2 + - name: Use + uses: + with: + # Here, use the LTS/stable version of the track's tooling, e.g.: + # node-version: 12.x + + - name: Install project dependencies + run: + + - name: Run exercism/ ci pre-check (checks config, lint code) for all exercises + run: scripts/ci-check + + ci: + runs-on: + + strategy: + matrix: + # Here, add all SUPPORTED versions only, e.g.: + # version: [10.x, 12.x, 14.x] + # Optionally, add more matrix variables, such as os or arch + + steps: + - uses: actions/checkout@v2 + - name: Use ${{ matrix.version }} + uses: + with: + # Use the ${{ matrix.x }} format to inject variables into commands + # node-version: ${{ matrix.version }} + + - name: Install project dependencies + run: + + - name: Run exercism/ ci (runs tests) for all exercises + run: scripts/ci diff --git a/workflows/configlet.yml b/workflows/configlet.yml new file mode 100644 index 0000000000..1b44888e66 --- /dev/null +++ b/workflows/configlet.yml @@ -0,0 +1,18 @@ +# This workflow will do a fetch the latest configlet binary and lint this repository. + +name: configlet + +on: [push, pull_request, workflow_dispatch] + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Fetch configlet + uses: exercism/github-actions/configlet-ci@master + + - name: Configlet Linter + run: configlet lint . diff --git a/workflows/pr.ci.yml b/workflows/pr.ci.yml new file mode 100644 index 0000000000..5c166c37bc --- /dev/null +++ b/workflows/pr.ci.yml @@ -0,0 +1,68 @@ +# This workflow will do a clean install of the dependencies and run tests across different versions +# +# Replace with the track name +# Replace with an image to run the jobs on +# Replace with a github action to setup tooling on the image +# Replace with a cli command to install the dependencies +# Replace with file extensions that should trigger the workflow +# +# Requires scripts: +# - scripts/pr-check path/to/changed/file path/to/changed/file +# - scripts/pr path/to/changed/file path/to/changed/file + +name: / pr + +on: pull_request + +jobs: + precheck: + runs-on: + + steps: + - name: Checkout PR + uses: actions/checkout@v2 + + - name: Use Node.js LTS (12.x) + uses: + with: + # Here, use the LTS/stable version of the track's tooling, e.g.: + # node-version: 12.x + + - name: Install project dependencies + run: + + # Replace with file extensions that should trigger this check. Replace with .* to allow anything. + - name: Run exercism/ ci pre-check (stub files, config integrity) for changed exercises + run: | + PULL_REQUEST_URL=$(jq -r ".pull_request.url" "$GITHUB_EVENT_PATH") + curl --url $"${PULL_REQUEST_URL}/files" --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' | \ + jq -c '.[] | select(.status == "added" or .status == "modified") | select(.filename | match("\\.(|md|json)$")) | .filename' | \ + xargs -r scripts/pr-check + + ci: + runs-on: + + strategy: + matrix: + # Here, add all SUPPORTED versions only, e.g.: + # version: [10.x, 12.x, 14.x] + # Optionally, add more matrix variables, such as os or arch + + steps: + - uses: actions/checkout@v2 + - name: Use ${{ matrix.version }} + uses: + with: + # Use the ${{ matrix.x }} format to inject variables into commands + # node-version: ${{ matrix.version }} + + - name: Install project dependencies + run: + + # Replace with file extensions that should trigger running tests. Replace with .* to allow anything. + - name: Run exercism/ ci (runs tests) for changed/added exercises + run: | + PULL_REQUEST_URL=$(jq -r ".pull_request.url" "$GITHUB_EVENT_PATH") + curl --url $"${PULL_REQUEST_URL}/files" --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' | \ + jq -c '.[] | select(.status == "added" or .status == "modified") | select(.filename | match("\\.(|md|json)$")) | .filename' | \ + xargs -r scripts/pr diff --git a/yarn.lock b/yarn.lock index 990b3c0ae3..1c812daea6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6,15 +6,18 @@ abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" -ajv-cli@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ajv-cli/-/ajv-cli-2.1.0.tgz#26f942ddf4b1d14d3c639cb28db807f02ca3787c" +ajv-cli@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/ajv-cli/-/ajv-cli-3.3.0.tgz#dd72207f5395051db7d620ab7d4da1cec3d50f06" + integrity sha512-4eiNNjDlainn5Rm+rU3egxLUUxzevcB+gviBLs9sm6etHNrE7l2JSQ3yoz5hE+eqrth3pTygELOafhSIO8Hiig== dependencies: - ajv "^5.0.0" + ajv "^6.7.0" ajv-pack "^0.3.0" - fast-json-patch "^0.5.6" - glob "^7.0.3" + fast-json-patch "^2.0.0" + glob "^7.1.0" + js-yaml "^3.13.1" json-schema-migrate "^0.2.0" + json5 "^2.1.3" minimist "^1.2.0" ajv-pack@^0.3.0: @@ -33,6 +36,23 @@ ajv@^5.0.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" +ajv@^6.7.0: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -77,13 +97,31 @@ editorconfig@^0.13.2: semver "^5.1.0" sigmund "^1.0.1" +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" -fast-json-patch@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-0.5.7.tgz#b5a8f49d259624596ef98b872f3fda895b4d8665" +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-patch@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-2.2.1.tgz#18150d36c9ab65c7209e7d4eb113f4f8eaabe6d9" + integrity sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig== + dependencies: + fast-deep-equal "^2.0.1" fast-json-stable-stringify@^2.0.0: version "2.0.0" @@ -93,9 +131,10 @@ fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" -glob@^7.0.3: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" +glob@^7.1.0: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -116,8 +155,9 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" ini@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + version "1.3.7" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" + integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== js-beautify@^1.6.4: version "1.7.5" @@ -128,6 +168,14 @@ js-beautify@^1.6.4: mkdirp "~0.5.0" nopt "~3.0.1" +js-yaml@^3.13.1: + version "3.14.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + json-schema-migrate@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/json-schema-migrate/-/json-schema-migrate-0.2.0.tgz#ba47a5b0072fc72396460e1bd60b44d52178bbc6" @@ -138,6 +186,18 @@ json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json5@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + lru-cache@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" @@ -150,13 +210,10 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" +minimist@0.0.8, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== mkdirp@~0.5.0: version "0.5.1" @@ -188,6 +245,11 @@ pseudomap@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + require-from-string@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" @@ -200,6 +262,18 @@ sigmund@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +uri-js@^4.2.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" + integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== + dependencies: + punycode "^2.1.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"