diff --git a/config.json b/config.json index 04df9f37..1553bde8 100644 --- a/config.json +++ b/config.json @@ -960,6 +960,14 @@ "prerequisites": [], "difficulty": 6 }, + { + "slug": "word-search", + "name": "Word Search", + "uuid": "246b4736-2a13-4298-a989-fb7ebc394c1b", + "practices": [], + "prerequisites": [], + "difficulty": 6 + }, { "slug": "book-store", "name": "Book Store", diff --git a/exercises/practice/word-search/.docs/instructions.md b/exercises/practice/word-search/.docs/instructions.md new file mode 100644 index 00000000..e2d08aa9 --- /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/WordSearch.example.ps1 b/exercises/practice/word-search/.meta/WordSearch.example.ps1 new file mode 100644 index 00000000..9c80f4f3 --- /dev/null +++ b/exercises/practice/word-search/.meta/WordSearch.example.ps1 @@ -0,0 +1,154 @@ +<# +.SYNOPSIS + Implement a program to find word in a search puzzle. + +.DESCRIPTION + Given a grid of letters, find the targey word that hides inside it. + Words can be hidden in all kinds of directions: left-to-right, right-to-left, vertical and diagonal. + + Implement a class that will take in an array of string(s) represent the grid. + Inside the class, implement a Search method that will take in a string as the target word. + If found, return the result in an object that contain the location of the first and last letter. + If the word doesn't exist in the grid, return $null. + + The object return must have these properties and their value in this format: + - Start: @(row value, column value) + - End : @(row value, column value) + Value of row and column follow the standard of 0-based index. + +.EXAMPLE + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ) + $puzzle = [WordSearch]::new($grid) + $puzzle.Search("clojure") + + Returns: [PsCustomObject]@{ + Start = @(9, 0) + End = @(9, 6) + } +#> +Class WordSearch { + [string []] hidden $_grid + [hashtable] hidden $_indicesTable + + WordSearch([string[]]$grid) { + $this._grid = $grid + $this._indicesTable = $this.GetIndices($this._grid) + } + + [hashtable] hidden GetIndices([string []]$grid) { + <# + .DESCRIPTION + Helper function for constructor, build a hashmap of all the letters in the grid and their indices. + #> + $table = @{} + for ($row = 0; $row -lt $grid.Count; $row++) { + for ($col = 0; $col -lt $grid[0].Length; $col++) { + $letter = $grid[$row][$col] + $table[$letter] += ,@($row, $col) + } + } + return $table + } + + [object]Search ([string]$word) { + <# + .DESCRIPTION + Main function of the class. + #> + if (-not $this.IsInGrid($word)) {return $null} + + $startIndices = $this._indicesTable[$word[0]] + $endIndices = $this._indicesTable[$word[-1]] + + foreach ($start in $startIndices) { + foreach ($end in $endIndices) { + $match = $this.TestMatching($start, $end, $word.Length -1) + if ($match.IsMatch) { + $wordToCompare = $this.ExtractWord($start,$end, $match.Direction, $word.Length-1) + if ($wordToCompare -eq $word) { + return [PSCustomObject]@{ + Start = $start + End = $end + } + } + } + } + } + return $null + } + + [bool] hidden IsInGrid([string]$word) { + <# + .DESCRIPTION + Helper function to check if all letters of the word appear in the grid, via the hashtable. + A quick check to make sure a word is viable before searching. + #> + $present = $word.ToCharArray() | Where-Object {$this._indicesTable.ContainsKey($_)} + return $present.Count -eq $word.Length + } + + [PSObject] hidden TestMatching($start, $end, $lenght) { + <# + .DESCRIPTION + A helper function to check if a possible start and end match a potential word, and which direction it is matching to. + #> + $horizontalMatch = ($start[0] -eq $end[0]) -and ([Math]::Abs($start[1] - $end[1]) -eq $lenght) + $verticalMatch = ($start[1] -eq $end[1]) -and ([Math]::Abs($start[0] - $end[0]) -eq $lenght) + $dexDiagMatch = ($start[0] - $end[0] -eq $start[1] - $end[1]) -and ([Math]::Abs($start[0] - $end[0]) -eq $lenght) + $sinDiagMatch = ($start[0] + $start[1] -eq $end[0] + $end[1]) -and ([Math]::Abs($start[0] - $end[0]) -eq $lenght) + + $match = switch ($true) { + $horizontalMatch {@{IsMatch=$true ; Direction="horizontal"}} + $verticalMatch {@{IsMatch=$true ; Direction="vertical"}} + $dexDiagMatch {@{IsMatch=$true ; Direction="dexter diagonal"}} + $sinDiagMatch {@{IsMatch=$true ; Direction="sinister diagonal"}} + Default {@{IsMatch=$false; Direction=$null}} + } + return $match + } + + [string] hidden ExtractWord($start, $end, $direction, $length) { + <# + .DESCRIPTION + Helper function to extract a word from start-end indices, and which direction of the word in the grid. + ALso account for the word being read in reverse (bottom up) + #> + $reverse = $false + $word = switch ($direction) { + "horizontal" { + $reverse = $start[1] -gt $end[1] + if ($reverse) {$start, $end = $end, $start} + 0..$length | ForEach-Object {$this._grid[$start[0]][$start[1] + $_]} + } + "vertical" { + $reverse = $start[0] -gt $end[0] + if ($reverse) {$start, $end = $end, $start} + 0..$length | ForEach-Object { $this._grid[$start[0] + $_][$start[1]]} + } + "dexter diagonal" { + $reverse = $start[1] -gt $end[1] + if ($reverse) {$start, $end = $end, $start} + 0..$length | ForEach-Object { $this._grid[$start[0] + $_][$start[1] + $_] } + } + "sinister diagonal" { + $reverse = $start[1] -gt $end[1] + if ($reverse) {$start, $end = $end, $start} + 0..$length | ForEach-Object { $this._grid[$start[0] - $_][$start[1] + $_] } + } + } + + $word = $reverse ? -join ($word[-1..-($word.Length)]) : -join $word + return $word + } +} \ No newline at end of file diff --git a/exercises/practice/word-search/.meta/config.json b/exercises/practice/word-search/.meta/config.json new file mode 100644 index 00000000..34310262 --- /dev/null +++ b/exercises/practice/word-search/.meta/config.json @@ -0,0 +1,17 @@ +{ + "authors": [ + "glaxxie" + ], + "files": { + "solution": [ + "WordSearch.ps1" + ], + "test": [ + "WordSearch.tests.ps1" + ], + "example": [ + ".meta/WordSearch.example.ps1" + ] + }, + "blurb": "Create a program to solve a word search puzzle." +} diff --git a/exercises/practice/word-search/.meta/tests.toml b/exercises/practice/word-search/.meta/tests.toml new file mode 100644 index 00000000..3f98113d --- /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.ps1 b/exercises/practice/word-search/WordSearch.ps1 new file mode 100644 index 00000000..4ee18e5c --- /dev/null +++ b/exercises/practice/word-search/WordSearch.ps1 @@ -0,0 +1,48 @@ +<# +.SYNOPSIS + Implement a program to find word in a search puzzle. + +.DESCRIPTION + Given a grid of letters, find the targey word that hides inside it. + Words can be hidden in all kinds of directions: left-to-right, right-to-left, vertical and diagonal. + + Implement a class that will take in an array of string(s) represent the grid. + Inside the class, implement a Search method that will take in a string as the target word. + If found, return the result in an object that contain the location of the first and last letter. + If the word doesn't exist in the grid, return $null. + + The object return must have these properties and their value in this format: + - Start: @(row value, column value) + - End : @(row value, column value) + Value of row and column follow the standard of 0-based index. + +.EXAMPLE + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ) + $puzzle = [WordSearch]::new($grid) + $puzzle.Search("clojure") + + Returns: [PsCustomObject]@{ + Start = @(9, 0) + End = @(9, 6) + } +#> +Class WordSearch { + WordSearch($grid) { + Throw "Please implement this class" + } + + Search ($word) { + Throw "Please implement this function" + } +} \ No newline at end of file diff --git a/exercises/practice/word-search/WordSearch.tests.ps1 b/exercises/practice/word-search/WordSearch.tests.ps1 new file mode 100644 index 00000000..e1bc60a7 --- /dev/null +++ b/exercises/practice/word-search/WordSearch.tests.ps1 @@ -0,0 +1,401 @@ +BeforeAll { + . "./WordSearch.ps1" +} + +Describe "WordSearch test cases" { + It "Should accept an initial game grid and a target search word" { + $grid = @("jefblpepre") + $puzzle = [WordSearch]::new($grid) + + $puzzle.Search("clojure") | Should -BeNullOrEmpty + } + + It "Should locate one word written left to right" { + $grid = @("clojurermt") + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(0, 0), @(0, 6) + } + + It "Should locate the same word written left to right in a different position" { + $grid = @("mtclojurer") + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(0, 2), @(0, 8) + } + + It "Should locate a different left to right word" { + $grid = @("coffeelplx") + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("coffee") + $got.Start, $got.End | Should -BeExactly @(0, 0), @(0, 5) + } + + It "Should locate that different left to right word in a different position" { + $grid = @("xcoffeezlp") + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("coffee") + $got.Start, $got.End | Should -BeExactly @(0, 1), @(0, 6) + } + + It "Should locate a left to right word in two line grid" { + $grid = @("jefblpepre", "tclojurerm") + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(1, 1), @(1, 7) + } + + It "Should locate a left to right word in three line grid" { + $grid = @("camdcimgtc", "jefblpepre", "clojurermt") + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(2, 0), @(2, 6) + } + + It "Should locate a left to right word in ten line grid" { + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ) + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(9, 0), @(9, 6) + } + + It "Should locate that left to right word in a different position in a ten line grid" { + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "clojurermt", + "jalaycalmp" + ) + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(8, 0), @(8, 6) + } + + It "Should locate a different left to right word in a ten line grid" { + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "fortranftw", + "alxhpburyi", + "clojurermt", + "jalaycalmp" + ) + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("fortran") + $got.Start, $got.End | Should -BeExactly @(6, 0), @(6, 6) + } + + It "Should locate multiple words" { + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "fortranftw", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ) + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("fortran") + $got.Start, $got.End | Should -BeExactly @(6, 0), @(6, 6) + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(9, 0), @(9, 6) + + } + + It "Should locate a single word written right to left" { + $grid = @("rixilelhrs") + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("elixir") + $got.Start, $got.End | Should -BeExactly @(0, 5), @(0, 0) + } + + It "Should locate multiple words written in different horizontal directions" { + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ) + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("elixir") + $got.Start, $got.End | Should -BeExactly @(4, 5), @(4, 0) + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(9, 0), @(9, 6) + } + + It "Should locate words written vertically" { + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ) + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(9, 0), @(9, 6) + $got = $puzzle.Search("elixir") + $got.Start, $got.End | Should -BeExactly @(4, 5), @(4, 0) + $got = $puzzle.Search("ecmascript") + $got.Start, $got.End | Should -BeExactly @(0, 9), @(9, 9) + } + + It "Should locate words written bottom to top" { + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ) + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(9, 0), @(9, 6) + $got = $puzzle.Search("elixir") + $got.Start, $got.End | Should -BeExactly @(4, 5), @(4, 0) + $got = $puzzle.Search("ecmascript") + $got.Start, $got.End | Should -BeExactly @(0, 9), @(9, 9) + $got = $puzzle.Search("rust") + $got.Start, $got.End | Should -BeExactly @(4, 8), @(1, 8) + } + + It "Should locate words written top left to bottom right" { + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ) + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(9, 0), @(9, 6) + $got = $puzzle.Search("elixir") + $got.Start, $got.End | Should -BeExactly @(4, 5), @(4, 0) + $got = $puzzle.Search("ecmascript") + $got.Start, $got.End | Should -BeExactly @(0, 9), @(9, 9) + $got = $puzzle.Search("rust") + $got.Start, $got.End | Should -BeExactly @(4, 8), @(1, 8) + $got = $puzzle.Search("java") + $got.Start, $got.End | Should -BeExactly @(0, 0), @(3, 3) + } + + It "Should locate words written bottom right to top left" { + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ) + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(9, 0), @(9, 6) + $got = $puzzle.Search("elixir") + $got.Start, $got.End | Should -BeExactly @(4, 5), @(4, 0) + $got = $puzzle.Search("ecmascript") + $got.Start, $got.End | Should -BeExactly @(0, 9), @(9, 9) + $got = $puzzle.Search("rust") + $got.Start, $got.End | Should -BeExactly @(4, 8), @(1, 8) + $got = $puzzle.Search("java") + $got.Start, $got.End | Should -BeExactly @(0, 0), @(3, 3) + $got = $puzzle.Search("lua") + $got.Start, $got.End | Should -BeExactly @(8, 7), @(6, 5) + } + + It "Should locate words written bottom left to top right" { + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ) + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(9, 0), @(9, 6) + $got = $puzzle.Search("elixir") + $got.Start, $got.End | Should -BeExactly @(4, 5), @(4, 0) + $got = $puzzle.Search("ecmascript") + $got.Start, $got.End | Should -BeExactly @(0, 9), @(9, 9) + $got = $puzzle.Search("rust") + $got.Start, $got.End | Should -BeExactly @(4, 8), @(1, 8) + $got = $puzzle.Search("java") + $got.Start, $got.End | Should -BeExactly @(0, 0), @(3, 3) + $got = $puzzle.Search("lua") + $got.Start, $got.End | Should -BeExactly @(8, 7), @(6, 5) + $got = $puzzle.Search("lisp") + $got.Start, $got.End | Should -BeExactly @(5, 2), @(2, 5) + } + + It "Should locate words written top right to bottom left" { + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ) + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(9, 0), @(9, 6) + $got = $puzzle.Search("elixir") + $got.Start, $got.End | Should -BeExactly @(4, 5), @(4, 0) + $got = $puzzle.Search("ecmascript") + $got.Start, $got.End | Should -BeExactly @(0, 9), @(9, 9) + $got = $puzzle.Search("rust") + $got.Start, $got.End | Should -BeExactly @(4, 8), @(1, 8) + $got = $puzzle.Search("java") + $got.Start, $got.End | Should -BeExactly @(0, 0), @(3, 3) + $got = $puzzle.Search("lua") + $got.Start, $got.End | Should -BeExactly @(8, 7), @(6, 5) + $got = $puzzle.Search("lisp") + $got.Start, $got.End | Should -BeExactly @(5, 2), @(2, 5) + $got = $puzzle.Search("ruby") + $got.Start, $got.End | Should -BeExactly @(5, 7), @(8, 4) + } + + It "Should fail to locate a word that is not in the puzzle" { + $grid = @( + "jefblpepre", + "camdcimgtc", + "oivokprjsm", + "pbwasqroua", + "rixilelhrs", + "wolcqlirpc", + "screeaumgr", + "alxhpburyi", + "jalaycalmp", + "clojurermt" + ) + $puzzle = [WordSearch]::new($grid) + + $got = $puzzle.Search("clojure") + $got.Start, $got.End | Should -BeExactly @(9, 0), @(9, 6) + $got = $puzzle.Search("elixir") + $got.Start, $got.End | Should -BeExactly @(4, 5), @(4, 0) + $got = $puzzle.Search("ecmascript") + $got.Start, $got.End | Should -BeExactly @(0, 9), @(9, 9) + $got = $puzzle.Search("rust") + $got.Start, $got.End | Should -BeExactly @(4, 8), @(1, 8) + $got = $puzzle.Search("java") + $got.Start, $got.End | Should -BeExactly @(0, 0), @(3, 3) + $got = $puzzle.Search("lua") + $got.Start, $got.End | Should -BeExactly @(8, 7), @(6, 5) + $got = $puzzle.Search("lisp") + $got.Start, $got.End | Should -BeExactly @(5, 2), @(2, 5) + $got = $puzzle.Search("ruby") + $got.Start, $got.End | Should -BeExactly @(5, 7), @(8, 4) + $puzzle.Search("haskell") | Should -BeNullOrEmpty + } + + It "Should fail to locate words that are not on horizontal, vertical, or diagonal lines" { + $grid = @("abc", "def") + $puzzle = [WordSearch]::new($grid) + + $puzzle.Search("aef") | Should -BeNullOrEmpty + $puzzle.Search("ced") | Should -BeNullOrEmpty + $puzzle.Search("abf") | Should -BeNullOrEmpty + $puzzle.Search("cbd") | Should -BeNullOrEmpty + } + + It "Should not concatenate different lines to find a horizontal word" { + $grid = @("abceli", "xirdfg") + $puzzle = [WordSearch]::new($grid) + + $puzzle.Search("elixir") | Should -BeNullOrEmpty + } + + It "Should not wrap around horizontally to find a word" { + $grid = @("silabcdefp") + $puzzle = [WordSearch]::new($grid) + + $puzzle.Search("lisp") | Should -BeNullOrEmpty + } + + It "Should not wrap around vertically to find a word" { + $grid = @("s", "u", "r", "a", "b", "c", "t") + $puzzle = [WordSearch]::new($grid) + + $puzzle.Search("rust") | Should -BeNullOrEmpty + } +} \ No newline at end of file