Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Sandbox

Post History

60%
+1 −0
Sandbox Arbitrary angle wrapping wordsearch

posted 2y ago by trichoplax‭  ·  edited 1y ago by trichoplax‭

#20: Post edited by user avatar trichoplax‭ · 2023-10-29T11:08:16Z (about 1 year ago)
Add extra consideration about negative offsets to Sandbox questions
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Should words that use the same grid position more than once be considered present? (Currently I am leaning towards allowing this, which I imagine is the easier approach to implement and likely easier to golf.)
  • - Does there need to be a limit on the horizontal and vertical offsets to keep them less than the grid width and height respectively? It appears that allowing larger offsets would allow the equivalent of some (all?) non-coprime offsets. Examples for a grid of width W and height H:
  • - If W and H are coprime, then an offset of (W, H) is otherwise valid, but is equivalent to an offset of (0, 0).
  • - An offset of (W, 1) is equivalent to an offset of (0, 1), which is valid, but an offset of (W, 2) is equivalent to an offset of (0, 2), which is not valid unless H=3 (making it equivalent to (0, -1)).
  • - If W+2 and H+2 are coprime, then an offset of (W+2, H+2) is otherwise valid, but is equivalent to an offset of (2, 2), which is not valid.
  • The alternative would be to allow all non-coprime offsets, slightly simplifying the challenge.
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • - An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any coprime integers, (which automatically excludes them both being 0).
  • Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word, that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets. This is the reason for requiring a and b to be coprime.
  • - A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • - An ***arbitrary angle wrapping wordsearch*** is both an arbitrary angle wordsearch and a wrapping wordsearch.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ]
  • ]
  • ```
  • Some of the test cases show "true" even though it may not always be obvious how the word can be found in the grid. Below are tiled grids for each "true" test case, showing how the word can be found in a straight line potentially over several grids, to visualise how the wrapping works. The found word shows in UPPER CASE, with all other letters reduced to lower case for contrast.
  • <details><summary>Test case visual justifications (hidden in case you want to work them out as an exercise)</summary>
  • ```text
  • TODO: this
  • ```
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Should words that use the same grid position more than once be considered present? (Currently I am leaning towards allowing this, which I imagine is the easier approach to implement and likely easier to golf.)
  • - Does there need to be a limit on the horizontal and vertical offsets to keep them less than the grid width and height respectively? It appears that allowing larger offsets would allow the equivalent of some (all?) non-coprime offsets. Examples for a grid of width W and height H:
  • - If W and H are coprime, then an offset of (W, H) is otherwise valid, but is equivalent to an offset of (0, 0).
  • - An offset of (W, 1) is equivalent to an offset of (0, 1), which is valid, but an offset of (W, 2) is equivalent to an offset of (0, 2), which is not valid unless H=3 (making it equivalent to (0, -1)).
  • - If W+2 and H+2 are coprime, then an offset of (W+2, H+2) is otherwise valid, but is equivalent to an offset of (2, 2), which is not valid.
  • An alternative would be to allow all non-coprime offsets, slightly simplifying the challenge.
  • - There is a similar potential problem with negative offsets being equivalent to non-coprime positive offsets:
  • - An offset of (2, 2) is not coprime, but it is equivalent to an offset of (-W+2, 2), (2, -H+2), or (-W+2, -H+2), all of which are less in magnitude than W and H horizontally and vertically respectively, and any of which can be coprime for some values of W and H.
  • This is not necessarily a problem, but may influence the decision on whether to allow non-coprime offsets.
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • - An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any coprime integers, (which automatically excludes them both being 0).
  • Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word, that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets. This is the reason for requiring a and b to be coprime.
  • - A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • - An ***arbitrary angle wrapping wordsearch*** is both an arbitrary angle wordsearch and a wrapping wordsearch.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ]
  • ]
  • ```
  • Some of the test cases show "true" even though it may not always be obvious how the word can be found in the grid. Below are tiled grids for each "true" test case, showing how the word can be found in a straight line potentially over several grids, to visualise how the wrapping works. The found word shows in UPPER CASE, with all other letters reduced to lower case for contrast.
  • <details><summary>Test case visual justifications (hidden in case you want to work them out as an exercise)</summary>
  • ```text
  • TODO: this
  • ```
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
#19: Post edited by user avatar trichoplax‭ · 2023-10-28T17:48:21Z (about 1 year ago)
Consider whether to limit offsets to less than grid width and height.
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Should words that use the same grid position more than once be considered present? (Currently I am leaning towards allowing this, which I imagine is the easier approach to implement and likely easier to golf.)
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • - An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any coprime integers, (which automatically excludes them both being 0).
  • Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word, that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets. This is the reason for requiring a and b to be coprime.
  • - A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • - An ***arbitrary angle wrapping wordsearch*** is both an arbitrary angle wordsearch and a wrapping wordsearch.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ]
  • ]
  • ```
  • Some of the test cases show "true" even though it may not always be obvious how the word can be found in the grid. Below are tiled grids for each "true" test case, showing how the word can be found in a straight line potentially over several grids, to visualise how the wrapping works. The found word shows in UPPER CASE, with all other letters reduced to lower case for contrast.
  • <details><summary>Test case visual justifications (hidden in case you want to work them out as an exercise)</summary>
  • ```text
  • TODO: this
  • ```
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Should words that use the same grid position more than once be considered present? (Currently I am leaning towards allowing this, which I imagine is the easier approach to implement and likely easier to golf.)
  • - Does there need to be a limit on the horizontal and vertical offsets to keep them less than the grid width and height respectively? It appears that allowing larger offsets would allow the equivalent of some (all?) non-coprime offsets. Examples for a grid of width W and height H:
  • - If W and H are coprime, then an offset of (W, H) is otherwise valid, but is equivalent to an offset of (0, 0).
  • - An offset of (W, 1) is equivalent to an offset of (0, 1), which is valid, but an offset of (W, 2) is equivalent to an offset of (0, 2), which is not valid unless H=3 (making it equivalent to (0, -1)).
  • - If W+2 and H+2 are coprime, then an offset of (W+2, H+2) is otherwise valid, but is equivalent to an offset of (2, 2), which is not valid.
  • The alternative would be to allow all non-coprime offsets, slightly simplifying the challenge.
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • - An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any coprime integers, (which automatically excludes them both being 0).
  • Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word, that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets. This is the reason for requiring a and b to be coprime.
  • - A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • - An ***arbitrary angle wrapping wordsearch*** is both an arbitrary angle wordsearch and a wrapping wordsearch.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ]
  • ]
  • ```
  • Some of the test cases show "true" even though it may not always be obvious how the word can be found in the grid. Below are tiled grids for each "true" test case, showing how the word can be found in a straight line potentially over several grids, to visualise how the wrapping works. The found word shows in UPPER CASE, with all other letters reduced to lower case for contrast.
  • <details><summary>Test case visual justifications (hidden in case you want to work them out as an exercise)</summary>
  • ```text
  • TODO: this
  • ```
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
#18: Post edited by user avatar trichoplax‭ · 2023-10-27T09:55:51Z (about 1 year ago)
Format terminology section for clarity
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Should words that use the same grid position more than once be considered present? (Currently I am leaning towards allowing this, which I imagine is the easier approach to implement and likely easier to golf.)
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any coprime integers, (which automatically excludes them both being 0).
  • Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word, that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets. This is the reason for requiring a and b to be coprime.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ]
  • ]
  • ```
  • Some of the test cases show "true" even though it may not always be obvious how the word can be found in the grid. Below are tiled grids for each "true" test case, showing how the word can be found in a straight line potentially over several grids, to visualise how the wrapping works. The found word shows in UPPER CASE, with all other letters reduced to lower case for contrast.
  • <details><summary>Test case visual justifications (hidden in case you want to work them out as an exercise)</summary>
  • ```text
  • TODO: this
  • ```
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Should words that use the same grid position more than once be considered present? (Currently I am leaning towards allowing this, which I imagine is the easier approach to implement and likely easier to golf.)
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • - An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any coprime integers, (which automatically excludes them both being 0).
  • Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word, that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets. This is the reason for requiring a and b to be coprime.
  • - A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • - An ***arbitrary angle wrapping wordsearch*** is both an arbitrary angle wordsearch and a wrapping wordsearch.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ]
  • ]
  • ```
  • Some of the test cases show "true" even though it may not always be obvious how the word can be found in the grid. Below are tiled grids for each "true" test case, showing how the word can be found in a straight line potentially over several grids, to visualise how the wrapping works. The found word shows in UPPER CASE, with all other letters reduced to lower case for contrast.
  • <details><summary>Test case visual justifications (hidden in case you want to work them out as an exercise)</summary>
  • ```text
  • TODO: this
  • ```
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
#17: Post edited by user avatar trichoplax‭ · 2023-10-27T09:45:28Z (about 1 year ago)
Be explicit about restricting offsets to be coprime
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Should words that use the same grid position more than once be considered present? (Currently I am leaning towards allowing this, which I imagine is the easier approach to implement and likely easier to golf.)
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ]
  • ]
  • ```
  • Some of the test cases show "true" even though it may not always be obvious how the word can be found in the grid. Below are tiled grids for each "true" test case, showing how the word can be found in a straight line potentially over several grids, to visualise how the wrapping works. The found word shows in UPPER CASE, with all other letters reduced to lower case for contrast.
  • <details><summary>Test case visual justifications (hidden in case you want to work them out as an exercise)</summary>
  • ```text
  • TODO: this
  • ```
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Should words that use the same grid position more than once be considered present? (Currently I am leaning towards allowing this, which I imagine is the easier approach to implement and likely easier to golf.)
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any coprime integers, (which automatically excludes them both being 0).
  • Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word, that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets. This is the reason for requiring a and b to be coprime.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ]
  • ]
  • ```
  • Some of the test cases show "true" even though it may not always be obvious how the word can be found in the grid. Below are tiled grids for each "true" test case, showing how the word can be found in a straight line potentially over several grids, to visualise how the wrapping works. The found word shows in UPPER CASE, with all other letters reduced to lower case for contrast.
  • <details><summary>Test case visual justifications (hidden in case you want to work them out as an exercise)</summary>
  • ```text
  • TODO: this
  • ```
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
#16: Post edited by user avatar trichoplax‭ · 2023-10-22T10:13:11Z (about 1 year ago)
Consider excluding words that use the same grid position more than once
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ]
  • ]
  • ```
  • Some of the test cases show "true" even though it may not always be obvious how the word can be found in the grid. Below are tiled grids for each "true" test case, showing how the word can be found in a straight line potentially over several grids, to visualise how the wrapping works. The found word shows in UPPER CASE, with all other letters reduced to lower case for contrast.
  • <details><summary>Test case visual justifications (hidden in case you want to work them out as an exercise)</summary>
  • ```text
  • TODO: this
  • ```
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Should words that use the same grid position more than once be considered present? (Currently I am leaning towards allowing this, which I imagine is the easier approach to implement and likely easier to golf.)
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ]
  • ]
  • ```
  • Some of the test cases show "true" even though it may not always be obvious how the word can be found in the grid. Below are tiled grids for each "true" test case, showing how the word can be found in a straight line potentially over several grids, to visualise how the wrapping works. The found word shows in UPPER CASE, with all other letters reduced to lower case for contrast.
  • <details><summary>Test case visual justifications (hidden in case you want to work them out as an exercise)</summary>
  • ```text
  • TODO: this
  • ```
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
#15: Post edited by user avatar trichoplax‭ · 2022-11-04T02:20:27Z (about 2 years ago)
Remove trailing comma from test cases
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without row delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no row delimiters, or allow them always?
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • Some of the test cases show "true" even though it may not always be obvious how the word can be found in the grid. Below are tiled grids for each "true" test case, showing how the word can be found in a straight line potentially over several grids, to visualise how the wrapping works. The found word shows in UPPER CASE, with all other letters reduced to lower case for contrast.
  • <details><summary>Test case visual justifications (hidden in case you want to work them out as an exercise)</summary>
  • ```text
  • TODO: this
  • ```
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ]
  • ]
  • ```
  • Some of the test cases show "true" even though it may not always be obvious how the word can be found in the grid. Below are tiled grids for each "true" test case, showing how the word can be found in a straight line potentially over several grids, to visualise how the wrapping works. The found word shows in UPPER CASE, with all other letters reduced to lower case for contrast.
  • <details><summary>Test case visual justifications (hidden in case you want to work them out as an exercise)</summary>
  • ```text
  • TODO: this
  • ```
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
#14: Post edited by user avatar trichoplax‭ · 2022-11-03T02:18:42Z (about 2 years ago)
Make test case explanations a hidden section
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without row delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no row delimiters, or allow them always?
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • # Test case visual justifications
  • ```text
  • TODO: this
  • ```
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without row delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no row delimiters, or allow them always?
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • Some of the test cases show "true" even though it may not always be obvious how the word can be found in the grid. Below are tiled grids for each "true" test case, showing how the word can be found in a straight line potentially over several grids, to visualise how the wrapping works. The found word shows in UPPER CASE, with all other letters reduced to lower case for contrast.
  • <details><summary>Test case visual justifications (hidden in case you want to work them out as an exercise)</summary>
  • ```text
  • TODO: this
  • ```
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
#13: Post edited by user avatar trichoplax‭ · 2022-10-22T15:57:37Z (about 2 years ago)
Make TODO stand out more
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without row delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no row delimiters, or allow them always?
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • # Test case visual justifications
  • TODO: this
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without row delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no row delimiters, or allow them always?
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • # Test case visual justifications
  • ```text
  • TODO: this
  • ```
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
#12: Post edited by user avatar trichoplax‭ · 2022-10-22T15:54:16Z (about 2 years ago)
Remove hidden sections
  • # Sandbox
  • - Do you prefer the version with collapsed expandable sections, or the version with just standard markdown headings? Or some combination with only some sections expandable?
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no row delimiters, or allow them always?
  • ---
  • Version with collapsed expandable sections:
  • ----
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • <details><summary>Input</summary>
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • </details>
  • <details><summary>Output</summary>
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • </details>
  • <details><summary>Test cases</summary>
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • </details>
  • <details><summary>Test case visual justifications</summary>
  • TODO: this
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
  • ----
  • Version with standard markdown headings:
  • ----
  • OMITTED FOR NOW
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without row delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no row delimiters, or allow them always?
  • ---
  • ----
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • # Terminology
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • # Examples
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • # Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • # Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • - You may choose to work with either only upper case letters or only lower case letters, or both, and your code may be case sensitive or insensitive
  • # Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • # Test case visual justifications
  • TODO: this
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
  • ----
  • ----
#11: Post edited by user avatar trichoplax‭ · 2022-10-21T19:08:14Z (about 2 years ago)
Test edit
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • <details><summary>Input</summary>
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • </details>
  • <details><summary>Output</summary>
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • </details>
  • <details><summary>Test cases</summary>
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • </details>
  • <details><summary>Test case visual justifications</summary>
  • TODO: this
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no delimiters, or allow them always?
  • # Sandbox
  • - Do you prefer the version with collapsed expandable sections, or the version with just standard markdown headings? Or some combination with only some sections expandable?
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no row delimiters, or allow them always?
  • ---
  • Version with collapsed expandable sections:
  • ---
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • <details><summary>Input</summary>
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • </details>
  • <details><summary>Output</summary>
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • </details>
  • <details><summary>Test cases</summary>
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • </details>
  • <details><summary>Test case visual justifications</summary>
  • TODO: this
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
  • ---
  • Version with standard markdown headings:
  • ---
  • OMITTED FOR NOW
#10: Post edited by user avatar trichoplax‭ · 2022-10-18T23:59:44Z (about 2 years ago)
Expand intro and hide sections
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • <details><summary>Test case visual justifications</summary>
  • TODO: this
  • </details>
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no delimiters, or allow them always?
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle (not just the 8 multiples of 45 degrees usually used), and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • <details><summary>Input</summary>
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • </details>
  • <details><summary>Output</summary>
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • </details>
  • <details><summary>Test cases</summary>
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • </details>
  • <details><summary>Test case visual justifications</summary>
  • TODO: this
  • </details>
  • > Explanations are optional, but I'm more likely to upvote answers that have one.
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no delimiters, or allow them always?
#9: Post edited by user avatar trichoplax‭ · 2022-10-15T00:40:12Z (about 2 years ago)
Make input requirements more lenient
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters[]())
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no delimiters, or allow them always?
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You may optionally also take the width and/or height of the grid as inputs
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters). See the Terminology and Examples sections above if there is doubt over interpretation
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • <details><summary>Test case visual justifications</summary>
  • TODO: this
  • </details>
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no delimiters, or allow them always?
#8: Post edited by user avatar trichoplax‭ · 2022-10-15T00:00:08Z (about 2 years ago)
Update test cases
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), and potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters[]())
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ]
  • ]
  • ```
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no delimiters, or allow them always?
  • ----
  • TODO: WRITE IMPLEMENTATION TO CHECK TEST CASES
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters[]())
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AB",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "BC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AF",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "IA",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AI",
  • "true"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHC",
  • "false"
  • ],
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "AHF",
  • "true"
  • ],
  • [
  • [
  • "AXBYC"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "AC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XAYAZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAYAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAZAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAYAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAZAAAAAAAAA",
  • "AAAAAAAAAAAAAAA",
  • "AAAAAAAAAAAAAAA"
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAYAAAAA",
  • "AAAAAAAAAAA",
  • "AAAAAAAAZAA",
  • "AAAAAAAAAAA"
  • ],
  • "XZY",
  • "true"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "Z",
  • "A",
  • "A",
  • "A"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZA",
  • "AA",
  • "AA",
  • "AA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • [
  • [
  • "ZAA",
  • "AAA",
  • "AAZ"
  • ],
  • "ZZ",
  • "true"
  • ],
  • [
  • [
  • "ZAAA",
  • "AAAA",
  • "AAZA",
  • "AAAA"
  • ],
  • "ZZ",
  • "false"
  • ],
  • ]
  • ```
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no delimiters, or allow them always?
  • ----
#7: Post edited by user avatar trichoplax‭ · 2022-10-13T10:11:22Z (about 2 years ago)
Add sandbox questions
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), and potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters[]())
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ]
  • ]
  • ```
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • ---
  • TODO: WRITE IMPLEMENTATION TO CHECK TEST CASES
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), and potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters[]())
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ]
  • ]
  • ```
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • - Is there any reason not to allow input to optionally include the width and height of the grid (to allow input as a single string of all letters, without delimiters)?
  • - If you allowed width and height as optional inputs, would you allow them only when the grid string / data structure has no delimiters, or allow them always?
  • ---
  • TODO: WRITE IMPLEMENTATION TO CHECK TEST CASES
#6: Post edited by user avatar trichoplax‭ · 2022-10-13T05:59:20Z (about 2 years ago)
Add sandbox question
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), and potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters[]())
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ]
  • ]
  • ```
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • ---
  • TODO: WRITE IMPLEMENTATION TO CHECK TEST CASES
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), and potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters[]())
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ]
  • ]
  • ```
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • - Are there any more edge cases to add to the test cases?
  • ---
  • TODO: WRITE IMPLEMENTATION TO CHECK TEST CASES
#5: Post edited by user avatar trichoplax‭ · 2022-10-13T05:53:52Z (about 2 years ago)
Clarify output section
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), and potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once)
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ]
  • ]
  • ```
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • ---
  • TODO: WRITE IMPLEMENTATION TO CHECK TEST CASES
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), and potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once if the word contains repeated letters[]())
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ]
  • ]
  • ```
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • ---
  • TODO: WRITE IMPLEMENTATION TO CHECK TEST CASES
#4: Post edited by user avatar trichoplax‭ · 2022-10-13T05:51:34Z (about 2 years ago)
Set minimum grid size
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), and potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once)
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ]
  • ]
  • ```
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • ---
  • TODO: WRITE IMPLEMENTATION TO CHECK TEST CASES
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - The grid will always have at least 1 row and at least 1 column (it will never be empty)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), and potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once)
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ]
  • ]
  • ```
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • ---
  • TODO: WRITE IMPLEMENTATION TO CHECK TEST CASES
#3: Post edited by user avatar trichoplax‭ · 2022-10-13T04:54:30Z (about 2 years ago)
Add test cases
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), and potentially wrapping over the edges of the grid one or more times
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • ---
  • TODO:
  • - ADD TEST CASES
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), and potentially wrapping over the edges of the grid one or more times (including running over some of the letters more than once)
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ```text
  • [
  • [
  • [
  • "ABC",
  • "DEF",
  • "GHI"
  • ],
  • "ABC",
  • "true"
  • ],
  • [
  • [
  • "AXBYCZ"
  • ],
  • "ABC",
  • "false"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAA",
  • "AAAAAAAAA",
  • "AAAAYAAAA",
  • "AAAAAAAAA",
  • "AAAAAAAAZ",
  • "AAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "true"
  • ],
  • [
  • [
  • "XAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAYAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAZA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • "AAAAAAAAAA",
  • ],
  • "XYZ",
  • "false"
  • ],
  • [
  • [
  • "YO"
  • ],
  • "YOYO",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EKE",
  • "true"
  • ],
  • [
  • [
  • "EK"
  • ],
  • "EEK",
  • "false"
  • ],
  • [
  • [
  • "Z"
  • ],
  • "ZZZZZZZZZZZZ",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDEFGHIJKLMNOPQRSTUVWXYZABCD",
  • "true"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCDA",
  • "false"
  • ],
  • [
  • [
  • "ASGYM",
  • "ZNBTH",
  • "UIAOC",
  • "PDVJB",
  • "KCQEW",
  • "FXLDR"
  • ],
  • "ABCDABCD",
  • "true"
  • ]
  • ]
  • ```
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • ---
  • TODO: WRITE IMPLEMENTATION TO CHECK TEST CASES
#2: Post edited by user avatar trichoplax‭ · 2022-10-13T03:40:57Z (about 2 years ago)
Hide terminology and examples, and better define output
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • ## Explanation
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • ## Examples
  • In these examples all of the letters are replaced with `.` apart from the word to be found, for ease of finding. In every grid the word to be found is `WORDSEARCH`.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ---
  • # Sandbox
  • - Should I exclude offsets that can be reduced to a smaller offset at the same angle? For example, should (0, 2) be a valid offset (even though it's just horizontal with gaps)? What about (6, 3)? I'm strongly leaning towards making both of these invalid
  • - Would you change anything about the test case format?
  • - Would this be better split into two questions?
  • - Arbitrary angle wordsearch
  • - Wrapping wordsearch
  • My inclination is currently to keep them together as one question, as the arbitary angle words will not fit on a reasonably sized grid without wrapping. I also suspect that in most languages the 2 subtasks will fit together well.
  • ---
  • TODO:
  • - ADD TEST CASES
  • - CONSIDER HIDING EXAMPLES IN A DETAILS TAG
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • <details><summary>Terminology</summary>
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling together 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • </details>
  • <details><summary>Examples</summary>
  • In these examples all of the letters are replaced with <code>.</code> apart from the word to be found, for ease of finding.
  • In every grid the word to be found is <code>WORDSEARCH</code>.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over the right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • </details>
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • - The word is present if it occurs at any angle with no gaps (no interjacent letters at that precise angle), and potentially wrapping over the edges of the grid one or more times
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ---
  • # Sandbox
  • - Would you change anything about the test case format?
  • ---
  • TODO:
  • - ADD TEST CASES
#1: Post edited by user avatar trichoplax‭ · 2022-10-12T10:06:48Z (about 2 years ago)
Add todo
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • ## Explanation
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • ## Examples
  • In these examples all of the letters are replaced with `.` apart from the word to be found, for ease of finding. In every grid the word to be found is `WORDSEARCH`.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ---
  • # Sandbox
  • - Should I exclude offsets that can be reduced to a smaller offset at the same angle? For example, should (0, 2) be a valid offset (even though it's just horizontal with gaps)? What about (6, 3)? I'm strongly leaning towards making both of these invalid
  • - Would you change anything about the test case format?
  • - Would this be better split into two questions?
  • - Arbitrary angle wordsearch
  • - Wrapping wordsearch
  • My inclination is currently to keep them together as one question, as the arbitary angle words will not fit on a reasonably sized grid without wrapping. I also suspect that in most languages the 2 subtasks will fit together well.
  • ---
  • TODO:
  • - ADD TEST CASES
  • Given a rectangular grid of letters and a word to search for, determine whether the word appears in the grid at any arbitrary angle, and possibly wrapping over the edges.
  • ## Explanation
  • A standard wordsearch with 8 possible angles can be thought of as looking for a word where each letter is at an offset (a, b) from the previous letter, where a and b are each one of -1, 0, or 1, but not both 0.
  • An ***arbitrary angle wordsearch*** is the same as a standard wordsearch, except a and b can be any integers, but not both 0. Note that multiples of a valid offset by N > 1 are not valid, as this would give a word with gaps. For example, an offset of (2, 0) is the same angle as (1, 0). So (1, 0) is a valid offset, but (2, 0) is not as it would have letters in between the letters of the word that are on the same line but not part of the word. Similarly (2, 1) is a valid offset, but multiples of it such as (4, 2) and (6, 3) are not valid offsets.
  • A ***wrapping wordsearch*** is the same as a standard wordsearch, but also allows a word to pass over an edge of the grid and continue on the opposite side, potentially more than once. Equivalently, a word can be found in a larger grid made by tiling 2 or more identical copies of the wordsearch grid.
  • An ***arbitrary angle wrapping wordsearch*** has both of these additional features.
  • ## Examples
  • In these examples all of the letters are replaced with `.` apart from the word to be found, for ease of finding. In every grid the word to be found is `WORDSEARCH`.
  • Standard diagonal word, each letter offset by (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • Diagonal word wrapping over the bottom edge:
  • ```text
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ```
  • The same example with the grid tiled twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....s.....
  • .....e....
  • ......a...
  • .......r..
  • ........c.
  • .........h
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • w.........
  • .o........
  • ..r.......
  • ...d......
  • ```
  • Diagonal word wrapping over the right edge:
  • ```text
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ...R......
  • ....C.....
  • .....H....
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....H.........H....
  • ```
  • Diagonal word wrapping over the right edge then the bottom edge:
  • ```text
  • ...R......
  • ....C.....
  • .....H....
  • ......W...
  • .......O..
  • ........R.
  • .........D
  • S.........
  • .E........
  • ..A.......
  • ```
  • The same example with the grid tiled twice horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ...r.........r......
  • ....c.........c.....
  • .....h.........h....
  • ......W.........w...
  • .......O.........o..
  • ........R.........r.
  • .........D.........d
  • s.........S.........
  • .e.........E........
  • ..a.........A.......
  • ...r.........R......
  • ....c.........C.....
  • .....h.........H....
  • ......w.........w...
  • .......o.........o..
  • ........r.........r.
  • .........d.........d
  • s.........s.........
  • .e.........e........
  • ..a.........a.......
  • ```
  • Each letter offset by (2, 1), wrapping over right edge:
  • ```text
  • W.........
  • ..O.......
  • ....R.....
  • ......D...
  • ........S.
  • E.........
  • ..A.......
  • ....R.....
  • ......C...
  • ........H.
  • ```
  • The same example with the grid tiled twice horizontally to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • W.........w.........
  • ..O.........o.......
  • ....R.........r.....
  • ......D.........d...
  • ........S.........s.
  • e.........E.........
  • ..a.........A.......
  • ....r.........R.....
  • ......c.........C...
  • ........h.........H.
  • ```
  • Each letter offset by (-3, 2), wrapping over left edge and then bottom edge and then left edge again:
  • ```text
  • ....E....W
  • ..........
  • .A....O...
  • ..........
  • ...R....R.
  • ..........
  • D....C....
  • ..........
  • ..H....S..
  • ..........
  • ```
  • The same example again but with the grid tiled 3 times horizontally and twice vertically to see how the word then ends up in a straight line (all other letters made lowercase so the unbroken word stands out):
  • ```text
  • ....e....w....e....w....e....W
  • ..............................
  • .a....o....a....o....a....O...
  • ..............................
  • ...r....r....r....r....R....r.
  • ..............................
  • d....c....d....c....D....c....
  • ..............................
  • ..h....s....h....S....h....s..
  • ..............................
  • ....e....w....E....w....e....w
  • ..............................
  • .a....o....A....o....a....o...
  • ..............................
  • ...r....R....r....r....r....r.
  • ..............................
  • d....C....d....c....d....c....
  • ..............................
  • ..H....s....h....s....h....s..
  • ..............................
  • ```
  • Each letter offset by (11, 11), wrapping over both the right and bottom edges every step, showing that this is exactly equivalent to an offset of (1, 1):
  • ```text
  • W.........
  • .O........
  • ..R.......
  • ...D......
  • ....S.....
  • .....E....
  • ......A...
  • .......R..
  • ........C.
  • .........H
  • ```
  • ## Input
  • - A grid of letters and a sequence of letters (a "word") to search for
  • - The grid of letters may be any ordered data structure of characters, or an ordered data structure of strings representing rows, or a single string containing letters and line delimiters
  • - The grid will always be rectangular (the rows will all be the same length)
  • - You must not take additional inputs to specify the width and height of the grid, so a single string containing only letters and no line delimiters will not be a valid input, since the dimensions of the rectangle would then in some cases be ambiguous
  • - The sequence of letters to search for (the word) may be any ordered data structure of characters, or a single string
  • - The word will always have at least 2 letters
  • - You may choose to take the 2 inputs in whichever order you prefer
  • ## Output
  • - Any truthy value if the word is present, or any falsy value otherwise
  • - You may instead choose any 2 distinct values or sets of values to represent true and false if you wish (even if they are not truthy or falsy respectively in your language of choice)
  • ## Test cases
  • Each test case is in the format:
  • `[["comma", "separated", "row", "strings"], "word", "true" or "false"]`
  • ---
  • # Sandbox
  • - Should I exclude offsets that can be reduced to a smaller offset at the same angle? For example, should (0, 2) be a valid offset (even though it's just horizontal with gaps)? What about (6, 3)? I'm strongly leaning towards making both of these invalid
  • - Would you change anything about the test case format?
  • - Would this be better split into two questions?
  • - Arbitrary angle wordsearch
  • - Wrapping wordsearch
  • My inclination is currently to keep them together as one question, as the arbitary angle words will not fit on a reasonably sized grid without wrapping. I also suspect that in most languages the 2 subtasks will fit together well.
  • ---
  • TODO:
  • - ADD TEST CASES
  • - CONSIDER HIDING EXAMPLES IN A DETAILS TAG