From d71270ee93d5e3da31c81c5fc9f047cee1ebc9fd Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Tue, 26 May 2026 08:52:08 -0700 Subject: [PATCH 01/16] Format all `instructions.append.md` to start with an H1 (required but ignored) and H2 (#3135) * Format all `instructions.append.md` to start with an H1 (required but ignored) and H2 * Revert deprecated diffie-hellman --- exercises/practice/affine-cipher/.docs/instructions.append.md | 2 ++ exercises/practice/anagram/.docs/instructions.append.md | 2 ++ .../practice/armstrong-numbers/.docs/instructions.append.md | 2 ++ exercises/practice/bank-account/.docs/instructions.append.md | 2 ++ exercises/practice/clock/.docs/instructions.append.md | 2 ++ exercises/practice/dot-dsl/.docs/instructions.append.md | 2 ++ exercises/practice/flatten-array/.docs/instructions.append.md | 2 ++ exercises/practice/hamming/.docs/instructions.append.md | 4 +++- exercises/practice/hangman/.docs/instructions.append.md | 4 +++- .../intergalactic-transmission/.docs/instructions.append.md | 2 ++ exercises/practice/isogram/.docs/instructions.append.md | 1 - exercises/practice/leap/.docs/instructions.append.md | 2 ++ exercises/practice/linked-list/.docs/instructions.append.md | 2 ++ exercises/practice/list-ops/.docs/instructions.append.md | 4 +++- .../parallel-letter-frequency/.docs/instructions.append.md | 2 ++ .../practice/reverse-string/.docs/instructions.append.md | 2 ++ .../practice/rna-transcription/.docs/instructions.append.md | 2 ++ exercises/practice/square-root/.docs/instructions.append.md | 4 +++- exercises/practice/two-fer/.docs/instructions.append.md | 2 ++ 19 files changed, 40 insertions(+), 5 deletions(-) delete mode 100644 exercises/practice/isogram/.docs/instructions.append.md diff --git a/exercises/practice/affine-cipher/.docs/instructions.append.md b/exercises/practice/affine-cipher/.docs/instructions.append.md index e724f3faa..0e61d91c7 100644 --- a/exercises/practice/affine-cipher/.docs/instructions.append.md +++ b/exercises/practice/affine-cipher/.docs/instructions.append.md @@ -1,4 +1,6 @@ # Instructions append +## Implementation + Please notice that the `%` operator is not equivalent to the one described in the problem description ([see Wikipedia entry for Modulo operation](https://en.wikipedia.org/wiki/Modulo_operation)). diff --git a/exercises/practice/anagram/.docs/instructions.append.md b/exercises/practice/anagram/.docs/instructions.append.md index 8d71a920b..273ca3cbe 100644 --- a/exercises/practice/anagram/.docs/instructions.append.md +++ b/exercises/practice/anagram/.docs/instructions.append.md @@ -1,3 +1,5 @@ # Instructions Append +## Implementation + The anagrams can be returned in any order. diff --git a/exercises/practice/armstrong-numbers/.docs/instructions.append.md b/exercises/practice/armstrong-numbers/.docs/instructions.append.md index 4f8e31eed..e36afb3dc 100644 --- a/exercises/practice/armstrong-numbers/.docs/instructions.append.md +++ b/exercises/practice/armstrong-numbers/.docs/instructions.append.md @@ -1,4 +1,6 @@ # Instructions append +## Implementation + For more help on how to solve this exercise, please refer to the tutorial provided as part of the hello world exercise: [instructions.append.md](https://github.com/exercism/java/blob/main/exercises/practice/hello-world/.docs/instructions.append.md#tutorial) diff --git a/exercises/practice/bank-account/.docs/instructions.append.md b/exercises/practice/bank-account/.docs/instructions.append.md index 9d3307ee3..0c2dd7775 100644 --- a/exercises/practice/bank-account/.docs/instructions.append.md +++ b/exercises/practice/bank-account/.docs/instructions.append.md @@ -1,5 +1,7 @@ # Instructions append +## Implementation + This exercise introduces [concurrency][oracle-docs-concurrency]. To pass the last test you might find the [`synchronized` keyword or locks][oracle-docs-synchronized] useful. diff --git a/exercises/practice/clock/.docs/instructions.append.md b/exercises/practice/clock/.docs/instructions.append.md index 4e1e0fbca..05b5e459d 100644 --- a/exercises/practice/clock/.docs/instructions.append.md +++ b/exercises/practice/clock/.docs/instructions.append.md @@ -1,5 +1,7 @@ # Instructions append +## Implementation + In order to satisfy the requirement that two clocks are considered equal just when they are set to the same time, you will need to override the [`equals`](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals(java.lang.Object)) and [`hashcode`](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode) methods in your `Clock` class. For more information on how to override these methods, see [this JavaWorld article](https://web.archive.org/web/20170528222153/http://www.javaworld.com/article/2072762/java-app-dev/object-equality.html). diff --git a/exercises/practice/dot-dsl/.docs/instructions.append.md b/exercises/practice/dot-dsl/.docs/instructions.append.md index e110bf76b..330706308 100644 --- a/exercises/practice/dot-dsl/.docs/instructions.append.md +++ b/exercises/practice/dot-dsl/.docs/instructions.append.md @@ -1,5 +1,7 @@ # Instructions append +## Implementation + The graph is represented in the DSL by the `Graph` class. The implementation for the nodes and edges (represented by the `Node` and `Edge` classes respectively) are provided. diff --git a/exercises/practice/flatten-array/.docs/instructions.append.md b/exercises/practice/flatten-array/.docs/instructions.append.md index c5bf8cb0c..d1b11d9df 100644 --- a/exercises/practice/flatten-array/.docs/instructions.append.md +++ b/exercises/practice/flatten-array/.docs/instructions.append.md @@ -1,3 +1,5 @@ # Instructions append +## Implementation + For the Java track, the input will be provided as a `List` instead of an array, and the output should also be a `List`. diff --git a/exercises/practice/hamming/.docs/instructions.append.md b/exercises/practice/hamming/.docs/instructions.append.md index 77d058700..d76e03c28 100644 --- a/exercises/practice/hamming/.docs/instructions.append.md +++ b/exercises/practice/hamming/.docs/instructions.append.md @@ -1,4 +1,6 @@ -# Hints +# Instructions append + +## Hints This is the first exercise with tests that require you to throw an [`Exception`][exception-docs]. `Exception`s are typically thrown to indicate that a program has encountered an unexpected input or state. diff --git a/exercises/practice/hangman/.docs/instructions.append.md b/exercises/practice/hangman/.docs/instructions.append.md index c5bd1e69e..db700e1e4 100644 --- a/exercises/practice/hangman/.docs/instructions.append.md +++ b/exercises/practice/hangman/.docs/instructions.append.md @@ -1,4 +1,6 @@ -# Hints +# Instructions append + +## Hints One main aspect of Functional Programming is to have side-effect free functions, not to have to wonder that hidden objects a function has changed. diff --git a/exercises/practice/intergalactic-transmission/.docs/instructions.append.md b/exercises/practice/intergalactic-transmission/.docs/instructions.append.md index a5f1cad0d..df86701a8 100644 --- a/exercises/practice/intergalactic-transmission/.docs/instructions.append.md +++ b/exercises/practice/intergalactic-transmission/.docs/instructions.append.md @@ -1,3 +1,5 @@ # Instructions append +## Implementation + Although we're dealing with bytes of data, the inputs and outputs are `List` (instead of `byte[]`) to avoid the need to cast or convert negative values for bytes 128 to 255. diff --git a/exercises/practice/isogram/.docs/instructions.append.md b/exercises/practice/isogram/.docs/instructions.append.md deleted file mode 100644 index 8f338339b..000000000 --- a/exercises/practice/isogram/.docs/instructions.append.md +++ /dev/null @@ -1 +0,0 @@ -# Instructions append diff --git a/exercises/practice/leap/.docs/instructions.append.md b/exercises/practice/leap/.docs/instructions.append.md index 8fd1498b1..f85ccac7e 100644 --- a/exercises/practice/leap/.docs/instructions.append.md +++ b/exercises/practice/leap/.docs/instructions.append.md @@ -1,5 +1,7 @@ # Instructions append +## Implementation + Before you start, make sure you understand how to write code that can pass the test cases. For more context, check out this [tutorial]. diff --git a/exercises/practice/linked-list/.docs/instructions.append.md b/exercises/practice/linked-list/.docs/instructions.append.md index f4b180b90..7fc5c4e7e 100644 --- a/exercises/practice/linked-list/.docs/instructions.append.md +++ b/exercises/practice/linked-list/.docs/instructions.append.md @@ -1,5 +1,7 @@ # Instructions append +## Implementation + This exercise introduces [generics](https://docs.oracle.com/javase/tutorial/java/generics/index.html). To make the tests pass you need to construct your class such that it accepts any type of input, e.g. `Integer` or `String`. diff --git a/exercises/practice/list-ops/.docs/instructions.append.md b/exercises/practice/list-ops/.docs/instructions.append.md index df6022661..054352553 100644 --- a/exercises/practice/list-ops/.docs/instructions.append.md +++ b/exercises/practice/list-ops/.docs/instructions.append.md @@ -1,4 +1,6 @@ -# Hints +# Instructions append + +## Hints In Java it's considered best practice to use instance methods over class methods. However, there are conditions in which it is absolutely appropriate for a function to be `static`. Since classes in Java are closed for modification (i.e. you cannot add members to a class outside its definition like you can in other languages like Ruby or JavaScript), you cannot add new behavior to the class directly. What to do if you still want to define behavior for a given type? The idiomatic solution in this case is to write a utility method. Collections of these kinds of methods are often referred to as "utility classes". Examples of such classes from within the JRE include [Arrays](https://docs.oracle.com/javase/9/docs/api/java/util/Arrays.html) and [Collections](https://docs.oracle.com/javase/9/docs/api/java/util/Collections.html). diff --git a/exercises/practice/parallel-letter-frequency/.docs/instructions.append.md b/exercises/practice/parallel-letter-frequency/.docs/instructions.append.md index 47e4bf6cc..1c9796ca2 100644 --- a/exercises/practice/parallel-letter-frequency/.docs/instructions.append.md +++ b/exercises/practice/parallel-letter-frequency/.docs/instructions.append.md @@ -1,3 +1,5 @@ # Instructions append +## Implementation + As a stretch goal, consider if your implementation will work for characters with [diacritics or accents](https://en.wikipedia.org/wiki/Diacritic). For example, such solutions should not consider e and ë the same character. An example text for this case is [Wilhelmus](https://en.wikipedia.org/wiki/Wilhelmus), the Dutch national anthem. diff --git a/exercises/practice/reverse-string/.docs/instructions.append.md b/exercises/practice/reverse-string/.docs/instructions.append.md index 8d7de0aa9..7870cec2a 100644 --- a/exercises/practice/reverse-string/.docs/instructions.append.md +++ b/exercises/practice/reverse-string/.docs/instructions.append.md @@ -1,3 +1,5 @@ # Instructions append +## Implementation + For more help on how to solve this exercise, please refer to the tutorial provided as part of the [hello world](https://exercism.org/tracks/java/exercises/hello-world) exercise. diff --git a/exercises/practice/rna-transcription/.docs/instructions.append.md b/exercises/practice/rna-transcription/.docs/instructions.append.md index 4f8e31eed..e36afb3dc 100644 --- a/exercises/practice/rna-transcription/.docs/instructions.append.md +++ b/exercises/practice/rna-transcription/.docs/instructions.append.md @@ -1,4 +1,6 @@ # Instructions append +## Implementation + For more help on how to solve this exercise, please refer to the tutorial provided as part of the hello world exercise: [instructions.append.md](https://github.com/exercism/java/blob/main/exercises/practice/hello-world/.docs/instructions.append.md#tutorial) diff --git a/exercises/practice/square-root/.docs/instructions.append.md b/exercises/practice/square-root/.docs/instructions.append.md index 97a502567..e1da715ff 100644 --- a/exercises/practice/square-root/.docs/instructions.append.md +++ b/exercises/practice/square-root/.docs/instructions.append.md @@ -1,4 +1,6 @@ -# Instructions (appended) +# Instructions append + +## Implementation The goal of this exercise is to practice working with numbers, so stay away from `java.lang.Math`! diff --git a/exercises/practice/two-fer/.docs/instructions.append.md b/exercises/practice/two-fer/.docs/instructions.append.md index 1005e7e9d..8c1f0c710 100644 --- a/exercises/practice/two-fer/.docs/instructions.append.md +++ b/exercises/practice/two-fer/.docs/instructions.append.md @@ -1,5 +1,7 @@ # Instructions append +## Implementation + Before you start, make sure you understand how to write code that can pass the test cases. For more context, check out this [tutorial]. From 8d95bc0900b8c24adbd9003e403c71103957c7ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jun 2026 21:25:12 +0530 Subject: [PATCH 02/16] Bump DavidAnson/markdownlint-cli2-action from 23.1.0 to 23.2.0 (#3137) Bumps [DavidAnson/markdownlint-cli2-action](https://github.com/davidanson/markdownlint-cli2-action) from 23.1.0 to 23.2.0. - [Release notes](https://github.com/davidanson/markdownlint-cli2-action/releases) - [Commits](https://github.com/davidanson/markdownlint-cli2-action/compare/6b51ade7a9e4a75a7ad929842dd298a3804ebe8b...ded1f9488f68a970bc66ea5619e13e9b52e601cd) --- updated-dependencies: - dependency-name: DavidAnson/markdownlint-cli2-action dependency-version: 23.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/markdown.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/markdown.yml b/.github/workflows/markdown.yml index 9467459c7..6bcb84e06 100644 --- a/.github/workflows/markdown.yml +++ b/.github/workflows/markdown.yml @@ -19,4 +19,4 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd - name: Lint markdown - uses: DavidAnson/markdownlint-cli2-action@6b51ade7a9e4a75a7ad929842dd298a3804ebe8b + uses: DavidAnson/markdownlint-cli2-action@ded1f9488f68a970bc66ea5619e13e9b52e601cd From fd1b44d7c39aa91c59dd06fa2a1d61bce4c408da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jun 2026 21:26:19 +0530 Subject: [PATCH 03/16] Bump actions/checkout from 4 to 6 (#3136) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Commits](https://github.com/actions/checkout/compare/v4...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/create-configlet-sync-issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/create-configlet-sync-issues.yml b/.github/workflows/create-configlet-sync-issues.yml index 1a256cfb9..3a497b2e6 100644 --- a/.github/workflows/create-configlet-sync-issues.yml +++ b/.github/workflows/create-configlet-sync-issues.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Fetch configlet run: ./bin/fetch-configlet From 86fe0ae33a6f9b648b487272b311ad44af7bf2a9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 15 Jun 2026 10:29:58 +0530 Subject: [PATCH 04/16] =?UTF-8?q?=F0=9F=A4=96=20Auto-sync=20docs,=20metada?= =?UTF-8?q?ta,=20and=20filepaths=20(#3138)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- exercises/practice/anagram/.meta/config.json | 2 +- exercises/practice/grep/.meta/config.json | 2 +- exercises/practice/isogram/.meta/config.json | 2 +- exercises/practice/pangram/.meta/config.json | 2 +- exercises/practice/sublist/.meta/config.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/exercises/practice/anagram/.meta/config.json b/exercises/practice/anagram/.meta/config.json index 1fae320a1..aa9251ddf 100644 --- a/exercises/practice/anagram/.meta/config.json +++ b/exercises/practice/anagram/.meta/config.json @@ -41,7 +41,7 @@ "build.gradle" ] }, - "blurb": "Given a word and a list of possible anagrams, select the correct sublist.", + "blurb": "Find the words that use the same letters as another word.", "source": "Inspired by the Extreme Startup game", "source_url": "https://github.com/rchatley/extreme_startup" } diff --git a/exercises/practice/grep/.meta/config.json b/exercises/practice/grep/.meta/config.json index dbf5fb02e..9b8ef04ad 100644 --- a/exercises/practice/grep/.meta/config.json +++ b/exercises/practice/grep/.meta/config.json @@ -26,7 +26,7 @@ "build.gradle" ] }, - "blurb": "Search a file for lines matching a regular expression pattern. Return the line number and contents of each matching line.", + "blurb": "Search a file for lines matching a regular expression pattern.", "source": "Conversation with Nate Foster.", "source_url": "https://www.cs.cornell.edu/courses/cs3110/2014sp/hw/0/ps0.pdf" } diff --git a/exercises/practice/isogram/.meta/config.json b/exercises/practice/isogram/.meta/config.json index 08e8e22f9..c6c0d3c56 100644 --- a/exercises/practice/isogram/.meta/config.json +++ b/exercises/practice/isogram/.meta/config.json @@ -38,7 +38,7 @@ "build.gradle" ] }, - "blurb": "Determine if a word or phrase is an isogram.", + "blurb": "Determine whether a phrase is an isogram, a word with no repeated letters.", "source": "Wikipedia", "source_url": "https://en.wikipedia.org/wiki/Isogram" } diff --git a/exercises/practice/pangram/.meta/config.json b/exercises/practice/pangram/.meta/config.json index 1a3fc5dae..dbf90a374 100644 --- a/exercises/practice/pangram/.meta/config.json +++ b/exercises/practice/pangram/.meta/config.json @@ -36,7 +36,7 @@ "build.gradle" ] }, - "blurb": "Determine if a sentence is a pangram.", + "blurb": "Determine whether a phrase uses every letter in the Latin alphabet.", "source": "Wikipedia", "source_url": "https://en.wikipedia.org/wiki/Pangram" } diff --git a/exercises/practice/sublist/.meta/config.json b/exercises/practice/sublist/.meta/config.json index 21d624fe6..3b6117ef0 100644 --- a/exercises/practice/sublist/.meta/config.json +++ b/exercises/practice/sublist/.meta/config.json @@ -38,5 +38,5 @@ "build.gradle" ] }, - "blurb": "Write a function to determine if a list is a sublist of another list." + "blurb": "Determine if a list is a sublist of another list." } From 0443ae57ff3d4842259bd30bc0b71aeb593fe39b Mon Sep 17 00:00:00 2001 From: Kah Goh Date: Sat, 20 Jun 2026 21:43:59 +0800 Subject: [PATCH 05/16] Update dot dsl exercise (#3143) * Update dot dsl exercise * Fix formating --- exercises/practice/dot-dsl/.meta/tests.toml | 90 +++++++++++++++++++ .../dot-dsl/src/test/java/GraphTest.java | 44 +++++++-- 2 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 exercises/practice/dot-dsl/.meta/tests.toml diff --git a/exercises/practice/dot-dsl/.meta/tests.toml b/exercises/practice/dot-dsl/.meta/tests.toml new file mode 100644 index 000000000..bb285760c --- /dev/null +++ b/exercises/practice/dot-dsl/.meta/tests.toml @@ -0,0 +1,90 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[3a50c618-2571-466b-9ee9-346d9943912e] +description = "empty graph" + +[5067feea-e49b-4a9d-865e-4502d6b0540c] +description = "graph with one node" + +[b66cf871-88c6-489a-b0b9-7c79b6819c45] +description = "graph with one node with attribute" + +[f7841da3-c0f8-4541-b594-21b626a764d2] +description = "graph with one edge" + +[bbee70e1-6b0d-4f3a-bd4e-41cd2cfc0e39] +description = "graph with one attribute" + +[ac736158-6684-418d-93d5-7b284e43294e] +description = "graph with comments" +comment = "Not possible to create scenario in test" +include = false + +[69068da9-7690-4d4d-a728-f5c2bf132a33] +description = "graph with nodes, edges, and attributes" + +[f6c53993-3937-4959-bcde-dc16411113ae] +description = "multiple edges on one line" + +[b853dfc1-1f05-45aa-bc98-b0fc6b57529b] +description = "only 1 edge between nodes" +include = false + +[bdc0fdac-aa46-457f-8385-65736ccdc1c7] +description = "malformed input" +comment = "Not possible to create the scenario in test" +include = false + +[f5c4f77d-359c-434a-9c33-b9eb795bafdd] +description = "malformed edge" +comment = "Not possible to create the scenario in test" +include = false + +[2238f6b8-20bb-489f-8ca0-084d1771d758] +description = "malformed edge 2" +comment = "Not possible to create the scenario in test" +include = false + +[4e3a4386-9e80-4315-b70f-253a06a2234e] +description = "invalid edge type" +comment = "Not possible to create the scenario in test" +include = false + +[793adce3-bd19-4458-ac41-c989f7f8d9db] +description = "multiple edges missing a node" +comment = "Not possible to create the scenario in test" +include = false + +[e2930b2c-3a03-4d8f-abe9-78a125a915a7] +description = "multiple edges missing a connector" +comment = "Not possible to create the scenario in test" +include = false + +[55d3f722-f9f1-46e1-b308-da61607952ab] +description = "empty attribute" +comment = "Not possible to create the scenario in test" +include = false + +[4ee2a9c3-54b1-4825-bd58-2b78c2c53953] +description = "malformed attribute" +comment = "Not possible to create the scenario in test" +include = false + +[382a13c8-6419-4286-8dd2-eac708f3e2a8] +description = "empty attribute name" +comment = "Not possible to create the scenario in test" +include = false + +[a6f9e6ab-8c3e-4475-a9fe-5dd061cadec6] +description = "non-alphanumeric node name" +comment = "Not possible to create the scenario in test" +include = false diff --git a/exercises/practice/dot-dsl/src/test/java/GraphTest.java b/exercises/practice/dot-dsl/src/test/java/GraphTest.java index 34c9c0a56..93a6df747 100644 --- a/exercises/practice/dot-dsl/src/test/java/GraphTest.java +++ b/exercises/practice/dot-dsl/src/test/java/GraphTest.java @@ -2,6 +2,7 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.Map; + import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -31,8 +32,8 @@ public void testGraphWithOneNode() { @Test @Disabled - @DisplayName("graph with one node with keywords") - public void testGraphWithOneNodeWithKeywords() { + @DisplayName("graph with one node with attribute") + public void testGraphWithOneNodeWithAttribute() { Graph graph = new Graph().node("a", Map.of("color", "green")); assertThat(graph.getNodes()) @@ -55,8 +56,8 @@ public void testGraphWithOneEdge() { @Test @Disabled - @DisplayName("graph with one edge with keywords") - public void testGraphWithOneEdgeWithKeywords() { + @DisplayName("graph with one edge with attribute") + public void testGraphWithOneEdgeWithAttribute() { Graph graph = new Graph().edge("a", "b", Map.of("color", "blue")); assertThat(graph.getNodes()).isEmpty(); @@ -78,8 +79,8 @@ public void testGraphWithOneAttribute() { @Test @Disabled - @DisplayName("graph with attributes") - public void testGraphWithAttributes() { + @DisplayName("graph with nodes, edges, and attributes") + public void testGraphWithNodesEdgesAndAttributes() { Graph graph = new Graph(Map.of("foo", "1", "title", "Testing Attrs", "bar", "true")) .node("a", Map.of("color", "green")) .node("c") @@ -95,11 +96,40 @@ public void testGraphWithAttributes() { assertThat(graph.getEdges()) .containsExactlyInAnyOrder( - new Edge("a", "b", Map.of("color", "blue")), + new Edge("a", "b", Map.of("color", "blue")), new Edge("b", "c")); assertThat(graph.getAttributes()) .containsExactlyInAnyOrderEntriesOf( Map.of("foo", "1", "title", "Testing Attrs", "bar", "true")); } + + @Test + @Disabled + @DisplayName("multiple edges on one line") + public void testMultipleEdgesOnOneLine() { + Graph graph = new Graph() + .node("a") + .node("b") + .node("c") + .node("d") + .edge("a", "b", Map.of("style", "dotted")) + .edge("b", "c", Map.of("style", "dotted")) + .edge("c", "d", Map.of("style", "dotted")); + + assertThat(graph.getNodes()).containsExactlyInAnyOrder( + new Node("a"), + new Node("b"), + new Node("c"), + new Node("d") + ); + + assertThat(graph.getEdges()) + .containsExactlyInAnyOrder( + new Edge("a", "b", Map.of("style", "dotted")), + new Edge("b", "c", Map.of("style", "dotted")), + new Edge("c", "d", Map.of("style", "dotted")) + ); + assertThat(graph.getAttributes()).isEmpty(); + } } From 641ae347ab9b2159f07b5a003e09123650674eaa Mon Sep 17 00:00:00 2001 From: habere-et-dispertire <18032974+habere-et-dispertire@users.noreply.github.com> Date: Sat, 27 Jun 2026 12:07:54 +0100 Subject: [PATCH 06/16] Add Modular Arithmetic approach to RaindropConverter (#3144) --- .../raindrops/.approaches/config.json | 9 ++++++ .../raindrops/.approaches/introduction.md | 27 ++++++++++++++++ .../raindrops/.approaches/modulus/content.md | 31 +++++++++++++++++++ .../raindrops/.approaches/modulus/snippet.txt | 8 +++++ 4 files changed, 75 insertions(+) create mode 100644 exercises/practice/raindrops/.approaches/modulus/content.md create mode 100644 exercises/practice/raindrops/.approaches/modulus/snippet.txt diff --git a/exercises/practice/raindrops/.approaches/config.json b/exercises/practice/raindrops/.approaches/config.json index a74c828a5..aa7fb01a6 100644 --- a/exercises/practice/raindrops/.approaches/config.json +++ b/exercises/practice/raindrops/.approaches/config.json @@ -22,6 +22,15 @@ "authors": [ "bobahop" ] + }, + { + "uuid": "d16d4056-2434-44ff-aae6-2bd57eb53dd7", + "slug": "modulus", + "title": "Modulus", + "blurb": "Use modular arithmetic to generalize.", + "authors": [ + "habere-et-dispertire" + ] } ] } diff --git a/exercises/practice/raindrops/.approaches/introduction.md b/exercises/practice/raindrops/.approaches/introduction.md index 48b7d6b07..cf1e4777c 100644 --- a/exercises/practice/raindrops/.approaches/introduction.md +++ b/exercises/practice/raindrops/.approaches/introduction.md @@ -54,6 +54,32 @@ class RaindropConverter { For more information, check the [`Map` approach][approach-map]. +## Approach: `Modulus` + +```java +import java.math.BigInteger; +import static java.math.BigInteger.valueOf; + +class RaindropConverter { + + String convert (int n) { + return switch ( valueOf(n).modPow( valueOf(12), valueOf(105) ).intValue() ) { + case 36 -> "Pling"; + case 85 -> "Plang"; + case 91 -> "Plong"; + case 15 -> "PlingPlang"; + case 21 -> "PlingPlong"; + case 70 -> "PlangPlong"; + case 0 -> "PlingPlangPlong"; + default -> String.valueOf(n); // 1 + }; + } + +} +``` + +For more information, check the [Modulus approach][approach-modulus]. + ## Which approach to use? Benchmarking with the [Java Microbenchmark Harness][jmh] is currently outside the scope of this document, @@ -64,4 +90,5 @@ and no other code would need to be added. [remainder-operator]: https://www.geeksforgeeks.org/modulo-or-remainder-operator-in-java/ [approach-if-statements]: https://exercism.org/tracks/java/exercises/raindrops/approaches/if-statements [approach-map]: https://exercism.org/tracks/java/exercises/raindrops/approaches/map +[approach-modulus]: https://exercism.org/tracks/java/exercises/raindrops/approaches/modulus [jmh]: https://github.com/openjdk/jmh diff --git a/exercises/practice/raindrops/.approaches/modulus/content.md b/exercises/practice/raindrops/.approaches/modulus/content.md new file mode 100644 index 000000000..2e2ceb2aa --- /dev/null +++ b/exercises/practice/raindrops/.approaches/modulus/content.md @@ -0,0 +1,31 @@ +# Modulus + +```java +import java.math.BigInteger; +import static java.math.BigInteger.valueOf; + +class RaindropConverter { + + String convert (int n) { + return switch ( valueOf(n).modPow( valueOf(12), valueOf(105) ).intValue() ) { + case 36 -> "Pling"; + case 85 -> "Plang"; + case 91 -> "Plong"; + case 15 -> "PlingPlang"; + case 21 -> "PlingPlong"; + case 70 -> "PlangPlong"; + case 0 -> "PlingPlangPlong"; + default -> String.valueOf(n); // 1 + }; + } + +} +``` + +We can generalize raindrops to any factors if they are [co-prime][co-prime]. +In raindrops, the factors 3, 5 and 7 are co-prime (all sets of prime numbers are co-prime), so we can use [Euler's totient function][euler-totient] to calculate `n¹² mod 105`, giving us unique values for the various sounds. +The math behind how we find the right exponent and modulus is explained in an article on the related problem of [Fizz-Buzz][fizz-buzz]. + +[co-prime]: https://en.wikipedia.org/wiki/Coprime_integers +[euler-totient]: https://en.wikipedia.org/wiki/Euler's_totient_function +[fizz-buzz]: https://philcrissman.net/posts/eulers-fizzbuzz/ diff --git a/exercises/practice/raindrops/.approaches/modulus/snippet.txt b/exercises/practice/raindrops/.approaches/modulus/snippet.txt new file mode 100644 index 000000000..1cefcc71c --- /dev/null +++ b/exercises/practice/raindrops/.approaches/modulus/snippet.txt @@ -0,0 +1,8 @@ +String convert (int n) { + return switch (BigInteger.valueOf(n).modPow(BigInteger.valueOf(12),BigInteger.valueOf(105)).intValue()) { + case 0 -> "PlingPlangPlong"; + case 36 -> "Pling"; + // other cases + default -> String.valueOf(n); // 1 + }; +} From 6a13a7f8085675a0a826c769bfbd030a5cb9b582 Mon Sep 17 00:00:00 2001 From: Aditya Pudasaini Date: Sun, 28 Jun 2026 10:52:26 +0545 Subject: [PATCH 07/16] simple-linked-list: sync missing test cases and add peek/toList (#3146) * simple-linked-list: sync missing test cases and add peek/toList * simple-linked-list: address review feedback * simple-linked-list: fix constructor order, update expectations, remove asArray * simple-linked-list: remove unused imports --- .../src/reference/java/SimpleLinkedList.java | 33 +-- .../simple-linked-list/.meta/tests.toml | 104 ++++++++ .../src/main/java/SimpleLinkedList.java | 15 +- .../src/test/java/SimpleLinkedListTest.java | 249 ++++++++++++++---- 4 files changed, 327 insertions(+), 74 deletions(-) create mode 100644 exercises/practice/simple-linked-list/.meta/tests.toml diff --git a/exercises/practice/simple-linked-list/.meta/src/reference/java/SimpleLinkedList.java b/exercises/practice/simple-linked-list/.meta/src/reference/java/SimpleLinkedList.java index a5e82d1bf..60f85c94b 100644 --- a/exercises/practice/simple-linked-list/.meta/src/reference/java/SimpleLinkedList.java +++ b/exercises/practice/simple-linked-list/.meta/src/reference/java/SimpleLinkedList.java @@ -1,20 +1,16 @@ - -import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; class SimpleLinkedList { - private static class Element { - final T value; Element next; - Element(T value) { this.value = value; } } - private Element head; private int size; @@ -22,8 +18,8 @@ private static class Element { } SimpleLinkedList(T[] values) { - for (int i = values.length - 1; i >= 0; i--) { - push(values[i]); + for (T value : values) { + push(value); } } @@ -48,6 +44,13 @@ T pop() { return value; } + T peek() { + if (Objects.isNull(head)) { + throw new NoSuchElementException(); + } + return head.value; + } + void reverse() { Element current = head; Element next; @@ -61,24 +64,16 @@ void reverse() { head = previous; } - T[] asArray(Class clazz) { - T[] result = newArray(clazz, size); - int index = 0; + List toList() { + List result = new ArrayList<>(); Element current = head; while (Objects.nonNull(current)) { - result[index++] = current.value; + result.add(current.value); current = current.next; } return result; } - private T[] newArray(Class clazz, int size) { - @SuppressWarnings("unchecked") - T[] arr = (T[]) Array.newInstance(clazz, size); - - return arr; - } - int size() { return this.size; } diff --git a/exercises/practice/simple-linked-list/.meta/tests.toml b/exercises/practice/simple-linked-list/.meta/tests.toml new file mode 100644 index 000000000..cbf51c34e --- /dev/null +++ b/exercises/practice/simple-linked-list/.meta/tests.toml @@ -0,0 +1,104 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[962d998c-c203-41e2-8fbd-85a7b98b79b9] +description = "count -> Empty list has length of zero" + +[9760262e-d7e4-4639-9840-87e2e2fbb115] +description = "count -> Singleton list has length of one" + +[d9955c90-637c-441b-b41d-8cfb48e924a8] +description = "count -> Non-empty list has correct length" + +[0c3966db-58f9-4632-b94c-8ea13e54c2c8] +description = "pop -> Pop from empty list is an error" + +[a4f9d2e1-7425-49ef-9ee8-6c0cb3407cf0] +description = "pop -> Can pop from singleton list" + +[6dcbb2c9-d98a-47bc-a010-9c19703d3ea2] +description = "pop -> Can pop from non-empty list" + +[e83aade9-f030-4096-aaf0-f9dc6491e6cf] +description = "pop -> Can pop multiple items" + +[5c46bcf2-c0a9-4654-ae17-f3192436fcf1] +description = "pop -> Pop updates the count" + +[70d747a1-2e84-4ebc-bc3f-dcbee6a05f6b] +description = "push -> Can push to an empty list" +include = false + +[f3197f0a-1fea-45a5-939f-4a5ea60387ec] +description = "push -> Can push to an empty list" +reimplements = "70d747a1-2e84-4ebc-bc3f-dcbee6a05f6b" + +[391e332e-1f91-4033-b1e0-0e0c17812fa7] +description = "push -> Can push to a non-empty list" + +[ed4b0e01-3bbd-4895-af25-152b5914b3da] +description = "push -> Push updates count" + +[41666790-b932-4e5a-b323-e848a83d12d5] +description = "push -> Push and pop" + +[930a4a5c-76f6-47ec-9be3-4e70993173a1] +description = "peek -> Peek on empty list is an error" + +[43255a50-d919-4e81-afce-e4a271eaedbd] +description = "peek -> Can peek on singleton list" + +[48353020-e25d-4621-a854-e35fb1e15fa7] +description = "peek -> Can peek on non-empty list" + +[96fcead9-a713-46c2-8005-3f246c873851] +description = "peek -> Peek does not change the count" + +[7576ed05-7ff7-4b84-8efb-d34d62c110f5] +description = "peek -> Can peek after a pop and push" + +[b97d00b6-2fab-435d-ae74-3233dcc13698] +description = "toList LIFO -> Empty linked list to list is empty" + +[eedeb95f-b5cf-431d-8ad6-5854ba6b251c] +description = "toList LIFO -> To list with multiple values" + +[838678de-eaf3-4c14-b34e-7e35b6d851e8] +description = "toList LIFO -> To list after a pop" + +[03fc83a5-48a8-470b-a2d2-a286c5e8365f] +description = "toList FIFO -> Empty linked list to list is empty" +include = false + +[1282484e-a58c-426a-972e-90746bda61fc] +description = "toList FIFO -> To list with multiple values" +include = false + +[05ca3109-1249-4c0c-a567-a3b2f8352a7c] +description = "toList FIFO -> To list after a pop" +include = false + +[5e6c1a3d-e34b-46d3-be59-3f132a820ed5] +description = "reverse -> Reversed empty list has same values" + +[93c87ed3-862a-474f-820b-ba3fd6b6daf6] +description = "reverse -> Reversed singleton list is same list" + +[92851ebe-9f52-4406-b92e-0718c441a2ab] +description = "reverse -> Reversed non-empty list is reversed" +include = false + +[1210eeda-b23f-4790-930c-7ac6d0c8e723] +description = "reverse -> Reversed non-empty list is reversed" +reimplements = "92851ebe-9f52-4406-b92e-0718c441a2ab" + +[9b53af96-7494-4cfa-9b77-b7366fed5c4c] +description = "reverse -> Double reverse" diff --git a/exercises/practice/simple-linked-list/src/main/java/SimpleLinkedList.java b/exercises/practice/simple-linked-list/src/main/java/SimpleLinkedList.java index 9cff1bdc7..64d388d8f 100644 --- a/exercises/practice/simple-linked-list/src/main/java/SimpleLinkedList.java +++ b/exercises/practice/simple-linked-list/src/main/java/SimpleLinkedList.java @@ -1,28 +1,27 @@ +import java.util.List; + class SimpleLinkedList { SimpleLinkedList() { throw new UnsupportedOperationException("Please implement the SimpleLinkedList() constructor."); } - SimpleLinkedList(T[] values) { throw new UnsupportedOperationException("Please implement the SimpleLinkedList(T[]) constructor."); } - void push(T value) { throw new UnsupportedOperationException("Please implement the SimpleLinkedList.push() method."); } - T pop() { throw new UnsupportedOperationException("Please implement the SimpleLinkedList.pop() method."); } - + T peek() { + throw new UnsupportedOperationException("Please implement the SimpleLinkedList.peek() method."); + } void reverse() { throw new UnsupportedOperationException("Please implement the SimpleLinkedList.reverse() method."); } - - T[] asArray(Class clazz) { - throw new UnsupportedOperationException("Please implement the SimpleLinkedList.asArray() method."); + List toList() { + throw new UnsupportedOperationException("Please implement the SimpleLinkedList.toList() method."); } - int size() { throw new UnsupportedOperationException("Please implement the SimpleLinkedList.size() method."); } diff --git a/exercises/practice/simple-linked-list/src/test/java/SimpleLinkedListTest.java b/exercises/practice/simple-linked-list/src/test/java/SimpleLinkedListTest.java index 109d3b3a7..c885893d3 100644 --- a/exercises/practice/simple-linked-list/src/test/java/SimpleLinkedListTest.java +++ b/exercises/practice/simple-linked-list/src/test/java/SimpleLinkedListTest.java @@ -1,91 +1,246 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; - import java.util.NoSuchElementException; - import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; public class SimpleLinkedListTest { @Test - @DisplayName("A new list is empty") - public void aNewListIsEmpty() { + @DisplayName("count -> Empty list has length of zero") + public void countEmptyListHasLengthOfZero() { SimpleLinkedList list = new SimpleLinkedList<>(); assertThat(list.size()).isEqualTo(0); } @Disabled("Remove to run test") @Test - @DisplayName("Create list from array") - public void canCreateFromArray() { - Character[] values = new Character[]{'1', '2', '3'}; - SimpleLinkedList list = new SimpleLinkedList(values); - assertThat(list.size()).isEqualTo(3); + @DisplayName("count -> Singleton list has length of one") + public void countSingletonListHasLengthOfOne() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1}); + assertThat(list.size()).isEqualTo(1); } @Disabled("Remove to run test") @Test - @DisplayName("Popping an empty list throws NoSuchElementException") - public void popOnEmptyListWillThrow() { - SimpleLinkedList list = new SimpleLinkedList(); + @DisplayName("count -> Non-empty list has correct length") + public void countNonEmptyListHasCorrectLength() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1, 2, 3}); + assertThat(list.size()).isEqualTo(3); + } + @Disabled("Remove to run test") + @Test + @DisplayName("pop -> Pop from empty list is an error") + public void popFromEmptyListIsAnError() { + SimpleLinkedList list = new SimpleLinkedList<>(); assertThatExceptionOfType(NoSuchElementException.class).isThrownBy(list::pop); } @Disabled("Remove to run test") @Test - @DisplayName("Pop returns last added element (LIFO)") - public void popReturnsLastAddedElement() { - SimpleLinkedList list = new SimpleLinkedList(); - list.push(9); - list.push(8); + @DisplayName("pop -> Can pop from singleton list") + public void canPopFromSingletonList() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1}); + assertThat(list.pop()).isEqualTo(1); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("pop -> Can pop from non-empty list") + public void canPopFromNonEmptyList() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1, 2}); + assertThat(list.pop()).isEqualTo(2); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("pop -> Can pop multiple items") + public void canPopMultipleItems() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1, 2}); + assertThat(list.pop()).isEqualTo(2); + assertThat(list.pop()).isEqualTo(1); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("pop -> Pop updates the count") + public void popUpdatesTheCount() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1, 2}); assertThat(list.size()).isEqualTo(2); - assertThat(list.pop()).isEqualTo(8); - assertThat(list.pop()).isEqualTo(9); + assertThat(list.pop()).isEqualTo(2); + assertThat(list.size()).isEqualTo(1); + assertThat(list.pop()).isEqualTo(1); assertThat(list.size()).isEqualTo(0); } @Disabled("Remove to run test") @Test - @DisplayName("Reverse reverses the list order") - public void reverseReversesList() { - SimpleLinkedList list = new SimpleLinkedList(); - list.push("9"); - list.push("8"); - list.push("7"); - list.push("6"); - list.push("5"); + @DisplayName("push -> Can push to an empty list") + public void canPushToAnEmptyList() { + SimpleLinkedList list = new SimpleLinkedList<>(); + list.push(1); + assertThat(list.size()).isEqualTo(1); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("push -> Can push to a non-empty list") + public void canPushToANonEmptyList() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1, 2}); + list.push(3); + assertThat(list.size()).isEqualTo(3); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("push -> Push updates count") + public void pushUpdatesCount() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1, 2}); + list.push(3); + assertThat(list.size()).isEqualTo(3); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("push -> Push and pop") + public void pushAndPop() { + SimpleLinkedList list = new SimpleLinkedList<>(); + list.push(1); + list.push(2); + assertThat(list.pop()).isEqualTo(2); + list.push(3); + assertThat(list.size()).isEqualTo(2); + assertThat(list.pop()).isEqualTo(3); + assertThat(list.pop()).isEqualTo(1); + assertThat(list.size()).isEqualTo(0); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("peek -> Peek on empty list is an error") + public void peekOnEmptyListIsAnError() { + SimpleLinkedList list = new SimpleLinkedList<>(); + assertThatExceptionOfType(NoSuchElementException.class).isThrownBy(list::peek); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("peek -> Can peek on singleton list") + public void canPeekOnSingletonList() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1}); + assertThat(list.peek()).isEqualTo(1); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("peek -> Can peek on non-empty list") + public void canPeekOnNonEmptyList() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1, 2}); + assertThat(list.peek()).isEqualTo(2); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("peek -> Peek does not change the count") + public void peekDoesNotChangeTheCount() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1, 2}); + assertThat(list.peek()).isEqualTo(2); + assertThat(list.size()).isEqualTo(2); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("peek -> Can peek after a pop and push") + public void canPeekAfterAPopAndPush() { + SimpleLinkedList list = new SimpleLinkedList<>(); + list.push(1); + list.push(2); + assertThat(list.peek()).isEqualTo(2); + assertThat(list.pop()).isEqualTo(2); + assertThat(list.peek()).isEqualTo(1); + list.push(3); + assertThat(list.peek()).isEqualTo(3); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("toList LIFO -> Empty linked list to list is empty") + public void toListLifoEmptyLinkedListToListIsEmpty() { + SimpleLinkedList list = new SimpleLinkedList<>(); + assertThat(list.toList()).isEmpty(); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("toList LIFO -> To list with multiple values") + public void toListLifoToListWithMultipleValues() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1, 2, 3}); + assertThat(list.toList()).containsExactly(3, 2, 1); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("toList LIFO -> To list after a pop") + public void toListLifoToListAfterAPop() { + SimpleLinkedList list = new SimpleLinkedList<>(); + list.push(1); + list.push(2); + list.push(3); + assertThat(list.pop()).isEqualTo(3); + list.push(4); + assertThat(list.toList()).containsExactly(4, 2, 1); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("reverse -> Reversed empty list has same values") + public void reversedEmptyListHasSameValues() { + SimpleLinkedList list = new SimpleLinkedList<>(); list.reverse(); - assertThat(list.pop()).isEqualTo("9"); - assertThat(list.pop()).isEqualTo("8"); - assertThat(list.pop()).isEqualTo("7"); - assertThat(list.pop()).isEqualTo("6"); - assertThat(list.pop()).isEqualTo("5"); + assertThat(list.toList()).isEmpty(); } @Disabled("Remove to run test") @Test - @DisplayName("Can return list as an array") - public void canReturnListAsArray() { - SimpleLinkedList list = new SimpleLinkedList(); - list.push('9'); - list.push('8'); - list.push('7'); - list.push('6'); - list.push('5'); - Character[] expected = {'5', '6', '7', '8', '9'}; - assertThat(list.asArray(Character.class)).isEqualTo(expected); + @DisplayName("reverse -> Reversed singleton list is same list") + public void reversedSingletonListIsSameList() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1}); + list.reverse(); + assertThat(list.toList()).containsExactly(1); } @Disabled("Remove to run test") @Test - @DisplayName("Can return empty list as an empty array") - public void canReturnEmptyListAsEmptyArray() { - SimpleLinkedList list = new SimpleLinkedList(); - Object[] expected = {}; - assertThat(list.asArray(Object.class)).isEqualTo(expected); + @DisplayName("reverse -> Reversed non-empty list is reversed") + public void reversedNonEmptyListIsReversed() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1, 2, 3}); + list.reverse(); + assertThat(list.size()).isEqualTo(3); + assertThat(list.pop()).isEqualTo(1); + assertThat(list.pop()).isEqualTo(2); + assertThat(list.pop()).isEqualTo(3); } + @Disabled("Remove to run test") + @Test + @DisplayName("reverse -> Double reverse") + public void doubleReverse() { + SimpleLinkedList list = new SimpleLinkedList<>(new Integer[]{1, 2, 3}); + list.reverse(); + list.reverse(); + assertThat(list.pop()).isEqualTo(3); + assertThat(list.pop()).isEqualTo(2); + assertThat(list.pop()).isEqualTo(1); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("Create list from array") + public void canCreateFromArray() { + Character[] values = new Character[]{'1', '2', '3'}; + SimpleLinkedList list = new SimpleLinkedList(values); + assertThat(list.size()).isEqualTo(3); + } } From 518e92683665cb3fc889565c5781d736eb906870 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2026 19:55:50 +0800 Subject: [PATCH 08/16] Bump actions/checkout from 6 to 7 (#3147) Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7. - [Release notes](https://github.com/actions/checkout/releases) - [Commits](https://github.com/actions/checkout/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-deprecated-exercises.yml | 2 +- .github/workflows/create-configlet-sync-issues.yml | 2 +- .github/workflows/java.yml | 12 ++++++------ .github/workflows/markdown.yml | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/check-deprecated-exercises.yml b/.github/workflows/check-deprecated-exercises.yml index 8defbd0cf..562d96ca0 100644 --- a/.github/workflows/check-deprecated-exercises.yml +++ b/.github/workflows/check-deprecated-exercises.yml @@ -14,7 +14,7 @@ jobs: name: Check for deprecated exercises runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 with: fetch-depth: 0 - name: Test deprecated exercises using test-deprecated-exercises diff --git a/.github/workflows/create-configlet-sync-issues.yml b/.github/workflows/create-configlet-sync-issues.yml index 3a497b2e6..9ffcae10d 100644 --- a/.github/workflows/create-configlet-sync-issues.yml +++ b/.github/workflows/create-configlet-sync-issues.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Fetch configlet run: ./bin/fetch-configlet diff --git a/.github/workflows/java.yml b/.github/workflows/java.yml index 867890a6c..da87903a5 100644 --- a/.github/workflows/java.yml +++ b/.github/workflows/java.yml @@ -16,7 +16,7 @@ jobs: if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - name: Set up JDK 25 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: @@ -31,7 +31,7 @@ jobs: if: github.event_name == 'pull_request' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 with: fetch-depth: 0 - name: Set up JDK 25 @@ -47,7 +47,7 @@ jobs: if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - name: Set up JDK 25 uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 with: @@ -62,7 +62,7 @@ jobs: if: github.event_name == 'pull_request' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 with: fetch-depth: 0 - name: Set up JDK 25 @@ -78,7 +78,7 @@ jobs: if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - name: Test all exercises using java-test-runner run: bin/test-with-test-runner - name: Print summary @@ -105,7 +105,7 @@ jobs: if: github.event_name == 'pull_request' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 with: fetch-depth: 0 - name: Test changed exercises using java-test-runner diff --git a/.github/workflows/markdown.yml b/.github/workflows/markdown.yml index 6bcb84e06..8367dc457 100644 --- a/.github/workflows/markdown.yml +++ b/.github/workflows/markdown.yml @@ -17,6 +17,6 @@ jobs: name: Lint Markdown files runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - name: Lint markdown uses: DavidAnson/markdownlint-cli2-action@ded1f9488f68a970bc66ea5619e13e9b52e601cd From d8e92d5ba47a37afb6f10f1d9e1117b72c1656d5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Jul 2026 19:59:12 +0800 Subject: [PATCH 09/16] Bump actions/setup-java from 5.2.0 to 5.4.0 (#3148) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.2.0 to 5.4.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/be666c2fcd27ec809703dec50e508c2fdc7f6654...1bcf9fb12cf4aa7d266a90ae39939e61372fe520) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 5.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/java.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/java.yml b/.github/workflows/java.yml index da87903a5..2e57aa5b5 100644 --- a/.github/workflows/java.yml +++ b/.github/workflows/java.yml @@ -18,7 +18,7 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - name: Set up JDK 25 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 + uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 with: java-version: 25 distribution: "temurin" @@ -35,7 +35,7 @@ jobs: with: fetch-depth: 0 - name: Set up JDK 25 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 + uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 with: java-version: 25 distribution: "temurin" @@ -49,7 +49,7 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - name: Set up JDK 25 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 + uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 with: java-version: 25 distribution: "temurin" @@ -66,7 +66,7 @@ jobs: with: fetch-depth: 0 - name: Set up JDK 25 - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 + uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 with: java-version: 25 distribution: "temurin" From 9f5b52d76cd8b05937a199fb0f46afaba65a8322 Mon Sep 17 00:00:00 2001 From: YC-TAN <150326068+YC-TAN@users.noreply.github.com> Date: Mon, 20 Jul 2026 23:44:44 +1200 Subject: [PATCH 10/16] Update Map.ofEntries usage (#3151) Looks like each entry should be wrapped in its own `Map.entry(K,V)` before being passed to `Map.ofEntries()` Change: From `Map temperatures = Map.ofEntries(Map.entry("Mon", 30, "Tue", 28, "Wed", 32));` To `Map temperatures2 = Map.ofEntries( Map.entry("Mon", 30), Map.entry("Tue", 28), Map.entry("Wed", 32) );` --- concepts/maps/about.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/concepts/maps/about.md b/concepts/maps/about.md index 86a820cf1..9590aefc0 100644 --- a/concepts/maps/about.md +++ b/concepts/maps/about.md @@ -145,7 +145,11 @@ Another common way to create maps is to use [Map.of][map-of-javadoc] or [Map.ofE Map temperatures = Map.of("Mon", 30, "Tue", 28, "Wed", 32); // or using Map.ofEntries -Map temperatures2 = Map.ofEntries(Map.entry("Mon", 30, "Tue", 28, "Wed", 32)); +Map temperatures2 = Map.ofEntries( + Map.entry("Mon", 30), + Map.entry("Tue", 28), + Map.entry("Wed", 32) +); ``` Unlike `HashMap`, they populate the map upfront and become read-only once created. From 814810f32e39e8b7fa606d3290a7db7a60e116e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Aug 2026 11:04:40 +0530 Subject: [PATCH 11/16] Bump DavidAnson/markdownlint-cli2-action from 23.2.0 to 24.1.0 (#3156) Bumps [DavidAnson/markdownlint-cli2-action](https://github.com/davidanson/markdownlint-cli2-action) from 23.2.0 to 24.1.0. - [Release notes](https://github.com/davidanson/markdownlint-cli2-action/releases) - [Commits](https://github.com/davidanson/markdownlint-cli2-action/compare/ded1f9488f68a970bc66ea5619e13e9b52e601cd...6bf21b07787794f89a243495939cd651942aeabe) --- updated-dependencies: - dependency-name: DavidAnson/markdownlint-cli2-action dependency-version: 24.1.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/markdown.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/markdown.yml b/.github/workflows/markdown.yml index 8367dc457..a719face7 100644 --- a/.github/workflows/markdown.yml +++ b/.github/workflows/markdown.yml @@ -19,4 +19,4 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - name: Lint markdown - uses: DavidAnson/markdownlint-cli2-action@ded1f9488f68a970bc66ea5619e13e9b52e601cd + uses: DavidAnson/markdownlint-cli2-action@6bf21b07787794f89a243495939cd651942aeabe From b17202ebf363390f1e5e58374bda54b03ef631b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Aug 2026 11:05:05 +0530 Subject: [PATCH 12/16] Bump actions/setup-java from 5.4.0 to 5.6.0 (#3155) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.4.0 to 5.6.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/1bcf9fb12cf4aa7d266a90ae39939e61372fe520...03ad4de0992f5dab5e18fcb136590ce7c4a0ac95) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 5.6.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/java.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/java.yml b/.github/workflows/java.yml index 2e57aa5b5..8e0e57895 100644 --- a/.github/workflows/java.yml +++ b/.github/workflows/java.yml @@ -18,7 +18,7 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - name: Set up JDK 25 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 with: java-version: 25 distribution: "temurin" @@ -35,7 +35,7 @@ jobs: with: fetch-depth: 0 - name: Set up JDK 25 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 with: java-version: 25 distribution: "temurin" @@ -49,7 +49,7 @@ jobs: steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 - name: Set up JDK 25 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 with: java-version: 25 distribution: "temurin" @@ -66,7 +66,7 @@ jobs: with: fetch-depth: 0 - name: Set up JDK 25 - uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 + uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 with: java-version: 25 distribution: "temurin" From fc789fb3584be01c6356e1dfd9da160d2296fbc1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Aug 2026 11:05:28 +0530 Subject: [PATCH 13/16] Bump actions/checkout from 7.0.0 to 7.0.1 (#3154) Bumps [actions/checkout](https://github.com/actions/checkout) from 7.0.0 to 7.0.1. - [Release notes](https://github.com/actions/checkout/releases) - [Commits](https://github.com/actions/checkout/compare/v7...v7.0.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-deprecated-exercises.yml | 2 +- .github/workflows/create-configlet-sync-issues.yml | 2 +- .github/workflows/java.yml | 12 ++++++------ .github/workflows/markdown.yml | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/check-deprecated-exercises.yml b/.github/workflows/check-deprecated-exercises.yml index 562d96ca0..47267841d 100644 --- a/.github/workflows/check-deprecated-exercises.yml +++ b/.github/workflows/check-deprecated-exercises.yml @@ -14,7 +14,7 @@ jobs: name: Check for deprecated exercises runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: fetch-depth: 0 - name: Test deprecated exercises using test-deprecated-exercises diff --git a/.github/workflows/create-configlet-sync-issues.yml b/.github/workflows/create-configlet-sync-issues.yml index 9ffcae10d..07a0ed615 100644 --- a/.github/workflows/create-configlet-sync-issues.yml +++ b/.github/workflows/create-configlet-sync-issues.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v7 + uses: actions/checkout@v7.0.1 - name: Fetch configlet run: ./bin/fetch-configlet diff --git a/.github/workflows/java.yml b/.github/workflows/java.yml index 8e0e57895..2fc8509d9 100644 --- a/.github/workflows/java.yml +++ b/.github/workflows/java.yml @@ -16,7 +16,7 @@ jobs: if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Set up JDK 25 uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 with: @@ -31,7 +31,7 @@ jobs: if: github.event_name == 'pull_request' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: fetch-depth: 0 - name: Set up JDK 25 @@ -47,7 +47,7 @@ jobs: if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Set up JDK 25 uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 with: @@ -62,7 +62,7 @@ jobs: if: github.event_name == 'pull_request' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: fetch-depth: 0 - name: Set up JDK 25 @@ -78,7 +78,7 @@ jobs: if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Test all exercises using java-test-runner run: bin/test-with-test-runner - name: Print summary @@ -105,7 +105,7 @@ jobs: if: github.event_name == 'pull_request' runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: fetch-depth: 0 - name: Test changed exercises using java-test-runner diff --git a/.github/workflows/markdown.yml b/.github/workflows/markdown.yml index a719face7..5a9f03fc3 100644 --- a/.github/workflows/markdown.yml +++ b/.github/workflows/markdown.yml @@ -17,6 +17,6 @@ jobs: name: Lint Markdown files runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Lint markdown uses: DavidAnson/markdownlint-cli2-action@6bf21b07787794f89a243495939cd651942aeabe From d8a4083107e08a7bc1a4bcdf7a73103bf7734576 Mon Sep 17 00:00:00 2001 From: Jay Mathpal <147831494+MathJAY10@users.noreply.github.com> Date: Mon, 3 Aug 2026 00:11:04 +0530 Subject: [PATCH 14/16] state-of-tic-tac-toe: add missing test cases for invalid board states (#3153) * state-of-tic-tac-toe: add missing test cases for invalid board states * fix: align test cases with canonical data and clean up comments * chore: sync tests.toml using configlet * fix: enable all tests and add trailing newline * fix: enable all tests and resolve checkstyle newline errors * remove comments * final commit for endlines * Update exercises/practice/state-of-tic-tac-toe/.meta/src/reference/java/StateOfTicTacToe.java Co-authored-by: Jagdish Prajapati * Update exercises/practice/state-of-tic-tac-toe/.meta/src/reference/java/StateOfTicTacToe.java Co-authored-by: Jagdish Prajapati * Update exercises/practice/state-of-tic-tac-toe/src/test/java/StateOfTicTacToeTest.java Co-authored-by: Jagdish Prajapati * rectify code --------- Co-authored-by: Jagdish Prajapati --- .../src/reference/java/StateOfTicTacToe.java | 13 +++++++++- .../state-of-tic-tac-toe/.meta/tests.toml | 6 +++++ .../src/test/java/StateOfTicTacToeTest.java | 24 +++++++++++++++++-- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/exercises/practice/state-of-tic-tac-toe/.meta/src/reference/java/StateOfTicTacToe.java b/exercises/practice/state-of-tic-tac-toe/.meta/src/reference/java/StateOfTicTacToe.java index 1fcee86d2..d3ed3ab82 100644 --- a/exercises/practice/state-of-tic-tac-toe/.meta/src/reference/java/StateOfTicTacToe.java +++ b/exercises/practice/state-of-tic-tac-toe/.meta/src/reference/java/StateOfTicTacToe.java @@ -51,6 +51,18 @@ public GameState determineState(String[] board) { } } + if (xWin > 0 && xCount != oCount + 1) { + throw new IllegalArgumentException( + "Impossible board: game should have ended after the game was won" + ); + } + + if (oWin > 0 && xCount != oCount) { + throw new IllegalArgumentException( + "Impossible board: game should have ended after the game was won" + ); + } + if (xWin > 0 || oWin > 0) { return GameState.WIN; } @@ -82,7 +94,6 @@ private List getDiagonals(String[] board) { String[] diags = new String[2]; for (int i = 0; i < 3; i++) { - if (diags[0] == null) { diags[0] = String.valueOf(board[i].charAt(i)); } else { diff --git a/exercises/practice/state-of-tic-tac-toe/.meta/tests.toml b/exercises/practice/state-of-tic-tac-toe/.meta/tests.toml index 8fc25e211..5f574b2a1 100644 --- a/exercises/practice/state-of-tic-tac-toe/.meta/tests.toml +++ b/exercises/practice/state-of-tic-tac-toe/.meta/tests.toml @@ -99,3 +99,9 @@ reimplements = "b1dc8b13-46c4-47db-a96d-aa90eedc4e8d" [4801cda2-f5b7-4c36-8317-3cdd167ac22c] description = "Invalid boards -> Invalid board: players kept playing after a win" + +[5a84757a-fc86-4328-aec9-a5759e6ed35d] +description = "Invalid boards -> Invalid board: O kept playing after X wins" + +[cf25543d-583a-4656-b9ab-f82dc00a4a02] +description = "Invalid boards -> Invalid board: X kept playing after O wins" diff --git a/exercises/practice/state-of-tic-tac-toe/src/test/java/StateOfTicTacToeTest.java b/exercises/practice/state-of-tic-tac-toe/src/test/java/StateOfTicTacToeTest.java index d264db005..5ae93502b 100644 --- a/exercises/practice/state-of-tic-tac-toe/src/test/java/StateOfTicTacToeTest.java +++ b/exercises/practice/state-of-tic-tac-toe/src/test/java/StateOfTicTacToeTest.java @@ -95,7 +95,7 @@ public void testFinishedGameWhereXWonViaMiddleRowVictory() { @Disabled("Remove to run test") @Test - @DisplayName("Finished game where X won via middle row victory") + @DisplayName("Finished game where X won via bottom row victory") public void testFinishedGameWhereXWonViaBottomRowVictory() { assertThat( @@ -207,7 +207,7 @@ public void testDraw() { @Test @DisplayName("Another draw") public void testAnotherDraw() { - + assertThat( stateOfTicTacToe.determineState(new String[]{"XXO", "OXX", "XOO"}) ).isEqualTo(GameState.DRAW); @@ -282,4 +282,24 @@ public void testInvalidBoardPlayersKeptPlayingAfterAWin() { .isThrownBy(() -> stateOfTicTacToe.determineState(new String[]{"XXX", "OOO", "XOX"})) .withMessage("Impossible board: game should have ended after the game was won"); } + + @Disabled("Remove to run test") + @Test + @DisplayName("Invalid board: O kept playing after X wins") + public void testInvalidBoardOKeptPlayingAfterXWins() { + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> stateOfTicTacToe.determineState(new String[]{"OO ", "XXX", " O "})) + .withMessage("Impossible board: game should have ended after the game was won"); + } + + @Disabled("Remove to run test") + @Test + @DisplayName("Invalid board: X kept playing after O wins") + public void testInvalidBoardXKeptPlayingAfterOWins() { + + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> stateOfTicTacToe.determineState(new String[]{"XX ", "OOO", " XX"})) + .withMessage("Impossible board: game should have ended after the game was won"); + } } From 388d96e15f0880c42ceed9a05ea32e07acbb81f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Pe=C3=B1a=20F=2E?= Date: Fri, 21 Aug 2026 06:16:47 -0500 Subject: [PATCH 15/16] test(bob): add missing shouting question mark test case (#3160) --- exercises/practice/bob/.meta/tests.toml | 3 +++ exercises/practice/bob/src/test/java/BobTest.java | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/exercises/practice/bob/.meta/tests.toml b/exercises/practice/bob/.meta/tests.toml index 5299e2895..8995c9235 100644 --- a/exercises/practice/bob/.meta/tests.toml +++ b/exercises/practice/bob/.meta/tests.toml @@ -18,6 +18,9 @@ description = "shouting" [d6c98afd-df35-4806-b55e-2c457c3ab748] description = "shouting gibberish" +[3c954328-86fb-4c71-8961-e18d6a5e2517] +description = "shouting a statement containing a question mark" + [8a2e771d-d6f1-4e3f-b6c6-b41495556e37] description = "asking a question" diff --git a/exercises/practice/bob/src/test/java/BobTest.java b/exercises/practice/bob/src/test/java/BobTest.java index 756fb93f8..3806670ab 100644 --- a/exercises/practice/bob/src/test/java/BobTest.java +++ b/exercises/practice/bob/src/test/java/BobTest.java @@ -37,6 +37,14 @@ public void shoutingGibberish() { .isEqualTo("Whoa, chill out!"); } + @Disabled("Remove to run test") + @Test + @DisplayName("shouting a statement containing a question mark") + public void shoutingAStatementContainingQuestionMark() { + assertThat(bob.hey("DO LIONS EAT PEOPLE? AHHHHH.")) + .isEqualTo("Whoa, chill out!"); + } + @Disabled("Remove to run test") @Test @DisplayName("asking a question") From 4a8369e6b69f9b6f0b64581ea5fcaaa7447f2d62 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 22 Aug 2026 02:29:17 +0530 Subject: [PATCH 16/16] =?UTF-8?q?=F0=9F=A4=96=20Auto-sync=20docs,=20metada?= =?UTF-8?q?ta,=20and=20filepaths=20(#3157)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Jagdish Prajapati --- exercises/practice/nucleotide-count/.meta/config.json | 2 +- exercises/practice/perfect-numbers/.meta/config.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/practice/nucleotide-count/.meta/config.json b/exercises/practice/nucleotide-count/.meta/config.json index f58c53240..b98277ed6 100644 --- a/exercises/practice/nucleotide-count/.meta/config.json +++ b/exercises/practice/nucleotide-count/.meta/config.json @@ -44,6 +44,6 @@ ] }, "blurb": "Given a DNA string, compute how many times each nucleotide occurs in the string.", - "source": "The Calculating DNA Nucleotides_problem at Rosalind", + "source": "The Counting DNA Nucleotides problem at Rosalind", "source_url": "https://rosalind.info/problems/dna/" } diff --git a/exercises/practice/perfect-numbers/.meta/config.json b/exercises/practice/perfect-numbers/.meta/config.json index 073f6f424..e65d254da 100644 --- a/exercises/practice/perfect-numbers/.meta/config.json +++ b/exercises/practice/perfect-numbers/.meta/config.json @@ -38,5 +38,5 @@ }, "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": "https://www.oreilly.com/library/view/functional-thinking/9781449365509/" + "source_url": "https://nealford.com/books/functionalthinking.html" }