12
\$\begingroup\$

My third word search related challenge in a row. :)

Challenge:

Brief explanation of what a word search is:

In a word search you'll be given a grid of letters and a list of words. The idea is to cross off the words from the list in the grid. The words can be in eight different directions: horizontally from left-to-right or right-to-left; vertically from top-to-bottom or bottom-to-top; diagonally from the topleft-to-bottomright or bottomright-to-topleft; or anti-diagonally from the topright-to-bottomleft or bottomleft-to-topright.

Actual challenge:

Given a list of coordinates indicating the crossed out words within a grid (in any reasonable format), output how many line-islands there are.

We've had challenges involving finding the amount of islands in a matrix. But in this case it's different: just looking at the grid, words could be right next to each other, but would still be two separated line-islands. E.g. In the following partially solved word search, we have four separated line-islands, even though the letters of the words are right next to each other.

enter image description here

This partially solved word search above would result in an output of 4.

If 'word' FG was FGH like this:

enter image description here

The output would have been 3 instead, because the FGH+NKH now form a single connected line-island.

In this challenge we'll only be taking the coordinates of the words in a grid as input, and output the amount of line-islands.

Challenge rules:

  • You're allowed to take the input in any reasonable format. It could be pair of coordinates per word to indicate their start/end positions (e.g. [[[0,0],[0,2]],[[1,1],[1,3]],[[3,1],[1,3]],[[3,2],[2,3]]] for the second example above); it could be a full list of coordinates per word (e.g. [[[0,0],[0,1],[0,2]],[[1,1],[1,2],[1,3]],[[3,1],[2,2],[1,3]],[[3,2],[2,3]]]); a list of bit-mask matrices per word (e.g. [[[1,1,1,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,1,1,1],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,1],[0,0,1,0],[0,1,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,1],[0,0,1,0]]]); etc. If you're unsure if a possible input-format is valid, leave a comment down below.
  • All 'words' are guaranteed to have at least two letters.
  • You can assume the input won't be empty.
  • You can optionally take the dimensions of the grid as additional input.
  • Note that coordinates of 'words' are not guaranteed to be in the same positions to still form a single line-island! E.g. this grid would result in 1 because the lines cross, but neither 'word' share the same letter-positions:
    enter image description here

General rules:

  • This is , so the shortest answer in bytes wins.
    Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
  • Standard rules apply for your answer with default I/O rules, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
  • Default Loopholes are forbidden.
  • If possible, please add a link with a test for your code (e.g. TIO).
  • Also, adding an explanation for your answer is highly recommended.

Test cases:

enter image description here

  • Input as start/ending coordinates of the 'words': [[[0,0],[0,2]],[[1,1],[1,2]],[[3,1],[1,3]],[[3,2],[2,3]]]
  • Input as coordinates of the complete 'words': [[[0,0],[0,1],[0,2]],[[1,1],[1,2]],[[3,1],[2,2],[1,3]],[[3,2],[2,3]]]
  • Input as bit-mask matrices of the 'words': [[[1,1,1,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,1,1,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,1],[0,0,1,0],[0,1,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,1],[0,0,1,0]]]

Output: 4


enter image description here

  • Input as start/ending coordinates of the 'words': [[[0,0],[0,2]],[[1,1],[1,3]],[[3,1],[1,3]],[[3,2],[2,3]]]
  • Input as coordinates of the complete 'words': [[[0,0],[0,1],[0,2]],[[1,1],[1,2],[1,3]],[[3,1],[2,2],[1,3]],[[3,2],[2,3]]]
  • Input as bit-mask matrices of the 'words': [[[1,1,1,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,1,1,1],[0,0,0,0],[0,0,0,0]],[[0,0,0,0],[0,0,0,1],[0,0,1,0],[0,1,0,0]],[[0,0,0,0],[0,0,0,0],[0,0,0,1],[0,0,1,0]]]

Output: 3


enter image description here

  • Input as start/ending coordinates of the 'words': [[[0,0],[1,1]],[[0,1],[1,0]]]
  • Input as coordinates of the complete 'words': [[[0,0],[1,1]],[[0,1],[1,0]]]
  • Input as bit-mask matrices of the 'words': [[[1,0],[0,1]],[[0,1],[1,0]]]

Output: 1


