Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Word-search/00-META.yaml
Normal file
2
Task/Word-search/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Word_search
|
||||
50
Task/Word-search/00-TASK.txt
Normal file
50
Task/Word-search/00-TASK.txt
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
A [[wp:Word_search|word search]] puzzle typically consists of a grid of letters in which words are hidden.
|
||||
|
||||
There are many varieties of word search puzzles. For the task at hand we will use a rectangular grid in which the words may be placed horizontally, vertically, or diagonally. The words may also be spelled backwards.
|
||||
|
||||
The words may overlap but are not allowed to zigzag, or wrap around.
|
||||
<br><br>
|
||||
;Task
|
||||
Create a 10 by 10 word search and fill it using words from the [http://www.puzzlers.org/pub/wordlists/unixdict.txt unixdict]. Use only words that are longer than 2, and contain no non-alphabetic characters.
|
||||
|
||||
The cells not used by the hidden words should contain the message: ''Rosetta Code'', read from left to right, top to bottom. These letters should be somewhat evenly distributed over the grid, not clumped together. The message should be in upper case, the hidden words in lower case. All cells should either contain letters from the hidden words or from the message.
|
||||
|
||||
Pack a minimum of 25 words into the grid.
|
||||
|
||||
Print the resulting grid and the solutions.
|
||||
<br><br>
|
||||
;Example
|
||||
|
||||
<pre>
|
||||
0 1 2 3 4 5 6 7 8 9
|
||||
|
||||
0 n a y r y R e l m f
|
||||
1 y O r e t s g n a g
|
||||
2 t n e d i S k y h E
|
||||
3 n o t n c p c w t T
|
||||
4 a l s u u n T m a x
|
||||
5 r o k p a r i s h h
|
||||
6 a A c f p a e a c C
|
||||
7 u b u t t t O l u n
|
||||
8 g y h w a D h p m u
|
||||
9 m i r p E h o g a n
|
||||
|
||||
parish (3,5)(8,5) gangster (9,1)(2,1)
|
||||
paucity (4,6)(4,0) guaranty (0,8)(0,1)
|
||||
prim (3,9)(0,9) huckster (2,8)(2,1)
|
||||
plasm (7,8)(7,4) fancy (3,6)(7,2)
|
||||
hogan (5,9)(9,9) nolo (1,2)(1,5)
|
||||
under (3,4)(3,0) chatham (8,6)(8,0)
|
||||
ate (4,8)(6,6) nun (9,7)(9,9)
|
||||
butt (1,7)(4,7) hawk (9,5)(6,2)
|
||||
why (3,8)(1,8) ryan (3,0)(0,0)
|
||||
fay (9,0)(7,2) much (8,8)(8,5)
|
||||
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>
|
||||
|
||||
|
||||
{{Template:Strings}}
|
||||
<br><br>
|
||||
|
||||
139
Task/Word-search/11l/word-search.11l
Normal file
139
Task/Word-search/11l/word-search.11l
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
-V
|
||||
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
|
||||
num_attempts = 0
|
||||
[[String]] cells = [[‘’] * :n_cols] * :n_rows
|
||||
[String] solutions
|
||||
|
||||
F read_words(filename)
|
||||
[String] words
|
||||
L(line) File(filename).read_lines()
|
||||
V s = line.lowercase()
|
||||
I re:‘^[a-z]{3,10}’.match(s)
|
||||
words.append(s)
|
||||
R words
|
||||
|
||||
F place_message(Grid &grid; =msg)
|
||||
msg = msg.uppercase().replace(re:‘[^A-Z]’, ‘’)
|
||||
V message_len = msg.len
|
||||
I message_len C 0 <.< :grid_size
|
||||
V gap_size = :grid_size I/ message_len
|
||||
|
||||
L(i) 0 .< message_len
|
||||
V pos = i * gap_size + random:(0 .. gap_size)
|
||||
grid.cells[pos I/ :n_cols][pos % :n_cols] = msg[i]
|
||||
|
||||
R message_len
|
||||
R 0
|
||||
|
||||
F try_location(Grid &grid; word, direction, pos)
|
||||
V r = pos I/ :n_cols
|
||||
V c = pos % :n_cols
|
||||
V length = word.len
|
||||
|
||||
I (:dirs[direction][0] == 1 & (length + c) > :n_cols) |
|
||||
(:dirs[direction][0] == -1 & (length - 1) > c) |
|
||||
(:dirs[direction][1] == 1 & (length + r) > :n_rows) |
|
||||
(:dirs[direction][1] == -1 & (length - 1) > r)
|
||||
R 0
|
||||
|
||||
V rr = r
|
||||
V cc = c
|
||||
V i = 0
|
||||
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’)))
|
||||
169
Task/Word-search/C++/word-search.cpp
Normal file
169
Task/Word-search/C++/word-search.cpp
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
#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;
|
||||
}
|
||||
209
Task/Word-search/C-sharp/word-search.cs
Normal file
209
Task/Word-search/C-sharp/word-search.cs
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Wordseach
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
readonly static int[,] dirs = {{1, 0}, {0, 1}, {1, 1}, {1, -1}, {-1, 0},
|
||||
{0, -1}, {-1, -1}, {-1, 1}};
|
||||
|
||||
class Grid
|
||||
{
|
||||
public char[,] Cells = new char[nRows, nCols];
|
||||
public List<string> Solutions = new List<string>();
|
||||
public int NumAttempts;
|
||||
}
|
||||
|
||||
readonly static int nRows = 10;
|
||||
readonly static int nCols = 10;
|
||||
readonly static int gridSize = nRows * nCols;
|
||||
readonly static int minWords = 25;
|
||||
|
||||
readonly static Random rand = new Random();
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
PrintResult(CreateWordSearch(ReadWords("unixdict.txt")));
|
||||
}
|
||||
|
||||
private static List<string> ReadWords(string filename)
|
||||
{
|
||||
int maxLen = Math.Max(nRows, nCols);
|
||||
|
||||
return System.IO.File.ReadAllLines(filename)
|
||||
.Select(s => s.Trim().ToLower())
|
||||
.Where(s => Regex.IsMatch(s, "^[a-z]{3," + maxLen + "}$"))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private static Grid CreateWordSearch(List<string> words)
|
||||
{
|
||||
int numAttempts = 0;
|
||||
|
||||
while (++numAttempts < 100)
|
||||
{
|
||||
words.Shuffle();
|
||||
|
||||
var grid = new Grid();
|
||||
int messageLen = PlaceMessage(grid, "Rosetta Code");
|
||||
int target = gridSize - messageLen;
|
||||
|
||||
int cellsFilled = 0;
|
||||
foreach (var word in words)
|
||||
{
|
||||
cellsFilled += TryPlaceWord(grid, word);
|
||||
if (cellsFilled == target)
|
||||
{
|
||||
if (grid.Solutions.Count >= minWords)
|
||||
{
|
||||
grid.NumAttempts = numAttempts;
|
||||
return grid;
|
||||
}
|
||||
else break; // grid is full but we didn't pack enough words, start over
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int TryPlaceWord(Grid grid, string word)
|
||||
{
|
||||
int randDir = rand.Next(dirs.GetLength(0));
|
||||
int randPos = rand.Next(gridSize);
|
||||
|
||||
for (int dir = 0; dir < dirs.GetLength(0); dir++)
|
||||
{
|
||||
dir = (dir + randDir) % dirs.GetLength(0);
|
||||
|
||||
for (int pos = 0; pos < gridSize; pos++)
|
||||
{
|
||||
pos = (pos + randPos) % gridSize;
|
||||
|
||||
int lettersPlaced = TryLocation(grid, word, dir, pos);
|
||||
if (lettersPlaced > 0)
|
||||
return lettersPlaced;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int TryLocation(Grid grid, string word, int dir, int pos)
|
||||
{
|
||||
int r = pos / nCols;
|
||||
int c = pos % nCols;
|
||||
int len = word.Length;
|
||||
|
||||
// check bounds
|
||||
if ((dirs[dir, 0] == 1 && (len + c) > nCols)
|
||||
|| (dirs[dir, 0] == -1 && (len - 1) > c)
|
||||
|| (dirs[dir, 1] == 1 && (len + r) > nRows)
|
||||
|| (dirs[dir, 1] == -1 && (len - 1) > r))
|
||||
return 0;
|
||||
|
||||
int rr, cc, i, overlaps = 0;
|
||||
|
||||
// check cells
|
||||
for (i = 0, rr = r, cc = c; i < len; i++)
|
||||
{
|
||||
if (grid.Cells[rr, cc] != 0 && grid.Cells[rr, cc] != word[i])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
cc += dirs[dir, 0];
|
||||
rr += dirs[dir, 1];
|
||||
}
|
||||
|
||||
// place
|
||||
for (i = 0, rr = r, cc = c; i < len; i++)
|
||||
{
|
||||
if (grid.Cells[rr, cc] == word[i])
|
||||
overlaps++;
|
||||
else
|
||||
grid.Cells[rr, cc] = word[i];
|
||||
|
||||
if (i < len - 1)
|
||||
{
|
||||
cc += dirs[dir, 0];
|
||||
rr += dirs[dir, 1];
|
||||
}
|
||||
}
|
||||
|
||||
int lettersPlaced = len - overlaps;
|
||||
if (lettersPlaced > 0)
|
||||
{
|
||||
grid.Solutions.Add($"{word,-10} ({c},{r})({cc},{rr})");
|
||||
}
|
||||
|
||||
return lettersPlaced;
|
||||
}
|
||||
|
||||
private static int PlaceMessage(Grid grid, string msg)
|
||||
{
|
||||
msg = Regex.Replace(msg.ToUpper(), "[^A-Z]", "");
|
||||
|
||||
int messageLen = msg.Length;
|
||||
if (messageLen > 0 && messageLen < gridSize)
|
||||
{
|
||||
int gapSize = gridSize / messageLen;
|
||||
|
||||
for (int i = 0; i < messageLen; i++)
|
||||
{
|
||||
int pos = i * gapSize + rand.Next(gapSize);
|
||||
grid.Cells[pos / nCols, pos % nCols] = msg[i];
|
||||
}
|
||||
return messageLen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void Shuffle<T>(this IList<T> list)
|
||||
{
|
||||
int n = list.Count;
|
||||
while (n > 1)
|
||||
{
|
||||
n--;
|
||||
int k = rand.Next(n + 1);
|
||||
T value = list[k];
|
||||
list[k] = list[n];
|
||||
list[n] = value;
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintResult(Grid grid)
|
||||
{
|
||||
if (grid == null || grid.NumAttempts == 0)
|
||||
{
|
||||
Console.WriteLine("No grid to display");
|
||||
return;
|
||||
}
|
||||
int size = grid.Solutions.Count;
|
||||
|
||||
Console.WriteLine("Attempts: " + grid.NumAttempts);
|
||||
Console.WriteLine("Number of words: " + size);
|
||||
|
||||
Console.WriteLine("\n 0 1 2 3 4 5 6 7 8 9");
|
||||
for (int r = 0; r < nRows; r++)
|
||||
{
|
||||
Console.Write("\n{0} ", r);
|
||||
for (int c = 0; c < nCols; c++)
|
||||
Console.Write(" {0} ", grid.Cells[r, c]);
|
||||
}
|
||||
|
||||
Console.WriteLine("\n");
|
||||
|
||||
for (int i = 0; i < size - 1; i += 2)
|
||||
{
|
||||
Console.WriteLine("{0} {1}", grid.Solutions[i],
|
||||
grid.Solutions[i + 1]);
|
||||
}
|
||||
if (size % 2 == 1)
|
||||
Console.WriteLine(grid.Solutions[size - 1]);
|
||||
|
||||
Console.ReadLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
194
Task/Word-search/D/word-search.d
Normal file
194
Task/Word-search/D/word-search.d
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
import std.random : Random, uniform, randomShuffle;
|
||||
import std.stdio;
|
||||
|
||||
immutable int[][] dirs = [
|
||||
[1, 0], [ 0, 1], [ 1, 1],
|
||||
[1, -1], [-1, 0],
|
||||
[0, -1], [-1, -1], [-1, 1]
|
||||
];
|
||||
|
||||
enum nRows = 10;
|
||||
enum nCols = 10;
|
||||
enum gridSize = nRows * nCols;
|
||||
enum minWords = 25;
|
||||
|
||||
auto rnd = Random();
|
||||
|
||||
class Grid {
|
||||
int numAttempts;
|
||||
char[nRows][nCols] cells;
|
||||
string[] solutions;
|
||||
|
||||
this() {
|
||||
for(int row=0; row<nRows; ++row) {
|
||||
cells[row] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
printResult(createWordSearch(readWords("unixdict.txt")));
|
||||
}
|
||||
|
||||
string[] readWords(string filename) {
|
||||
import std.algorithm : all, max;
|
||||
import std.ascii : isAlpha;
|
||||
import std.string : chomp, toLower;
|
||||
|
||||
auto maxlen = max(nRows, nCols);
|
||||
|
||||
string[] words;
|
||||
auto source = File(filename);
|
||||
foreach(line; source.byLine) {
|
||||
chomp(line);
|
||||
if (line.length >= 3 && line.length <= maxlen) {
|
||||
if (all!isAlpha(line)) {
|
||||
words ~= line.toLower.idup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return words;
|
||||
}
|
||||
|
||||
Grid createWordSearch(string[] words) {
|
||||
Grid grid;
|
||||
int numAttempts;
|
||||
|
||||
outer:
|
||||
while(++numAttempts < 100) {
|
||||
randomShuffle(words);
|
||||
|
||||
grid = new Grid();
|
||||
int messageLen = placeMessage(grid, "Rosetta Code");
|
||||
int target = gridSize - messageLen;
|
||||
|
||||
int cellsFilled;
|
||||
foreach (string word; words) {
|
||||
cellsFilled += tryPlaceWord(grid, word);
|
||||
if (cellsFilled == target) {
|
||||
if (grid.solutions.length >= minWords) {
|
||||
grid.numAttempts = numAttempts;
|
||||
break outer;
|
||||
} else break; // grid is full but we didn't pack enough words, start over
|
||||
}
|
||||
}
|
||||
}
|
||||
return grid;
|
||||
}
|
||||
|
||||
int placeMessage(Grid grid, string msg) {
|
||||
import std.algorithm : filter;
|
||||
import std.ascii : isUpper;
|
||||
import std.conv : to;
|
||||
import std.string : toUpper;
|
||||
|
||||
msg = to!string(msg.toUpper.filter!isUpper);
|
||||
|
||||
if (msg.length > 0 && msg.length < gridSize) {
|
||||
int gapSize = gridSize / msg.length;
|
||||
|
||||
for (int i=0; i<msg.length; i++) {
|
||||
int pos = i * gapSize + uniform(0, gapSize, rnd);
|
||||
grid.cells[pos / nCols][pos % nCols] = msg[i];
|
||||
}
|
||||
return msg.length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tryPlaceWord(Grid grid, string word) {
|
||||
int randDir = uniform(0, dirs.length, rnd);
|
||||
int randPos = uniform(0, gridSize, rnd);
|
||||
|
||||
for (int dir=0; dir<dirs.length; dir++) {
|
||||
dir = (dir + randDir) % dirs.length;
|
||||
|
||||
for (int pos=0; pos<gridSize; pos++) {
|
||||
pos = (pos + randPos) % gridSize;
|
||||
|
||||
int lettersPlaced = tryLocation(grid, word, dir, pos);
|
||||
if (lettersPlaced > 0) {
|
||||
return lettersPlaced;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tryLocation(Grid grid, string word, int dir, int pos) {
|
||||
import std.format;
|
||||
|
||||
int r = pos / nCols;
|
||||
int c = pos % nCols;
|
||||
int len = word.length;
|
||||
|
||||
// check bounds
|
||||
if ((dirs[dir][0] == 1 && (len + c) > nCols)
|
||||
|| (dirs[dir][0] == -1 && (len - 1) > c)
|
||||
|| (dirs[dir][1] == 1 && (len + r) > nRows)
|
||||
|| (dirs[dir][1] == -1 && (len - 1) > r)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i, rr, cc, overlaps = 0;
|
||||
|
||||
// check cells
|
||||
for (i=0, rr=r, cc=c; i<len; i++) {
|
||||
if (grid.cells[rr][cc] != 0 && grid.cells[rr][cc] != word[i]) {
|
||||
return 0;
|
||||
}
|
||||
cc += dirs[dir][0];
|
||||
rr += dirs[dir][1];
|
||||
}
|
||||
|
||||
// place
|
||||
for (i=0, rr=r, cc=c; i<len; i++) {
|
||||
if (grid.cells[rr][cc] == word[i]) {
|
||||
overlaps++;
|
||||
} else {
|
||||
grid.cells[rr][cc] = word[i];
|
||||
}
|
||||
|
||||
if (i < len - 1) {
|
||||
cc += dirs[dir][0];
|
||||
rr += dirs[dir][1];
|
||||
}
|
||||
}
|
||||
|
||||
int lettersPlaced = len - overlaps;
|
||||
if (lettersPlaced > 0) {
|
||||
grid.solutions ~= format("%-10s (%d,%d)(%d,%d)", word, c, r, cc, rr);
|
||||
}
|
||||
|
||||
return lettersPlaced;
|
||||
}
|
||||
|
||||
void printResult(Grid grid) {
|
||||
if (grid is null || grid.numAttempts == 0) {
|
||||
writeln("No grid to display");
|
||||
return;
|
||||
}
|
||||
int size = grid.solutions.length;
|
||||
|
||||
writeln("Attempts: ", grid.numAttempts);
|
||||
writeln("Number of words: ", size);
|
||||
|
||||
writeln("\n 0 1 2 3 4 5 6 7 8 9");
|
||||
for (int r=0; r<nRows; r++) {
|
||||
writef("\n%d ", r);
|
||||
for (int c=0; c<nCols; c++) {
|
||||
writef(" %c ", grid.cells[r][c]);
|
||||
}
|
||||
}
|
||||
|
||||
writeln;
|
||||
writeln;
|
||||
|
||||
for (int i=0; i<size-1; i+=2) {
|
||||
writef("%s %s\n", grid.solutions[i], grid.solutions[i + 1]);
|
||||
}
|
||||
if (size % 2 == 1) {
|
||||
writeln(grid.solutions[size - 1]);
|
||||
}
|
||||
}
|
||||
359
Task/Word-search/FreeBASIC/word-search.basic
Normal file
359
Task/Word-search/FreeBASIC/word-search.basic
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
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
|
||||
189
Task/Word-search/Go/word-search.go
Normal file
189
Task/Word-search/Go/word-search.go
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var dirs = [][]int{{1, 0}, {0, 1}, {1, 1}, {1, -1}, {-1, 0}, {0, -1}, {-1, -1}, {-1, 1}}
|
||||
|
||||
const (
|
||||
nRows = 10
|
||||
nCols = nRows
|
||||
gridSize = nRows * nCols
|
||||
minWords = 25
|
||||
)
|
||||
|
||||
var (
|
||||
re1 = regexp.MustCompile(fmt.Sprintf("^[a-z]{3,%d}$", nRows))
|
||||
re2 = regexp.MustCompile("[^A-Z]")
|
||||
)
|
||||
|
||||
type grid struct {
|
||||
numAttempts int
|
||||
cells [nRows][nCols]byte
|
||||
solutions []string
|
||||
}
|
||||
|
||||
func check(err error) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func readWords(fileName string) []string {
|
||||
file, err := os.Open(fileName)
|
||||
check(err)
|
||||
defer file.Close()
|
||||
var words []string
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
word := strings.ToLower(strings.TrimSpace(scanner.Text()))
|
||||
if re1.MatchString(word) {
|
||||
words = append(words, word)
|
||||
}
|
||||
}
|
||||
check(scanner.Err())
|
||||
return words
|
||||
}
|
||||
|
||||
func createWordSearch(words []string) *grid {
|
||||
var gr *grid
|
||||
outer:
|
||||
for i := 1; i < 100; i++ {
|
||||
gr = new(grid)
|
||||
messageLen := gr.placeMessage("Rosetta Code")
|
||||
target := gridSize - messageLen
|
||||
cellsFilled := 0
|
||||
rand.Shuffle(len(words), func(i, j int) {
|
||||
words[i], words[j] = words[j], words[i]
|
||||
})
|
||||
for _, word := range words {
|
||||
cellsFilled += gr.tryPlaceWord(word)
|
||||
if cellsFilled == target {
|
||||
if len(gr.solutions) >= minWords {
|
||||
gr.numAttempts = i
|
||||
break outer
|
||||
} else { // grid is full but we didn't pack enough words, start over
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return gr
|
||||
}
|
||||
|
||||
func (gr *grid) placeMessage(msg string) int {
|
||||
msg = strings.ToUpper(msg)
|
||||
msg = re2.ReplaceAllLiteralString(msg, "")
|
||||
messageLen := len(msg)
|
||||
if messageLen > 0 && messageLen < gridSize {
|
||||
gapSize := gridSize / messageLen
|
||||
for i := 0; i < messageLen; i++ {
|
||||
pos := i*gapSize + rand.Intn(gapSize)
|
||||
gr.cells[pos/nCols][pos%nCols] = msg[i]
|
||||
}
|
||||
return messageLen
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (gr *grid) tryPlaceWord(word string) int {
|
||||
randDir := rand.Intn(len(dirs))
|
||||
randPos := rand.Intn(gridSize)
|
||||
for dir := 0; dir < len(dirs); dir++ {
|
||||
dir = (dir + randDir) % len(dirs)
|
||||
for pos := 0; pos < gridSize; pos++ {
|
||||
pos = (pos + randPos) % gridSize
|
||||
lettersPlaced := gr.tryLocation(word, dir, pos)
|
||||
if lettersPlaced > 0 {
|
||||
return lettersPlaced
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (gr *grid) tryLocation(word string, dir, pos int) int {
|
||||
r := pos / nCols
|
||||
c := pos % nCols
|
||||
le := len(word)
|
||||
|
||||
// check bounds
|
||||
if (dirs[dir][0] == 1 && (le+c) > nCols) ||
|
||||
(dirs[dir][0] == -1 && (le-1) > c) ||
|
||||
(dirs[dir][1] == 1 && (le+r) > nRows) ||
|
||||
(dirs[dir][1] == -1 && (le-1) > r) {
|
||||
return 0
|
||||
}
|
||||
overlaps := 0
|
||||
|
||||
// check cells
|
||||
rr := r
|
||||
cc := c
|
||||
for i := 0; i < le; i++ {
|
||||
if gr.cells[rr][cc] != 0 && gr.cells[rr][cc] != word[i] {
|
||||
return 0
|
||||
}
|
||||
cc += dirs[dir][0]
|
||||
rr += dirs[dir][1]
|
||||
}
|
||||
|
||||
// place
|
||||
rr = r
|
||||
cc = c
|
||||
for i := 0; i < le; i++ {
|
||||
if gr.cells[rr][cc] == word[i] {
|
||||
overlaps++
|
||||
} else {
|
||||
gr.cells[rr][cc] = word[i]
|
||||
}
|
||||
if i < le-1 {
|
||||
cc += dirs[dir][0]
|
||||
rr += dirs[dir][1]
|
||||
}
|
||||
}
|
||||
|
||||
lettersPlaced := le - overlaps
|
||||
if lettersPlaced > 0 {
|
||||
sol := fmt.Sprintf("%-10s (%d,%d)(%d,%d)", word, c, r, cc, rr)
|
||||
gr.solutions = append(gr.solutions, sol)
|
||||
}
|
||||
return lettersPlaced
|
||||
}
|
||||
|
||||
func printResult(gr *grid) {
|
||||
if gr.numAttempts == 0 {
|
||||
fmt.Println("No grid to display")
|
||||
return
|
||||
}
|
||||
size := len(gr.solutions)
|
||||
fmt.Println("Attempts:", gr.numAttempts)
|
||||
fmt.Println("Number of words:", size)
|
||||
fmt.Println("\n 0 1 2 3 4 5 6 7 8 9")
|
||||
for r := 0; r < nRows; r++ {
|
||||
fmt.Printf("\n%d ", r)
|
||||
for c := 0; c < nCols; c++ {
|
||||
fmt.Printf(" %c ", gr.cells[r][c])
|
||||
}
|
||||
}
|
||||
fmt.Println("\n")
|
||||
for i := 0; i < size-1; i += 2 {
|
||||
fmt.Printf("%s %s\n", gr.solutions[i], gr.solutions[i+1])
|
||||
}
|
||||
if size%2 == 1 {
|
||||
fmt.Println(gr.solutions[size-1])
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
unixDictPath := "/usr/share/dict/words"
|
||||
printResult(createWordSearch(readWords(unixDictPath)))
|
||||
}
|
||||
53
Task/Word-search/J/word-search-1.j
Normal file
53
Task/Word-search/J/word-search-1.j
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
require'web/gethttp'
|
||||
|
||||
unixdict=:verb define
|
||||
if. _1 -: fread 'unixdict.txt' do.
|
||||
(gethttp 'http://www.puzzlers.org/pub/wordlists/unixdict.txt') fwrite 'unixdict.txt'
|
||||
end.
|
||||
fread 'unixdict.txt'
|
||||
)
|
||||
|
||||
words=:verb define
|
||||
(#~ 1 - 0&e.@e.&'abcdefghijklmnopqrstuvwxyz'@>) (#~ [: (2&< * 10&>:) #@>) <;._2 unixdict''
|
||||
)
|
||||
|
||||
dirs=: 10#.0 0-.~>,{,~<i:1
|
||||
lims=: _10+,"2 +/&>/"1 (0~:i:4)#>,{,~<<"1]1 10 1 +i."0]10*i:_1
|
||||
dnms=: ;:'nw north ne west east sw south se'
|
||||
|
||||
genpuz=:verb define
|
||||
words=. words''
|
||||
fill=. 'ROSETTACODE'
|
||||
grid=. ,10 10$' '
|
||||
inds=. ,i.10 10
|
||||
patience=. -:#words
|
||||
key=. i.0 0
|
||||
inuse=. i.0 2
|
||||
while. (26>#key)+.0<cap=. (+/' '=grid)-#fill do.
|
||||
word=. >({~ ?@#) words
|
||||
dir=. ?@#dirs
|
||||
offs=. (inds#~(#word)<:inds{dir{lims)+/(i.#word)*/dir{dirs
|
||||
cool=. ' '=offs{grid
|
||||
sel=. */"1 cool+.(offs{grid)="1 word
|
||||
offs=. (sel*cap>:+/"1 cool)#offs
|
||||
if. (#offs) do.
|
||||
off=. ({~ ?@#) offs
|
||||
loc=. ({.off),dir
|
||||
if. -. loc e. inuse do.
|
||||
inuse=. inuse,loc
|
||||
grid=. word off} grid
|
||||
patience=. patience+1
|
||||
key=. /:~ key,' ',(10{.word),(3":1+10 10#:{.off),' ',dir{::dnms
|
||||
end.
|
||||
else. NB. grr...
|
||||
if. 0 > patience=. patience-1 do.
|
||||
inuse=.i.0 2
|
||||
key=.i.0 0
|
||||
grid=. ,10 10$' '
|
||||
patience=. -:#words
|
||||
end.
|
||||
end.
|
||||
end.
|
||||
puz=. (_23{.":i.10),' ',1j1#"1(":i.10 1),.' ',.10 10$fill (I.grid=' ')} grid
|
||||
puz,' ',1 1}._1 _1}.":((</.~ <.) i.@# * 3%#)key
|
||||
)
|
||||
23
Task/Word-search/J/word-search-2.j
Normal file
23
Task/Word-search/J/word-search-2.j
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
genpuz''
|
||||
0 1 2 3 4 5 6 7 8 9
|
||||
|
||||
0 y R p y r f O a p S
|
||||
1 l o l s i f c c e a
|
||||
2 l n v z i e n r n l
|
||||
3 o p z s t e E i n l
|
||||
4 h l s a v e r d a o
|
||||
5 e a t a g r e e d y
|
||||
6 m e m a g T f T A C
|
||||
7 a y e r s p f z a p
|
||||
8 O e c n a w o l l a
|
||||
9 e s o p o r p c D E
|
||||
|
||||
acetate 1 8 sw │ gam 7 5 west │ pol 1 3 sw
|
||||
acrid 1 8 south│ holly 5 1 north│ propose 10 7 west
|
||||
agreed 6 4 east │ massif 7 1 ne │ rsvp 1 5 sw
|
||||
allowance 9 10 west │ neva 3 7 sw │ sao 8 5 south
|
||||
alloy 2 10 south│ offer 9 7 north│ save 5 3 east
|
||||
arm 9 5 nw │ only 4 1 ne │ sop 10 2 east
|
||||
ayers 8 1 east │ pap 10 4 ne │ tee 4 5 se
|
||||
cop 10 8 nw │ paz 8 10 west │ wan 9 6 west
|
||||
fizzle 1 6 sw │ penna 1 9 south│
|
||||
173
Task/Word-search/Java/word-search.java
Normal file
173
Task/Word-search/Java/word-search.java
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
import java.io.*;
|
||||
import static java.lang.String.format;
|
||||
import java.util.*;
|
||||
|
||||
public class WordSearch {
|
||||
static class Grid {
|
||||
int numAttempts;
|
||||
char[][] cells = new char[nRows][nCols];
|
||||
List<String> solutions = new ArrayList<>();
|
||||
}
|
||||
|
||||
final static int[][] dirs = {{1, 0}, {0, 1}, {1, 1}, {1, -1}, {-1, 0},
|
||||
{0, -1}, {-1, -1}, {-1, 1}};
|
||||
|
||||
final static int nRows = 10;
|
||||
final static int nCols = 10;
|
||||
final static int gridSize = nRows * nCols;
|
||||
final static int minWords = 25;
|
||||
|
||||
final static Random rand = new Random();
|
||||
|
||||
public static void main(String[] args) {
|
||||
printResult(createWordSearch(readWords("unixdict.txt")));
|
||||
}
|
||||
|
||||
static List<String> readWords(String filename) {
|
||||
int maxLen = Math.max(nRows, nCols);
|
||||
|
||||
List<String> words = new ArrayList<>();
|
||||
try (Scanner sc = new Scanner(new FileReader(filename))) {
|
||||
while (sc.hasNext()) {
|
||||
String s = sc.next().trim().toLowerCase();
|
||||
if (s.matches("^[a-z]{3," + maxLen + "}$"))
|
||||
words.add(s);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
System.out.println(e);
|
||||
}
|
||||
return words;
|
||||
}
|
||||
|
||||
static Grid createWordSearch(List<String> words) {
|
||||
Grid grid = null;
|
||||
int numAttempts = 0;
|
||||
|
||||
outer:
|
||||
while (++numAttempts < 100) {
|
||||
Collections.shuffle(words);
|
||||
|
||||
grid = new Grid();
|
||||
int messageLen = placeMessage(grid, "Rosetta Code");
|
||||
int target = gridSize - messageLen;
|
||||
|
||||
int cellsFilled = 0;
|
||||
for (String word : words) {
|
||||
cellsFilled += tryPlaceWord(grid, word);
|
||||
if (cellsFilled == target) {
|
||||
if (grid.solutions.size() >= minWords) {
|
||||
grid.numAttempts = numAttempts;
|
||||
break outer;
|
||||
} else break; // grid is full but we didn't pack enough words, start over
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
static int placeMessage(Grid grid, String msg) {
|
||||
msg = msg.toUpperCase().replaceAll("[^A-Z]", "");
|
||||
|
||||
int messageLen = msg.length();
|
||||
if (messageLen > 0 && messageLen < gridSize) {
|
||||
int gapSize = gridSize / messageLen;
|
||||
|
||||
for (int i = 0; i < messageLen; i++) {
|
||||
int pos = i * gapSize + rand.nextInt(gapSize);
|
||||
grid.cells[pos / nCols][pos % nCols] = msg.charAt(i);
|
||||
}
|
||||
return messageLen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tryPlaceWord(Grid grid, String word) {
|
||||
int randDir = rand.nextInt(dirs.length);
|
||||
int randPos = rand.nextInt(gridSize);
|
||||
|
||||
for (int dir = 0; dir < dirs.length; dir++) {
|
||||
dir = (dir + randDir) % dirs.length;
|
||||
|
||||
for (int pos = 0; pos < gridSize; pos++) {
|
||||
pos = (pos + randPos) % gridSize;
|
||||
|
||||
int lettersPlaced = tryLocation(grid, word, dir, pos);
|
||||
if (lettersPlaced > 0)
|
||||
return lettersPlaced;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tryLocation(Grid grid, String word, int dir, int pos) {
|
||||
|
||||
int r = pos / nCols;
|
||||
int c = pos % nCols;
|
||||
int len = word.length();
|
||||
|
||||
// check bounds
|
||||
if ((dirs[dir][0] == 1 && (len + c) > nCols)
|
||||
|| (dirs[dir][0] == -1 && (len - 1) > c)
|
||||
|| (dirs[dir][1] == 1 && (len + r) > nRows)
|
||||
|| (dirs[dir][1] == -1 && (len - 1) > r))
|
||||
return 0;
|
||||
|
||||
int rr, cc, i, overlaps = 0;
|
||||
|
||||
// check cells
|
||||
for (i = 0, rr = r, cc = c; i < len; i++) {
|
||||
if (grid.cells[rr][cc] != 0 && grid.cells[rr][cc] != word.charAt(i))
|
||||
return 0;
|
||||
cc += dirs[dir][0];
|
||||
rr += dirs[dir][1];
|
||||
}
|
||||
|
||||
// place
|
||||
for (i = 0, rr = r, cc = c; i < len; i++) {
|
||||
if (grid.cells[rr][cc] == word.charAt(i))
|
||||
overlaps++;
|
||||
else
|
||||
grid.cells[rr][cc] = word.charAt(i);
|
||||
|
||||
if (i < len - 1) {
|
||||
cc += dirs[dir][0];
|
||||
rr += dirs[dir][1];
|
||||
}
|
||||
}
|
||||
|
||||
int lettersPlaced = len - overlaps;
|
||||
if (lettersPlaced > 0) {
|
||||
grid.solutions.add(format("%-10s (%d,%d)(%d,%d)", word, c, r, cc, rr));
|
||||
}
|
||||
|
||||
return lettersPlaced;
|
||||
}
|
||||
|
||||
static void printResult(Grid grid) {
|
||||
if (grid == null || grid.numAttempts == 0) {
|
||||
System.out.println("No grid to display");
|
||||
return;
|
||||
}
|
||||
int size = grid.solutions.size();
|
||||
|
||||
System.out.println("Attempts: " + grid.numAttempts);
|
||||
System.out.println("Number of words: " + size);
|
||||
|
||||
System.out.println("\n 0 1 2 3 4 5 6 7 8 9");
|
||||
for (int r = 0; r < nRows; r++) {
|
||||
System.out.printf("%n%d ", r);
|
||||
for (int c = 0; c < nCols; c++)
|
||||
System.out.printf(" %c ", grid.cells[r][c]);
|
||||
}
|
||||
|
||||
System.out.println("\n");
|
||||
|
||||
for (int i = 0; i < size - 1; i += 2) {
|
||||
System.out.printf("%s %s%n", grid.solutions.get(i),
|
||||
grid.solutions.get(i + 1));
|
||||
}
|
||||
if (size % 2 == 1)
|
||||
System.out.println(grid.solutions.get(size - 1));
|
||||
}
|
||||
}
|
||||
116
Task/Word-search/Julia/word-search.julia
Normal file
116
Task/Word-search/Julia/word-search.julia
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
using Random
|
||||
|
||||
const stepdirections = [[1, 0], [0, 1], [1, 1], [1, -1], [-1, 0], [0, -1], [-1, -1], [-1, 1]]
|
||||
const nrows = 10
|
||||
const ncols = nrows
|
||||
const gridsize = nrows * ncols
|
||||
const minwords = 25
|
||||
const minwordsize = 3
|
||||
|
||||
mutable struct LetterGrid
|
||||
nattempts::Int
|
||||
nrows::Int
|
||||
ncols::Int
|
||||
cells::Matrix{Char}
|
||||
solutions::Vector{String}
|
||||
LetterGrid() = new(0, nrows, ncols, fill(' ', nrows, ncols), Vector{String}())
|
||||
end
|
||||
|
||||
function wordmatrix(filename, usepropernames = true)
|
||||
words = [lowercase(line) for line in readlines(filename)
|
||||
if match(r"^[a-zA-Z]+$", line) != nothing && (usepropernames ||
|
||||
match(r"^[a-z]", line) != nothing) && length(line) >= minwordsize && length(line) <= ncols]
|
||||
n = 1000
|
||||
for i in 1:n
|
||||
grid = LetterGrid()
|
||||
messagelen = placemessage(grid, "Rosetta Code")
|
||||
target = grid.nrows * grid.ncols - messagelen
|
||||
cellsfilled = 0
|
||||
shuffle!(words)
|
||||
for word in words
|
||||
cellsfilled += tryplaceword(grid, word)
|
||||
if cellsfilled == target
|
||||
if length(grid.solutions) >= minwords
|
||||
grid.nattempts = i
|
||||
return grid
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
throw("Failed to place words after $n attempts")
|
||||
end
|
||||
|
||||
function placemessage(grid, msg)
|
||||
msg = uppercase(msg)
|
||||
msg = replace(msg, r"[^A-Z]" => "")
|
||||
messagelen = length(msg)
|
||||
if messagelen > 0 && messagelen < gridsize
|
||||
p = Int.(floor.(LinRange(messagelen, gridsize, messagelen) .+
|
||||
(rand(messagelen) .- 0.5) * messagelen / 3)) .- div(messagelen, 3)
|
||||
foreach(i -> grid.cells[div(p[i], nrows) + 1, p[i] % nrows + 1] = msg[i], 1:length(p))
|
||||
return messagelen
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function tryplaceword(grid, word)
|
||||
for dir in shuffle(stepdirections)
|
||||
for pos in shuffle(1:length(grid.cells))
|
||||
lettersplaced = trylocation(grid, word, dir, pos)
|
||||
if lettersplaced > 0
|
||||
return lettersplaced
|
||||
end
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function trylocation(grid, word, dir, pos)
|
||||
r, c = divrem(pos, nrows) .+ [1, 1]
|
||||
positions = [[r, c] .+ (dir .* i) for i in 1:length(word)]
|
||||
if !all(x -> 0 < x[1] <= nrows && 0 < x[2] <= ncols, positions)
|
||||
return 0
|
||||
end
|
||||
for (i, p) in enumerate(positions)
|
||||
letter = grid.cells[p[1],p[2]]
|
||||
if letter != ' ' && letter != word[i]
|
||||
return 0
|
||||
end
|
||||
end
|
||||
lettersplaced = 0
|
||||
for (i, p) in enumerate(positions)
|
||||
if grid.cells[p[1], p[2]] == ' '
|
||||
lettersplaced += 1
|
||||
grid.cells[p[1],p[2]] = word[i]
|
||||
end
|
||||
end
|
||||
if lettersplaced > 0
|
||||
push!(grid.solutions, lpad(word, 10) * " $(positions[1]) to $(positions[end])")
|
||||
end
|
||||
return lettersplaced
|
||||
end
|
||||
|
||||
function printresult(grid)
|
||||
if grid.nattempts == 0
|
||||
println("No grid to display: no solution found.")
|
||||
return
|
||||
end
|
||||
size = length(grid.solutions)
|
||||
println("Attempts: ", grid.nattempts)
|
||||
println("Number of words: ", size)
|
||||
println("\n 0 1 2 3 4 5 6 7 8 9")
|
||||
for r in 1:nrows
|
||||
print("\n", rpad(r, 4))
|
||||
for c in 1:ncols
|
||||
print(" $(grid.cells[r, c]) ")
|
||||
end
|
||||
end
|
||||
println()
|
||||
for i in 1:2:size
|
||||
println("$(grid.solutions[i]) $(i < size ? grid.solutions[i+1] : "")")
|
||||
end
|
||||
end
|
||||
|
||||
printresult(wordmatrix("words.txt", false))
|
||||
151
Task/Word-search/Kotlin/word-search.kotlin
Normal file
151
Task/Word-search/Kotlin/word-search.kotlin
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
// version 1.2.0
|
||||
|
||||
import java.util.Random
|
||||
import java.io.File
|
||||
|
||||
val dirs = listOf(
|
||||
intArrayOf( 1, 0), intArrayOf(0, 1), intArrayOf( 1, 1), intArrayOf( 1, -1),
|
||||
intArrayOf(-1, 0), intArrayOf(0, -1), intArrayOf(-1, -1), intArrayOf(-1, 1)
|
||||
)
|
||||
|
||||
val nRows = 10
|
||||
val nCols = 10
|
||||
val gridSize = nRows * nCols
|
||||
val minWords = 25
|
||||
val rand = Random()
|
||||
|
||||
class Grid {
|
||||
var numAttempts = 0
|
||||
val cells = List(nRows) { CharArray(nCols) }
|
||||
val solutions = mutableListOf<String>()
|
||||
}
|
||||
|
||||
fun readWords(fileName: String): List<String> {
|
||||
val maxLen = maxOf(nRows, nCols)
|
||||
val rx = Regex("^[a-z]{3,$maxLen}$")
|
||||
val f = File(fileName)
|
||||
return f.readLines().map { it.trim().toLowerCase() }
|
||||
.filter { it.matches(rx) }
|
||||
}
|
||||
|
||||
fun createWordSearch(words: List<String>): Grid {
|
||||
var numAttempts = 0
|
||||
lateinit var grid: Grid
|
||||
outer@ while (++numAttempts < 100) {
|
||||
grid = Grid()
|
||||
val messageLen = placeMessage(grid, "Rosetta Code")
|
||||
val target = gridSize - messageLen
|
||||
var cellsFilled = 0
|
||||
for (word in words.shuffled()) {
|
||||
cellsFilled += tryPlaceWord(grid, word)
|
||||
if (cellsFilled == target) {
|
||||
if (grid.solutions.size >= minWords) {
|
||||
grid.numAttempts = numAttempts
|
||||
break@outer
|
||||
}
|
||||
else { // grid is full but we didn't pack enough words, start over
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return grid
|
||||
}
|
||||
|
||||
fun placeMessage(grid: Grid, msg: String): Int {
|
||||
val rx = Regex("[^A-Z]")
|
||||
val msg2 = msg.toUpperCase().replace(rx, "")
|
||||
val messageLen = msg2.length
|
||||
if (messageLen in (1 until gridSize)) {
|
||||
val gapSize = gridSize / messageLen
|
||||
for (i in 0 until messageLen) {
|
||||
val pos = i * gapSize + rand.nextInt(gapSize)
|
||||
grid.cells[pos / nCols][pos % nCols] = msg2[i]
|
||||
}
|
||||
return messageLen
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
fun tryPlaceWord(grid: Grid, word: String): Int {
|
||||
val randDir = rand.nextInt(dirs.size)
|
||||
val randPos = rand.nextInt(gridSize)
|
||||
for (d in 0 until dirs.size) {
|
||||
val dir = (d + randDir) % dirs.size
|
||||
for (p in 0 until gridSize) {
|
||||
val pos = (p + randPos) % gridSize
|
||||
val lettersPlaced = tryLocation(grid, word, dir, pos)
|
||||
if (lettersPlaced > 0) return lettersPlaced
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
fun tryLocation(grid: Grid, word: String, dir: Int, pos: Int): Int {
|
||||
val r = pos / nCols
|
||||
val c = pos % nCols
|
||||
val len = word.length
|
||||
|
||||
// check bounds
|
||||
if ((dirs[dir][0] == 1 && (len + c) > nCols)
|
||||
|| (dirs[dir][0] == -1 && (len - 1) > c)
|
||||
|| (dirs[dir][1] == 1 && (len + r) > nRows)
|
||||
|| (dirs[dir][1] == -1 && (len - 1) > r)) return 0
|
||||
var overlaps = 0
|
||||
|
||||
// check cells
|
||||
var rr = r
|
||||
var cc = c
|
||||
for (i in 0 until len) {
|
||||
if (grid.cells[rr][cc] != '\u0000' && grid.cells[rr][cc] != word[i]) return 0
|
||||
cc += dirs[dir][0]
|
||||
rr += dirs[dir][1]
|
||||
}
|
||||
|
||||
// place
|
||||
rr = r
|
||||
cc = c
|
||||
for (i in 0 until len) {
|
||||
if (grid.cells[rr][cc] == word[i])
|
||||
overlaps++
|
||||
else
|
||||
grid.cells[rr][cc] = word[i]
|
||||
|
||||
if (i < len - 1) {
|
||||
cc += dirs[dir][0]
|
||||
rr += dirs[dir][1]
|
||||
}
|
||||
}
|
||||
|
||||
val lettersPlaced = len - overlaps
|
||||
if (lettersPlaced > 0) {
|
||||
grid.solutions.add(String.format("%-10s (%d,%d)(%d,%d)", word, c, r, cc, rr))
|
||||
}
|
||||
return lettersPlaced
|
||||
}
|
||||
|
||||
fun printResult(grid: Grid) {
|
||||
if (grid.numAttempts == 0) {
|
||||
println("No grid to display")
|
||||
return
|
||||
}
|
||||
val size = grid.solutions.size
|
||||
println("Attempts: ${grid.numAttempts}")
|
||||
println("Number of words: $size")
|
||||
println("\n 0 1 2 3 4 5 6 7 8 9")
|
||||
for (r in 0 until nRows) {
|
||||
print("\n$r ")
|
||||
for (c in 0 until nCols) print(" ${grid.cells[r][c]} ")
|
||||
}
|
||||
|
||||
println("\n")
|
||||
|
||||
for (i in 0 until size - 1 step 2) {
|
||||
println("${grid.solutions[i]} ${grid.solutions[i + 1]}")
|
||||
}
|
||||
if (size % 2 == 1) println(grid.solutions[size - 1])
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
printResult(createWordSearch(readWords("unixdict.txt")))
|
||||
}
|
||||
130
Task/Word-search/Nim/word-search.nim
Normal file
130
Task/Word-search/Nim/word-search.nim
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
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()
|
||||
99
Task/Word-search/Perl/word-search.pl
Normal file
99
Task/Word-search/Perl/word-search.pl
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
use feature <bitwise>;
|
||||
use Path::Tiny;
|
||||
use List::Util qw( shuffle );
|
||||
|
||||
my $size = 10;
|
||||
my $s1 = $size + 1;
|
||||
$_ = <<END;
|
||||
.....R....
|
||||
......O...
|
||||
.......S..
|
||||
........E.
|
||||
T........T
|
||||
.A........
|
||||
..C.......
|
||||
...O......
|
||||
....D.....
|
||||
.....E....
|
||||
END
|
||||
|
||||
my @words = shuffle path('/usr/share/dict/words')->slurp =~ /^[a-z]{3,7}$/gm;
|
||||
my @played;
|
||||
my %used;
|
||||
|
||||
for my $word ( (@words) x 5 )
|
||||
{
|
||||
my ($pat, $start, $end, $mask, $nulls) = find( $word );
|
||||
defined $pat or next;
|
||||
$used{$word}++ and next; # only use words once
|
||||
$nulls //= '';
|
||||
my $expand = $word =~ s/\B/$nulls/gr;
|
||||
my $pos = $start;
|
||||
if( $start > $end )
|
||||
{
|
||||
$pos = $end;
|
||||
$expand = reverse $expand;
|
||||
}
|
||||
substr $_, $pos, length $mask,
|
||||
(substr( $_, $pos, length $mask ) &. ~. "$mask") |. "$expand";
|
||||
push @played, join ' ', $word, $start, $end;
|
||||
tr/.// > 0 or last;
|
||||
}
|
||||
|
||||
print " 0 1 2 3 4 5 6 7 8 9\n\n";
|
||||
my $row = 0;
|
||||
print s/(?<=.)(?=.)/ /gr =~ s/^/ $row++ . ' ' /gemr;
|
||||
print "\nNumber of words: ", @played . "\n\n";
|
||||
my @where = map
|
||||
{
|
||||
my ($word, $start, $end) = split;
|
||||
sprintf "%11s %s", $word, $start < $end
|
||||
? "(@{[$start % $s1]},@{[int $start / $s1]})->" .
|
||||
"(@{[$end % $s1 - 1]},@{[int $end / $s1]})"
|
||||
: "(@{[$start % $s1 - 1]},@{[int $start / $s1]})->" .
|
||||
"(@{[$end % $s1]},@{[int $end / $s1]})";
|
||||
} sort @played;
|
||||
print splice(@where, 0, 3), "\n" while @where;
|
||||
tr/.// and die "incomplete";
|
||||
|
||||
sub find
|
||||
{
|
||||
my ($word) = @_;
|
||||
my $n = length $word;
|
||||
my $nm1 = $n - 1;
|
||||
my %pats;
|
||||
|
||||
for my $space ( 0, $size - 1 .. $size + 1 )
|
||||
{
|
||||
my $nulls = "\0" x $space;
|
||||
my $mask = "\xff" . ($nulls . "\xff") x $nm1; # vert
|
||||
my $gap = qr/.{$space}/s;
|
||||
while( /(?=(.(?:$gap.){$nm1}))/g )
|
||||
{
|
||||
my $pat = ($1 &. $mask) =~ tr/\0//dr;
|
||||
$pat =~ tr/.// or next;
|
||||
my $pos = "$-[1] $+[1]";
|
||||
$word =~ /$pat/ or reverse($word) =~ /$pat/ or next;
|
||||
push @{ $pats{$pat} }, "$pos $mask $nulls";
|
||||
}
|
||||
}
|
||||
|
||||
for my $key ( sort keys %pats )
|
||||
{
|
||||
if( $word =~ /^$key$/ )
|
||||
{
|
||||
my @all = @{ $pats{$key} };
|
||||
return $key, split ' ', $all[ rand @all ];
|
||||
}
|
||||
elsif( (reverse $word) =~ /^$key$/ )
|
||||
{
|
||||
my @all = @{ $pats{$key} };
|
||||
my @parts = split ' ', $all[ rand @all ];
|
||||
return $key, @parts[ 1, 0, 2, 3]
|
||||
}
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
111
Task/Word-search/Phix/word-search.phix
Normal file
111
Task/Word-search/Phix/word-search.phix
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
(phixonline)-->
|
||||
<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>
|
||||
<!--
|
||||
163
Task/Word-search/Python/word-search.py
Normal file
163
Task/Word-search/Python/word-search.py
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
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")))
|
||||
326
Task/Word-search/QB64/word-search.qb64
Normal file
326
Task/Word-search/QB64/word-search.qb64
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
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
|
||||
112
Task/Word-search/Racket/word-search.rkt
Normal file
112
Task/Word-search/Racket/word-search.rkt
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
#lang racket
|
||||
;; ---------------------------------------------------------------------------------------------------
|
||||
(module+ main
|
||||
(display-puzzle (create-word-search))
|
||||
(newline)
|
||||
(parameterize ((current-min-words 50))
|
||||
(display-puzzle (create-word-search #:n-rows 20 #:n-cols 20))))
|
||||
|
||||
;; ---------------------------------------------------------------------------------------------------
|
||||
(define current-min-words (make-parameter 25))
|
||||
|
||||
;; ---------------------------------------------------------------------------------------------------
|
||||
(define (all-words pzl)
|
||||
(filter-map (good-word? pzl) (file->lines "data/unixdict.txt")))
|
||||
|
||||
(define (good-word? pzl)
|
||||
(let ((m (puzzle-max-word-size pzl)))
|
||||
(λ (w) (and (<= 3 (string-length w) m) (regexp-match #px"^[A-Za-z]*$" w) (string-downcase w)))))
|
||||
|
||||
(struct puzzle (n-rows n-cols cells solutions) #:transparent)
|
||||
|
||||
(define puzzle-max-word-size (match-lambda [(puzzle n-rows n-cols _ _) (max n-rows n-cols)]))
|
||||
|
||||
(define dirs '((-1 -1 ↖) (-1 0 ↑) (-1 1 ↗) (0 -1 ←) (0 1 →) (1 -1 ↙) (1 0 ↓) (1 1 ↘)))
|
||||
|
||||
;; ---------------------------------------------------------------------------------------------------
|
||||
(define (display-puzzle pzl) (displayln (puzzle->string pzl)))
|
||||
|
||||
(define (puzzle->string pzl)
|
||||
(match-let*
|
||||
(((and pzl (puzzle n-rows n-cols cells (and solutions (app length size)))) pzl)
|
||||
(column-numbers (cons "" (range n-cols)))
|
||||
(render-row (λ (r) (cons r (map (λ (c) (hash-ref cells (cons r c) #\_)) (range n-cols)))))
|
||||
(the-grid (add-between (map (curry map (curry ~a #:width 3))
|
||||
(cons column-numbers (map render-row (range n-rows)))) "\n"))
|
||||
(solutions§ (solutions->string (sort solutions string<? #:key car))))
|
||||
(string-join (flatten (list the-grid "\n\n" solutions§)) "")))
|
||||
|
||||
(define (solutions->string solutions)
|
||||
(let* ((l1 (compose string-length car))
|
||||
(format-solution-to-max-word-size (format-solution (l1 (argmax l1 solutions)))))
|
||||
(let recur ((solutions solutions) (need-newline? #f) (acc null))
|
||||
(if (null? solutions)
|
||||
(reverse (if need-newline? (cons "\n" acc) acc))
|
||||
(let* ((spacer (if need-newline? "\n" " "))
|
||||
(solution (format "~a~a" (format-solution-to-max-word-size (car solutions)) spacer)))
|
||||
(recur (cdr solutions) (not need-newline?) (cons solution acc)))))))
|
||||
|
||||
(define (format-solution max-word-size)
|
||||
(match-lambda [(list word row col dir)
|
||||
(string-append (~a word #:width (+ max-word-size 1))
|
||||
(~a (format "(~a,~a ~a)" row col dir) #:width 9))]))
|
||||
|
||||
;; ---------------------------------------------------------------------------------------------------
|
||||
(define (create-word-search #:msg (msg "Rosetta Code") #:n-rows (n-rows 10) #:n-cols (n-cols 10))
|
||||
(let* ((pzl (puzzle n-rows n-cols (hash) null))
|
||||
(MSG (sanitise-message msg))
|
||||
(n-holes (- (* n-rows n-cols) (string-length MSG))))
|
||||
(place-message (place-words pzl (shuffle (all-words pzl)) (current-min-words) n-holes) MSG)))
|
||||
|
||||
(define (sanitise-message msg) (regexp-replace* #rx"[^A-Z]" (string-upcase msg) ""))
|
||||
|
||||
(define (place-words pzl words needed-words holes)
|
||||
(let inner ((pzl pzl) (words words) (needed-words needed-words) (holes holes))
|
||||
(cond [(and (not (positive? needed-words)) (zero? holes)) pzl]
|
||||
[(null? words)
|
||||
(eprintf "no solution... retrying (~a words remaining)~%" needed-words)
|
||||
(inner pzl (shuffle words) needed-words)]
|
||||
[else
|
||||
(let/ec no-fit
|
||||
(let*-values
|
||||
(([word words...] (values (car words) (cdr words)))
|
||||
([solution cells′ holes′]
|
||||
(fit-word word pzl holes (λ () (no-fit (inner pzl words... needed-words holes)))))
|
||||
([solutions′] (cons solution (puzzle-solutions pzl)))
|
||||
([pzl′] (struct-copy puzzle pzl (solutions solutions′) (cells cells′))))
|
||||
(inner pzl′ words... (sub1 needed-words) holes′)))])))
|
||||
|
||||
(define (fit-word word pzl holes fail)
|
||||
(match-let* (((puzzle n-rows n-cols cells _) pzl)
|
||||
(rows (shuffle (range n-rows)))
|
||||
(cols (shuffle (range n-cols)))
|
||||
(fits? (let ((l (string-length word))) (λ (maxz z0 dz) (< -1 (+ z0 (* dz l)) maxz)))))
|
||||
(let/ec return
|
||||
(for* ((dr-dc-↗ (shuffle dirs))
|
||||
(r0 rows) (dr (in-value (car dr-dc-↗))) #:when (fits? n-rows r0 dr)
|
||||
(c0 cols) (dc (in-value (cadr dr-dc-↗))) #:when (fits? n-cols c0 dc)
|
||||
(↗ (in-value (caddr dr-dc-↗))))
|
||||
(let/ec retry/ec (attempt-word-fit pzl word r0 c0 dr dc ↗ holes return retry/ec)))
|
||||
(fail))))
|
||||
|
||||
(define (attempt-word-fit pzl word r0 c0 dr dc ↗ holes return retry)
|
||||
(let-values (([cells′ available-cells′]
|
||||
(for/fold ((cells′ (puzzle-cells pzl)) (holes′ holes))
|
||||
((w word) (i (in-naturals)))
|
||||
(define k (cons (+ r0 (* dr i)) (+ c0 (* dc i))))
|
||||
(cond [(not (hash-has-key? cells′ k))
|
||||
(if (zero? holes′) (retry) (values (hash-set cells′ k w) (sub1 holes′)))]
|
||||
[(char=? (hash-ref cells′ k) w) (values cells′ holes′)]
|
||||
[else (retry)]))))
|
||||
(return (list word r0 c0 ↗) cells′ available-cells′)))
|
||||
|
||||
;; ---------------------------------------------------------------------------------------------------
|
||||
(define (place-message pzl MSG)
|
||||
(match-define (puzzle n-rows n-cols cells _) pzl)
|
||||
(struct-copy puzzle pzl
|
||||
(cells
|
||||
(let loop ((r 0) (c 0) (cells cells) (msg (string->list MSG)))
|
||||
(cond [(or (null? msg) (= r n-rows)) cells]
|
||||
[(= c n-cols) (loop (add1 r) 0 cells msg)]
|
||||
[(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))])))))
|
||||
129
Task/Word-search/Raku/word-search.raku
Normal file
129
Task/Word-search/Raku/word-search.raku
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
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
|
||||
}
|
||||
224
Task/Word-search/Visual-Basic-.NET/word-search.vb
Normal file
224
Task/Word-search/Visual-Basic-.NET/word-search.vb
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
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
|
||||
158
Task/Word-search/Wren/word-search.wren
Normal file
158
Task/Word-search/Wren/word-search.wren
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
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")))
|
||||
27
Task/Word-search/Zkl/word-search-1.zkl
Normal file
27
Task/Word-search/Zkl/word-search-1.zkl
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
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();
|
||||
foreach dr,dc in (dirs){ v.clear(); r,c:=R,C;
|
||||
while( (0<=r<10) and (0<=c<10) ){ v.append(grid[r][c]); r+=dr; c+=dc; }
|
||||
vs.append(T(v.concat(), // eg "???e??????" would match "cohen" or "mineral"
|
||||
dr,dc));
|
||||
}
|
||||
vs.filter(fcn(v){ v[0].len()>2 }).shuffle()
|
||||
}
|
||||
fcn findFit(vs,words){ //-->(n, word) ie (nth vector,word), empty vs not seen
|
||||
do(1000){ foreach n,v in (vs.enumerate()){ do(10){ // lots of ties
|
||||
word:=words[(0).random(nwds)];
|
||||
if(word.matches(v[0][0,word.len()])) return(word,n); // "??" !match "abc"
|
||||
}}}
|
||||
False
|
||||
}
|
||||
fcn pasteWord(r,c, dr,dc, word) // jam word into grid along vector
|
||||
{ foreach char in (word){ grid[r][c]=char; r+=dr; c+=dc; } }
|
||||
fcn printGrid{
|
||||
println("\n 0 1 2 3 4 5 6 7 8 9");
|
||||
foreach n,line in (grid.enumerate()){ println(n," ",line.concat(" ")) }
|
||||
}
|
||||
fcn stuff(msg){ MSG:=msg.toUpper() : Utils.Helpers.cycle(_);
|
||||
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?
|
||||
}
|
||||
30
Task/Word-search/Zkl/word-search-2.zkl
Normal file
30
Task/Word-search/Zkl/word-search-2.zkl
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
msg:="RosettaCode";
|
||||
|
||||
validWord:=RegExp("[A-Za-z]+\n$").matches;
|
||||
File("unixdict.txt").read(*) // dictionary file to blob, copied from web
|
||||
// blob to list of valid words
|
||||
.filter('wrap(w){ (3<w.len()<=10) and validWord(w) }) // "word\n"
|
||||
.howza(11).pump(List,"toLower") // convert blob to list of words, removing \n
|
||||
: words:=(_);
|
||||
|
||||
reg fitted; do{
|
||||
var nwds=words.len(), grid=(10).pump(List(),(10).pump(List(),"?".copy).copy);
|
||||
fitted=List(); do(100){
|
||||
r,c:=(0).random(10), (0).random(10);
|
||||
if(grid[r][c]=="?"){
|
||||
vs,wn:=buildVectors(r,c), findFit(vs,words);
|
||||
if(wn){
|
||||
w,n:=wn; pasteWord(r,c,vs[n][1,*].xplode(),w);
|
||||
fitted.append(T(r,c,w));
|
||||
}
|
||||
}}
|
||||
print(".");
|
||||
}while(fitted.len()<25 or not stuff(msg));
|
||||
|
||||
printGrid();
|
||||
println(fitted.len()," words fitted");
|
||||
fitted.pump(Console.println, T(Void.Read,3,False),
|
||||
fcn{ vm.arglist.pump(String,
|
||||
fcn([(r,c,w)]){ "%-19s".fmt("[%d,%d]: %s ".fmt(r,c,w)) }) }
|
||||
);
|
||||
fitted.apply(fcn(w){ w[2].len() }).sum(0).println();
|
||||
Loading…
Add table
Add a link
Reference in a new issue