Word Search Puzzle
Java : 183 211 321
boolean s(char[]w,char[]s){int j,z,a=s.length,i=a*9,f=1,q=0;for(;s[q++]>10;);for(;i-->0;)for(j=w.length,z=i/9;i%9!=4&j-->0&z>=0&z<a&&s[z]==w[j];z+=q*(i/3%3)+i%3-q-1)f*=j;return f==0;}
A basic brute force. There's not much else to say, I guess. Input is needle first and haystack second. Assumes grid is newline-terminated.
A slightly more readable version with test case shown:
public class WordSearch {
static String grid = "WVERTICALL\nROOAFFLSAB\nACRILIATOA\nNDODKONWDC\nDRKESOODDK\nOEEPZEGLIW\nMSIIHOAERA\nALRKRRIRER\nKODIDEDRCD\nHELWSLEUTH";
static String search = "RANDOM";
public static void main(String[] args) {
System.out.println(new WordSearch().s(search.toCharArray(),grid.toCharArray()));
}
boolean s(char[]w,char[]s){
int j,z,a=s.length,i=a*9,f=1,q=0;
for(;s[q++]>10;);
for(;i-->0;)
for(j=w.length,z=i/9;
i%9!=4&j-->0&z>=0&z<a&&s[z]==w[j];
z+=q*(i/3%3)+i%3-q-1)
f*=j;
return f==0;
}
}
CJam, 46 37 bytes
qN%{_zW%__,N**2$2$+,)/z\}4*]:+N*eas#)
Reads the grid from STDIN and the word as a command-line argument. Prints positive integers for matches and 0 for non-matches.
At the cost of two extra bytes, both strings (word, linefeed, grid) can be read from STDIN:
qN%(\{_zW%__,N**2$2$+,)/z\}4*](\:+N*\#)
You can try this version online with the CJam interpreter.
Example run
$ for W in Lorem mine uma\ bop tuetdod snol,a texas pii.d\ \ v vexta WordSearch CODEGOLF UNICORN; do echo -e "$(cjam wordsearch.cjam "$W" < grid)\t$W"; done
1 Lorem
3085 mine
2055 uma bop
5142 tuetdod
3878 snol,a
1426 texas
5371 pii.d v
2536 vexta
0 WordSearch
0 CODEGOLF
0 UNICORN
Background
Assume the input was the following grid:
ABCD
EFGH
IJKL
Splitting at linefeeds, we obtain the following array:
A := [
"ABCD"
"EFGH"
"IJKL"
]
That covers East words (words going from left to right).
Now, we join the elements of A
using a string of len(A)
linefeeds as separator:
"ABCD⏎⏎⏎EFGH⏎⏎⏎IJKL"
Then, we chop the resulting string in chunks of length len(A) + len(A[0]) + 1
:
[
"ABCD⏎⏎⏎E"
"FGH⏎⏎⏎IJ"
"KL"
]
If we "zip" the array (transpose rows and columns), we obtain:
[
"AFK"
"BGL"
"CH"
"D⏎"
"⏎⏎"
"⏎⏎"
"I⏎"
"EJ"
]
That covers South East words.
If we zip A and reverse the order of the result's rows, we obtain:
[
"DHL"
"CGK"
"BFJ"
"AEI"
]
That covers South and – after repeating the process for diagonals – South West words.
Zipping and reversing again, we obtain:
[
"LKJI"
"HGFE"
"DCBA"
]
That covers West and – after repeating the process for diagonals – North West words.
Zipping and reversing once more, we obtain:
[
"IEA"
"JFB"
"KGC"
"LHD"
]
That covers North and – after repeating the process for diagonals – North East words.
How it works
The code does as explained in the previous section, with two minor differences:
- It zips and reverses once at the very beginning.
- It computes
len(A) + len(A[0])
aslen(A + zip(A))
.
Finally, it joins all rows of all generated arrays using linefeeds as separators and searches for the word in the resulting string.
qN% " A := split(input(),'\n') ";
{ }4* " Do 4 times: ";
_zW% " B := reverse(zip(A)) ";
__,N** " C := B.join(len(B) * '\n') ";
2$2$+,)/z " D := zip(C.chunks(len(A + B) + 1)) ";
\ " A := B ";
] " Collect all values of A and D in an array R. ";
:+ " R := flatten(R) ";
N* " R := R.join('\n') ";
eas " I := flatten(ARGV) ";
#) " print R.index(I) + 1 ";
JavaScript (E6) 111 116
Brute force search for every character in every direction - as golfed as I can
F=(b,w)=>
[1,-1,r=b.search('\n'),-r,++r,-r,++r,-r].some(d=>
[...b].some((_,p)=>
[...w].every(c=>c==b[p+=d],p-=d)
)
)
Test In FireFox/Firebug console
;["RANDOM", "VERTICAL", "HORIZONTAL", "WORDSEARCH", "WIKIPEDIA", "TAIL",
"WordSearch", "CODEGOLF", "UNICORN"]
.forEach(w=>console.log('\n'+ w +' -> '+
F("WVERTICALL\nROOAFFLSAB\nACRILIATOA\nNDODKONWDC\nDRKESOODDK\nOEEPZEGLIW\nMSIIHOAERA\nALRKRRIRER\nKODIDEDRCD\nHELWSLEUTH",w)))
Output
RANDOM -> true
VERTICAL -> true
HORIZONTAL -> true
WORDSEARCH -> true
WIKIPEDIA -> true
TAIL -> true
WordSearch -> false
CODEGOLF -> false
UNICORN -> false