enter image description here

  • Input as start/ending coordinates of the 'words': [[[1,9],[8,9]],[[8,6],[1,6]],[[1,4],[4,7]],[[9,0],[0,9]],[[1,0],[6,0]],[[6,1],[3,4]],[[9,4],[9,9]],[[0,1],[0,8]],[[9,3],[1,3]],[[0,0],[9,9]]]
  • Input as coordinates of the complete 'words': [[[1,9],[2,9],[3,9],[4,9],[5,9],[6,9],[7,9],[8,9]],[[8,6],[7,6],[6,6],[5,6],[4,6],[3,6],[2,6],[1,6]],[[1,4],[2,5],[3,6],[4,7]],[[9,0],[8,1],[7,2],[6,3],[5,4],[4,5],[3,6],[2,7],[1,8],[0,9]],[[1,0],[2,0],[3,0],[4,0],[5,0],[6,0]],[[6,1],[5,2],[4,3],[3,4]],[[9,4],[9,5],[9,6],[9,7],[9,8],[9,9]],[[0,1],[0,2],[0,3],[0,4],[0,5],[0,6],[0,7],[0,8]],[[9,3],[8,3],[7,3],[6,3],[5,3],[4,3],[3,3],[2,3],[1,3]],[[0,0],[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7],[8,8],[9,9]]]
  • Input as bit-mask matrices of the 'words': pastebin

Output: 4


enter image description here

  • Input as start/ending coordinates of the 'words': [[[8,6],[1,6]],[[1,4],[4,7]],[[9,0],[0,9]],[[6,1],[3,4]],[[9,4],[9,9]],[[9,3],[1,3]],[[0,0],[9,9]]]
  • Input as coordinates of the complete 'words': [[[8,6],[7,6],[6,6],[5,6],[4,6],[3,6],[2,6],[1,6]],[[1,4],[2,5],[3,6],[4,7]],[[9,0],[8,1],[7,2],[6,3],[5,4],[4,5],[3,6],[2,7],[1,8],[0,9]],[[6,1],[5,2],[4,3],[3,4]],[[9,4],[9,5],[9,6],[9,7],[9,8],[9,9]],[[9,3],[8,3],[7,3],[6,3],[5,3],[4,3],[3,3],[2,3],[1,3]],[[0,0],[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7],[8,8],[9,9]]]
  • Input as bit-mask matrices of the 'words': pastebin

Output: 1

\$\endgroup\$
3
  • \$\begingroup\$ Can I take the board dimensions as a 2nd argument? \$\endgroup\$
    – Jonah
    Mar 15, 2022 at 3:10
  • 1
    \$\begingroup\$ @Jonah "You can optionally take the dimensions of the grid as additional input." It was already one of the rules, so yes. :) \$\endgroup\$ Mar 15, 2022 at 7:33
  • \$\begingroup\$ Woops. Thsnks Kevin \$\endgroup\$
    – Jonah
    Mar 15, 2022 at 12:52

3 Answers 3

3
\$\begingroup\$

Jelly,  22  20 bytes

żSH$ƝẎ)ṭfƇ@ẎQʋ€ÐL`QL

A monadic Link that accepts a list of lists of pairs of integers - the full list of coordinates for each word - and yields the island count.

Try it online! (Two islands each being two words crossing at cell corners, where equal-island words are non-adjacent in the input list.)

Or see the test-suite.

How?

Needs updating:

ṭfƇ@ẎṢQ - Link 1, add crossing words: Coordinates, (all) Word Coordinates
   @    - with swapped arguments:
  Ƈ     -   filter keep (those Word Coordinate lists) for which:
 f      -     filter keep (i.e. contain some of the same entries)
ṭ       - tack to Coordinates
    Ẏ   - tighten
     Ṣ  - sort
      Q - deduplicate

żSH$ƝẎ)ç€ÐL`QL - Main Link: Word Coordinates
      )        - for each list in Word Coordinates:
   $Ɲ          -   for neighbours:
 S             -     sum (vectorises)
  H            -     halve
