Word search: Difference between revisions

m
m (→‎{{header|Wren}}: Minor tidy)
 
(19 intermediate revisions by 11 users not shown)
Line 18:
;Example
 
<pre>
<pre> 0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
 
0 n a y r y R e l m f
Line 43 ⟶ 44:
tar (5,7)(5,5) elm (6,0)(8,0)
max (7,4)(9,4) pup (5,3)(3,5)
mph (8,8)(6,8)</pre>
</pre>
 
 
{{Template:Strings}}
<br><br>
 
=={{header|C++11l}}==
{{trans|Python}}
<lang cpp>
#include <iomanip>
#include <ctime>
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <fstream>
 
<syntaxhighlight lang="11l">-V
const int WID = 10, HEI = 10, MIN_WORD_LEN = 3, MIN_WORD_CNT = 25;
dirs = [[1, 0], [ 0, 1], [ 1, 1],
[1, -1], [-1, 0],
[0, -1], [-1, -1], [-1, 1]]
n_rows = 10
n_cols = 10
grid_size = n_rows * n_cols
min_words = 25
 
T Grid
class Cell {
num_attempts = 0
public:
[[String]] cells = [[‘’] * :n_cols] * :n_rows
Cell() : val( 0 ), cntOverlap( 0 ) {}
[String] solutions
char val; int cntOverlap;
};
class Word {
public:
Word( std::string s, int cs, int rs, int ce, int re, int dc, int dr ) :
word( s ), cols( cs ), rows( rs ), cole( ce ), rowe( re ), dx( dc ), dy( dr ) {}
bool operator ==( const std::string& s ) { return 0 == word.compare( s ); }
std::string word;
int cols, rows, cole, rowe, dx, dy;
};
class words {
public:
void create( std::string& file ) {
std::ifstream f( file.c_str(), std::ios_base::in );
std::string word;
while( f >> word ) {
if( word.length() < MIN_WORD_LEN || word.length() > WID || word.length() > HEI ) continue;
if( word.find_first_not_of( "abcdefghijklmnopqrstuvwxyz" ) != word.npos ) continue;
dictionary.push_back( word );
}
f.close();
std::random_shuffle( dictionary.begin(), dictionary.end() );
buildPuzzle();
}
 
F read_words(filename)
void printOut() {
[String] words
std::cout << "\t";
L(line) File(filename).read_lines()
for( int x = 0; x < WID; x++ ) std::cout << x << " ";
V s std::cout= << "\n\n";line.lowercase()
I re:‘^[a-z]{3,10}’.match(s)
for( int y = 0; y < HEI; y++ ) {
std::cout << y << "\t";words.append(s)
R words
for( int x = 0; x < WID; x++ )
std::cout << puzzle[x][y].val << " ";
std::cout << "\n";
}
size_t wid1 = 0, wid2 = 0;
for( size_t x = 0; x < used.size(); x++ ) {
if( x & 1 ) {
if( used[x].word.length() > wid1 ) wid1 = used[x].word.length();
} else {
if( used[x].word.length() > wid2 ) wid2 = used[x].word.length();
}
}
std::cout << "\n";
std::vector<Word>::iterator w = used.begin();
while( w != used.end() ) {
std::cout << std::right << std::setw( wid1 ) << ( *w ).word << " (" << ( *w ).cols << ", " << ( *w ).rows << ") ("
<< ( *w ).cole << ", " << ( *w ).rowe << ")\t";
w++;
if( w == used.end() ) break;
std::cout << std::setw( wid2 ) << ( *w ).word << " (" << ( *w ).cols << ", " << ( *w ).rows << ") ("
<< ( *w ).cole << ", " << ( *w ).rowe << ")\n";
w++;
}
std::cout << "\n\n";
}
private:
void addMsg() {
std::string msg = "ROSETTACODE";
int stp = 9, p = rand() % stp;
for( size_t x = 0; x < msg.length(); x++ ) {
puzzle[p % WID][p / HEI].val = msg.at( x );
p += rand() % stp + 4;
}
}
int getEmptySpaces() {
int es = 0;
for( int y = 0; y < HEI; y++ ) {
for( int x = 0; x < WID; x++ ) {
if( !puzzle[x][y].val ) es++;
}
}
return es;
}
bool check( std::string word, int c, int r, int dc, int dr ) {
for( size_t a = 0; a < word.length(); a++ ) {
if( c < 0 || r < 0 || c >= WID || r >= HEI ) return false;
if( puzzle[c][r].val && puzzle[c][r].val != word.at( a ) ) return false;
c += dc; r += dr;
}
return true;
}
bool setWord( std::string word, int c, int r, int dc, int dr ) {
if( !check( word, c, r, dc, dr ) ) return false;
int sx = c, sy = r;
for( size_t a = 0; a < word.length(); a++ ) {
if( !puzzle[c][r].val ) puzzle[c][r].val = word.at( a );
else puzzle[c][r].cntOverlap++;
c += dc; r += dr;
}
used.push_back( Word( word, sx, sy, c - dc, r - dr, dc, dr ) );
return true;
}
bool add2Puzzle( std::string word ) {
int x = rand() % WID, y = rand() % HEI,
z = rand() % 8;
for( int d = z; d < z + 8; d++ ) {
switch( d % 8 ) {
case 0: if( setWord( word, x, y, 1, 0 ) ) return true; break;
case 1: if( setWord( word, x, y, -1, -1 ) ) return true; break;
case 2: if( setWord( word, x, y, 0, 1 ) ) return true; break;
case 3: if( setWord( word, x, y, 1, -1 ) ) return true; break;
case 4: if( setWord( word, x, y, -1, 0 ) ) return true; break;
case 5: if( setWord( word, x, y, -1, 1 ) ) return true; break;
case 6: if( setWord( word, x, y, 0, -1 ) ) return true; break;
case 7: if( setWord( word, x, y, 1, 1 ) ) return true; break;
}
}
return false;
}
void clearWord() {
if( used.size() ) {
Word lastW = used.back();
used.pop_back();
 
F place_message(Grid &grid; =msg)
for( size_t a = 0; a < lastW.word.length(); a++ ) {
msg = msg.uppercase().replace(re:‘[^A-Z]’, ‘’)
if( puzzle[lastW.cols][lastW.rows].cntOverlap == 0 ) {
V message_len = msg.len
puzzle[lastW.cols][lastW.rows].val = 0;
I message_len C 0 <.< }:grid_size
V gap_size = :grid_size I/ message_len
if( puzzle[lastW.cols][lastW.rows].cntOverlap > 0 ) {
 
puzzle[lastW.cols][lastW.rows].cntOverlap--;
L(i) 0 .< }message_len
V pos = i * lastW.colsgap_size += lastW.dx;random:(0 lastW.rows. += lastW.dy;gap_size)
grid.cells[pos I/ :n_cols][pos }% :n_cols] = msg[i]
 
}
} R message_len
R 0
void buildPuzzle() {
 
addMsg();
F try_location(Grid &grid; word, direction, pos)
int es = 0, cnt = 0;
V r = pos I/ size_t idx = 0;:n_cols
V c = pos % do {:n_cols
V length = word.len
for( std::vector<std::string>::iterator w = dictionary.begin(); w != dictionary.end(); w++ ) {
 
if( std::find( used.begin(), used.end(), *w ) != used.end() ) continue;
I (:dirs[direction][0] == 1 & (length + c) > :n_cols) |
(:dirs[direction][0] == -1 & if(length add2Puzzle(- *w1) )> c) {|
(:dirs[direction][1] == 1 & (length + r) > :n_rows) |
es = getEmptySpaces();
(:dirs[direction][1] == -1 & (length - 1) > r)
if( !es && used.size() >= MIN_WORD_CNT )
R return;0
 
}
V rr = }r
V cc = clearWord();c
V i = 0
std::random_shuffle( dictionary.begin(), dictionary.end() );
V overlaps = 0
 
L i < length
I grid.cells[rr][cc] != ‘’ & grid.cells[rr][cc] != word[i]
R 0
cc += :dirs[direction][0]
rr += :dirs[direction][1]
i++
 
rr = r
cc = c
i = 0
 
L i < length
I grid.cells[rr][cc] == word[i]
overlaps++
E
grid.cells[rr][cc] = word[i]
 
I i < length - 1
cc += :dirs[direction][0]
rr += :dirs[direction][1]
i++
 
V letters_placed = length - overlaps
I letters_placed > 0
grid.solutions.append(‘#<10 (#.,#.)(#.,#.)’.format(word, c, r, cc, rr))
 
R letters_placed
 
F try_place_word(Grid &grid; word)
V rand_dir = random:(0 .. :dirs.len)
V rand_pos = random:(0 .. :grid_size)
 
L(=direction) 0 .< :dirs.len
direction = (direction + rand_dir) % :dirs.len
 
L(=pos) 0 .< :grid_size
pos = (pos + rand_pos) % :grid_size
V letters_placed = try_location(&grid, word, direction, pos)
I letters_placed > 0
R letters_placed
R 0
 
F create_word_search(&words)
V grid = Grid()
V num_attempts = 0
 
L num_attempts < 100
num_attempts++
random:shuffle(&words)
grid = Grid()
V message_len = place_message(&grid, ‘Rosetta Code’)
V target = :grid_size - message_len
V cells_filled = 0
L(word) words
cells_filled += try_place_word(&grid, word)
I cells_filled == target
I grid.solutions.len >= :min_words
grid.num_attempts = num_attempts
R grid
E
L.break
R grid
 
F print_result(grid)
I grid.num_attempts == 0
print(‘No grid to display’)
R
 
V size = grid.solutions.len
 
print(‘Attempts: #.’.format(grid.num_attempts))
print(‘Number of words: #.’.format(size))
 
print("\n 0 1 2 3 4 5 6 7 8 9\n")
L(r) 0 .< :n_rows
print(‘#. ’.format(r), end' ‘’)
L(c) 0 .< :n_cols
print(‘ #. ’.format(grid.cells[r][c]), end' ‘’)
print()
print()
 
L(i) (0 .< size - 1).step(2)
print(‘#. #.’.format(grid.solutions[i], grid.solutions[i + 1]))
 
I size % 2 == 1
print(grid.solutions[size - 1])
 
print_result(create_word_search(&read_words(‘unixdict.txt’)))</syntaxhighlight>
 
} while( ++cnt < 100 );
}
std::vector<Word> used;
std::vector<std::string> dictionary;
Cell puzzle[WID][HEI];
};
int main( int argc, char* argv[] ) {
unsigned s = unsigned( time( 0 ) );
srand( s );
words w; w.create( std::string( "unixdict.txt" ) );
w.printOut();
return 0;
}
</lang>
{{out}}
<pre>
Attempts: 2
Number of words: 26
 
0 1 2 3 4 5 6 7 8 9
 
0 a s d i b R fa t ai uc nR pw wt
1 O n O o i l ol bi ht ao m a oc
2 a Sa r eo en ra pS Er tk r he
3 d a e l c y o h r E a i T n l i er Tv
4 t T f n a t m u e T w i A o e d n t se
5 d e l na Cy ht uc yn pw g o ln
6 d r o A n ps ta OC no sa e o Dt
7 t c w o e uO b ec fd ig ao c bf
8 s w E e i l n l e n m i a r d D a m eu
9 s h e a s l s e k E a p lw a nc el
 
thereofdeny (30, 6) (3, 03) tan seen (23, 94) (53, 6)
paretocotillion (89, 01) (81, 51) aaron wolf (0, 72) (04, 42)
albacore crib (12, 39) (19, 02) eventful tinge (79, 2) (79, 69)
siennastink (14, 96) (18, 42) endow war (4, 49) (48, 25)
dispelasiatic (60, 80) (6, 30) daly kaplan (30, 93) (83, 93)
swell tau (40, 08) (64, 08) delay lob (20, 15) (4, 15)
shale how (0,9, 2) (4,9, 0) argon same (67, 69) (97, 95)
tori men (49, 80) (26, 83) oct feb (52, 7) (30, 7)
yuh ham (54, 15) (74, 13) sci moe (2, (4,6) (26, 28)
tor pan (59, 26) (7, 08) wac yuh (56, 59) (38, 59)
lord pun (2, 6) (23, 8)(0,5) rat load (92, 52) (60, 84)
ode can (17, 34) (19, 54) fan madame (4, 8) (9, 87)(7,5)
ala gob (7, (5,2) (93, 70) wok rib (1, 2) (18, 0)(8,2)
nee (5, 6) (3, 8) set (9, 4) (7, 2)
alp (7, 9) (5, 9) wolfe (0, 7) (0, 3)
the (3, 6) (3, 4) low (0, 5) (0, 7)
tea (3, 6) (5, 8) era (8, 3) (8, 1)
nne (1, 5) (1, 7) amen (5, 8) (2, 8)
coot (8, 7) (8, 4) anne (1, 4) (1, 7)
reid (3, 3) (0, 0) sse (2, 9) (0, 9)
</pre>
 
=={{header|BASIC}}==
==={{header|FreeBASIC}}===
{{trans|QB64}}
Changes:
ShowPuzzle gets call only after a word is inserted in the grid.
Added a check if unixdict.txt was found.
Made FilePuzzle print to the file.
If enough words are found but there where still spaces, fill them with random letters.
FILLED was not set to FALSE every time Initialize was called.
Set all integer to (U)long.
<syntaxhighlight lang="freebasic">Randomize Timer ' OK getting a good puzzle every time
 
#Macro TrmSS (n)
LTrim(Str(n))
#EndMacro
 
'overhauled
Dim Shared As ULong LengthLimit(3 To 10) 'reset in Initialize, track and limit longer words
 
'LoadWords opens file of words and sets
Dim Shared As ULong NWORDS 'set in LoadWords, number of words with length: > 2 and < 11 and just letters
 
' word file words (shuffled) to be fit into puzzle and index position
Dim Shared As String WORDSSS(1 To 24945), CWORDSSS(1 To 24945)
Dim Shared As ULong WORDSINDEX 'the file has 24945 words but many are unsuitable
 
'words placed in Letters grid, word itself (WSS) x, y head (WX, WY) and direction (WD), WI is the index to all these
Dim Shared As String WSS(1 To 100)
Dim Shared As ULong WX(1 To 100), WY(1 To 100), WD(1 To 100), WI
 
' letters grid and direction arrays
Dim Shared As String LSS(0 To 9, 0 To 9)
Dim Shared As Long DX(0 To 7), DY(0 To 7)
DX(0) = 1: DY(0) = 0
DX(1) = 1: DY(1) = 1
DX(2) = 0: DY(2) = 1
DX(3) = -1: DY(3) = 1
DX(4) = -1: DY(4) = 0
DX(5) = -1: DY(5) = -1
DX(6) = 0: DY(6) = -1
DX(7) = 1: DY(7) = -1
 
'to store all the words found embedded in the grid LSS()
Dim Shared As String ALLSS(1 To 200)
Dim Shared As ULong AllX(1 To 200), AllY(1 To 200), AllD(1 To 200) 'to store all the words found embedded in the grid LSS()
Dim Shared As ULong ALLindex
 
' signal successful fill of puzzle
Dim Shared FILLED As Boolean
Dim Shared As ULong try = 1
 
Sub LoadWords
Dim As String wdSS
Dim As ULong i, m, ff = FreeFile
Dim ok As Boolean
 
Open "unixdict.txt" For Input As #ff
If Err > 0 Then
Print !"\n unixdict.txt not found, program will end"
Sleep 5000
End
End If
While Eof(1) = 0
Input #ff, wdSS
If Len(wdSS) > 2 And Len(wdSS) < 11 Then
ok = TRUE
For m = 1 To Len(wdSS)
If Asc(wdSS, m) < 97 Or Asc(wdSS, m) > 122 Then ok = FALSE: Exit For
Next
If ok Then i += 1: WORDSSS(i) = wdSS: CWORDSSS(i) = wdSS
End If
Wend
Close #ff
NWORDS = i
End Sub
 
Sub Shuffle
Dim As ULong i, r
For i = NWORDS To 2 Step -1
r = Int(Rnd * i) + 1
Swap WORDSSS(i), WORDSSS(r)
Next
End Sub
 
Sub Initialize
Dim As ULong r, c'', x, y, d
Dim As String wdSS
 
FILLED = FALSE
For r = 0 To 9
For c = 0 To 9
LSS(c, r) = " "
Next
Next
 
'reset word arrays by resetting the word index back to zero
WI = 0
 
'fun stuff for me but doubt others would like that much fun!
'pluggin "basic", 0, 0, 2
'pluggin "plus", 1, 0, 0
 
'to assure the spreading of ROSETTA CODE
LSS(Int(Rnd * 5) + 5, 0) = "R": LSS(Int(Rnd * 9) + 1, 1) = "O"
LSS(Int(Rnd * 9) + 1, 2) = "S": LSS(Int(Rnd * 9) + 1, 3) = "E"
LSS(1, 4) = "T": LSS(9, 4) = "T": LSS(Int(10 * Rnd), 5) = "A"
LSS(Int(10 * Rnd), 6) = "C": LSS(Int(10 * Rnd), 7) = "O"
LSS(Int(10 * Rnd), 8) = "D": LSS(Int(10 * Rnd), 9) = "E"
 
'reset limits
LengthLimit(3) = 200
LengthLimit(4) = 6
LengthLimit(5) = 3
LengthLimit(6) = 2
LengthLimit(7) = 1
LengthLimit(8) = 0
LengthLimit(9) = 0
LengthLimit(10) = 0
 
'reset word order
Shuffle
End Sub
 
'for fun plug-in of words
Sub pluggin (wdSS As String, x As Long, y As Long, d As Long)
 
For i As ULong = 0 To Len(wdSS) - 1
LSS(x + i * DX(d), y + i * DY(d)) = Mid(wdSS, i + 1, 1)
Next
WI += WI
WSS(WI) = wdSS: WX(WI) = x: WY(WI) = y: WD(WI) = d
End Sub
 
' Function TrmSS (n As Integer) As String
' TrmSS = RTrim(LTrim(Str(n)))
' End Function
 
'used in PlaceWord
Function CountSpaces () As ULong
Dim As ULong x, y, count
 
For y = 0 To 9
For x = 0 To 9
If LSS(x, y) = " " Then count += 1
Next
Next
CountSpaces = count
End Function
 
Sub ShowPuzzle
Dim As ULong i, x, y
'Dim As String wateSS
 
Cls
Print " 0 1 2 3 4 5 6 7 8 9"
Locate 3, 1
For i = 0 To 9
Print TrmSS(i)
Next
For y = 0 To 9
For x = 0 To 9
Locate y + 3, 2 * x + 5: Print LSS(x, y)
Next
Next
For i = 1 To WI
If i < 21 Then
Locate i + 1, 30: Print TrmSS(i); " "; WSS(i)
ElseIf i < 41 Then
Locate i - 20 + 1, 45: Print TrmSS(i); " "; WSS(i)
ElseIf i < 61 Then
Locate i - 40 + 1, 60: Print TrmSS(i); " "; WSS(i)
End If
Next
Locate 18, 1: Print "Spaces left:"; CountSpaces
Locate 19, 1: Print NWORDS
Locate 20, 1: Print Space(16)
If WORDSINDEX Then Locate 20, 1: Print TrmSS(WORDSINDEX); " "; WORDSSS(WORDSINDEX)
'LOCATE 15, 1: INPUT "OK, press enter... "; wateSS
End Sub
 
'used in PlaceWord
Function Match (word As String, template As String) As Long
Dim i As ULong
Dim c As String
Match = 0
If Len(word) <> Len(template) Then Exit Function
For i = 1 To Len(template)
If Asc(template, i) <> 32 And (Asc(word, i) <> Asc(template, i)) Then Exit Function
Next
Match = -1
End Function
 
'heart of puzzle builder
Sub PlaceWord
' place the words randomly in the grid
' start at random spot and work forward or back 100 times = all the squares
' for each open square try the 8 directions for placing the word
' even if word fits Rossetta Challenge task requires leaving 11 openings to insert ROSETTA CODE,
' exactly 11 spaces needs to be left, if/when this occurs FILLED will be set true to signal finished to main loop
' if place a word update LSS, WI, WSS(WI), WX(WI), WY(WI), WD(WI)
 
Dim As String wdSS, templateSS
Dim As Long rdir
Dim As ULong wLen, spot, testNum
Dim As ULong x, y, d, dNum, rdd, i, j
 
Dim As Boolean b1, b2
 
wdSS = WORDSSS(WORDSINDEX) ' the right side is all shared
' skip too many long words
If LengthLimit(Len(wdSS)) Then LengthLimit(Len(wdSS)) += 1 Else Exit Sub 'skip long ones
wLen = Len(wdSS) - 1 ' from the spot there are this many letters to check
spot = Int(Rnd * 100) ' a random spot on grid
testNum = 1 ' when this hits 100 we've tested all possible spots on grid
If Rnd < .5 Then rdir = -1 Else rdir = 1 ' go forward or back from spot for next test
While testNum < 101
y = spot \ 10
x = spot Mod 10
If LSS(x, y) = Mid(wdSS, 1, 1) Or LSS(x, y) = " " Then
d = Int(8 * Rnd)
If Rnd < .5 Then rdd = -1 Else rdd = 1
dNum = 1
While dNum < 9
'will wdSS fit? from at x, y
templateSS = ""
b1 = wLen * DX(d) + x >= 0 And wLen * DX(d) + x <= 9
b2 = wLen * DY(d) + y >= 0 And wLen * DY(d) + y <= 9
If b1 And b2 Then 'build the template of letters and spaces from Letter grid
For i = 0 To wLen
templateSS += LSS(x + i * DX(d), y + i * DY(d))
Next
If Match(wdSS, templateSS) Then 'the word will fit but does it fill anything?
For j = 1 To Len(templateSS)
If Asc(templateSS, j) = 32 Then 'yes a space to fill
For i = 0 To wLen
LSS(x + i * DX(d), y + i * DY(d)) = Mid(wdSS, i + 1, 1)
Next
WI += 1
WSS(WI) = wdSS: WX(WI) = x: WY(WI) = y: WD(WI) = d
ShowPuzzle
If CountSpaces = 0 Then FILLED = TRUE
Exit Sub 'get out now that word is loaded
End If
Next
'if still here keep looking
End If
End If
d = (d + 8 + rdd) Mod 8
dNum += 1
Wend
End If
spot = (spot + 100 + rdir) Mod 100
testNum += 1
Wend
End Sub
 
Sub FindAllWords
Dim As String wdSS, templateSS, wateSS
Dim As ULong wLen, x, y, d, j
Dim As Boolean b1, b2
 
For i As ULong = 1 To NWORDS
wdSS = CWORDSSS(i)
wLen = Len(wdSS) - 1
For y = 0 To 9
For x = 0 To 9
If LSS(x, y) = Mid(wdSS, 1, 1) Then
For d = 0 To 7
b1 = wLen * DX(d) + x >= 0 And wLen * DX(d) + x <= 9
b2 = wLen * DY(d) + y >= 0 And wLen * DY(d) + y <= 9
If b1 And b2 Then 'build the template of letters and spaces from Letter grid
templateSS = ""
For j = 0 To wLen
templateSS += LSS(x + j * DX(d), y + j * DY(d))
Next
If templateSS = wdSS Then 'found a word
'store it
ALLindex += 1
ALLSS(ALLindex) = wdSS: AllX(ALLindex) = x: AllY(ALLindex) = y: AllD(ALLindex) = d
'report it
Locate 22, 1: Print Space(50)
Locate 22, 1: Print "Found: "; wdSS; " ("; TrmSS(x); ", "; TrmSS(y); ") >>>---> "; TrmSS(d);
Input " Press enter...", wateSS
End If
End If
Next
End If
Next
Next
Next
End Sub
 
Sub FilePuzzle
Dim As ULong i, r, c, ff = FreeFile
Dim As String bSS
 
Open "WS Puzzle.txt" For Output As #ff
Print #ff, " 0 1 2 3 4 5 6 7 8 9"
Print #ff,
For r = 0 To 9
bSS = TrmSS(r) + " "
For c = 0 To 9
bSS += LSS(c, r) + " "
Next
Print #ff, bSS
Next
Print #ff,
Print #ff, "Directions >>>---> 0 = East, 1 = SE, 2 = South, 3 = SW, 4 = West, 5 = NW, 6 = North, 7 = NE"
Print #ff,
Print #ff, " These are the items from unixdict.txt used to build the puzzle:"
Print #ff,
For i = 1 To WI Step 2
Print #ff, Right(Space(7) + TrmSS(i), 7); ") "; Right(Space(7) + WSS(i), 10); " ("; TrmSS(WX(i)); ", "; TrmSS(WY(i)); ") >>>---> "; TrmSS(WD(i));
If i + 1 <= WI Then
Print #ff, Right(Space(7) + TrmSS(i + 1), 7); ") "; Right(Space(7) + WSS(i + 1), 10); " ("; TrmSS(WX(i + 1)); ", "; TrmSS(WY(i + 1)); ") >>>---> "; TrmSS(WD(i + 1))
Else
Print #ff,
End If
Next
Print #ff,
Print #ff, " These are the items from unixdict.txt found embedded in the puzzle:"
Print #ff,
For i = 1 To ALLindex Step 2
Print #ff, Right(Space(7) + TrmSS(i), 7); ") "; Right(Space(7) + ALLSS(i), 10); " ("; TrmSS(AllX(i)); ", "; TrmSS(AllY(i)); ") >>>---> "; TrmSS(AllD(i));
If i + 1 <= ALLindex Then
Print #ff, Right(Space(7) + TrmSS(i + 1), 7); ") "; Right(Space(7) + ALLSS(i + 1), 10); " ("; TrmSS(AllX(i + 1)); ", "; TrmSS(AllY(i + 1)); ") >>>---> "; TrmSS(AllD(i + 1))
Else
Print #ff, ""
End If
Next
Print #ff,
Print #ff, "On try #" + TrmSS(try) + " a successful puzzle was built and filed."
Close #ff
End Sub
 
 
LoadWords 'this sets NWORDS count to work with
 
While try < 11
Initialize
ShowPuzzle
For WORDSINDEX = 1 To NWORDS
PlaceWord
' ShowPuzzle
If FILLED Then Exit For
Next
If Not filled And WI > 24 Then ' we have 25 or more words
For y As ULong = 0 To 9 ' fill spaces with random letters
For x As ULong = 0 To 9
If LSS(x, y) = " " Then LSS(x, y) = Chr(Int(Rnd * 26) + 1 + 96)
Next
Next
filled = TRUE
ShowPuzzle
End If
If FILLED And WI > 24 Then
FindAllWords
FilePuzzle
Locate 23, 1: Print "On try #"; TrmSS(try); " a successful puzzle was built and filed."
Exit While
Else
try += 1
End If
Wend
 
If Not FILLED Then Locate 23, 1: Print "Sorry, 10 tries and no success."
 
Sleep
End</syntaxhighlight>
{{out}}
<pre style="height:52ex;overflow:scroll"> 0 1 2 3 4 5 6 7 8 9
 
0 m g y m l a i r R u
1 s e u i o n n p s O
2 a p S l s s u n e n
3 h w o e l t j E a t
4 c T r l n a e i s T
5 c t e a c A r w i g
6 C w m m r b a i d a
7 O d s t u m b r e l
8 D o a i t h i g h h
9 l p E g d b o r h t
 
Directions >>>---> 0 = East, 1 = SE, 2 = South, 3 = SW, 4 = West, 5 = NW, 6 = North, 7 = NE
 
These are the items from unixdict.txt used to build the puzzle:
 
1) yea (2, 0) >>>---> 3 2) thigh (4, 8) >>>---> 0
3) wells (1, 6) >>>---> 7 4) jacm (6, 3) >>>---> 3
5) tumbrel (3, 7) >>>---> 0 6) mile (3, 0) >>>---> 2
7) seaside (8, 1) >>>---> 2 8) putnam (7, 1) >>>---> 3
9) throb (9, 9) >>>---> 4 10) insert (6, 0) >>>---> 3
11) brian (5, 6) >>>---> 7 12) chasm (0, 4) >>>---> 6
13) los (0, 9) >>>---> 7 14) aida (6, 6) >>>---> 0
15) anna (5, 0) >>>---> 1 16) dis (4, 9) >>>---> 5
17) heir (9, 8) >>>---> 5 18) lop (3, 4) >>>---> 5
19) gull (1, 0) >>>---> 1 20) sol (4, 2) >>>---> 6
21) gad (3, 9) >>>---> 5 22) stew (4, 2) >>>---> 1
23) ncr (4, 4) >>>---> 2 24) pat (1, 9) >>>---> 7
25) lair (4, 0) >>>---> 0 26) woe (1, 3) >>>---> 0
27) pet (7, 1) >>>---> 1 28) usn (9, 0) >>>---> 3
29) lag (9, 7) >>>---> 6 30) etc (2, 5) >>>---> 4
 
