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 ) ));
SergeiBaklan
Jul 19, 2022Diamond Contributor
Not sure I understood your idea correctly. If we scan only one row (one by one) and expected result is like
when it could be
///--- SCAN row on Words
getWord=
LAMBDA( str, words,
XLOOKUP( str, words, words, 0) );
getWordOnRight=
LAMBDA( str, words,
IFNA( INDEX( Words, XMATCH( TRUE, RIGHT(str, LEN(Words) )= Words ) ), 0 )
);
getReversedWordOnRight=
LAMBDA( str, words,
IFNA( INDEX( Words, XMATCH( TRUE, LEFT( reversedText(str), LEN(Words) )= Words ) ), 0 )
);
scanVector=
LAMBDA( vector, words,
SCAN("", vector, LAMBDA(a,v,
IF( getWord( a, Words ) <> 0, v,
IF( getWordOnRight( a&v, Words ) <> 0,
getWordOnRight( a&v, Words ),
IF( getReversedWordOnRight( a&v, Words ) <> 0,
getReversedWordOnRight( a&v, Words ),
a&v )
)
)
) )
);
I guess could could be more compact, just first iteration.
Patrick2788
Jul 19, 2022Silver Contributor
That's exactly it. My idea involved scanning the entire target array, but it looks like going by row is much better. No need to account for the change in row and less text to discard.
- PeterBartholomew1Jul 20, 2022Silver ContributorI have been trying something different with some success. I reduce the entire puzzle to a single string, padded with "|" between source rows and, rather than reversing the puzzle, I reverse the search words and append them to the original set. The location of the matches within the string is related to the position within the puzzle grid. So far, I have 0 and 1 to show where the matches are, but by combining that with the original grid, I could display the words in their original setting.