ż              - Word Coordinates zip-with those "intermediate coordinates"
     Ẏ         - tighten
           `   - use as both arguments of:
         ÐL    -   loop until no change with:
       ç€      -     call Link 1 for each
            Q  - deduplicate
             L - length
\$\endgroup\$
1
\$\begingroup\$

Python3, 560 bytes:

lambda w:len({str(i[0])for i in g(w)})
S=lambda a:[(t:=(a[1][0]-a[0][0])/([1,(k:=a[1][1]-a[0][1])][k!=0])*(k>0)),[a[0][1],t*-1*a[0][1]+a[0][0]][k!=0]]
M=lambda j,k:[(x:=(k[1]-j[1])/(j[0]-k[0])),j[0]*x+j[1]][::-1]
N=lambda s,p:min(t:=[s[0][0],s[1][0]])<=p[0]<=max(t)and min(t:=[s[0][1],s[1][1]])<=p[1]<=max(t)
V=lambda a,b:(j:=S(a))[0]!=(k:=S(b))[0]and N(a,m:=M(j,k))and N(b,m)
def g(w):
 Q,S=[[i]for i in w],[]
 while Q:
  if(v:=Q.pop(0))[-1]not in S:
   if[]==(j:=[i for i in w if i not in S and V(v[-1],i)]):yield v
   else:Q=[v+[i]for i in j]+Q
   S+=v[-1:]

Try it online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ t*-1* can be -t* :) \$\endgroup\$ Mar 15, 2022 at 7:45
1
\$\begingroup\$

Wolfram Language (Mathematica), 90 bytes

Length@ConnectedComponents@Graph[#->If[#⋂#2=={},##]&@@@Tuples[Total/@#~Tuples~2&/@#,2]]&

Try it online!

A simple set intersection between the lists of coordinates would detect almost all the cases except the 'phantom intersection' of two diagonal 'words'.
In this special case, these phantom intersecting diagonals, have both 2 coordinates that add up to a same one.

+---------+---------+
|A        |B        |
|  x   y  | x+1  y  |
|         |         |
+---------X---------+         A coords.          B coords.    
|B        |A        |    (x,y) + (x+1,y+1) = (x,y+1) + (x+1,y)
|  x  y+1 | x+1 y+1 |
|         |         |
+---------+---------+

Unfortunately a test for this would not detect the standard intersection of two words that actually have one common coordinate. As such my first implementation combined two test:

  • the intersection between the plain lists of coordinates #
  • the intersection between the lists of the sums of consecutive coordinates Partition[#,2,1] (this also assumed the lists would always be in order).

But then I thought why not sum every pair of coordinates (multisets) of a 'word'?
Also pushed by the fact that Tuples[#,2] is shorter than Partition[#,2,1]

Technicalities

The only doubt: can there be false positives?
That is, can two 'words' that do not share any coordinate be mapped into 'words' that do share some coordinates?

To sum all the coordinates in a 'word' with themselves is essentially a x2 scaling done in a redundant fashion.

So, for each mapped coordinate of a 'word' \$(x_i+x_j,y_i+y_j)\$ we can infer its preimage: a pair of coordinates of 'word' that yield the mapped one. Hence if two 'words' share a mapped coordinate they also have to share the relative pair of 'core coordinates'.

This pair of 'core coordinates' (P,b) are the two coordinates around the possibly 'phantom point' (@) \$(\frac{x_i+x_j}{2},\frac{y_i+y_j}{2})\$

+---------+---------+   +---------+---------+   +---------+---------+   +---------+---------+    +---------+---------+
|BBBBBBBBB|         |   |PPPPPPPPP|         |   |         |         |   |PPPPPPPPP|         |    |         |PPPPPPPPP|
|BBBB@BBBB|         |   |PPPPPPPPP|         |   |         |         |   |PPPPPPPPP|         |    |         |PPPPPPPPP|
|BBBBBBBBB|         |   |PPPPPPPPP|         |   |         |         |   |PPPPPPPPP|         |    |         |PPPPPPPPP|
+---------+---------+ , +----@----+---------+ , +---------+---------+ , +---------@---------+ OR +---------@---------+
|         |         |   |bbbbbbbbb|         |   |PPPPPPPPP|bbbbbbbbb|   |         |bbbbbbbbb|    |bbbbbbbbb|         |
|         |         |   |bbbbbbbbb|         |   |PPPPPPPPP@bbbbbbbbb|   |         |bbbbbbbbb|    |bbbbbbbbb|         |
|         |         |   |bbbbbbbbb|         |   |PPPPPPPPP|bbbbbbbbb|   |         |bbbbbbbbb|    |bbbbbbbbb|         |
+---------+---------+   +---------+---------+   +---------+---------+   +---------+---------+    +---------+---------+
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.