These are the items from unixdict.txt found embedded in the puzzle:
 
1) acm (5, 4) >>>---> 3 2) aid (6, 6) >>>---> 0
3) aida (6, 6) >>>---> 0 4) air (5, 0) >>>---> 0
5) air (8, 3) >>>---> 3 6) ale (3, 5) >>>---> 6
7) all (5, 4) >>>---> 5 8) ann (5, 0) >>>---> 1
9) ann (8, 3) >>>---> 5 10) anna (5, 0) >>>---> 1
11) anna (8, 3) >>>---> 5 12) ant (3, 5) >>>---> 7
13) are (6, 6) >>>---> 6 14) arm (3, 5) >>>---> 1
15) aside (8, 3) >>>---> 2 16) bar (6, 7) >>>---> 6
17) bare (6, 7) >>>---> 6 18) bird (5, 9) >>>---> 7
19) brian (5, 6) >>>---> 7 20) chasm (0, 4) >>>---> 6
21) dis (8, 6) >>>---> 6 22) dis (4, 9) >>>---> 5
23) drib (8, 6) >>>---> 3 24) ego (8, 7) >>>---> 3
25) eli (3, 3) >>>---> 6 26) ell (2, 5) >>>---> 7
27) era (6, 4) >>>---> 2 28) etc (2, 5) >>>---> 4
29) gad (3, 9) >>>---> 5 30) gal (9, 5) >>>---> 2
31) gull (1, 0) >>>---> 1 32) gym (1, 0) >>>---> 0
33) heir (9, 8) >>>---> 5 34) high (5, 8) >>>---> 0
35) hum (5, 8) >>>---> 5 36) ian (7, 4) >>>---> 7
37) ida (7, 6) >>>---> 0 38) insert (6, 0) >>>---> 3
39) ion (3, 1) >>>---> 0 40) ira (7, 6) >>>---> 5
41) jacm (6, 3) >>>---> 3 42) lag (9, 7) >>>---> 6
43) lair (4, 0) >>>---> 0 44) lam (3, 4) >>>---> 2
45) leo (4, 3) >>>---> 4 46) lew (3, 4) >>>---> 3
47) lim (3, 2) >>>---> 6 48) lop (3, 4) >>>---> 5
49) los (4, 0) >>>---> 2 50) los (0, 9) >>>---> 7
51) lug (3, 2) >>>---> 5 52) male (3, 6) >>>---> 6
53) man (2, 6) >>>---> 7 54) maw (5, 7) >>>---> 7
55) mile (3, 0) >>>---> 2 56) nair (9, 2) >>>---> 3
57) ncr (4, 4) >>>---> 2 58) ore (2, 3) >>>---> 2
59) pat (1, 9) >>>---> 7 60) peg (1, 2) >>>---> 6
61) pet (7, 1) >>>---> 1 62) pod (1, 9) >>>---> 6
63) pol (1, 2) >>>---> 1 64) put (7, 1) >>>---> 3
65) putnam (7, 1) >>>---> 3 66) rib (7, 7) >>>---> 3
67) rim (7, 9) >>>---> 5 68) rob (7, 9) >>>---> 4
69) rut (4, 6) >>>---> 2 70) sea (8, 1) >>>---> 2
71) seaside (8, 1) >>>---> 2 72) side (8, 4) >>>---> 2
73) sol (4, 2) >>>---> 6 74) sol (2, 7) >>>---> 3
75) stew (4, 2) >>>---> 1 76) stu (2, 7) >>>---> 0
77) sun (5, 2) >>>---> 0 78) swam (8, 4) >>>---> 3
79) tap (3, 7) >>>---> 3 80) tea (1, 5) >>>---> 0
81) thigh (4, 8) >>>---> 0 82) throb (9, 9) >>>---> 4
83) tum (3, 7) >>>---> 0 84) tumbrel (3, 7) >>>---> 0
85) usn (9, 0) >>>---> 3 86) well (1, 6) >>>---> 7
87) wells (1, 6) >>>---> 7 88) wet (7, 5) >>>---> 5
89) wig (7, 5) >>>---> 0 90) woe (1, 3) >>>---> 0
91) yea (2, 0) >>>---> 3
 
On try #1 a successful puzzle was built and filed.</pre>
 
==={{header|QB64}}===
''bplus'': 2020/03/13
 
