Forum Discussion
Patrick2788
Jul 14, 2022Silver Contributor
A LAMBDA Word Search Puzzle
I've created a 15x10 Word Search. I've included a word list (dynamic range) containing words which might be found in the word search. The goal is to then extract those words when they appear in the...
- Jul 16, 2022
Here is one more variant
//------ variant without TEXTJOIN() reverseColumns= LAMBDA( data, LET( n, COLUMNS( data ), CHOOSECOLS( data, SEQUENCE(n,,n,-1) ) )); reversedText= LAMBDA( str, LET( head, LEFT(str), tail, RIGHT(str, LEN(str) - 1), IF(str = "", "", reversedText(tail) & head) )); isPolindrom= LAMBDA( text, text = reversedText( text ) ); checkSingleWord= LAMBDA( str, vector, LET( getWord, REDUCE("", vector, LAMBDA( a,v, IF( LEFT(str, LEN(a&v)) = a&v, a&v, IF( LEFT(str) = a, v, IF( a = str, a, "" ) ) ) ) ), IF( getWord = str, str, "") )); checkListOfWords= LAMBDA( wordsVector, vector, LET( getWords, REDUCE("", wordsVector, LAMBDA(a,v, VSTACK(a, checkSingleWord( v, vector) ) ) ), IFERROR( FILTER( getWords, getWords <> ""), "" ) )); wordsInMatrix= LAMBDA( data, wordsVector, LET( k, SEQUENCE( ROWS(data) ), scanData, REDUCE(1, k, LAMBDA(a,v, CHOOSECOLS( IF( v < SEQUENCE(,v,v,-1), a, VSTACK(a, checkListOfWords( Words, CHOOSEROWS(data,v) ) ) ), 1 ) )), removeFirst, DROP( scanData, 1 ), FILTER( removeFirst, removeFirst <> "") )); wordsInPuzzle= LAMBDA( data, wordsVector, LET( allWords, SORT( VSTACK( wordsInMatrix( data, wordsVector ), wordsInMatrix( reverseColumns( data ), wordsVector ), wordsInMatrix( TRANSPOSE( data ), wordsVector ), wordsInMatrix( reverseColumns( TRANSPOSE( data ) ), wordsVector ) )), ifPolindroms, MAP(allWords, LAMBDA(v, isPolindrom(v) ) ), polindroms, UNIQUE( FILTER(allWords, ifPolindroms)), notPolindroms, FILTER(allWords, ifPolindroms -1), stack, IF( ISERR(polindroms), notPolindroms, VSTACK( polindroms, notPolindroms ) ), SORT( stack ) ));
mtarler
Jul 25, 2022Silver Contributor
yes I saw the no diagonals but didn't see any exclusion for overlap. Besides, I don't think overlap adds a lot of complexity, just prevents some tricks that make it more efficient.
Patrick2788
Jul 23, 2023Silver Contributor
I thought it would be interesting to re-visit this task with a fresh set of eyes. I scrapped my solution from 2022 and made things more interesting.
Functionality added:
- Diagonals are now supported
- Multiple dictionary support
There's a bit of calculation crunch when using the dictionary with 9,500+ words. I was going to add an Oxford dictionary that contained 100,000 words but the CSV needed extensive cleanup (Probably for the best as larger word lists contain a lot of made-up words).
=LET(
height, ROWS(Puzzle),
width, COLUMNS(Puzzle),
AccumulateText, LAMBDA(a, letter, a & letter),
Letter2Array, LAMBDA(arr, SCAN("", arr, AccumulateText)),
WordsReversed, MAP(dictionary, LAMBDA(e, Reverse(e))),
results, REDUCE(
"",
Puzzle,
LAMBDA(a, letter,
LET(
r, ROW(letter),
c, COLUMN(letter),
across, INDEX(Puzzle, r, SEQUENCE(, width - c + 1, c, 1)),
down, INDEX(Puzzle, SEQUENCE(height - r + 1, , r), c),
diagonal_c, SEQUENCE(width - c + 1, , c),
diagonal_r, SEQUENCE(width - c + 1, , r),
diagonal, INDEX(Puzzle, diagonal_r, diagonal_c),
neg_diagonal_c, SEQUENCE(c, , c, -1),
neg_diagonal_r, SEQUENCE(width - c, , r),
neg_diagonal, INDEX(Puzzle, neg_diagonal_r, neg_diagonal_c),
arrAcross, TOCOL(Letter2Array(across)),
arrDown, Letter2Array(down),
arrDiagonal, Letter2Array(diagonal),
arrDiagonalNeg, TOCOL(Letter2Array(neg_diagonal)),
WordStack, IF(
c = width,
VSTACK(arrDown, arrDiagonalNeg),
IF(
r = height,
VSTACK(arrAcross, arrDiagonal, arrDiagonalNeg),
IF(
c = 1,
VSTACK(arrAcross, arrDown, arrDiagonal),
VSTACK(arrAcross, arrDown, arrDiagonal, arrDiagonalNeg)
)
)
),
WordBank, VSTACK(dictionary, WordsReversed),
FoundWords, VSTACK(dictionary, dictionary),
GetWords, TOCOL(XLOOKUP(WordStack, WordBank, FoundWords, ""), 2),
VSTACK(a, GetWords)
)
)
),
SORT(FILTER(results, results <> "", "no words found"))
)