From a8dcb142c72282e7ee8e7799266ad429785bdd1a Mon Sep 17 00:00:00 2001 From: resu-xuniL Date: Sun, 19 Jul 2026 11:38:22 +0200 Subject: [PATCH] Add `word-search` exercise --- config.json | 8 + .../word-search/.docs/instructions.md | 24 + .../practice/word-search/.meta/config.json | 17 + .../practice/word-search/.meta/example.php | 79 ++ .../practice/word-search/.meta/tests.toml | 82 ++ exercises/practice/word-search/WordSearch.php | 38 + .../practice/word-search/WordSearchTest.php | 769 ++++++++++++++++++ 7 files changed, 1017 insertions(+) create mode 100644 exercises/practice/word-search/.docs/instructions.md create mode 100644 exercises/practice/word-search/.meta/config.json create mode 100644 exercises/practice/word-search/.meta/example.php create mode 100644 exercises/practice/word-search/.meta/tests.toml create mode 100644 exercises/practice/word-search/WordSearch.php create mode 100644 exercises/practice/word-search/WordSearchTest.php diff --git a/config.json b/config.json index 670d309ad..a9ee4e004 100644 --- a/config.json +++ b/config.json @@ -1138,6 +1138,14 @@ "strings" ] }, + { + "slug": "word-search", + "name": "Word Search", + "uuid": "6b215857-f382-4926-b5f8-3e61db9283d6", + "practices": [], + "prerequisites": [], + "difficulty": 4 + }, { "slug": "alphametics", "name": "Alphametics", diff --git a/exercises/practice/word-search/.docs/instructions.md b/exercises/practice/word-search/.docs/instructions.md new file mode 100644 index 000000000..e2d08aa9e --- /dev/null +++ b/exercises/practice/word-search/.docs/instructions.md @@ -0,0 +1,24 @@ +# Instructions + +In word search puzzles you get a square of letters and have to find specific words in them. + +For example: + +```text +jefblpepre +camdcimgtc +oivokprjsm +pbwasqroua +rixilelhrs +wolcqlirpc +screeaumgr +alxhpburyi +jalaycalmp +clojurermt +``` + +There are several programming languages hidden in the above square. + +Words can be hidden in all kinds of directions: left-to-right, right-to-left, vertical and diagonal. + +Given a puzzle and a list of words return the location of the first and last letter of each word. diff --git a/exercises/practice/word-search/.meta/config.json b/exercises/practice/word-search/.meta/config.json new file mode 100644 index 000000000..c67cfaf96 --- /dev/null +++ b/exercises/practice/word-search/.meta/config.json @@ -0,0 +1,17 @@ +{ + "authors": [ + "resu-xuniL" + ], + "files": { + "solution": [ + "WordSearch.php" + ], + "test": [ + "WordSearchTest.php" + ], + "example": [ + ".meta/example.php" + ] + }, + "blurb": "Create a program to solve a word search puzzle." +} diff --git a/exercises/practice/word-search/.meta/example.php b/exercises/practice/word-search/.meta/example.php new file mode 100644 index 000000000..c21b1679b --- /dev/null +++ b/exercises/practice/word-search/.meta/example.php @@ -0,0 +1,79 @@ +width = strlen($this->grid[0]); + $this->height = count($this->grid); + } + + public function search(array $words): array + { + foreach ($words as $word) { + for ($X = 0; $X < $this->width; $X++) { + for ($Y = 0; $Y < $this->height; $Y++) { + foreach (self::NEIGHBORHOOD as [$checkX, $checkY]) { + $search = $this->find($word, $X, $Y, $checkX, $checkY); + + if (isset($search)) { + $this->found[$word] = $search; + continue 4; + } else { + $this->found[$word] = null; + } + } + } + } + } + + return $this->found; + } + + private function find(string $word, int $X, int $Y, int $nextX, int $nextY): ?array + { + $currentX = $X; + $currentY = $Y; + + for ($i = 0; $i < strlen($word); $i++) { + if ($this->findNextLetter($currentX, $currentY) !== $word[$i]) { + return null; + } + + $currentX += $nextX; + $currentY += $nextY; + } + + return [ + "start" => [ + "column" => $X + 1, + "row" => $Y + 1 + ], + "end" => [ + "column" => $currentX + 1 - $nextX, + "row" => $currentY + 1 - $nextY + ] + ]; + } + + private function findNextLetter(int $X, int $Y): ?string + { + if ($X < 0 || $Y < 0 || $X >= $this->width || $Y >= $this->height) { + return null; + } + + return $this->grid[$Y][$X]; + } +} diff --git a/exercises/practice/word-search/.meta/tests.toml b/exercises/practice/word-search/.meta/tests.toml new file mode 100644 index 000000000..3f98113d7 --- /dev/null +++ b/exercises/practice/word-search/.meta/tests.toml @@ -0,0 +1,82 @@ +# 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. + +[b4057815-0d01-41f0-9119-6a91f54b2a0a] +description = "Should accept an initial game grid and a target search word" + +[6b22bcc5-6cbf-4674-931b-d2edbff73132] +description = "Should locate one word written left to right" + +[ff462410-434b-442d-9bc3-3360c75f34a8] +description = "Should locate the same word written left to right in a different position" + +[a02febae-6347-443e-b99c-ab0afb0b8fca] +description = "Should locate a different left to right word" + +[e42e9987-6304-4e13-8232-fa07d5280130] +description = "Should locate that different left to right word in a different position" + +[9bff3cee-49b9-4775-bdfb-d55b43a70b2f] +description = "Should locate a left to right word in two line grid" + +[851a35fb-f499-4ec1-9581-395a87903a22] +description = "Should locate a left to right word in three line grid" + +[2f3dcf84-ba7d-4b75-8b8d-a3672b32c035] +description = "Should locate a left to right word in ten line grid" + +[006d4856-f365-4e84-a18c-7d129ce9eefb] +description = "Should locate that left to right word in a different position in a ten line grid" + +[eff7ac9f-ff11-443e-9747-40850c12ab60] +description = "Should locate a different left to right word in a ten line grid" + +[dea39f86-8c67-4164-8884-13bfc48bd13b] +description = "Should locate multiple words" + +[29e6a6a5-f80c-48a6-8e68-05bbbe187a09] +description = "Should locate a single word written right to left" + +[3cf34428-b43f-48b6-b332-ea0b8836011d] +description = "Should locate multiple words written in different horizontal directions" + +[2c8cd344-a02f-464b-93b6-8bf1bd890003] +description = "Should locate words written top to bottom" + +[9ee1e43d-e59d-4c32-9a5f-6a22d4a1550f] +description = "Should locate words written bottom to top" + +[6a21a676-f59e-4238-8e88-9f81015afae9] +description = "Should locate words written top left to bottom right" + +[c9125189-1861-4b0d-a14e-ba5dab29ca7c] +description = "Should locate words written bottom right to top left" + +[b19e2149-7fc5-41ec-a8a9-9bc6c6c38c40] +description = "Should locate words written bottom left to top right" + +[69e1d994-a6d7-4e24-9b5a-db76751c2ef8] +description = "Should locate words written top right to bottom left" + +[695531db-69eb-463f-8bad-8de3bf5ef198] +description = "Should fail to locate a word that is not in the puzzle" + +[fda5b937-6774-4a52-8f89-f64ed833b175] +description = "Should fail to locate words that are not on horizontal, vertical, or diagonal lines" + +[5b6198eb-2847-4e2f-8efe-65045df16bd3] +description = "Should not concatenate different lines to find a horizontal word" + +[eba44139-a34f-4a92-98e1-bd5f259e5769] +description = "Should not wrap around horizontally to find a word" + +[cd1f0fa8-76af-4167-b105-935f78364dac] +description = "Should not wrap around vertically to find a word" diff --git a/exercises/practice/word-search/WordSearch.php b/exercises/practice/word-search/WordSearch.php new file mode 100644 index 000000000..725efbce8 --- /dev/null +++ b/exercises/practice/word-search/WordSearch.php @@ -0,0 +1,38 @@ +. + * + * To disable strict typing, comment out the directive below. + */ + +declare(strict_types=1); + +class WordSearch +{ + public function __construct(array $grid) + { + throw new \BadMethodCallException(sprintf('Implement the %s method', __FUNCTION__)); + } + + public function search(array $words): array + { + throw new \BadMethodCallException(sprintf('Implement the %s method', __FUNCTION__)); + } +} diff --git a/exercises/practice/word-search/WordSearchTest.php b/exercises/practice/word-search/WordSearchTest.php new file mode 100644 index 000000000..8e5a1641a --- /dev/null +++ b/exercises/practice/word-search/WordSearchTest.php @@ -0,0 +1,769 @@ + null]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: 6b22bcc5-6cbf-4674-931b-d2edbff73132 + */ + #[TestDox('Should locate one word written left to right')] + public function testShouldLocateOneWordWrittenLeftToRight(): void + { + $wordsToSearchFor = ["clojure"]; + $grid = ["clojurermt"]; + $expected = [ + "clojure" => [ + "start" => ["column" => 1, "row" => 1], + "end" => ["column" => 7, "row" => 1] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: ff462410-434b-442d-9bc3-3360c75f34a8 + */ + #[TestDox('Should locate the same word written left to right in a different position')] + public function testShouldLocateTheSameWordWrittenLeftToRightInADifferentPosition(): void + { + $wordsToSearchFor = ["clojure"]; + $grid = ["mtclojurer"]; + $expected = [ + "clojure" => [ + "start" => ["column" => 3, "row" => 1], + "end" => ["column" => 9, "row" => 1] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: a02febae-6347-443e-b99c-ab0afb0b8fca + */ + #[TestDox('Should locate a different left to right word')] + public function testShouldLocateADifferentLeftToRightWord(): void + { + $wordsToSearchFor = ["coffee"]; + $grid = ["coffeelplx"]; + $expected = [ + "coffee" => [ + "start" => ["column" => 1, "row" => 1], + "end" => ["column" => 6, "row" => 1] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: e42e9987-6304-4e13-8232-fa07d5280130 + */ + #[TestDox('Should locate that different left to right word in a different position')] + public function testShouldLocateThatDifferentLeftToRightWordInADifferentPosition(): void + { + $wordsToSearchFor = ["coffee"]; + $grid = ["xcoffeezlp"]; + $expected = [ + "coffee" => [ + "start" => ["column" => 2, "row" => 1], + "end" => ["column" => 7, "row" => 1] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: 9bff3cee-49b9-4775-bdfb-d55b43a70b2f + */ + #[TestDox('Should locate a left to right word in two line grid')] + public function testShouldLocateALeftToRightWordInTwoLineGrid(): void + { + $wordsToSearchFor = ["clojure"]; + $grid = ["jefblpepre", "tclojurerm"]; + $expected = [ + "clojure" => [ + "start" => ["column" => 2, "row" => 2], + "end" => ["column" => 8, "row" => 2] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: 851a35fb-f499-4ec1-9581-395a87903a22 + */ + #[TestDox('Should locate a left to right word in three line grid')] + public function testShouldLocateALeftToRightWordInThreeLineGrid(): void + { + $wordsToSearchFor = ["clojure"]; + $grid = ["camdcimgtc", "jefblpepre", "clojurermt"]; + $expected = [ + "clojure" => [ + "start" => ["column" => 1, "row" => 3], + "end" => ["column" => 7, "row" => 3] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: 2f3dcf84-ba7d-4b75-8b8d-a3672b32c035 + */ + #[TestDox('Should locate a left to right word in ten line grid')] + public function testShouldLocateALeftToRightWordInTenLineGrid(): void + { + $wordsToSearchFor = ["clojure"]; + $grid = [ + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ]; + $expected = [ + "clojure" => [ + "start" => ["column" => 1, "row" => 10], + "end" => ["column" => 7, "row" => 10] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: 006d4856-f365-4e84-a18c-7d129ce9eefb + */ + #[TestDox('Should locate that left to right word in a different position in a ten line grid')] + public function testShouldLocateThatLeftToRightWordInADifferentPositionInATenLineGrid(): void + { + $wordsToSearchFor = ["clojure"]; + $grid = [ + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "clojurermt", + "jalaycalmp" + ]; + $expected = [ + "clojure" => [ + "start" => ["column" => 1, "row" => 9], + "end" => ["column" => 7, "row" => 9] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: eff7ac9f-ff11-443e-9747-40850c12ab60 + */ + #[TestDox('Should locate a different left to right word in a ten line grid')] + public function testShouldLocateADifferentLeftToRightWordInATenLineGrid(): void + { + $wordsToSearchFor = ["fortran"]; + $grid = [ + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "fortranftw", + "alxhpburyi", + "clojurermt", + "jalaycalmp" + ]; + $expected = [ + "fortran" => [ + "start" => ["column" => 1, "row" => 7], + "end" => ["column" => 7, "row" => 7] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: dea39f86-8c67-4164-8884-13bfc48bd13b + */ + #[TestDox('Should locate multiple words')] + public function testShouldLocateMultipleWords(): void + { + $wordsToSearchFor = ["fortran", "clojure"]; + $grid = [ + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "fortranftw", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ]; + $expected = [ + "clojure" => [ + "start" => ["column" => 1, "row" => 10], + "end" => ["column" => 7, "row" => 10] + ], + "fortran" => [ + "start" => ["column" => 1, "row" => 7], + "end" => ["column" => 7, "row" => 7] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: 29e6a6a5-f80c-48a6-8e68-05bbbe187a09 + */ + #[TestDox('Should locate a single word written right to left')] + public function testShouldLocateASingleWordWrittenRightToLeft(): void + { + $wordsToSearchFor = ["elixir"]; + $grid = ["rixilelhrs"]; + $expected = [ + "elixir" => [ + "start" => ["column" => 6, "row" => 1], + "end" => ["column" => 1, "row" => 1] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: 3cf34428-b43f-48b6-b332-ea0b8836011d + */ + #[TestDox('Should locate multiple words written in different horizontal directions')] + public function testShouldLocateMultipleWordsWrittenInDifferentHorizontalDirections(): void + { + $wordsToSearchFor = ["elixir", "clojure"]; + $grid = [ + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ]; + $expected = [ + "clojure" => [ + "start" => ["column" => 1, "row" => 10], + "end" => ["column" => 7, "row" => 10] + ], + "elixir" => [ + "start" => ["column" => 6, "row" => 5], + "end" => ["column" => 1, "row" => 5] + ], + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: 2c8cd344-a02f-464b-93b6-8bf1bd890003 + */ + #[TestDox('Should locate words written top to bottom')] + public function testShouldLocateWordsWrittenTopToBottom(): void + { + $wordsToSearchFor = ["clojure", "elixir", "ecmascript"]; + $grid = [ + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ]; + $expected = [ + "clojure" => [ + "start" => ["column" => 1, "row" => 10], + "end" => ["column" => 7, "row" => 10] + ], + "elixir" => [ + "start" => ["column" => 6, "row" => 5], + "end" => ["column" => 1, "row" => 5] + ], + "ecmascript" => [ + "start" => ["column" => 10, "row" => 1], + "end" => ["column" => 10, "row" => 10] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: 9ee1e43d-e59d-4c32-9a5f-6a22d4a1550f + */ + #[TestDox('Should locate words written bottom to top')] + public function testShouldLocateWordsWrittenBottomToTop(): void + { + $wordsToSearchFor = ["clojure", "elixir", "ecmascript", "rust"]; + $grid = [ + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ]; + $expected = [ + "clojure" => [ + "start" => ["column" => 1, "row" => 10], + "end" => ["column" => 7, "row" => 10] + ], + "elixir" => [ + "start" => ["column" => 6, "row" => 5], + "end" => ["column" => 1, "row" => 5] + ], + "ecmascript" => [ + "start" => ["column" => 10, "row" => 1], + "end" => ["column" => 10, "row" => 10] + ], + "rust" => [ + "start" => ["column" => 9, "row" => 5], + "end" => ["column" => 9, "row" => 2] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: 6a21a676-f59e-4238-8e88-9f81015afae9 + */ + #[TestDox('Should locate words written top left to bottom right')] + public function testShouldLocateWordsWrittenTopLeftToBottomRight(): void + { + $wordsToSearchFor = ["clojure", "elixir", "ecmascript", "rust", "java"]; + $grid = [ + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ]; + $expected = [ + "clojure" => [ + "start" => ["column" => 1, "row" => 10], + "end" => ["column" => 7, "row" => 10] + ], + "elixir" => [ + "start" => ["column" => 6, "row" => 5], + "end" => ["column" => 1, "row" => 5] + ], + "ecmascript" => [ + "start" => ["column" => 10, "row" => 1], + "end" => ["column" => 10, "row" => 10] + ], + "rust" => [ + "start" => ["column" => 9, "row" => 5], + "end" => ["column" => 9, "row" => 2] + ], + "java" => [ + "start" => ["column" => 1, "row" => 1], + "end" => ["column" => 4, "row" => 4] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: c9125189-1861-4b0d-a14e-ba5dab29ca7c + */ + #[TestDox('Should locate words written bottom right to top left')] + public function testShouldLocateWordsWrittenBottomRightToTopLeft(): void + { + $wordsToSearchFor = [ + "clojure", + "elixir", + "ecmascript", + "rust", + "java", + "lua" + ]; + $grid = [ + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ]; + $expected = [ + "clojure" => [ + "start" => ["column" => 1, "row" => 10], + "end" => ["column" => 7, "row" => 10] + ], + "elixir" => [ + "start" => ["column" => 6, "row" => 5], + "end" => ["column" => 1, "row" => 5] + ], + "ecmascript" => [ + "start" => ["column" => 10, "row" => 1], + "end" => ["column" => 10, "row" => 10] + ], + "rust" => [ + "start" => ["column" => 9, "row" => 5], + "end" => ["column" => 9, "row" => 2] + ], + "java" => [ + "start" => ["column" => 1, "row" => 1], + "end" => ["column" => 4, "row" => 4] + ], + "lua" => [ + "start" => ["column" => 8, "row" => 9], + "end" => ["column" => 6, "row" => 7] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: b19e2149-7fc5-41ec-a8a9-9bc6c6c38c40 + */ + #[TestDox('Should locate words written bottom left to top right')] + public function testShouldLocateWordsWrittenBottomLeftToTopRight(): void + { + $wordsToSearchFor = [ + "clojure", + "elixir", + "ecmascript", + "rust", + "java", + "lua", + "lisp" + ]; + $grid = [ + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ]; + $expected = [ + "clojure" => [ + "start" => ["column" => 1, "row" => 10], + "end" => ["column" => 7, "row" => 10] + ], + "elixir" => [ + "start" => ["column" => 6, "row" => 5], + "end" => ["column" => 1, "row" => 5] + ], + "ecmascript" => [ + "start" => ["column" => 10, "row" => 1], + "end" => ["column" => 10, "row" => 10] + ], + "rust" => [ + "start" => ["column" => 9, "row" => 5], + "end" => ["column" => 9, "row" => 2] + ], + "java" => [ + "start" => ["column" => 1, "row" => 1], + "end" => ["column" => 4, "row" => 4] + ], + "lua" => [ + "start" => ["column" => 8, "row" => 9], + "end" => ["column" => 6, "row" => 7] + ], + "lisp" => [ + "start" => ["column" => 3, "row" => 6], + "end" => ["column" => 6, "row" => 3] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: 69e1d994-a6d7-4e24-9b5a-db76751c2ef8 + */ + #[TestDox('Should locate words written top right to bottom left')] + public function testShouldLocateWordsWrittenTopRightToBottomLeft(): void + { + $wordsToSearchFor = [ + "clojure", + "elixir", + "ecmascript", + "rust", + "java", + "lua", + "lisp", + "ruby" + ]; + $grid = [ + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ]; + $expected = [ + "clojure" => [ + "start" => ["column" => 1, "row" => 10], + "end" => ["column" => 7, "row" => 10] + ], + "elixir" => [ + "start" => ["column" => 6, "row" => 5], + "end" => ["column" => 1, "row" => 5] + ], + "ecmascript" => [ + "start" => ["column" => 10, "row" => 1], + "end" => ["column" => 10, "row" => 10] + ], + "rust" => [ + "start" => ["column" => 9, "row" => 5], + "end" => ["column" => 9, "row" => 2] + ], + "java" => [ + "start" => ["column" => 1, "row" => 1], + "end" => ["column" => 4, "row" => 4] + ], + "lua" => [ + "start" => ["column" => 8, "row" => 9], + "end" => ["column" => 6, "row" => 7] + ], + "lisp" => [ + "start" => ["column" => 3, "row" => 6], + "end" => ["column" => 6, "row" => 3] + ], + "ruby" => [ + "start" => ["column" => 8, "row" => 6], + "end" => ["column" => 5, "row" => 9] + ] + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: 695531db-69eb-463f-8bad-8de3bf5ef198 + */ + #[TestDox('Should fail to locate a word that is not in the puzzle')] + public function testShouldFail(): void + { + $wordsToSearchFor = [ + "clojure", + "elixir", + "ecmascript", + "rust", + "java", + "lua", + "lisp", + "ruby", + "haskell" + ]; + $grid = [ + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ]; + $expected = [ + "clojure" => [ + "start" => ["column" => 1, "row" => 10], + "end" => ["column" => 7, "row" => 10] + ], + "elixir" => [ + "start" => ["column" => 6, "row" => 5], + "end" => ["column" => 1, "row" => 5] + ], + "ecmascript" => [ + "start" => ["column" => 10, "row" => 1], + "end" => ["column" => 10, "row" => 10] + ], + "rust" => [ + "start" => ["column" => 9, "row" => 5], + "end" => ["column" => 9, "row" => 2] + ], + "java" => [ + "start" => ["column" => 1, "row" => 1], + "end" => ["column" => 4, "row" => 4] + ], + "lua" => [ + "start" => ["column" => 8, "row" => 9], + "end" => ["column" => 6, "row" => 7] + ], + "lisp" => [ + "start" => ["column" => 3, "row" => 6], + "end" => ["column" => 6, "row" => 3] + ], + "ruby" => [ + "start" => ["column" => 8, "row" => 6], + "end" => ["column" => 5, "row" => 9] + ], + "haskell" => null + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: fda5b937-6774-4a52-8f89-f64ed833b175 + */ + #[TestDox('Should fail to locate words that are not on horizontal, vertical, or diagonal lines')] + public function testShouldFailToLocateWordsThatAreNotOnHorizontalVerticalOrDiagonalLines(): void + { + $wordsToSearchFor = ["aef", "ced", "abf", "cbd"]; + $grid = ["abc", "def"]; + $expected = [ + "aef" => null, + "ced" => null, + "abf" => null, + "cbd" => null + ]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: 5b6198eb-2847-4e2f-8efe-65045df16bd3 + */ + #[TestDox('Should not concatenate different lines to find a horizontal word')] + public function testShouldNotConcatenateDifferentLinesToFindAHorizontalWord(): void + { + $wordsToSearchFor = ["elixir"]; + $grid = ["abceli", "xirdfg"]; + $expected = ["elixir" => null]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: eba44139-a34f-4a92-98e1-bd5f259e5769 + */ + #[TestDox('Should not wrap around horizontally to find a word')] + public function testShouldNotWrapAroundHorizontallyToFindAWord(): void + { + $wordsToSearchFor = ["lisp"]; + $grid = ["silabcdefp"]; + $expected = ["lisp" => null]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } + + /** + * uuid: cd1f0fa8-76af-4167-b105-935f78364dac + */ + #[TestDox('Should not wrap around vertically to find a word')] + public function testShouldNotWrapAroundVerticallyToFindAWord(): void + { + $wordsToSearchFor = ["rust"]; + $grid = [ + "s", + "u", + "r", + "a", + "b", + "c", + "t" + ]; + $expected = ["rust" => null]; + $wordSearch = new WordSearch($grid); + + $this->assertEquals($expected, $wordSearch->search($wordsToSearchFor)); + } +}