The following zip file is needed for the Unix dictionary and a QB64 words mod for fun! ...and some samples.<br>
[https://www.qb64.org/forum/index.php?action=dlattach;topic=2334.0;attach=5434 Rosetta Code Word Search Challenge.zip]
<syntaxhighlight lang="qbasic"> OPTION _EXPLICIT
_TITLE "Puzzle Builder for Rosetta" 'by B+ started 2018-10-31
' 2018-11-02 Now that puzzle is working with basic and plus starters remove them and make sure puzzle works as well.
' Added Direction legend to printout.
' OverHauled LengthLimit()
' Reorgnize this to try a couple of times at given Randomize number
' TODO create alphabetical copy of word list and check grid for all words embedded in it.
' LoadWords makes a copy of word list in alpha order
' FindAllWords finds all the items from the dictionary
' OK it all seems to be working OK
RANDOMIZE TIMER ' OK getting a good puzzle every time
'overhauled
DIM SHARED LengthLimit(3 TO 10) AS _BYTE 'reset in Initialize, track and limit longer words
'LoadWords opens file of words and sets
DIM SHARED NWORDS 'set in LoadWords, number of words with length: > 2 and < 11 and just letters
' word file words (shuffled) to be fit into puzzle and index position
DIM SHARED WORDS$(1 TO 24945), CWORDS$(1 TO 24945), WORDSINDEX AS INTEGER 'the file has 24945 words but many are unsuitable
'words placed in Letters grid, word itself (W$) x, y head (WX, WY) and direction (WD), WI is the index to all these
DIM SHARED W$(1 TO 100), WX(1 TO 100) AS _BYTE, WY(1 TO 100) AS _BYTE, WD(1 TO 100) AS _BYTE, WI AS _BYTE
' letters grid and direction arrays
DIM SHARED L$(0 TO 9, 0 TO 9), DX(0 TO 7) AS _BYTE, DY(0 TO 7) AS _BYTE
DX(0) = 1: DY(0) = 0
DX(1) = 1: DY(1) = 1
DX(2) = 0: DY(2) = 1
DX(3) = -1: DY(3) = 1
DX(4) = -1: DY(4) = 0
DX(5) = -1: DY(5) = -1
DX(6) = 0: DY(6) = -1
DX(7) = 1: DY(7) = -1
'to store all the words found embedded in the grid L$()
DIM SHARED ALL$(1 TO 200), AllX(1 TO 200) AS _BYTE, AllY(1 TO 200) AS _BYTE, AllD(1 TO 200) AS _BYTE 'to store all the words found embedded in the grid L$()
DIM SHARED ALLindex AS INTEGER
' signal successful fill of puzzle
DIM SHARED FILLED AS _BIT
FILLED = 0
DIM try AS _BYTE
try = 1
LoadWords 'this sets NWORDS count to work with
WHILE try < 11
Initialize
ShowPuzzle
FOR WORDSINDEX = 1 TO NWORDS
PlaceWord
ShowPuzzle
IF FILLED THEN EXIT FOR
NEXT
IF FILLED AND WI > 24 THEN
FindAllWords
FilePuzzle
LOCATE 23, 1: PRINT "On try #"; Trm$(try); " a successful puzzle was built and filed."
EXIT WHILE
ELSE
try = try + 1
END IF
WEND
IF FILLED = 0 THEN LOCATE 23, 1: PRINT "Sorry, 10 tries and no success."
END
SUB LoadWords
DIM wd$, i AS INTEGER, m AS INTEGER, ok AS _BIT
OPEN "unixdict.txt" FOR INPUT AS #1
WHILE EOF(1) = 0
INPUT #1, wd$
IF LEN(wd$) > 2 AND LEN(wd$) < 11 THEN
ok = -1
FOR m = 1 TO LEN(wd$)
IF ASC(wd$, m) < 97 OR ASC(wd$, m) > 122 THEN ok = 0: EXIT FOR
NEXT
IF ok THEN i = i + 1: WORDS$(i) = wd$: CWORDS$(i) = wd$
END IF
WEND
CLOSE #1
NWORDS = i
END SUB
SUB Shuffle
DIM i AS INTEGER, r AS INTEGER
FOR i = NWORDS TO 2 STEP -1
r = INT(RND * i) + 1
SWAP WORDS$(i), WORDS$(r)
NEXT
END SUB
SUB Initialize
DIM r AS _BYTE, c AS _BYTE, x AS _BYTE, y AS _BYTE, d AS _BYTE, wd$
FOR r = 0 TO 9
FOR c = 0 TO 9
L$(c, r) = " "
NEXT
NEXT
'reset word arrays by resetting the word index back to zero
WI = 0
'fun stuff for me but doubt others would like that much fun!
'pluggin "basic", 0, 0, 2
'pluggin "plus", 1, 0, 0
'to assure the spreading of ROSETTA CODE
L$(INT(RND * 5) + 5, 0) = "R": L$(INT(RND * 9) + 1, 1) = "O"
L$(INT(RND * 9) + 1, 2) = "S": L$(INT(RND * 9) + 1, 3) = "E"
L$(1, 4) = "T": L$(9, 4) = "T": L$(INT(10 * RND), 5) = "A"
L$(INT(10 * RND), 6) = "C": L$(INT(10 * RND), 7) = "O"
L$(INT(10 * RND), 8) = "D": L$(INT(10 * RND), 9) = "E"
'reset limits
LengthLimit(3) = 200
LengthLimit(4) = 6
LengthLimit(5) = 3
LengthLimit(6) = 2
LengthLimit(7) = 1
LengthLimit(8) = 0
LengthLimit(9) = 0
LengthLimit(10) = 0
'reset word order
Shuffle
END SUB
'for fun plug-in of words
SUB pluggin (wd$, x AS INTEGER, y AS INTEGER, d AS INTEGER)
DIM i AS _BYTE
FOR i = 0 TO LEN(wd$) - 1
L$(x + i * DX(d), y + i * DY(d)) = MID$(wd$, i + 1, 1)
NEXT
WI = WI + 1
W$(WI) = wd$: WX(WI) = x: WY(WI) = y: WD(WI) = d
END SUB
FUNCTION Trm$ (n AS INTEGER)
Trm$ = RTRIM$(LTRIM$(STR$(n)))
END FUNCTION
SUB ShowPuzzle
DIM i AS _BYTE, x AS _BYTE, y AS _BYTE, wate$
CLS
PRINT " 0 1 2 3 4 5 6 7 8 9"
LOCATE 3, 1
FOR i = 0 TO 9
PRINT Trm$(i)
NEXT
FOR y = 0 TO 9
FOR x = 0 TO 9
LOCATE y + 3, 2 * x + 5: PRINT L$(x, y)
NEXT
NEXT
FOR i = 1 TO WI
IF i < 20 THEN
LOCATE i + 1, 30: PRINT Trm$(i); " "; W$(i)
ELSEIF i < 40 THEN
LOCATE i - 20 + 1, 45: PRINT Trm$(i); " "; W$(i)
ELSEIF i < 60 THEN
LOCATE i - 40 + 1, 60: PRINT Trm$(i); " "; W$(i)
END IF
NEXT
LOCATE 18, 1: PRINT "Spaces left:"; CountSpaces%
LOCATE 19, 1: PRINT NWORDS
LOCATE 20, 1: PRINT SPACE$(16)
IF WORDSINDEX THEN LOCATE 20, 1: PRINT Trm$(WORDSINDEX); " "; WORDS$(WORDSINDEX)
'LOCATE 15, 1: INPUT "OK, press enter... "; wate$
END SUB
'used in PlaceWord
FUNCTION CountSpaces% ()
DIM x AS _BYTE, y AS _BYTE, count AS INTEGER
FOR y = 0 TO 9
FOR x = 0 TO 9
IF L$(x, y) = " " THEN count = count + 1
NEXT
NEXT
CountSpaces% = count
END FUNCTION
'used in PlaceWord
FUNCTION Match% (word AS STRING, template AS STRING)
DIM i AS INTEGER, c AS STRING
Match% = 0
IF LEN(word) <> LEN(template) THEN EXIT FUNCTION
FOR i = 1 TO LEN(template)
IF ASC(template, i) <> 32 AND (ASC(word, i) <> ASC(template, i)) THEN EXIT FUNCTION
NEXT
Match% = -1
END FUNCTION
'heart of puzzle builder
SUB PlaceWord
' place the words randomly in the grid
' start at random spot and work forward or back 100 times = all the squares
' for each open square try the 8 directions for placing the word
' even if word fits Rossetta Challenge task requires leaving 11 openings to insert ROSETTA CODE,
' exactly 11 spaces needs to be left, if/when this occurs FILLED will be set true to signal finished to main loop
' if place a word update L$, WI, W$(WI), WX(WI), WY(WI), WD(WI)
DIM wd$, wLen AS _BYTE, spot AS _BYTE, testNum AS _BYTE, rdir AS _BYTE
DIM x AS _BYTE, y AS _BYTE, d AS _BYTE, dNum AS _BYTE, rdd AS _BYTE
DIM template$, b1 AS _BIT, b2 AS _BIT
DIM i AS _BYTE, j AS _BYTE, wate$
wd$ = WORDS$(WORDSINDEX) 'the right side is all shared
'skip too many long words
IF LengthLimit(LEN(wd$)) THEN LengthLimit(LEN(wd$)) = LengthLimit(LEN(wd$)) - 1 ELSE EXIT SUB 'skip long ones
wLen = LEN(wd$) - 1 ' from the spot there are this many letters to check
spot = INT(RND * 100) ' a random spot on grid
testNum = 1 ' when this hits 100 we've tested all possible spots on grid
IF RND < .5 THEN rdir = -1 ELSE rdir = 1 ' go forward or back from spot for next test
WHILE testNum < 101
y = INT(spot / 10)
x = spot MOD 10
IF L$(x, y) = MID$(wd$, 1, 1) OR L$(x, y) = " " THEN
d = INT(8 * RND)
IF RND < .5 THEN rdd = -1 ELSE rdd = 1
dNum = 1
WHILE dNum < 9
'will wd$ fit? from at x, y
template$ = ""
b1 = wLen * DX(d) + x >= 0 AND wLen * DX(d) + x <= 9
b2 = wLen * DY(d) + y >= 0 AND wLen * DY(d) + y <= 9
IF b1 AND b2 THEN 'build the template of letters and spaces from Letter grid
FOR i = 0 TO wLen
template$ = template$ + L$(x + i * DX(d), y + i * DY(d))
NEXT
IF Match%(wd$, template$) THEN 'the word will fit but does it fill anything?
FOR j = 1 TO LEN(template$)
IF ASC(template$, j) = 32 THEN 'yes a space to fill
FOR i = 0 TO wLen
L$(x + i * DX(d), y + i * DY(d)) = MID$(wd$, i + 1, 1)
NEXT
WI = WI + 1
W$(WI) = wd$: WX(WI) = x: WY(WI) = y: WD(WI) = d
IF CountSpaces% = 0 THEN FILLED = -1
EXIT SUB 'get out now that word is loaded
END IF
NEXT
'if still here keep looking
END IF
END IF
d = (d + 8 + rdd) MOD 8
dNum = dNum + 1
WEND
END IF
spot = (spot + 100 + rdir) MOD 100
testNum = testNum + 1
WEND
END SUB
SUB FindAllWords
DIM wd$, wLen AS _BYTE, i AS INTEGER, x AS _BYTE, y AS _BYTE, d AS _BYTE
DIM template$, b1 AS _BIT, b2 AS _BIT, j AS _BYTE, wate$
FOR i = 1 TO NWORDS
wd$ = CWORDS$(i)
wLen = LEN(wd$) - 1
FOR y = 0 TO 9
FOR x = 0 TO 9
IF L$(x, y) = MID$(wd$, 1, 1) THEN
FOR d = 0 TO 7
b1 = wLen * DX(d) + x >= 0 AND wLen * DX(d) + x <= 9
b2 = wLen * DY(d) + y >= 0 AND wLen * DY(d) + y <= 9
IF b1 AND b2 THEN 'build the template of letters and spaces from Letter grid
template$ = ""
FOR j = 0 TO wLen
template$ = template$ + L$(x + j * DX(d), y + j * DY(d))
NEXT
IF template$ = wd$ THEN 'founda word
'store it
ALLindex = ALLindex + 1
ALL$(ALLindex) = wd$: AllX(ALLindex) = x: AllY(ALLindex) = y: AllD(ALLindex) = d
'report it
LOCATE 22, 1: PRINT SPACE$(50)
LOCATE 22, 1: PRINT "Found: "; wd$; " ("; Trm$(x); ", "; Trm$(y); ") >>>---> "; Trm$(d);
INPUT " Press enter...", wate$
END IF
END IF
NEXT d
END IF
NEXT x
NEXT y
NEXT i
END SUB
SUB FilePuzzle
DIM i AS _BYTE, r AS _BYTE, c AS _BYTE, b$
OPEN "WS Puzzle.txt" FOR OUTPUT AS #1
PRINT #1, " 0 1 2 3 4 5 6 7 8 9"
PRINT #1, ""
FOR r = 0 TO 9
b$ = Trm$(r) + " "
FOR c = 0 TO 9
b$ = b$ + L$(c, r) + " "
NEXT
PRINT #1, b$
NEXT
PRINT #1, ""
PRINT #1, "Directions >>>---> 0 = East, 1 = SE, 2 = South, 3 = SW, 4 = West, 5 = NW, 6 = North, 7 = NE"
PRINT #1, ""
PRINT #1, " These are the items from unixdict.txt used to build the puzzle:"
PRINT #1, ""
FOR i = 1 TO WI STEP 2
PRINT #1, RIGHT$(SPACE$(7) + Trm$(i), 7); ") "; RIGHT$(SPACE$(7) + W$(i), 10); " ("; Trm$(WX(i)); ", "; Trm$(WY(i)); ") >>>---> "; Trm$(WD(i));
IF i + 1 <= WI THEN
PRINT #1, RIGHT$(SPACE$(7) + Trm$(i + 1), 7); ") "; RIGHT$(SPACE$(7) + W$(i + 1), 10); " ("; Trm$(WX(i + 1)); ", "; Trm$(WY(i + 1)); ") >>>---> "; Trm$(WD(i + 1))
ELSE
PRINT #1, ""
END IF
NEXT
PRINT #1, ""
PRINT #1, " These are the items from unixdict.txt found embedded in the puzzle:"
PRINT #1, ""
FOR i = 1 TO ALLindex STEP 2
PRINT #1, RIGHT$(SPACE$(7) + Trm$(i), 7); ") "; RIGHT$(SPACE$(7) + ALL$(i), 10); " ("; Trm$(AllX(i)); ", "; Trm$(AllY(i)); ") >>>---> "; Trm$(AllD(i));
IF i + 1 <= ALLindex THEN
PRINT #1, RIGHT$(SPACE$(7) + Trm$(i + 1), 7); ") "; RIGHT$(SPACE$(7) + ALL$(i + 1), 10); " ("; Trm$(AllX(i + 1)); ", "; Trm$(AllY(i + 1)); ") >>>---> "; Trm$(AllD(i + 1))
ELSE
PRINT #1, ""
END IF
NEXT
CLOSE #1
END SUB</syntaxhighlight>
 
----
 
'''Sample Output:'''
<br><br><code>
&nbsp;0 1 2 3 4 5 6 7 8 9 <br>
0 t g a m m R l b a r <br>
1 o e O k y u i l u b <br>
2 l S e e n n i o a t <br>
3 s a g d E u i d e w <br>
4 k T c t e h g s a T <br>
5 s e n o j b o A e r <br>
6 C l g n c o a p g r <br>
7 l i o d i u m u e O <br>
8 k a e r f D d y c t <br>
9 t j E a i d r a p h <br></code>
<br>Directions >>>---> 0 = East, 1 = SE, 2 = South, 3 = SW, 4 = West, 5 = NW, 6 = North, 7 = NE<br>
<br>
These are the items from unixdict.txt used to build the puzzle:
1) odium (2, 7) >>>---> 0 2) resiny (9, 6) >>>---> 5
3) debauch (3, 3) >>>---> 1 4) freak (4, 8) >>>---> 4
5) jones (4, 5) >>>---> 4 6) radium (9, 5) >>>---> 5
7) hope (5, 4) >>>---> 1 8) coca (4, 6) >>>---> 5
9) slot (0, 3) >>>---> 6 10) aid (3, 9) >>>---> 0
11) gunk (6, 4) >>>---> 5 12) keg (0, 4) >>>---> 1
13) aile (1, 8) >>>---> 6 14) set (7, 4) >>>---> 7
15) wall (9, 3) >>>---> 5 16) rye (6, 9) >>>---> 7
17) our (7, 2) >>>---> 7 18) bar (7, 0) >>>---> 0
19) par (8, 9) >>>---> 4 20) gam (1, 0) >>>---> 0
21) dee (3, 3) >>>---> 5 22) ton (3, 4) >>>---> 2
23) dab (7, 3) >>>---> 7 24) jed (1, 9) >>>---> 7
25) bin (7, 0) >>>---> 3 26) pet (7, 6) >>>---> 1
27) sag (0, 3) >>>---> 0 28) nco (3, 6) >>>---> 0
29) dug (6, 8) >>>---> 7 30) oat (2, 7) >>>---> 3
31) oil (2, 7) >>>---> 4 32) nee (4, 2) >>>---> 4
These are the items from unixdict.txt found embedded in the puzzle:<br>
1) abe (6, 6) >>>---> 5 2) abed (6, 6) >>>---> 5
3) aid (3, 9) >>>---> 0 4) ail (1, 8) >>>---> 6
5) aile (1, 8) >>>---> 6 6) ali (8, 0) >>>---> 3
7) all (8, 2) >>>---> 5 8) bad (9, 1) >>>---> 3
9) bar (7, 0) >>>---> 0 10) bed (5, 5) >>>---> 5
11) bin (7, 0) >>>---> 3 12) but (7, 0) >>>---> 1
13) cal (2, 4) >>>---> 5 14) coca (4, 6) >>>---> 5
15) cud (4, 6) >>>---> 1 16) dab (7, 3) >>>---> 7
17) dar (7, 3) >>>---> 1 18) debauch (3, 3) >>>---> 1
19) dee (3, 3) >>>---> 5 20) dew (7, 3) >>>---> 0
21) dug (6, 8) >>>---> 7 22) edt (3, 2) >>>---> 2
23) eli (1, 5) >>>---> 2 24) etc (4, 4) >>>---> 4
25) freak (4, 8) >>>---> 4 26) gam (1, 0) >>>---> 0
27) gas (2, 3) >>>---> 4 28) goa (6, 4) >>>---> 2
29) gsa (6, 4) >>>---> 0 30) gun (6, 4) >>>---> 5
31) gunk (6, 4) >>>---> 5 32) hop (5, 4) >>>---> 1
33) hope (5, 4) >>>---> 1 34) hun (5, 4) >>>---> 6
35) ida (6, 2) >>>---> 1 36) iii (6, 1) >>>---> 2
37) iii (6, 3) >>>---> 6 38) inn (6, 2) >>>---> 4
39) inn (4, 7) >>>---> 5 40) jail (1, 9) >>>---> 6
41) jed (1, 9) >>>---> 7 42) jon (4, 5) >>>---> 4
43) jones (4, 5) >>>---> 4 44) keg (0, 4) >>>---> 1
45) lac (0, 2) >>>---> 1 46) law (7, 1) >>>---> 1
47) lea (0, 2) >>>---> 7 48) lot (0, 2) >>>---> 6
49) lund (6, 0) >>>---> 3 50) mao (6, 7) >>>---> 6
51) nco (3, 6) >>>---> 0 52) nee (4, 2) >>>---> 4
53) nib (5, 2) >>>---> 7 54) nne (5, 2) >>>---> 4
55) not (3, 6) >>>---> 6 56) oat (7, 2) >>>---> 0
57) oat (2, 7) >>>---> 3 58) odium (2, 7) >>>---> 0
59) oil (2, 7) >>>---> 4 60) one (3, 5) >>>---> 4
61) our (7, 2) >>>---> 7 62) par (8, 9) >>>---> 4
63) pet (7, 6) >>>---> 1 64) radium (9, 5) >>>---> 5
65) rap (6, 9) >>>---> 0 66) resin (9, 6) >>>---> 5
67) resiny (9, 6) >>>---> 5 68) rio (3, 8) >>>---> 7
69) rye (6, 9) >>>---> 7 70) sag (0, 3) >>>---> 0
71) sen (0, 5) >>>---> 0 72) set (7, 4) >>>---> 7
73) sin (7, 4) >>>---> 5 74) slot (0, 3) >>>---> 6
75) tao (9, 2) >>>---> 4 76) tao (0, 9) >>>---> 7
77) tee (0, 0) >>>---> 1 78) ton (3, 4) >>>---> 2
79) tub (9, 2) >>>---> 5 80) wall (9, 3) >>>---> 5
81) wed (9, 3) >>>---> 4
<br>
 
==={{header|Visual Basic .NET}}===
{{trans|C#}}
<syntaxhighlight lang="vbnet">Module Module1
 
ReadOnly Dirs As Integer(,) = {
{1, 0}, {0, 1}, {1, 1},
{1, -1}, {-1, 0},
{0, -1}, {-1, -1}, {-1, 1}
}
 
Const RowCount = 10
Const ColCount = 10
Const GridSize = RowCount * ColCount
Const MinWords = 25
 
Class Grid
Public cells(RowCount - 1, ColCount - 1) As Char
Public solutions As New List(Of String)
Public numAttempts As Integer
 
Sub New()
For i = 0 To RowCount - 1
For j = 0 To ColCount - 1
cells(i, j) = ControlChars.NullChar
Next
Next
End Sub
End Class
 
Dim Rand As New Random()
 
Sub Main()
PrintResult(CreateWordSearch(ReadWords("unixdict.txt")))
End Sub
 
Function ReadWords(filename As String) As List(Of String)
Dim maxlen = Math.Max(RowCount, ColCount)
Dim words As New List(Of String)
 
Dim objReader As New IO.StreamReader(filename)
Dim line As String
Do While objReader.Peek() <> -1
line = objReader.ReadLine()
If line.Length > 3 And line.Length < maxlen Then
If line.All(Function(c) Char.IsLetter(c)) Then
words.Add(line)
End If
End If
Loop
 
Return words
End Function
 
Function CreateWordSearch(words As List(Of String)) As Grid
For numAttempts = 1 To 1000
Shuffle(words)
 
Dim grid As New Grid()
Dim messageLen = PlaceMessage(grid, "Rosetta Code")
Dim target = GridSize - messageLen
 
Dim cellsFilled = 0
For Each word In words
cellsFilled = cellsFilled + TryPlaceWord(grid, word)
If cellsFilled = target Then
If grid.solutions.Count >= MinWords Then
grid.numAttempts = numAttempts
Return grid
Else
'grid is full but we didn't pack enough words, start over
Exit For
End If
End If
Next
Next
 
Return Nothing
End Function
 
Function PlaceMessage(grid As Grid, msg As String) As Integer
msg = msg.ToUpper()
msg = msg.Replace(" ", "")
 
If msg.Length > 0 And msg.Length < GridSize Then
Dim gapSize As Integer = GridSize / msg.Length
 
Dim pos = 0
Dim lastPos = -1
For i = 0 To msg.Length - 1
If i = 0 Then
pos = pos + Rand.Next(gapSize - 1)
Else
pos = pos + Rand.Next(2, gapSize - 1)
End If
Dim r As Integer = Math.Floor(pos / ColCount)
Dim c = pos Mod ColCount
 
grid.cells(r, c) = msg(i)
 
lastPos = pos
Next
Return msg.Length
End If
 
Return 0
End Function
 
Function TryPlaceWord(grid As Grid, word As String) As Integer
Dim randDir = Rand.Next(Dirs.GetLength(0))
Dim randPos = Rand.Next(GridSize)
 
For d = 0 To Dirs.GetLength(0) - 1
Dim dd = (d + randDir) Mod Dirs.GetLength(0)
 
For p = 0 To GridSize - 1
Dim pp = (p + randPos) Mod GridSize
 
Dim lettersPLaced = TryLocation(grid, word, dd, pp)
If lettersPLaced > 0 Then
Return lettersPLaced
End If
Next
Next
 
Return 0
End Function
 
Function TryLocation(grid As Grid, word As String, dir As Integer, pos As Integer) As Integer
Dim r As Integer = pos / ColCount
Dim c = pos Mod ColCount
Dim len = word.Length
 
'check bounds
If (Dirs(dir, 0) = 1 And len + c >= ColCount) Or (Dirs(dir, 0) = -1 And len - 1 > c) Or (Dirs(dir, 1) = 1 And len + r >= RowCount) Or (Dirs(dir, 1) = -1 And len - 1 > r) Then
Return 0
End If
If r = RowCount OrElse c = ColCount Then
Return 0
End If
 
Dim rr = r
Dim cc = c
 
'check cells
For i = 0 To len - 1
If grid.cells(rr, cc) <> ControlChars.NullChar AndAlso grid.cells(rr, cc) <> word(i) Then
Return 0
End If
 
cc = cc + Dirs(dir, 0)
rr = rr + Dirs(dir, 1)
Next
 
'place
Dim overlaps = 0
rr = r
cc = c
For i = 0 To len - 1
If grid.cells(rr, cc) = word(i) Then
overlaps = overlaps + 1
Else
grid.cells(rr, cc) = word(i)
End If
 
If i < len - 1 Then
cc = cc + Dirs(dir, 0)
rr = rr + Dirs(dir, 1)
End If
Next
 
Dim lettersPlaced = len - overlaps
If lettersPlaced > 0 Then
grid.solutions.Add(String.Format("{0,-10} ({1},{2})({3},{4})", word, c, r, cc, rr))
End If
 
Return lettersPlaced
End Function
 
Sub PrintResult(grid As Grid)
If IsNothing(grid) OrElse grid.numAttempts = 0 Then
Console.WriteLine("No grid to display")
Return
End If
 
Console.WriteLine("Attempts: {0}", grid.numAttempts)
Console.WriteLine("Number of words: {0}", GridSize)
Console.WriteLine()
 
Console.WriteLine(" 0 1 2 3 4 5 6 7 8 9")
For r = 0 To RowCount - 1
Console.WriteLine()
Console.Write("{0} ", r)
For c = 0 To ColCount - 1
Console.Write(" {0} ", grid.cells(r, c))
Next
Next
 
Console.WriteLine()
Console.WriteLine()
 
For i = 0 To grid.solutions.Count - 1
If i Mod 2 = 0 Then
Console.Write("{0}", grid.solutions(i))
Else
Console.WriteLine(" {0}", grid.solutions(i))
End If
Next
 
Console.WriteLine()
End Sub
 
'taken from https://stackoverflow.com/a/20449161
Sub Shuffle(Of T)(list As IList(Of T))
Dim r As Random = New Random()
For i = 0 To list.Count - 1
Dim index As Integer = r.Next(i, list.Count)
If i <> index Then
' swap list(i) and list(index)
Dim temp As T = list(i)
list(i) = list(index)
list(index) = temp
End If
Next
End Sub
 
End Module</syntaxhighlight>
{{out}}
<pre>Attempts: 148
Number of words: 100
 
0 1 2 3 4 5 6 7 8 9
 
0 c d p R e c h a r e
1 O i u b a k e S l v
2 k n l E m c a c a i
3 T e s i T x A s n t
4 t C e s a l O a g a
5 a j D l l e E h l g
6 l u f e m a h s e r
7 l t c a r f e r y u
8 f e r r e i r a m p
9 f a m i l i s m i s
 
refract (7,7)(1,7) shameful (7,6)(0,6)
ferreira (0,8)(7,8) familism (0,9)(7,9)
langley (8,1)(8,7) sake (7,3)(4,0)
pulse (2,0)(2,4) purgative (9,8)(9,0)
cacm (7,2)(4,2) enid (1,3)(1,0)
char (5,0)(8,0) flax (2,6)(5,3)
tall (0,4)(0,7) isle (3,3)(3,6)
jute (1,5)(1,8) myel (8,8)(8,5)
bake (3,1)(6,1) cell (2,7)(5,4)
marsh (7,9)(7,5) keel (0,2)(3,5)
spur (9,9)(9,6) leaf (5,4)(5,7)
cilia (0,0)(4,4) sims (9,9)(6,9)
marsha (7,9)(7,4)</pre>
 
=={{header|C sharp}}==
{{trans|Java}}
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Linq;
Line 466 ⟶ 1,558:
}
}
}</langsyntaxhighlight>
 
<pre>
Line 499 ⟶ 1,591:
nyu (5,2)(7,4) ape (5,7)(3,7)
era (3,7)(5,9) ere (1,2)(3,0)
</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">
#include <iomanip>
#include <ctime>
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <fstream>
 
const int WID = 10, HEI = 10, MIN_WORD_LEN = 3, MIN_WORD_CNT = 25;
 
class Cell {
public:
Cell() : val( 0 ), cntOverlap( 0 ) {}
char val; int cntOverlap;
};
class Word {
public:
Word( std::string s, int cs, int rs, int ce, int re, int dc, int dr ) :
word( s ), cols( cs ), rows( rs ), cole( ce ), rowe( re ), dx( dc ), dy( dr ) {}
bool operator ==( const std::string& s ) { return 0 == word.compare( s ); }
std::string word;
int cols, rows, cole, rowe, dx, dy;
};
class words {
public:
void create( std::string& file ) {
std::ifstream f( file.c_str(), std::ios_base::in );
std::string word;
while( f >> word ) {
if( word.length() < MIN_WORD_LEN || word.length() > WID || word.length() > HEI ) continue;
if( word.find_first_not_of( "abcdefghijklmnopqrstuvwxyz" ) != word.npos ) continue;
dictionary.push_back( word );
}
f.close();
std::random_shuffle( dictionary.begin(), dictionary.end() );
buildPuzzle();
}
 
void printOut() {
std::cout << "\t";
for( int x = 0; x < WID; x++ ) std::cout << x << " ";
std::cout << "\n\n";
for( int y = 0; y < HEI; y++ ) {
std::cout << y << "\t";
for( int x = 0; x < WID; x++ )
std::cout << puzzle[x][y].val << " ";
std::cout << "\n";
}
size_t wid1 = 0, wid2 = 0;
for( size_t x = 0; x < used.size(); x++ ) {
if( x & 1 ) {
if( used[x].word.length() > wid1 ) wid1 = used[x].word.length();
} else {
if( used[x].word.length() > wid2 ) wid2 = used[x].word.length();
}
}
std::cout << "\n";
std::vector<Word>::iterator w = used.begin();
while( w != used.end() ) {
std::cout << std::right << std::setw( wid1 ) << ( *w ).word << " (" << ( *w ).cols << ", " << ( *w ).rows << ") ("
<< ( *w ).cole << ", " << ( *w ).rowe << ")\t";
w++;
if( w == used.end() ) break;
std::cout << std::setw( wid2 ) << ( *w ).word << " (" << ( *w ).cols << ", " << ( *w ).rows << ") ("
<< ( *w ).cole << ", " << ( *w ).rowe << ")\n";
w++;
}
std::cout << "\n\n";
}
private:
void addMsg() {
std::string msg = "ROSETTACODE";
int stp = 9, p = rand() % stp;
for( size_t x = 0; x < msg.length(); x++ ) {
puzzle[p % WID][p / HEI].val = msg.at( x );
p += rand() % stp + 4;
}
}
int getEmptySpaces() {
int es = 0;
for( int y = 0; y < HEI; y++ ) {
for( int x = 0; x < WID; x++ ) {
if( !puzzle[x][y].val ) es++;
}
}
return es;
}
bool check( std::string word, int c, int r, int dc, int dr ) {
for( size_t a = 0; a < word.length(); a++ ) {
if( c < 0 || r < 0 || c >= WID || r >= HEI ) return false;
if( puzzle[c][r].val && puzzle[c][r].val != word.at( a ) ) return false;
c += dc; r += dr;
}
return true;
}
bool setWord( std::string word, int c, int r, int dc, int dr ) {
if( !check( word, c, r, dc, dr ) ) return false;
int sx = c, sy = r;
for( size_t a = 0; a < word.length(); a++ ) {
if( !puzzle[c][r].val ) puzzle[c][r].val = word.at( a );
else puzzle[c][r].cntOverlap++;
c += dc; r += dr;
}
used.push_back( Word( word, sx, sy, c - dc, r - dr, dc, dr ) );
return true;
}
bool add2Puzzle( std::string word ) {
int x = rand() % WID, y = rand() % HEI,
z = rand() % 8;
for( int d = z; d < z + 8; d++ ) {
switch( d % 8 ) {
case 0: if( setWord( word, x, y, 1, 0 ) ) return true; break;
case 1: if( setWord( word, x, y, -1, -1 ) ) return true; break;
case 2: if( setWord( word, x, y, 0, 1 ) ) return true; break;
case 3: if( setWord( word, x, y, 1, -1 ) ) return true; break;
case 4: if( setWord( word, x, y, -1, 0 ) ) return true; break;
case 5: if( setWord( word, x, y, -1, 1 ) ) return true; break;
case 6: if( setWord( word, x, y, 0, -1 ) ) return true; break;
case 7: if( setWord( word, x, y, 1, 1 ) ) return true; break;
}
}
return false;
}
void clearWord() {
if( used.size() ) {
Word lastW = used.back();
used.pop_back();
 
for( size_t a = 0; a < lastW.word.length(); a++ ) {
if( puzzle[lastW.cols][lastW.rows].cntOverlap == 0 ) {
puzzle[lastW.cols][lastW.rows].val = 0;
}
if( puzzle[lastW.cols][lastW.rows].cntOverlap > 0 ) {
puzzle[lastW.cols][lastW.rows].cntOverlap--;
}
lastW.cols += lastW.dx; lastW.rows += lastW.dy;
}
}
}
void buildPuzzle() {
addMsg();
int es = 0, cnt = 0;
size_t idx = 0;
do {
for( std::vector<std::string>::iterator w = dictionary.begin(); w != dictionary.end(); w++ ) {
if( std::find( used.begin(), used.end(), *w ) != used.end() ) continue;
if( add2Puzzle( *w ) ) {
es = getEmptySpaces();
if( !es && used.size() >= MIN_WORD_CNT )
return;
}
}
clearWord();
std::random_shuffle( dictionary.begin(), dictionary.end() );
 
} while( ++cnt < 100 );
}
std::vector<Word> used;
std::vector<std::string> dictionary;
Cell puzzle[WID][HEI];
};
int main( int argc, char* argv[] ) {
unsigned s = unsigned( time( 0 ) );
srand( s );
words w; w.create( std::string( "unixdict.txt" ) );
w.printOut();
return 0;
}
</syntaxhighlight>
{{out}}
<pre>
 
0 1 2 3 4 5 6 7 8 9
 
0 d b R f t a u n p w
1 O i l o b h a m a o
2 S r e e r p E t r h
3 e c o r a T l i e T
4 f a m e w A e n t s
5 l n C h u y p g o l
6 o n p t O n s e o D
7 w e u b e f i a c b
8 E i n e m a d a m e
9 e s s k a p l a n e
 
thereof (3, 6) (3, 0) seen (2, 9) (5, 6)
pareto (8, 0) (8, 5) wolf (0, 7) (0, 4)
crib (1, 3) (1, 0) tinge (7, 2) (7, 6)
sienna (1, 9) (1, 4) war (4, 4) (4, 2)
dispel (6, 8) (6, 3) kaplan (3, 9) (8, 9)
tau (4, 0) (6, 0) lob (2, 1) (4, 1)
how (9, 2) (9, 0) same (6, 6) (9, 9)
men (4, 8) (2, 8) feb (5, 7) (3, 7)
ham (5, 1) (7, 1) moe (2, 4) (2, 2)
pan (5, 2) (7, 0) yuh (5, 5) (3, 5)
pun (2, 6) (2, 8) load (9, 5) (6, 8)
can (1, 3) (1, 5) madame (4, 8) (9, 8)
gob (7, 5) (9, 7) rib (1, 2) (1, 0)
nee (5, 6) (3, 8) set (9, 4) (7, 2)
alp (7, 9) (5, 9) wolfe (0, 7) (0, 3)
the (3, 6) (3, 4) low (0, 5) (0, 7)
tea (3, 6) (5, 8) era (8, 3) (8, 1)
nne (1, 5) (1, 7) amen (5, 8) (2, 8)
coot (8, 7) (8, 4) anne (1, 4) (1, 7)
reid (3, 3) (0, 0) sse (2, 9) (0, 9)
</pre>
 
=={{header|D}}==
{{trans|Java}}
<langsyntaxhighlight Dlang="d">import std.random : Random, uniform, randomShuffle;
import std.stdio;
 
Line 696 ⟶ 1,998:
writeln(grid.solutions[size - 1]);
}
}</langsyntaxhighlight>
 
{{out}}
Line 735 ⟶ 2,037:
<br>
The link to "unixdict" appears to be broken so I've used instead the dictionary at "/usr/share/dict/words" which came pre-installed with my Ubuntu 16.04 distribution. I've no idea whether these dictionaries are the same or not.
<langsyntaxhighlight lang="go">package main
 
import (
Line 923 ⟶ 2,225:
unixDictPath := "/usr/share/dict/words"
printResult(createWordSearch(readWords(unixDictPath)))
}</langsyntaxhighlight>
 
{{out}}
Line 964 ⟶ 2,266:
Implementation:
 
<langsyntaxhighlight Jlang="j">require'web/gethttp'
 
unixdict=:verb define
Line 1,016 ⟶ 2,318:
puz=. (_23{.":i.10),' ',1j1#"1(":i.10 1),.' ',.10 10$fill (I.grid=' ')} grid
puz,' ',1 1}._1 _1}.":((</.~ <.) i.@# * 3%#)key
)</langsyntaxhighlight>
 
Notes:
Line 1,060 ⟶ 2,362:
Example run:
 
<langsyntaxhighlight Jlang="j"> genpuz''
0 1 2 3 4 5 6 7 8 9
Line 1,083 ⟶ 2,385:
cop 10 8 nw │ paz 8 10 west │ wan 9 6 west
fizzle 1 6 sw │ penna 1 9 south│
</syntaxhighlight>
</lang>
 
=={{header|Java}}==
{{works with|Java|7}}
<langsyntaxhighlight lang="java">import java.io.*;
import static java.lang.String.format;
import java.util.*;
Line 1,259 ⟶ 2,561:
System.out.println(grid.solutions.get(size - 1));
}
}</langsyntaxhighlight>
 
<pre>Attempts: 2
Line 1,291 ⟶ 2,593:
liz (9,8)(7,8) dam (2,0)(0,2)
via (8,9)(8,7)</pre>
 
 
=={{header|Julia}}==
Modified from the Go version. The task listed word list is offline, so the Debian distribution file "words.txt" was used instead.
<langsyntaxhighlight lang="julia">using Random
 
const stepdirections = [[1, 0], [0, 1], [1, 1], [1, -1], [-1, 0], [0, -1], [-1, -1], [-1, 1]]
Line 1,411 ⟶ 2,712:
 
printresult(wordmatrix("words.txt", false))
</langsyntaxhighlight>{{output}}<pre>
Attempts: 1
Number of words: 25
Line 1,444 ⟶ 2,745:
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">// version 1.2.0
 
import java.util.Random
Line 1,594 ⟶ 2,895:
fun main(args: Array<String>) {
printResult(createWordSearch(readWords("unixdict.txt")))
}</langsyntaxhighlight>
 
Sample output:
Line 1,629 ⟶ 2,930:
act (2,0)(0,2)
</pre>
=={{header|Perl}}==
<lang perl>#!/usr/bin/perl
 
=={{header|Nim}}==
use strict; # http://www.rosettacode.org/wiki/Word_search
{{trans|D}}
<syntaxhighlight lang="nim">import random, sequtils, strformat, strutils
 
const
 
Dirs = [[1, 0], [ 0, 1], [ 1, 1],
[1, -1], [-1, 0],
[0, -1], [-1, -1], [-1, 1]]
 
NRows = 10
NCols = 10
GridSize = NRows * NCols
MinWords = 25
 
type Grid = ref object
numAttempts: Natural
cells: array[NRows, array[NCols, char]]
solutions: seq[string]
 
proc readWords(filename: string): seq[string] =
 
const MaxLen = max(NRows, NCols)
 
for word in filename.lines():
if word.len in 3..MaxLen:
if word.allCharsInSet(Letters):
result.add word.toLowerAscii
 
 
proc placeMessage(grid: var Grid; msg: string): int =
let msg = msg.map(toUpperAscii).filter(isUpperAscii).join()
if msg.len in 1..<GridSize:
let gapSize = GridSize div msg.len
for i in 0..msg.high:
let pos = i * gapSize + rand(gapSize - 1)
grid.cells[pos div NCols][pos mod NCols] = msg[i]
result = msg.len
 
 
proc tryLocation(grid: var Grid; word: string; dir, pos: Natural): int =
let row = pos div NCols
let col = pos mod NCols
let length = word.len
 
# Check bounds.
if (Dirs[dir][0] == 1 and (length + col) > NCols) or
(Dirs[dir][0] == -1 and (length - 1) > col) or
(Dirs[dir][1] == 1 and (length + row) > NRows) or
(Dirs[dir][1] == -1 and (length - 1) > row):
return 0
 
# Check cells.
var r = row
var c = col
for ch in word:
if grid.cells[r][c] != '\0' and grid.cells[r][c] != ch: return 0
c += Dirs[dir][0]
r += Dirs[dir][1]
 
# Place.
r = row
c = col
var overlaps = 0
for i, ch in word:
if grid.cells[r][c] == ch: inc overlaps
else: grid.cells[r][c] = ch
if i < word.high:
c += Dirs[dir][0]
r += Dirs[dir][1]
 
let lettersPlaced = length - overlaps
if lettersPlaced > 0:
grid.solutions.add &"{word:<10} ({col}, {row}) ({c}, {r})"
 
result = lettersPlaced
 
 
proc tryPlaceWord(grid: var Grid; word: string): int =
let randDir = rand(Dirs.high)
let randPos = rand(GridSize - 1)
 
for dir in 0..Dirs.high:
let dir = (dir + randDir) mod Dirs.len
for pos in 0..<GridSize:
let pos = (pos + randPos) mod GridSize
let lettersPlaced = grid.tryLocation(word, dir, pos)
if lettersPlaced > 0:
return lettersPlaced
 
 
proc initGrid(words: seq[string]): Grid =
var words = words
for numAttempts in 1..100:
words.shuffle()
new(result)
let messageLen = result.placeMessage("Rosetta Code")
let target = GridSize - messageLen
 
var cellsFilled = 0
for word in words:
cellsFilled += result.tryPlaceWord(word)
if cellsFilled == target:
if result.solutions.len >= MinWords:
result.numAttempts = numAttempts
return
# Grid is full but we didn't pack enough words: start over.
break
 
proc printResult(grid: Grid) =
if grid.isNil or grid.numAttempts == 0:
echo "No grid to display."
return
 
let size = grid.solutions.len
echo "Attempts: ", grid.numAttempts
echo "Number of words: ", size
 
echo "\n 0 1 2 3 4 5 6 7 8 9\n"
for r in 0..<NRows:
echo &"{r} ", grid.cells[r].join(" ")
echo()
 
for i in countup(0, size - 2, 2):
echo grid.solutions[i], " ", grid.solutions[i + 1]
if (size and 1) == 1:
echo grid.solutions[^1]
 
 
randomize()
let grid = initGrid("unixdict.txt".readWords())
grid.printResult()</syntaxhighlight>
 
{{out}}
<pre>Attempts: 2
Number of words: 29
 
0 1 2 3 4 5 6 7 8 9
 
0 s i a b l R d a t d
1 u x i i m e O l b e
2 n o v i r w S l u j
3 k n l a E b z i b T
4 a k n y o y e e T e
5 y g t l e A a d d l
6 e f u l f i l l C d
7 r e g a y o v O l d
8 f o h s l e w D i a
9 f o g y r E p i n s
 
derange (6, 0) (0, 6) fulfill (1, 6) (7, 6)
frey (0, 8) (0, 5) allied (7, 0) (7, 5)
sally (3, 8) (3, 4) anvil (0, 4) (4, 0)
saddle (9, 9) (9, 4) voyage (6, 7) (1, 7)
iii (3, 2) (1, 0) sunk (0, 0) (0, 3)
bub (8, 1) (8, 3) fogy (0, 9) (3, 9)
zeal (6, 3) (6, 6) milky (4, 1) (0, 5)
welsh (6, 8) (2, 8) knox (1, 4) (1, 1)
allay (9, 8) (5, 4) jed (9, 2) (9, 0)
snip (9, 9) (6, 9) bed (5, 3) (7, 5)
bmw (3, 0) (5, 2) gut (2, 7) (2, 5)
rev (4, 9) (6, 7) tad (8, 0) (6, 0)
via (2, 2) (2, 0) ogle (1, 8) (4, 5)
add (6, 5) (8, 5) lob (3, 5) (5, 3)
lin (8, 7) (8, 9)</pre>
 
=={{header|Perl}}==
<syntaxhighlight lang="perl">use strict;
use warnings;
use feature <bitwise>;
use Path::Tiny;
use List::Util qw( shuffle );
Line 1,670 ⟶ 3,137:
}
substr $_, $pos, length $mask,
(substr( $_, $pos, length $mask ) &. ~. "$mask") |. "$expand";
push @played, join ' ', $word, $start, $end;
tr/.// > 0 or last;
Line 1,705 ⟶ 3,172:
while( /(?=(.(?:$gap.){$nm1}))/g )
{
my $pat = ($1 &. $mask) =~ tr/\0//dr;
$pat =~ tr/.// or next;
my $pos = "$-[1] $+[1]";
Line 1,729 ⟶ 3,196:
 
return undef;
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,758 ⟶ 3,225:
</pre>
 
=={{header|Perl 6Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
{{works with|Rakudo|2020.01}}
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\wordsearch.exw
-- ===========================
--</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">message</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"ROSETTACODE"</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">words</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">unix_dict</span><span style="color: #0000FF;">(),</span> <span style="color: #000000;">solution</span><span style="color: #0000FF;">=</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">placed</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">grid</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"""
X 0 1 2 3 4 5 6 7 8 9 X
0 X
1 X
2 X
3 X
4 X
5 X
6 X
7 X
8 X
9 X
X X X X X X X X X X X X"""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">DX</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">DY</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,+</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">wordsearch</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">grid</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">rqd</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">left</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">done</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">rw</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">shuffle</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">))),</span>
<span style="color: #000000;">rd</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">shuffle</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)),</span>
<span style="color: #000000;">rs</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">shuffle</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">100</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rs</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">sx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">((</span><span style="color: #000000;">rs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">sy</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)*</span><span style="color: #000000;">3</span><span style="color: #0000FF;">+</span><span style="color: #000000;">4</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rw</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rw</span><span style="color: #0000FF;">[</span><span style="color: #000000;">w</span><span style="color: #0000FF;">]]</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">,</span><span style="color: #000000;">done</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">rd</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dy</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">DX</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rd</span><span style="color: #0000FF;">[</span><span style="color: #000000;">d</span><span style="color: #0000FF;">]],</span><span style="color: #000000;">DY</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rd</span><span style="color: #0000FF;">[</span><span style="color: #000000;">d</span><span style="color: #0000FF;">]]},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">sx</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sy</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">chcount</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">newgrid</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">grid</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">grid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">!=</span><span style="color: #008000;">' '</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">word</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">chcount</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">chcount</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">newgrid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">nx</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dx</span>
<span style="color: #000000;">ny</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">dy</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">chcount</span><span style="color: #0000FF;">!=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">posinfo</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">sx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,(</span><span style="color: #000000;">sy</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">dx</span><span style="color: #0000FF;">-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,(</span><span style="color: #000000;">ny</span><span style="color: #0000FF;">-</span><span style="color: #000000;">dy</span><span style="color: #0000FF;">-</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">newdone</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">done</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]),</span><span style="color: #000000;">word</span><span style="color: #0000FF;">),</span>
<span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">done</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]),</span><span style="color: #000000;">posinfo</span><span style="color: #0000FF;">)}</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">rqd</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">left</span><span style="color: #0000FF;">-</span><span style="color: #000000;">chcount</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">message</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">placed</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">newgrid</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">newdone</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">return</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">left</span><span style="color: #0000FF;">-</span><span style="color: #000000;">chcount</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">message</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">wordsearch</span><span style="color: #0000FF;">(</span><span style="color: #000000;">newgrid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rqd</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">left</span><span style="color: #0000FF;">-</span><span style="color: #000000;">chcount</span><span style="color: #0000FF;">,</span><span style="color: #000000;">newdone</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">valid_word</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">3</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><</span><span style="color: #008000;">'a'</span>
<span style="color: #008080;">or</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">></span><span style="color: #008000;">'z'</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">valid_word</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">words</span><span style="color: #0000FF;">[$]</span>
<span style="color: #000000;">words</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..$-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d words loaded\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">))</span> <span style="color: #000080;font-style:italic;">-- 24822</span>
<span style="color: #000000;">wordsearch</span><span style="color: #0000FF;">(</span><span style="color: #000000;">grid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">25</span><span style="color: #0000FF;">,</span><span style="color: #000000;">100</span><span style="color: #0000FF;">,{{},{}})</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">11</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">4</span> <span style="color: #008080;">to</span> <span style="color: #000000;">31</span> <span style="color: #008080;">by</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">solution</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">][</span><span style="color: #000000;">y</span><span style="color: #0000FF;">]=</span><span style="color: #008000;">' '</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">solution</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">][</span><span style="color: #000000;">y</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">message</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">message</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">message</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..$]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">message</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">),</span><span style="color: #008000;">"X"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">))</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n%d words\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">placed</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]))</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">placed</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%10s %10s "</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">placed</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #7060A8;">sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">placed</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])})</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
24822 words loaded
0 1 2 3 4 5 6 7 8 9
0 R y g e r m a n y O
1 d r a g a v e S o E
2 c a t n w e w T l T
3 r t s e p h a o k A
4 a u e v p e d t k C
5 g l c a o l k O a e
6 n a t r h l c h o u
7 a s m p a c a d i a
8 v n r a d s j o i l
9 D y i p i E s a s h
 
42 words
<lang perl6>my $rows = 10;
salutary {7,1,0,1} idaho {9,4,5,4} jackdaw {8,6,2,6}
my $cols = 10;
darn {8,4,8,1} avenge {5,3,0,3} van {8,0,6,0}
war {2,4,0,4} crag {2,0,5,0} drag {1,0,1,3}
gam {5,0,7,2} stag {3,2,0,2} crass {5,2,9,6}
apr {8,3,6,3} staph {7,1,3,5} germany {0,2,0,8}
laos {6,5,9,8} chou {6,6,6,9} hell {3,5,6,5}
wee {2,4,4,2} acadia {7,4,7,9} yolk {0,8,3,8}
pap {7,3,9,3} pry {7,3,9,1} usn {4,1,2,3}
agave {1,2,1,6} nat {6,0,6,2} pee {3,4,1,6}
sash {9,6,9,9} eel {3,3,5,1} hid {9,9,7,7}
yip {9,1,9,3} wok {2,6,4,8} raw {0,4,2,4}
rave {6,3,3,3} oak {6,8,4,8} oil {8,7,8,9}
lao {6,5,8,7} pest {3,4,3,1} doe {7,7,5,9}
pet {4,4,2,2} arc {4,0,2,0} tau {4,7,6,9}
</pre>
 
=={{header|Python}}==
my $message = q:to/END/;
{{trans|Java}}
.....R....
{{works with|Python|3.x}}
......O...
<syntaxhighlight lang="python">
.......S..
import re
........E.
from random import shuffle, randint
T........T
.A........
..C.......
...O......
....D.....
.....E....
END
 
dirs = [[1, 0], [0, 1], [1, 1], [1, -1], [-1, 0], [0, -1], [-1, -1], [-1, 1]]
my %dir =
n_rows = 10
'→' => (1,0),
n_cols = 10
'↘' => (1,1),
grid_size = n_rows * n_cols
'↓' => (0,1),
min_words = 25
'↙' => (-1,1),
'←' => (-1,0),
'↖' => (-1,-1),
'↑' => (0,-1),
'↗' => (1,-1)
;
 
my @ws = $message.comb(/<print>/);
 
class Grid:
my $path = './unixdict.txt'; # or wherever
def __init__(self):
self.num_attempts = 0
self.cells = [['' for _ in range(n_cols)] for _ in range(n_rows)]
self.solutions = []
 
my @words = $path.IO.slurp.words.grep( { $_ !~~ /<-[a..z]>/ and 2 < .chars < 11 } ).pick(*);
my %index;
my %used;
 
def read_words(filename):
while @ws.first( * eq '.') {
max_len = max(n_rows, n_cols)
 
words = []
# find an unfilled cell
with open(filename, "r") as file:
my $i = @ws.grep( * eq '.', :k ).pick;
for line in file:
s = line.strip().lower()
if re.match(r'^[a-z]{3,' + re.escape(str(max_len)) + r'}$', s) is not None:
words.append(s)
 
return words
# translate the index to x / y coordinates
my ($x, $y) = $i % $cols, floor($i / $rows);
 
# find a word that fits
my $word = find($x, $y);
 
def place_message(grid, msg):
# Meh, reached an impasse, easier to just throw it all
msg = re.sub(r'[^A-Z]', "", msg.upper())
# away and start over rather than trying to backtrack.
restart, next unless $word;
 
message_len = len(msg)
%used{"$word"}++;
if 0 < message_len < grid_size:
gap_size = grid_size // message_len
 
# Keeps trying to placefor ani alreadyin used wordrange(0, choicesmessage_len):
pos = i * gap_size + randint(0, gap_size)
# must be limited, start over
grid.cells[pos // n_cols][pos % n_cols] = msg[i]
restart, next if %used{$word} > 15;
 
# Already used this word,return try againmessage_len
next if %index{$word.key};
 
return 0
# Add word to used word index
%index ,= $word;
 
# place the word into the grid
place($x, $y, $word);
 
def try_location(grid, word, direction, pos):
}
r = pos // n_cols
c = pos % n_cols
length = len(word)
 
# check bounds
display();
if (dirs[direction][0] == 1 and (length + c) > n_cols) or \
(dirs[direction][0] == -1 and (length - 1) > c) or \
(dirs[direction][1] == 1 and (length + r) > n_rows) or \
(dirs[direction][1] == -1 and (length - 1) > r):
return 0
 
rr = r
sub display {
cc = c
put flat " ", 'ABCDEFGHIJ'.comb;
i = 0
.put for (^10).map: { ($_).fmt(" %2d"), @ws[$_ * $cols .. ($_ + 1) * $cols - 1] }
overlaps = 0
put "\n Words used:";
my $max = 1 + %index.keys.max( *.chars ).chars;
for %index.sort {
printf "%{$max}s %4s %s ", .key, .value.key, .value.value;
print "\n" if $++ % 2;
}
say "\n"
}
 
# check cells
sub restart {
while i < length:
@ws = $message.comb(/<print>/);
if grid.cells[rr][cc] != '' and grid.cells[rr][cc] != word[i]:
%index = ();
%used = (); return 0
cc += dirs[direction][0]
}
rr += dirs[direction][1]
i += 1
 
rr = r
sub place ($x is copy, $y is copy, $w) {
my @wordcc = $w.key.comb;c
i = 0
my $dir = %dir{$w.value.value};
# place
@ws[$y * $rows + $x] = @word.shift;
while @wordi {< length:
($x,if $y)grid.cells[rr][cc] »+=«= $dir;word[i]:
@ws[$y * $rows + $x]overlaps += @word.shift;1
} else:
grid.cells[rr][cc] = word[i]
}
 
if i < length - 1:
sub find ($x, $y) {
cc += dirs[direction][0]
my @trials = %dir.keys.map: -> $dir {
my $spacerr += '.';dirs[direction][1]
my ($c, $r) = $x, $y;
loop {
($c, $r) »+=« %dir{$dir};
last if 9 < $r|$c;
last if 0 > $r|$c;
my $l = @ws[$r * $rows + $c];
last if $l ~~ /<:Lu>/;
$space ~= $l;
}
next if $space.chars < 3;
[$space.trans( '.' => ' ' ),
("{'ABCDEFGHIJ'.comb[$x]} {$y}" => $dir)]
};
 
for @words.pick(*) -> $word {i += 1
for @trials -> $space {
next if $word.chars > $space[0].chars;
return ($word => $space[1]) if compare($space[0].comb, $word.comb)
}
}
}
 
letters_placed = length - overlaps
sub compare (@s, @w) {
forif ^@wletters_placed {> 0:
grid.solutions.append("{0:<10} ({1},{2})({3},{4})".format(word, c, r, cc, rr))
next if @s[$_] eq ' ';
return False if @s[$_] ne @w[$_]
}
True
}</lang>
{{out|Sample output}}
<pre> A B C D E F G H I J
0 b y e e a R s w u k
1 r g e n p f O s e s
2 d i n l e i i S t i
3 r e b i l a c e E f
4 T g t a d a g n l T
5 d A a t d o w a i d
6 g i C n a n a l r c
7 a o g O p a l p r f
8 p g n p D d a i o a
9 c r u s h E s p t d
 
return letters_placed
Words used:
aaa G 8 ↖ afield E 0 ↘
alley F 4 ↖ bye A 0 →
caliber G 3 ← crush A 9 →
dan F 8 ↑ dig A 5 ↘
epic D 0 ↘ fad J 7 ↓
fisk J 3 ↑ gap A 6 ↓
geigy B 4 ↑ get G 4 ↗
gnp B 8 → goa C 7 ←
lane H 6 ↑ law G 7 ↑
nag D 6 ↖ nne D 1 ↙
odin F 5 ↖ orr I 8 ↑
paddle E 7 ↑ picnic E 1 ↘
pip H 9 ↑ rib A 1 ↘
sir G 9 ↗ sst G 0 ↘
tail D 5 ↑ ted C 4 ↖
tor I 9 ↑ usia I 0 ↙
wei H 0 ↘ </pre>
 
=={{header|Phix}}==
<lang Phix>--
-- demo\rosetta\wordsearch.exw
-- ===========================
--
string message = "ROSETTACODE"
sequence words, solution="", placed
 
def try_place_word(grid, word):
constant grid = split("""
rand_dir = randint(0, len(dirs))
X 0 1 2 3 4 5 6 7 8 9 X
rand_pos = randint(0, grid_size)
0 X
1 X
2 X
3 X
4 X
5 X
6 X
7 X
8 X
9 X
X X X X X X X X X X X X""",'\n')
 
for direction in range(0, len(dirs)):
constant DX = {-1, 0,+1,+1,+1, 0,-1,-1},
DYdirection = {-3,-3,-3,(direction 0,+3,+3,+3, 0}rand_dir) % len(dirs)
 
for pos in range(0, grid_size):
procedure wordsearch(sequence grid, integer rqd, integer left, sequence done)
pos = (pos + rand_pos) % grid_size
sequence rw = shuffle(tagset(length(words))),
rd = shuffle(tagset(8)),
rs = shuffle(tagset(100))
for i=1 to length(rs) do
integer sx = floor((rs[i]-1)/10)+2,
sy = remainder(rs[i]-1,10)*3+4
for w=1 to length(rw) do
string word = words[rw[w]]
if not find(word,done[1]) then
for d=1 to length(rd) do
integer {dx,dy} = {DX[rd[d]],DY[rd[d]]},
{nx,ny} = {sx,sy},
chcount = length(word)
sequence newgrid = grid
for c=1 to length(word) do
integer ch = grid[nx][ny]
if ch!=' ' then
if ch!=word[c] then
chcount = -1
exit
end if
chcount -= 1
end if
newgrid[nx][ny] = word[c]
nx += dx
ny += dy
end for
if chcount!=-1 then
sequence posinfo = {sx-2,(sy-4)/3,nx-dx-2,(ny-dy-4)/3},
newdone = {append(done[1],word),append(done[2],posinfo)}
if rqd<=1 and left-chcount=length(message) then
{solution, placed} = {newgrid, newdone}
return
elsif left-chcount>length(message) then
wordsearch(newgrid,rqd-1,left-chcount,newdone)
if length(solution) then return end if
end if
end if
end for
end if
end for
end for
end procedure
 
letters_placed = try_location(grid, word, direction, pos)
function valid_word(string word)
if letters_placed > 0:
if length(word)<3 then return false end if
return letters_placed
for i=1 to length(word) do
integer ch = word[i]
if ch<'a'
or ch>'z' then
return false
end if
end for
return true
end function
 
return 0
integer fn = open("..\\unixdict.txt","r")
words = get_text(fn,GT_LF_STRIPPED)
close(fn)
for i=length(words) to 1 by -1 do
if not valid_word(words[i]) then
words[i] = words[$]
words = words[1..$-1]
end if
end for
printf(1,"%d words loaded\n",length(words))
 
wordsearch(grid,25,100,{{},{}})
for x=2 to 11 do
for y=4 to 31 by 3 do
if solution[x][y]=' ' then
solution[x][y] = message[1]
message = message[2..$]
end if
end for
end for
if length(message) then ?9/0 end if
puts(1,substitute(join(solution,'\n'),"X"," "))
printf(1,"\n%d words\n",length(placed[1]))
for i=1 to length(placed[1]) do
printf(1,"%10s %10s ",{placed[1][i],sprint(placed[2][i])})
if mod(i,3)=0 then puts(1,"\n") end if
end for</lang>
{{out}}
<pre>
24822 words loaded
0 1 2 3 4 5 6 7 8 9
0 R y g e r m a n y O
1 d r a g a v e S o E
2 c a t n w e w T l T
3 r t s e p h a o k A
4 a u e v p e d t k C
5 g l c a o l k O a e
6 n a t r h l c h o u
7 a s m p a c a d i a
8 v n r a d s j o i l
9 D y i p i E s a s h
 
def create_word_search(words):
42 words
grid = None
salutary {7,1,0,1} idaho {9,4,5,4} jackdaw {8,6,2,6}
num_attempts = 0
darn {8,4,8,1} avenge {5,3,0,3} van {8,0,6,0}
war {2,4,0,4} crag {2,0,5,0} drag {1,0,1,3}
gam {5,0,7,2} stag {3,2,0,2} crass {5,2,9,6}
apr {8,3,6,3} staph {7,1,3,5} germany {0,2,0,8}
laos {6,5,9,8} chou {6,6,6,9} hell {3,5,6,5}
wee {2,4,4,2} acadia {7,4,7,9} yolk {0,8,3,8}
pap {7,3,9,3} pry {7,3,9,1} usn {4,1,2,3}
agave {1,2,1,6} nat {6,0,6,2} pee {3,4,1,6}
sash {9,6,9,9} eel {3,3,5,1} hid {9,9,7,7}
yip {9,1,9,3} wok {2,6,4,8} raw {0,4,2,4}
rave {6,3,3,3} oak {6,8,4,8} oil {8,7,8,9}
lao {6,5,8,7} pest {3,4,3,1} doe {7,7,5,9}
pet {4,4,2,2} arc {4,0,2,0} tau {4,7,6,9}
</pre>
 
while num_attempts < 100:
=={{header|QB64}}==
num_attempts += 1
''bplus'': 2020/03/13
shuffle(words)
 
grid = Grid()
message_len = place_message(grid, "Rosetta Code")
target = grid_size - message_len
 
cells_filled = 0
The following zip file is needed for the Unix dictionary and a QB64 words mod for fun! ...and some samples.
for word in words:
[https://www.qb64.org/forum/index.php?action=dlattach;topic=2334.0;attach=5434 Rosetta Code Word Search Challenge.zip]
cells_filled += try_place_word(grid, word)
<lang vb> OPTION _EXPLICIT
if cells_filled == target:
_TITLE "Puzzle Builder for Rosetta" 'by B+ started 2018-10-31
if len(grid.solutions) >= min_words:
' 2018-11-02 Now that puzzle is working with basic and plus starters remove them and make sure puzzle works as well.
grid.num_attempts = num_attempts
' Added Direction legend to printout.
return grid
' OverHauled LengthLimit()
' Reorgnize this to try a couple of times at given Randomize numberelse:
break # grid is full but we didn't pack enough words, start over
' TODO create alphabetical copy of word list and check grid for all words embedded in it.
' LoadWords makes a copy of word list in alpha order
' FindAllWords finds all the items from the dictionary
' OK it all seems to be working OK
RANDOMIZE TIMER ' OK getting a good puzzle every time
'overhauled
DIM SHARED LengthLimit(3 TO 10) AS _BYTE 'reset in Initialize, track and limit longer words
'LoadWords opens file of words and sets
DIM SHARED NWORDS 'set in LoadWords, number of words with length: > 2 and < 11 and just letters
' word file words (shuffled) to be fit into puzzle and index position
DIM SHARED WORDS$(1 TO 24945), CWORDS$(1 TO 24945), WORDSINDEX AS INTEGER 'the file has 24945 words but many are unsuitable
'words placed in Letters grid, word itself (W$) x, y head (WX, WY) and direction (WD), WI is the index to all these
DIM SHARED W$(1 TO 100), WX(1 TO 100) AS _BYTE, WY(1 TO 100) AS _BYTE, WD(1 TO 100) AS _BYTE, WI AS _BYTE
' letters grid and direction arrays
DIM SHARED L$(0 TO 9, 0 TO 9), DX(0 TO 7) AS _BYTE, DY(0 TO 7) AS _BYTE
DX(0) = 1: DY(0) = 0
DX(1) = 1: DY(1) = 1
DX(2) = 0: DY(2) = 1
DX(3) = -1: DY(3) = 1
DX(4) = -1: DY(4) = 0
DX(5) = -1: DY(5) = -1
DX(6) = 0: DY(6) = -1
DX(7) = 1: DY(7) = -1
'to store all the words found embedded in the grid L$()
DIM SHARED ALL$(1 TO 200), AllX(1 TO 200) AS _BYTE, AllY(1 TO 200) AS _BYTE, AllD(1 TO 200) AS _BYTE 'to store all the words found embedded in the grid L$()
DIM SHARED ALLindex AS INTEGER
' signal successful fill of puzzle
DIM SHARED FILLED AS _BIT
FILLED = 0
DIM try AS _BYTE
try = 1
LoadWords 'this sets NWORDS count to work with
WHILE try < 11
Initialize
ShowPuzzle
FOR WORDSINDEX = 1 TO NWORDS
PlaceWord
ShowPuzzle
IF FILLED THEN EXIT FOR
NEXT
IF FILLED AND WI > 24 THEN
FindAllWords
FilePuzzle
LOCATE 23, 1: PRINT "On try #"; Trm$(try); " a successful puzzle was built and filed."
EXIT WHILE
ELSE
try = try + 1
END IF
WEND
IF FILLED = 0 THEN LOCATE 23, 1: PRINT "Sorry, 10 tries and no success."
END
SUB LoadWords
DIM wd$, i AS INTEGER, m AS INTEGER, ok AS _BIT
OPEN "unixdict.txt" FOR INPUT AS #1
WHILE EOF(1) = 0
INPUT #1, wd$
IF LEN(wd$) > 2 AND LEN(wd$) < 11 THEN
ok = -1
FOR m = 1 TO LEN(wd$)
IF ASC(wd$, m) < 97 OR ASC(wd$, m) > 122 THEN ok = 0: EXIT FOR
NEXT
IF ok THEN i = i + 1: WORDS$(i) = wd$: CWORDS$(i) = wd$
END IF
WEND
CLOSE #1
NWORDS = i
END SUB
SUB Shuffle
DIM i AS INTEGER, r AS INTEGER
FOR i = NWORDS TO 2 STEP -1
r = INT(RND * i) + 1
SWAP WORDS$(i), WORDS$(r)
NEXT
END SUB
SUB Initialize
DIM r AS _BYTE, c AS _BYTE, x AS _BYTE, y AS _BYTE, d AS _BYTE, wd$
FOR r = 0 TO 9
FOR c = 0 TO 9
L$(c, r) = " "
NEXT
NEXT
'reset word arrays by resetting the word index back to zero
WI = 0
'fun stuff for me but doubt others would like that much fun!
'pluggin "basic", 0, 0, 2
'pluggin "plus", 1, 0, 0
'to assure the spreading of ROSETTA CODE
L$(INT(RND * 5) + 5, 0) = "R": L$(INT(RND * 9) + 1, 1) = "O"
L$(INT(RND * 9) + 1, 2) = "S": L$(INT(RND * 9) + 1, 3) = "E"
L$(1, 4) = "T": L$(9, 4) = "T": L$(INT(10 * RND), 5) = "A"
L$(INT(10 * RND), 6) = "C": L$(INT(10 * RND), 7) = "O"
L$(INT(10 * RND), 8) = "D": L$(INT(10 * RND), 9) = "E"
'reset limits
LengthLimit(3) = 200
LengthLimit(4) = 6
LengthLimit(5) = 3
LengthLimit(6) = 2
LengthLimit(7) = 1
LengthLimit(8) = 0
LengthLimit(9) = 0
LengthLimit(10) = 0
'reset word order
Shuffle
END SUB
'for fun plug-in of words
SUB pluggin (wd$, x AS INTEGER, y AS INTEGER, d AS INTEGER)
DIM i AS _BYTE
FOR i = 0 TO LEN(wd$) - 1
L$(x + i * DX(d), y + i * DY(d)) = MID$(wd$, i + 1, 1)
NEXT
WI = WI + 1
W$(WI) = wd$: WX(WI) = x: WY(WI) = y: WD(WI) = d
END SUB
FUNCTION Trm$ (n AS INTEGER)
Trm$ = RTRIM$(LTRIM$(STR$(n)))
END FUNCTION
SUB ShowPuzzle
DIM i AS _BYTE, x AS _BYTE, y AS _BYTE, wate$
CLS
PRINT " 0 1 2 3 4 5 6 7 8 9"
LOCATE 3, 1
FOR i = 0 TO 9
PRINT Trm$(i)
NEXT
FOR y = 0 TO 9
FOR x = 0 TO 9
LOCATE y + 3, 2 * x + 5: PRINT L$(x, y)
NEXT
NEXT
FOR i = 1 TO WI
IF i < 20 THEN
LOCATE i + 1, 30: PRINT Trm$(i); " "; W$(i)
ELSEIF i < 40 THEN
LOCATE i - 20 + 1, 45: PRINT Trm$(i); " "; W$(i)
ELSEIF i < 60 THEN
LOCATE i - 40 + 1, 60: PRINT Trm$(i); " "; W$(i)
END IF
NEXT
LOCATE 18, 1: PRINT "Spaces left:"; CountSpaces%
LOCATE 19, 1: PRINT NWORDS
LOCATE 20, 1: PRINT SPACE$(16)
IF WORDSINDEX THEN LOCATE 20, 1: PRINT Trm$(WORDSINDEX); " "; WORDS$(WORDSINDEX)
'LOCATE 15, 1: INPUT "OK, press enter... "; wate$
END SUB
'used in PlaceWord
FUNCTION CountSpaces% ()
DIM x AS _BYTE, y AS _BYTE, count AS INTEGER
FOR y = 0 TO 9
FOR x = 0 TO 9
IF L$(x, y) = " " THEN count = count + 1
NEXT
NEXT
CountSpaces% = count
END FUNCTION
'used in PlaceWord
FUNCTION Match% (word AS STRING, template AS STRING)
DIM i AS INTEGER, c AS STRING
Match% = 0
IF LEN(word) <> LEN(template) THEN EXIT FUNCTION
FOR i = 1 TO LEN(template)
IF ASC(template, i) <> 32 AND (ASC(word, i) <> ASC(template, i)) THEN EXIT FUNCTION
NEXT
Match% = -1
END FUNCTION
'heart of puzzle builder
SUB PlaceWord
' place the words randomly in the grid
' start at random spot and work forward or back 100 times = all the squares
' for each open square try the 8 directions for placing the word
' even if word fits Rossetta Challenge task requires leaving 11 openings to insert ROSETTA CODE,
' exactly 11 spaces needs to be left, if/when this occurs FILLED will be set true to signal finished to main loop
' if place a word update L$, WI, W$(WI), WX(WI), WY(WI), WD(WI)
DIM wd$, wLen AS _BYTE, spot AS _BYTE, testNum AS _BYTE, rdir AS _BYTE
DIM x AS _BYTE, y AS _BYTE, d AS _BYTE, dNum AS _BYTE, rdd AS _BYTE
DIM template$, b1 AS _BIT, b2 AS _BIT
DIM i AS _BYTE, j AS _BYTE, wate$
wd$ = WORDS$(WORDSINDEX) 'the right side is all shared
'skip too many long words
IF LengthLimit(LEN(wd$)) THEN LengthLimit(LEN(wd$)) = LengthLimit(LEN(wd$)) - 1 ELSE EXIT SUB 'skip long ones
wLen = LEN(wd$) - 1 ' from the spot there are this many letters to check
spot = INT(RND * 100) ' a random spot on grid
testNum = 1 ' when this hits 100 we've tested all possible spots on grid
IF RND < .5 THEN rdir = -1 ELSE rdir = 1 ' go forward or back from spot for next test
WHILE testNum < 101
y = INT(spot / 10)
x = spot MOD 10
IF L$(x, y) = MID$(wd$, 1, 1) OR L$(x, y) = " " THEN
d = INT(8 * RND)
IF RND < .5 THEN rdd = -1 ELSE rdd = 1
dNum = 1
WHILE dNum < 9
'will wd$ fit? from at x, y
template$ = ""
b1 = wLen * DX(d) + x >= 0 AND wLen * DX(d) + x <= 9
b2 = wLen * DY(d) + y >= 0 AND wLen * DY(d) + y <= 9
IF b1 AND b2 THEN 'build the template of letters and spaces from Letter grid
FOR i = 0 TO wLen
template$ = template$ + L$(x + i * DX(d), y + i * DY(d))
NEXT
IF Match%(wd$, template$) THEN 'the word will fit but does it fill anything?
FOR j = 1 TO LEN(template$)
IF ASC(template$, j) = 32 THEN 'yes a space to fill
FOR i = 0 TO wLen
L$(x + i * DX(d), y + i * DY(d)) = MID$(wd$, i + 1, 1)
NEXT
WI = WI + 1
W$(WI) = wd$: WX(WI) = x: WY(WI) = y: WD(WI) = d
IF CountSpaces% = 0 THEN FILLED = -1
EXIT SUB 'get out now that word is loaded
END IF
NEXT
'if still here keep looking
END IF
END IF
d = (d + 8 + rdd) MOD 8
dNum = dNum + 1
WEND
END IF
spot = (spot + 100 + rdir) MOD 100
testNum = testNum + 1
WEND
END SUB
SUB FindAllWords
DIM wd$, wLen AS _BYTE, i AS INTEGER, x AS _BYTE, y AS _BYTE, d AS _BYTE
DIM template$, b1 AS _BIT, b2 AS _BIT, j AS _BYTE, wate$
FOR i = 1 TO NWORDS
wd$ = CWORDS$(i)
wLen = LEN(wd$) - 1
FOR y = 0 TO 9
FOR x = 0 TO 9
IF L$(x, y) = MID$(wd$, 1, 1) THEN
FOR d = 0 TO 7
b1 = wLen * DX(d) + x >= 0 AND wLen * DX(d) + x <= 9
b2 = wLen * DY(d) + y >= 0 AND wLen * DY(d) + y <= 9
IF b1 AND b2 THEN 'build the template of letters and spaces from Letter grid
template$ = ""
FOR j = 0 TO wLen
template$ = template$ + L$(x + j * DX(d), y + j * DY(d))
NEXT
IF template$ = wd$ THEN 'founda word
'store it
ALLindex = ALLindex + 1
ALL$(ALLindex) = wd$: AllX(ALLindex) = x: AllY(ALLindex) = y: AllD(ALLindex) = d
'report it
LOCATE 22, 1: PRINT SPACE$(50)
LOCATE 22, 1: PRINT "Found: "; wd$; " ("; Trm$(x); ", "; Trm$(y); ") >>>---> "; Trm$(d);
INPUT " Press enter...", wate$
END IF
END IF
NEXT d
END IF
NEXT x
NEXT y
NEXT i
END SUB
SUB FilePuzzle
DIM i AS _BYTE, r AS _BYTE, c AS _BYTE, b$
OPEN "WS Puzzle.txt" FOR OUTPUT AS #1
PRINT #1, " 0 1 2 3 4 5 6 7 8 9"
PRINT #1, ""
FOR r = 0 TO 9
b$ = Trm$(r) + " "
FOR c = 0 TO 9
b$ = b$ + L$(c, r) + " "
NEXT
PRINT #1, b$
NEXT
PRINT #1, ""
PRINT #1, "Directions >>>---> 0 = East, 1 = SE, 2 = South, 3 = SW, 4 = West, 5 = NW, 6 = North, 7 = NE"
PRINT #1, ""
PRINT #1, " These are the items from unixdict.txt used to build the puzzle:"
PRINT #1, ""
FOR i = 1 TO WI STEP 2
PRINT #1, RIGHT$(SPACE$(7) + Trm$(i), 7); ") "; RIGHT$(SPACE$(7) + W$(i), 10); " ("; Trm$(WX(i)); ", "; Trm$(WY(i)); ") >>>---> "; Trm$(WD(i));
IF i + 1 <= WI THEN
PRINT #1, RIGHT$(SPACE$(7) + Trm$(i + 1), 7); ") "; RIGHT$(SPACE$(7) + W$(i + 1), 10); " ("; Trm$(WX(i + 1)); ", "; Trm$(WY(i + 1)); ") >>>---> "; Trm$(WD(i + 1))
ELSE
PRINT #1, ""
END IF
NEXT
PRINT #1, ""
PRINT #1, " These are the items from unixdict.txt found embedded in the puzzle:"
PRINT #1, ""
FOR i = 1 TO ALLindex STEP 2
PRINT #1, RIGHT$(SPACE$(7) + Trm$(i), 7); ") "; RIGHT$(SPACE$(7) + ALL$(i), 10); " ("; Trm$(AllX(i)); ", "; Trm$(AllY(i)); ") >>>---> "; Trm$(AllD(i));
IF i + 1 <= ALLindex THEN
PRINT #1, RIGHT$(SPACE$(7) + Trm$(i + 1), 7); ") "; RIGHT$(SPACE$(7) + ALL$(i + 1), 10); " ("; Trm$(AllX(i + 1)); ", "; Trm$(AllY(i + 1)); ") >>>---> "; Trm$(AllD(i + 1))
ELSE
PRINT #1, ""
END IF
NEXT
CLOSE #1
END SUB</lang>
 
return grid
----
 
'''Sample Output:'''
<br><code><br>
&nbsp;&nbsp;0 1 2 3 4 5 6 7 8 9 <br>
0 t g a m m R l b a r <br>
1 o e O k y u i l u b <br>
2 l S e e n n i o a t <br>
3 s a g d E u i d e w <br>
4 k T c t e h g s a T <br>
5 s e n o j b o A e r <br>
6 C l g n c o a p g r <br>
7 l i o d i u m u e O <br>
8 k a e r f D d y c t <br>
9 t j E a i d r a p h <br>
<br>Directions >>>---> 0 = East, 1 = SE, 2 = South, 3 = SW, 4 = West, 5 = NW, 6 = North, 7 = NE
<br>
These are the items from unixdict.txt used to build the puzzle:
1) odium (2, 7) >>>---> 0 2) resiny (9, 6) >>>---> 5
3) debauch (3, 3) >>>---> 1 4) freak (4, 8) >>>---> 4
5) jones (4, 5) >>>---> 4 6) radium (9, 5) >>>---> 5
7) hope (5, 4) >>>---> 1 8) coca (4, 6) >>>---> 5
9) slot (0, 3) >>>---> 6 10) aid (3, 9) >>>---> 0
11) gunk (6, 4) >>>---> 5 12) keg (0, 4) >>>---> 1
13) aile (1, 8) >>>---> 6 14) set (7, 4) >>>---> 7
15) wall (9, 3) >>>---> 5 16) rye (6, 9) >>>---> 7
17) our (7, 2) >>>---> 7 18) bar (7, 0) >>>---> 0
19) par (8, 9) >>>---> 4 20) gam (1, 0) >>>---> 0
21) dee (3, 3) >>>---> 5 22) ton (3, 4) >>>---> 2
23) dab (7, 3) >>>---> 7 24) jed (1, 9) >>>---> 7
25) bin (7, 0) >>>---> 3 26) pet (7, 6) >>>---> 1
27) sag (0, 3) >>>---> 0 28) nco (3, 6) >>>---> 0
29) dug (6, 8) >>>---> 7 30) oat (2, 7) >>>---> 3
31) oil (2, 7) >>>---> 4 32) nee (4, 2) >>>---> 4
These are the items from unixdict.txt found embedded in the puzzle:<br>
1) abe (6, 6) >>>---> 5 2) abed (6, 6) >>>---> 5
3) aid (3, 9) >>>---> 0 4) ail (1, 8) >>>---> 6
5) aile (1, 8) >>>---> 6 6) ali (8, 0) >>>---> 3
7) all (8, 2) >>>---> 5 8) bad (9, 1) >>>---> 3
9) bar (7, 0) >>>---> 0 10) bed (5, 5) >>>---> 5
11) bin (7, 0) >>>---> 3 12) but (7, 0) >>>---> 1
13) cal (2, 4) >>>---> 5 14) coca (4, 6) >>>---> 5
15) cud (4, 6) >>>---> 1 16) dab (7, 3) >>>---> 7
17) dar (7, 3) >>>---> 1 18) debauch (3, 3) >>>---> 1
19) dee (3, 3) >>>---> 5 20) dew (7, 3) >>>---> 0
21) dug (6, 8) >>>---> 7 22) edt (3, 2) >>>---> 2
23) eli (1, 5) >>>---> 2 24) etc (4, 4) >>>---> 4
25) freak (4, 8) >>>---> 4 26) gam (1, 0) >>>---> 0
27) gas (2, 3) >>>---> 4 28) goa (6, 4) >>>---> 2
29) gsa (6, 4) >>>---> 0 30) gun (6, 4) >>>---> 5
31) gunk (6, 4) >>>---> 5 32) hop (5, 4) >>>---> 1
33) hope (5, 4) >>>---> 1 34) hun (5, 4) >>>---> 6
35) ida (6, 2) >>>---> 1 36) iii (6, 1) >>>---> 2
37) iii (6, 3) >>>---> 6 38) inn (6, 2) >>>---> 4
39) inn (4, 7) >>>---> 5 40) jail (1, 9) >>>---> 6
41) jed (1, 9) >>>---> 7 42) jon (4, 5) >>>---> 4
43) jones (4, 5) >>>---> 4 44) keg (0, 4) >>>---> 1
45) lac (0, 2) >>>---> 1 46) law (7, 1) >>>---> 1
47) lea (0, 2) >>>---> 7 48) lot (0, 2) >>>---> 6
49) lund (6, 0) >>>---> 3 50) mao (6, 7) >>>---> 6
51) nco (3, 6) >>>---> 0 52) nee (4, 2) >>>---> 4
53) nib (5, 2) >>>---> 7 54) nne (5, 2) >>>---> 4
55) not (3, 6) >>>---> 6 56) oat (7, 2) >>>---> 0
57) oat (2, 7) >>>---> 3 58) odium (2, 7) >>>---> 0
59) oil (2, 7) >>>---> 4 60) one (3, 5) >>>---> 4
61) our (7, 2) >>>---> 7 62) par (8, 9) >>>---> 4
63) pet (7, 6) >>>---> 1 64) radium (9, 5) >>>---> 5
65) rap (6, 9) >>>---> 0 66) resin (9, 6) >>>---> 5
67) resiny (9, 6) >>>---> 5 68) rio (3, 8) >>>---> 7
69) rye (6, 9) >>>---> 7 70) sag (0, 3) >>>---> 0
71) sen (0, 5) >>>---> 0 72) set (7, 4) >>>---> 7
73) sin (7, 4) >>>---> 5 74) slot (0, 3) >>>---> 6
75) tao (9, 2) >>>---> 4 76) tao (0, 9) >>>---> 7
77) tee (0, 0) >>>---> 1 78) ton (3, 4) >>>---> 2
79) tub (9, 2) >>>---> 5 80) wall (9, 3) >>>---> 5
81) wed (9, 3) >>>---> 4
</code><br>
[index-php-action-dlattach-topic-2334.png](https://postimg.cc/qNPn9FVZ)
 
def print_result(grid):
=={{header|Racket}}==
if grid is None or grid.num_attempts == 0:
print("No grid to display")
return
 
size = len(grid.solutions)
 
print("Attempts: {0}".format(grid.num_attempts))
print("Number of words: {0}".format(size))
 
print("\n 0 1 2 3 4 5 6 7 8 9\n")
for r in range(0, n_rows):
print("{0} ".format(r), end='')
for c in range(0, n_cols):
print(" %c " % grid.cells[r][c], end='')
print()
print()
 
for i in range(0, size - 1, 2):
print("{0} {1}".format(grid.solutions[i], grid.solutions[i+1]))
 
if size % 2 == 1:
print(grid.solutions[size - 1])
 
 
if __name__ == "__main__":
print_result(create_word_search(read_words("unixdict.txt")))
</syntaxhighlight>
 
{{out}}
<pre>
Attempts: 1
Number of words: 25
 
0 1 2 3 4 5 6 7 8 9
 
0 f b R u e r u l t h
1 o n o t v O e r o p
2 a S a b a x o b E m
3 l e d s h w T p e u
4 w p v a n s u c k i
5 o T u r A t u t s r
6 n s o p u m y d i t
7 t h C j a c o b i O
8 t i r e h n i m D p
9 y n o l o c E s a c
 
exhaust (6,1)(0,7) hornwort (1,7)(8,0)
btu (3,2)(3,0) jacobi (3,7)(8,7)
foal (0,0)(0,3) triumph (9,6)(9,0)
inherit (6,8)(0,8) mecum (9,2)(5,6)
colony (5,9)(0,9) curve (5,7)(1,3)
wont (0,4)(0,7) lure (7,0)(4,0)
hob (9,0)(7,2) tidy (9,6)(6,6)
suck (5,4)(8,4) san (3,3)(1,1)
sac (7,9)(9,9) put (7,3)(5,5)
led (0,3)(2,3) stu (8,5)(6,5)
have (4,3)(4,0) min (7,8)(5,8)
bob (1,0)(3,2) pup (3,6)(1,4)
dip (7,6)(9,8)
</pre>
 
=={{header|Racket}}==
{{trans|Java}}
(or at least it started out that way... so more "inspired by")
 
<langsyntaxhighlight lang="racket">#lang racket
;; ---------------------------------------------------------------------------------------------------
(module+ main
Line 2,592 ⟶ 3,687:
[(hash-has-key? cells (cons r c)) (loop r (add1 c) cells msg)]
[else (loop r (add1 c) (hash-set cells (cons r c) (car msg)) (cdr msg))])))))
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,687 ⟶ 3,782:
visit (9,12 ↖) von (3,4 ↗)
way (18,17 ←) wham (11,5 ↓) </pre>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2020.01}}
 
<syntaxhighlight lang="raku" line>my $rows = 10;
my $cols = 10;
 
my $message = q:to/END/;
.....R....
......O...
.......S..
........E.
T........T
.A........
..C.......
...O......
....D.....
.....E....
END
 
my %dir =
'→' => (1,0),
'↘' => (1,1),
'↓' => (0,1),
'↙' => (-1,1),
'←' => (-1,0),
'↖' => (-1,-1),
'↑' => (0,-1),
'↗' => (1,-1)
;
 
my @ws = $message.comb(/<print>/);
 
my $path = './unixdict.txt'; # or wherever
 
my @words = $path.IO.slurp.words.grep( { $_ !~~ /<-[a..z]>/ and 2 < .chars < 11 } ).pick(*);
my %index;
my %used;
 
while @ws.first( * eq '.') {
 
# find an unfilled cell
my $i = @ws.grep( * eq '.', :k ).pick;
 
# translate the index to x / y coordinates
my ($x, $y) = $i % $cols, floor($i / $rows);
 
# find a word that fits
my $word = find($x, $y);
 
# Meh, reached an impasse, easier to just throw it all
# away and start over rather than trying to backtrack.
restart, next unless $word;
 
%used{"$word"}++;
 
# Keeps trying to place an already used word, choices
# must be limited, start over
restart, next if %used{$word} > 15;
 
# Already used this word, try again
next if %index{$word.key};
 
# Add word to used word index
%index ,= $word;
 
# place the word into the grid
place($x, $y, $word);
 
}
 
display();
 
sub display {
put flat " ", 'ABCDEFGHIJ'.comb;
.put for (^10).map: { ($_).fmt(" %2d"), @ws[$_ * $cols .. ($_ + 1) * $cols - 1] }
put "\n Words used:";
my $max = 1 + %index.keys.max( *.chars ).chars;
for %index.sort {
printf "%{$max}s %4s %s ", .key, .value.key, .value.value;
print "\n" if $++ % 2;
}
say "\n"
}
 
sub restart {
@ws = $message.comb(/<print>/);
%index = ();
%used = ();
}
 
sub place ($x is copy, $y is copy, $w) {
my @word = $w.key.comb;
my $dir = %dir{$w.value.value};
@ws[$y * $rows + $x] = @word.shift;
while @word {
($x, $y) »+=« $dir;
@ws[$y * $rows + $x] = @word.shift;
}
}
 
sub find ($x, $y) {
my @trials = %dir.keys.map: -> $dir {
my $space = '.';
my ($c, $r) = $x, $y;
loop {
($c, $r) »+=« %dir{$dir};
last if 9 < $r|$c;
last if 0 > $r|$c;
my $l = @ws[$r * $rows + $c];
last if $l ~~ /<:Lu>/;
$space ~= $l;
}
next if $space.chars < 3;
[$space.trans( '.' => ' ' ),
("{'ABCDEFGHIJ'.comb[$x]} {$y}" => $dir)]
};
 
for @words.pick(*) -> $word {
for @trials -> $space {
next if $word.chars > $space[0].chars;
return ($word => $space[1]) if compare($space[0].comb, $word.comb)
}
}
}
 
sub compare (@s, @w) {
for ^@w {
next if @s[$_] eq ' ';
return False if @s[$_] ne @w[$_]
}
True
}</syntaxhighlight>
{{out|Sample output}}
<pre> A B C D E F G H I J
0 b y e e a R s w u k
1 r g e n p f O s e s
2 d i n l e i i S t i
3 r e b i l a c e E f
4 T g t a d a g n l T
5 d A a t d o w a i d
6 g i C n a n a l r c
7 a o g O p a l p r f
8 p g n p D d a i o a
9 c r u s h E s p t d
 
Words used:
aaa G 8 ↖ afield E 0 ↘
alley F 4 ↖ bye A 0 →
caliber G 3 ← crush A 9 →
dan F 8 ↑ dig A 5 ↘
epic D 0 ↘ fad J 7 ↓
fisk J 3 ↑ gap A 6 ↓
geigy B 4 ↑ get G 4 ↗
gnp B 8 → goa C 7 ←
lane H 6 ↑ law G 7 ↑
nag D 6 ↖ nne D 1 ↙
odin F 5 ↖ orr I 8 ↑
paddle E 7 ↑ picnic E 1 ↘
pip H 9 ↑ rib A 1 ↘
sir G 9 ↗ sst G 0 ↘
tail D 5 ↑ ted C 4 ↖
tor I 9 ↑ usia I 0 ↙
wei H 0 ↘ </pre>
 
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-ioutil}}
{{libheader|Wren-pattern}}
{{libheader|Wren-str}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "random" for Random
import "./ioutil" for FileUtil
import "./pattern" for Pattern
import "./str" for Str
import "./fmt" for Fmt
 
var dirs = [ [1, 0], [0, 1], [1, 1], [1, -1], [-1, 0], [0, -1], [-1, -1], [-1, 1] ]
var Rows = 10
var Cols = 10
var gridSize = Rows * Cols
var minWords = 25
var rand = Random.new()
 
class Grid {
construct new() {
_numAttempts = 0
_cells = List.filled(Rows, null)
for (i in 0...Rows) _cells[i] = List.filled(Cols, " ")
_solutions = []
}
 
numAttempts { _numAttempts }
numAttempts=(n) { _numAttempts = n }
cells { _cells }
solutions { _solutions }
}
 
var readWords = Fn.new { |fileName|
var maxLen = Rows.max(Cols)
var p = Pattern.new("=3/l#0%(maxLen-3)/l", Pattern.whole)
return FileUtil.readLines(fileName)
.map { |l| Str.lower(l.trim()) }
.where { |l| p.isMatch(l) }.toList
}
 
var placeMessage = Fn.new { |grid, msg|
var p = Pattern.new("/U")
var msg2 = p.replaceAll(Str.upper(msg), "")
var messageLen = msg2.count
if (messageLen >= 1 && messageLen < gridSize) {
var gapSize = (gridSize / messageLen).floor
for (i in 0...messageLen) {
var pos = i * gapSize + rand.int(gapSize)
grid.cells[(pos / Cols).floor][pos % Cols] = msg2[i]
}
return messageLen
}
return 0
}
 
var tryLocation = Fn.new { |grid, word, dir, pos|
var r = (pos / Cols).floor
var c = pos % Cols
var len = word.count
 
// check bounds
if ((dirs[dir][0] == 1 && (len + c) > Cols) ||
(dirs[dir][0] == -1 && (len - 1) > c) ||
(dirs[dir][1] == 1 && (len + r) > Rows) ||
(dirs[dir][1] == -1 && (len - 1) > r)) return 0
var overlaps = 0
 
// check cells
var rr = r
var cc = c
for (i in 0...len) {
if (grid.cells[rr][cc] != " " && grid.cells[rr][cc] != word[i]) return 0
cc = cc + dirs[dir][0]
rr = rr + dirs[dir][1]
}
 
// place
rr = r
cc = c
for (i in 0...len) {
if (grid.cells[rr][cc] == word[i]) {
overlaps = overlaps + 1
} else {
grid.cells[rr][cc] = word[i]
}
if (i < len - 1) {
cc = cc + dirs[dir][0]
rr = rr + dirs[dir][1]
}
}
 
var lettersPlaced = len - overlaps
if (lettersPlaced > 0) {
grid.solutions.add(Fmt.swrite("$-10s ($d,$d)($d,$d)", word, c, r, cc, rr))
}
return lettersPlaced
}
 
var tryPlaceWord = Fn.new { |grid, word|
var randDir = rand.int(dirs.count)
var randPos = rand.int(gridSize)
for (d in 0...dirs.count) {
var dir = (d + randDir) % dirs.count
for (p in 0...gridSize) {
var pos = (p + randPos) % gridSize
var lettersPlaced = tryLocation.call(grid, word, dir, pos)
if (lettersPlaced > 0) return lettersPlaced
}
}
return 0
}
 
var createWordSearch = Fn.new { |words|
var numAttempts = 1
var grid
while (numAttempts < 100) {
var outer = false
grid = Grid.new()
var messageLen = placeMessage.call(grid, "Rosetta Code")
var target = gridSize - messageLen
var cellsFilled = 0
rand.shuffle(words)
for (word in words) {
cellsFilled = cellsFilled + tryPlaceWord.call(grid, word)
if (cellsFilled == target) {
if (grid.solutions.count >= minWords) {
grid.numAttempts = numAttempts
outer = true
break
}
// grid is full but we didn't pack enough words, start over
break
}
}
if (outer) break
numAttempts = numAttempts + 1
}
return grid
}
 
var printResult = Fn.new { |grid|
if (grid.numAttempts == 0) {
System.print("No grid to display")
return
}
var size = grid.solutions.count
System.print("Attempts: %(grid.numAttempts)")
System.print("Number of words: %(size)")
System.print("\n 0 1 2 3 4 5 6 7 8 9")
for (r in 0...Rows) {
System.write("\n%(r) ")
for (c in 0...Cols) System.write(" %(grid.cells[r][c]) ")
}
System.print("\n")
var i = 0
while (i < size - 1) {
System.print("%(grid.solutions[i]) %(grid.solutions[i + 1])")
i = i + 2
}
if (size % 2 == 1) System.print(grid.solutions[size - 1])
}
 
printResult.call(createWordSearch.call(readWords.call("unixdict.txt")))</syntaxhighlight>
 
{{out}}
Sample run:
<pre>
Attempts: 2
Number of words: 29
 
0 1 2 3 4 5 6 7 8 9
 
0 s t u c c o R e e f
1 h c r e p O d r f k
2 x e t a l S o u r f
3 i E p e n g n u o b
4 m r n T l s m o u T
5 e i k i d a p h n e
6 A v k w y s h o C e
7 a e a b O k s o r b
8 n n i g u D c k n t
9 d a h E a t r i m k
 
kilgore (2,6)(8,0) daphne (4,5)(9,5)
agave (4,9)(0,5) tub (5,9)(3,7)
transport (1,0)(9,8) perch (4,1)(0,1)
snuff (5,4)(9,0) stucco (0,0)(5,0)
icky (7,9)(4,6) murk (6,4)(9,1)
honk (6,6)(9,9) irk (0,3)(2,5)
spoof (5,6)(9,2) latex (4,2)(0,2)
trim (5,9)(8,9) sorb (6,7)(9,7)
len (4,2)(2,4) riven (1,4)(1,8)
wand (3,6)(0,9) hub (7,5)(9,3)
pap (4,1)(2,3) had (2,9)(0,9)
ginn (3,8)(0,8) don (6,1)(6,3)
fee (9,0)(7,0) none (6,3)(9,6)
kim (2,6)(0,4) dna (0,9)(0,7)
hook (7,5)(7,8)
</pre>
 
=={{header|zkl}}==
Repeat words allowed. Rather brute force as I didn't realize that the message has to fit exactly.
<langsyntaxhighlight lang="zkl">fcn buildVectors(R,C){ //-->up to 8 vectors of wild card strings
var [const] dirs=T(T(1,0), T(0,1), T(1,1), T(1,-1), T(-1,0),T(0,-1), T(-1,-1), T(-1,1));
vs,v:=List(),List();
Line 2,716 ⟶ 4,178:
foreach r,c in (10,10){ if(grid[r][c]=="?") grid[r][c]=MSG.next() }
MSG._n==msg.len() // use all of, not more, not less, of msg?
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">msg:="RosettaCode";
 
validWord:=RegExp("[A-Za-z]+\n$").matches;
Line 2,746 ⟶ 4,208:
fcn([(r,c,w)]){ "%-19s".fmt("[%d,%d]: %s ".fmt(r,c,w)) }) }
);
fitted.apply(fcn(w){ w[2].len() }).sum(0).println();</langsyntaxhighlight>
{{out}}
<pre>
Line 2,771 ⟶ 4,233:
102
</pre>
 
=={{header|Python}}==
{{trans|Java}}
{{works with|Python|3.x}}
<lang python>
import re
from random import shuffle, randint
 
dirs = [[1, 0], [0, 1], [1, 1], [1, -1], [-1, 0], [0, -1], [-1, -1], [-1, 1]]
n_rows = 10
n_cols = 10
grid_size = n_rows * n_cols
min_words = 25
 
 
class Grid:
def __init__(self):
self.num_attempts = 0
self.cells = [['' for _ in range(n_cols)] for _ in range(n_rows)]
self.solutions = []
 
 
def read_words(filename):
max_len = max(n_rows, n_cols)
 
words = []
with open(filename, "r") as file:
for line in file:
s = line.strip().lower()
if re.match(r'^[a-z]{3,' + re.escape(str(max_len)) + r'}$', s) is not None:
words.append(s)
 
return words
 
 
def place_message(grid, msg):
msg = re.sub(r'[^A-Z]', "", msg.upper())
 
message_len = len(msg)
if 0 < message_len < grid_size:
gap_size = grid_size // message_len
 
for i in range(0, message_len):
pos = i * gap_size + randint(0, gap_size)
grid.cells[pos // n_cols][pos % n_cols] = msg[i]
 
return message_len
 
return 0
 
 
def try_location(grid, word, direction, pos):
r = pos // n_cols
c = pos % n_cols
length = len(word)
 
# check bounds
if (dirs[direction][0] == 1 and (length + c) > n_cols) or \
(dirs[direction][0] == -1 and (length - 1) > c) or \
(dirs[direction][1] == 1 and (length + r) > n_rows) or \
(dirs[direction][1] == -1 and (length - 1) > r):
return 0
 
rr = r
cc = c
i = 0
overlaps = 0
 
# check cells
while i < length:
if grid.cells[rr][cc] != '' and grid.cells[rr][cc] != word[i]:
return 0
cc += dirs[direction][0]
rr += dirs[direction][1]
i += 1
 
rr = r
cc = c
i = 0
# place
while i < length:
if grid.cells[rr][cc] == word[i]:
overlaps += 1
else:
grid.cells[rr][cc] = word[i]
 
if i < length - 1:
cc += dirs[direction][0]
rr += dirs[direction][1]
 
i += 1
 
letters_placed = length - overlaps
if letters_placed > 0:
grid.solutions.append("{0:<10} ({1},{2})({3},{4})".format(word, c, r, cc, rr))
 
return letters_placed
 
 
def try_place_word(grid, word):
rand_dir = randint(0, len(dirs))
rand_pos = randint(0, grid_size)
 
for direction in range(0, len(dirs)):
direction = (direction + rand_dir) % len(dirs)
 
for pos in range(0, grid_size):
pos = (pos + rand_pos) % grid_size
 
letters_placed = try_location(grid, word, direction, pos)
if letters_placed > 0:
return letters_placed
 
return 0
 
 
def create_word_search(words):
grid = None
num_attempts = 0
 
while num_attempts < 100:
num_attempts += 1
shuffle(words)
 
grid = Grid()
message_len = place_message(grid, "Rosetta Code")
target = grid_size - message_len
 
cells_filled = 0
for word in words:
cells_filled += try_place_word(grid, word)
if cells_filled == target:
if len(grid.solutions) >= min_words:
grid.num_attempts = num_attempts
return grid
else:
break # grid is full but we didn't pack enough words, start over
 
return grid
 
 
def print_result(grid):
if grid is None or grid.num_attempts == 0:
print("No grid to display")
return
 
size = len(grid.solutions)
 
print("Attempts: {0}".format(grid.num_attempts))
print("Number of words: {0}".format(size))
 
print("\n 0 1 2 3 4 5 6 7 8 9\n")
for r in range(0, n_rows):
print("{0} ".format(r), end='')
for c in range(0, n_cols):
print(" %c " % grid.cells[r][c], end='')
print()
print()
 
for i in range(0, size - 1, 2):
print("{0} {1}".format(grid.solutions[i], grid.solutions[i+1]))
 
if size % 2 == 1:
print(grid.solutions[size - 1])
 
 
if __name__ == "__main__":
print_result(create_word_search(read_words("unixdict.txt")))
</lang>
 
{{out}}
<pre>
Attempts: 1
Number of words: 25
 
0 1 2 3 4 5 6 7 8 9
 
0 f b R u e r u l t h
1 o n o t v O e r o p
2 a S a b a x o b E m
3 l e d s h w T p e u
4 w p v a n s u c k i
5 o T u r A t u t s r
6 n s o p u m y d i t
7 t h C j a c o b i O
8 t i r e h n i m D p
9 y n o l o c E s a c
 
exhaust (6,1)(0,7) hornwort (1,7)(8,0)
btu (3,2)(3,0) jacobi (3,7)(8,7)
foal (0,0)(0,3) triumph (9,6)(9,0)
inherit (6,8)(0,8) mecum (9,2)(5,6)
colony (5,9)(0,9) curve (5,7)(1,3)
wont (0,4)(0,7) lure (7,0)(4,0)
hob (9,0)(7,2) tidy (9,6)(6,6)
suck (5,4)(8,4) san (3,3)(1,1)
sac (7,9)(9,9) put (7,3)(5,5)
led (0,3)(2,3) stu (8,5)(6,5)
have (4,3)(4,0) min (7,8)(5,8)
bob (1,0)(3,2) pup (3,6)(1,4)
dip (7,6)(9,8)
</pre>
 
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<lang vbnet>Module Module1
 
ReadOnly Dirs As Integer(,) = {
{1, 0}, {0, 1}, {1, 1},
{1, -1}, {-1, 0},
{0, -1}, {-1, -1}, {-1, 1}
}
 
Const RowCount = 10
Const ColCount = 10
Const GridSize = RowCount * ColCount
Const MinWords = 25
 
Class Grid
Public cells(RowCount - 1, ColCount - 1) As Char
Public solutions As New List(Of String)
Public numAttempts As Integer
 
Sub New()
For i = 0 To RowCount - 1
For j = 0 To ColCount - 1
cells(i, j) = ControlChars.NullChar
Next
Next
End Sub
End Class
 
Dim Rand As New Random()
 
Sub Main()
PrintResult(CreateWordSearch(ReadWords("unixdict.txt")))
End Sub
 
Function ReadWords(filename As String) As List(Of String)
Dim maxlen = Math.Max(RowCount, ColCount)
Dim words As New List(Of String)
 
Dim objReader As New IO.StreamReader(filename)
Dim line As String
Do While objReader.Peek() <> -1
line = objReader.ReadLine()
If line.Length > 3 And line.Length < maxlen Then
If line.All(Function(c) Char.IsLetter(c)) Then
words.Add(line)
End If
End If
Loop
 
Return words
End Function
 
Function CreateWordSearch(words As List(Of String)) As Grid
For numAttempts = 1 To 1000
Shuffle(words)
 
Dim grid As New Grid()
Dim messageLen = PlaceMessage(grid, "Rosetta Code")
Dim target = GridSize - messageLen
 
Dim cellsFilled = 0
For Each word In words
cellsFilled = cellsFilled + TryPlaceWord(grid, word)
If cellsFilled = target Then
If grid.solutions.Count >= MinWords Then
grid.numAttempts = numAttempts
Return grid
Else
'grid is full but we didn't pack enough words, start over
Exit For
End If
End If
Next
Next
 
Return Nothing
End Function
 
Function PlaceMessage(grid As Grid, msg As String) As Integer
msg = msg.ToUpper()
msg = msg.Replace(" ", "")
 
If msg.Length > 0 And msg.Length < GridSize Then
Dim gapSize As Integer = GridSize / msg.Length
 
Dim pos = 0
Dim lastPos = -1
For i = 0 To msg.Length - 1
If i = 0 Then
pos = pos + Rand.Next(gapSize - 1)
Else
pos = pos + Rand.Next(2, gapSize - 1)
End If
Dim r As Integer = Math.Floor(pos / ColCount)
Dim c = pos Mod ColCount
 
grid.cells(r, c) = msg(i)
 
lastPos = pos
Next
Return msg.Length
End If
 
Return 0
End Function
 
Function TryPlaceWord(grid As Grid, word As String) As Integer
Dim randDir = Rand.Next(Dirs.GetLength(0))
Dim randPos = Rand.Next(GridSize)
 
For d = 0 To Dirs.GetLength(0) - 1
Dim dd = (d + randDir) Mod Dirs.GetLength(0)
 
For p = 0 To GridSize - 1
Dim pp = (p + randPos) Mod GridSize
 
Dim lettersPLaced = TryLocation(grid, word, dd, pp)
If lettersPLaced > 0 Then
Return lettersPLaced
End If
Next
Next
 
Return 0
End Function
 
Function TryLocation(grid As Grid, word As String, dir As Integer, pos As Integer) As Integer
Dim r As Integer = pos / ColCount
Dim c = pos Mod ColCount
Dim len = word.Length
 
'check bounds
If (Dirs(dir, 0) = 1 And len + c >= ColCount) Or (Dirs(dir, 0) = -1 And len - 1 > c) Or (Dirs(dir, 1) = 1 And len + r >= RowCount) Or (Dirs(dir, 1) = -1 And len - 1 > r) Then
Return 0
End If
If r = RowCount OrElse c = ColCount Then
Return 0
End If
 
Dim rr = r
Dim cc = c
 
'check cells
For i = 0 To len - 1
If grid.cells(rr, cc) <> ControlChars.NullChar AndAlso grid.cells(rr, cc) <> word(i) Then
Return 0
End If
 
cc = cc + Dirs(dir, 0)
rr = rr + Dirs(dir, 1)
Next
 
'place
Dim overlaps = 0
rr = r
cc = c
For i = 0 To len - 1
If grid.cells(rr, cc) = word(i) Then
overlaps = overlaps + 1
Else
grid.cells(rr, cc) = word(i)
End If
 
If i < len - 1 Then
cc = cc + Dirs(dir, 0)
rr = rr + Dirs(dir, 1)
End If
Next
 
Dim lettersPlaced = len - overlaps
If lettersPlaced > 0 Then
grid.solutions.Add(String.Format("{0,-10} ({1},{2})({3},{4})", word, c, r, cc, rr))
End If
 
Return lettersPlaced
End Function
 
Sub PrintResult(grid As Grid)
If IsNothing(grid) OrElse grid.numAttempts = 0 Then
Console.WriteLine("No grid to display")
Return
End If
 
Console.WriteLine("Attempts: {0}", grid.numAttempts)
Console.WriteLine("Number of words: {0}", GridSize)
Console.WriteLine()
 
Console.WriteLine(" 0 1 2 3 4 5 6 7 8 9")
For r = 0 To RowCount - 1
Console.WriteLine()
Console.Write("{0} ", r)
For c = 0 To ColCount - 1
Console.Write(" {0} ", grid.cells(r, c))
Next
Next
 
Console.WriteLine()
Console.WriteLine()
 
For i = 0 To grid.solutions.Count - 1
If i Mod 2 = 0 Then
Console.Write("{0}", grid.solutions(i))
Else
Console.WriteLine(" {0}", grid.solutions(i))
End If
Next
 
Console.WriteLine()
End Sub
 
'taken from https://stackoverflow.com/a/20449161
Sub Shuffle(Of T)(list As IList(Of T))
Dim r As Random = New Random()
For i = 0 To list.Count - 1
Dim index As Integer = r.Next(i, list.Count)
If i <> index Then
' swap list(i) and list(index)
Dim temp As T = list(i)
list(i) = list(index)
list(index) = temp
End If
Next
End Sub
 
End Module</lang>
{{out}}
<pre>Attempts: 148
Number of words: 100
 
0 1 2 3 4 5 6 7 8 9
 
0 c d p R e c h a r e
1 O i u b a k e S l v
2 k n l E m c a c a i
3 T e s i T x A s n t
4 t C e s a l O a g a
5 a j D l l e E h l g
6 l u f e m a h s e r
7 l t c a r f e r y u
8 f e r r e i r a m p
9 f a m i l i s m i s
 
refract (7,7)(1,7) shameful (7,6)(0,6)
ferreira (0,8)(7,8) familism (0,9)(7,9)
langley (8,1)(8,7) sake (7,3)(4,0)
pulse (2,0)(2,4) purgative (9,8)(9,0)
cacm (7,2)(4,2) enid (1,3)(1,0)
char (5,0)(8,0) flax (2,6)(5,3)
tall (0,4)(0,7) isle (3,3)(3,6)
jute (1,5)(1,8) myel (8,8)(8,5)
bake (3,1)(6,1) cell (2,7)(5,4)
marsh (7,9)(7,5) keel (0,2)(3,5)
spur (9,9)(9,6) leaf (5,4)(5,7)
cilia (0,0)(4,4) sims (9,9)(6,9)
marsha (7,9)(7,4)</pre>
9,476

edits