[Question]
  [
#### Background
[*Scrabble*](https://en.wikipedia.org/wiki/Scrabble) is a word game in which players collaboratively build a board consisting of letter tiles that spell words. Each word must be connected to another word, and players gain points based on the letters they use and where they are placed. Words can be spelled either from left-to-right or top-to-bottom, and their validity is determined via the Scrabble Dictionary. Each contiguous set of more than one letter in a row or column must be a valid word.
#### The Challenge
Your challenge is to write a function that accepts a 2D grid of letters and determines whether or not it consitutes a valid Scrabble board. A board is valid if every word in every column and row is a valid word according to [this text file containing a Scrabble Dictionary](https://raw.githubusercontent.com/redbo/scrabble/master/dictionary.txt).
Your function should take a 2D grid of characters and a list of valid words as input. The board is assumed to be contiguous (every word is connected to the board) and padded with spaces to be rectangular. Your function must return a truthy value of your choice if the board is valid, and a falsey one otherwise. The board is assumed to contain at least 2 letters. This is [Code Golf,](https://codegolf.stackexchange.com/questions/tagged/code-golf) so the shortest answer wins, and the usual rules/loopholes apply.
#### Test Cases
All boards' validity is determined according to [this list of Scrabble words.](https://scrabble.hasbro.com/en-us/tools)
Valid boards:
```
MAP   
O APP
NEW O
T EEL
HAD E
```
---
```
DANCING 
  A     
  SEEING
  A    O 
  LAZY T
```
---
```
SORDID   
O U      
LEEWAY   
E        
L        
YESTERDAY
       A   
```
Invalid boards:
```
MOLAR
A    
RATS 
CR   
HC   
 H   
```
---
```
RASCAL
A     
BAKING
B   OO
ISLAND
T     
```
---
```
JOYFUL 
  OFFER
```
  
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~12~~ 9 bytes
-3 bytes thanks to Jonathan Allan
A dyadic function taking a list of lines on the left and a list of words on the right.
```
Z;⁸KḲḊƇfƑ
```
[Try it online!](https://tio.run/##TZExcsMgEEX7nGI7Gt0g1VqsLMUYNIBGgzUq4yLjC6RMmsykyynSpEqlPjO@h30RhQUpDoXe18KH5fP0eDo9z/Ph/voy7S7T92V6P78dzx/zz@f19Wueh0HssQUQhTCAbRupqQcT6YFIRdYogcRY3A1Coi4bveXVAAg8knREsXyrmlxWeAjgs9UZKxsJy0kdrGZF1GPImgBu9X86kPNkJYa0axoIedu9UWhjGZelFr1jljb/1@XSY81MFouuRLV6eHKDu9z@hnvnuzdOoZYpBPgzPphQdSpfzVQVWTGO8yBQFCAwfzlAWGNimSIEsTWeEaNkcC6J6e6s4hskGO1rFhodJmN8DEaLPSVraxQxbZewBh9VnFAhK06a1S238Rc "Jelly – Try It Online")
```
Z;⁸         -- concatenate list of columns and list of rows
   KḲ       -- join on spaces and split on spaces to get list of words
      Ƈ     -- keep words that are truthy (non-empty)
     Ḋ      --   when the first character is removed
         Ƒ  -- is this resulting word list invariant when
        f   --   all words not in the dictionary are removed?
```
[Answer]
# [Ruby](https://www.ruby-lang.org/), ~~60~~ 57 bytes
```
->b,d{(b+b.transpose).all?{|c|d==d|c.join.scan(/\w\w+/)}}
```
[Try it online!](https://tio.run/##PZJbT8JAEIXf51fMk6UBy7tJNSNdBF27TVtCqvLQCwYMFEJVYqy/HXeGSx96Tqc7nTNfuvsqfg7v/uH6tuhVv52iW3ifu7xutptm7nr5anX325Zt5ftVW3ofm2XtNWVed/pv@7d9t@/@/R2@89Wy8l/BeaYIEQxSFEGopmggRaU0jChA5fQAnIDCwTh8QEAk5MuaRClbOleMNZpeMkylITFxMA5QPjvBY4tWakoZO4V4rl1cppJUxQFlcKoQOjADWNaSE33kpEZTDDIQYkoThEHMfjSQTCN7l/ExJQPScMp6T0@c9J5jGhgnmsLArojn048mG060LIVmOFSxDJaRDpHTQ8eSYTlhYGv5sDyYlMWSYmEAorIpO4tWxITpiE1ICUmj5cwS0VRJa2S0Yo0nIke44uwLnR0dM2V3YeXMoCN4uidMrjfPywVWG2yL1u5T2CUKb7Ws5423zredq5tysVlv3ctDvmtce26L76/2P5rBvK4O/w "Ruby – Try It Online")
Takes the board as a list of lists of characters. Returns `true` for valid boards, `false` otherwise.
The board is valid if for every word on the board, the union of that word with the dictionary is equal to the dictionary.
[Answer]
# [Python 3](https://docs.python.org/3/), ~~138~~ \$\cdots\$ ~~86~~ 79 bytes
```
lambda b,d:all(i in d+[*s]for s in[*map(''.join,zip(*b))]+b for i in s.split())
```
[Try it online!](https://tio.run/##TVJhb9owEP2eX3HKF8fUq9Z2UqVKmeQSU9hCjJIgxNJ8ABLUrBQi7KpdEb@d5ewQEVl5zz4/vzv76n/6Zbe9O63959Nm8bYsFrBkxcNis/EqqLZQXGU9la93e1DNNOu9LWqPkOu/u2rLvqra6y0pza@WgDuMQF2relNpj9LTx25fKD8jnDAg3P4nE4SAR/1R9IRUiBDhSaYIQx4ghPzP3KAQM27YmBvhWEbpEEnEE26EkZghTPhMGOlEhgIxnhpIhGiNkiYQzi2Lg5HZPBdJKuKgscgdXSqtwAcvcxszAJeBK6FJGEnjAhJJCk3CSJpMQbg5g8xtqzEKAA74WW7dL9al5VgfpFZts4Gz4RQ6va2@nQiAi8jlpCvCnm0@NLPHj2XIY4zw8/6Yp4kh/bhdGfbPGQ87XcyTPg87oQk/8t9tOY9YiylmlIQ8CuzVQKf@JeeDadjeghwMROzm1Ck/63KlywJv@YaBHd/toM7qpVy9lnsMkuf32/sfK3wiZDd3hDrYYZqV2GPYeOa5GJyPpA8OuuMDrj3NTOtRs1Tvq6321uSgj/DtJxzUEQ6tVVb6vsqPhJ7@Aw "Python 3 – Try It Online")
*Saved a whopping ~~27~~ 33 bytes thanks to [Bubbler](https://codegolf.stackexchange.com/users/78410/bubbler)!!!*  
*Saved 7 bytes thanks to [Jonathan Allan](https://codegolf.stackexchange.com/users/53748/jonathan-allan)!!!*  
*TIO testing now works thanks to [ovs](https://codegolf.stackexchange.com/users/64121/ovs) and [Bubbler](https://codegolf.stackexchange.com/users/78410/bubbler)!!!*
Inputs the boards as a list of strings (space padded so they're all the same length) and the dictionary as a list of strings.  
Returns `True` for a valid board or `False` otherwise.
[Answer]
# [Gaia](https://github.com/splcurran/Gaia), 8 bytes
Basically the same as my Jelly answer, but Gaia has a superset builtin.
```
:t+ṡṡḥ⁇⊃
```
[Try it online!](https://tio.run/##FYwxCsIwGEZ3T5FBcFBw95t@zE9bSJPQRErcOoh09wLiUPEWgvYMuvYm9iIxgQcfHw/eueu7GHeX9e/7zHze83WYH7e4WWE7jafptZzGebjHmqwQMIKsheZWGHjBrFCSFLwgUCIpSXpf6QJZFcZnDUXHAMXcUkDKoDbal9DkSOUULLUsYY1iNAeGY84Fl74KaRpZSQR2nhtJ4Q8 "Gaia – Try It Online")
```
:t+ṡṡḥ⁇⊃     -- function that expects a 2d-list character above the dictionary as a list of strings
:t           -- duplicate the grid on the stack and transpose the copy
  +          -- append transpose to original grid
   ṡ         -- join list by spaces
    ṡ        -- split resulting string on spaces
     ḥ⁇      -- keep words that are truthy when the first character is removed
       ⊃     -- is the dictionary a superset of this word list
```
`⊃` only considers unique item and a list is a superset of itself (`⊇` might've been a more accurate symbol).
Almost all operators in Gaia are overloaded for different types, which is why `ṡ` can both split and join.
[Answer]
# [05AB1E (legacy)](https://github.com/Adriandmen/05AB1E/tree/fb4a2ce2bce6660e1a680a74dd61b72c945e6c3b), 12 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
Dø«ðý#ʒ¦Ā}åP
```
First input is the board as a list of string lines; second is a list of words.
Uses the legacy version of 05AB1E, because it can zip/transpose lists of strings, where in the new version zip/transpose can only be done on character-matrices.
[Try it online.](https://tio.run/##JY0xDsIwDEV3ThGFlQEGDmARq60UkigJqkrVAaQeA4kzcAdYWBhZWBomLhXsZnn/2/r2X29P582Ys0rv6Zle6bP83abH93pJd5dzL/fghJAraQU4R2qwFZY0CkRNWoMSKIdFL4EmmDEHFZhdYypyJVjZWOJEDceOBbEFNlTCtCbWXAEBdKkiOmiRb5zVSOIPzIBYfgfa6m42XjWc6zBE9Ir@Dn8)
**Explanation:**
```
D          # Duplicate the first (implicit) input-list
 ø         # Zip/transpose; swapping rows/columns
  «        # Merge the two lists together
   ðý      # Join the strings with space delimiter
     #     # Then split the entire string by spaces
      ʒ    # Filter this list of strings:
       ¦   #  Remove the first character
        Ā  #  And check if it's non-empty
      }    # After the filter: we have a list of the words
       å   # Check for each word if it's in the second (implicit) input-list
        P  # Check if this is truthy for all of them
           # (after which the result is output implicitly)
```
I came up with it independently, but I noticed it's basically a port of [*@ovs*' Jelly answer](https://codegolf.stackexchange.com/a/236410/52210), with just larger builtins / stack management. (For convenient I also copied their test case to my TIO.)
[Answer]
# [Japt](https://github.com/ETHproductions/japt), 12 [bytes](https://en.wikipedia.org/wiki/ISO/IEC_8859-1)
```
cUy)¸¸fÅe!øV
```
[Try it](https://petershaggynoble.github.io/Japt-Interpreter/?v=1.4.6&code=Y1V5Kbi4ZsVlIfhW&input=WyJNQVAgICIsIk8gQVBQIiwiTkVXIE8iLCJUIEVFTCIsIkhBRCBFIl0KWyJBIiwiQUEiLCJBUFAiLCJEQU5DSU5HIiwiRUVMIiwiR09UIiwiSEFEIiwiTEFaWSIsIkxFRVdBWSIsIk1BUCIsIk1PTlRIIiwiTkFTQUwiLCJORVciLCJQQVdFRCIsIlBPTEUiLCJSVUUiLCJTRUVJTkciLCJTT0xFTFkiLCJTT1JESUQiLCJZRVNURVJEQVkiXQ)
[Answer]
# [Kotlin](https://kotlinlang.org/), ~~159~~ 129 bytes
```
{d,b->(b+b[0].indices.map{c->b.indices.joinToString(""){"${b[it][c]}"}}).all{r->r.split(" ").filter{it.length>1}.all{w->w in d}}}
```
-30 bytes thanks to using lambda and type inference (Parlor Trick)
[Try it online!](https://tio.run/##jVTfb9owEH7vX3GyeEi0EG2v04hkwBS2QFAShBjiIeRH6y1NUGLWalH@dmY7NBRirfWD73y@8/fdne3fOUtpdkqOGTwFNANNh@oO@PgTpPCcF1EJA0hpyZxEQxgZgHAzL5dCjPFiNFvcC5UQW4h7xxdiisdC2PjnRkpC1lhqcywD587CnwplgT0sAxdkLcQSrwkPlRwUAy0dmwg/dyWFR8gZ3@Mb9qbR3PFMwm@I5xN3zJH1NikWl@xNUi3Q7VqicbZ8vmaDHJDZXxs5fXBujT7IqlwbeWmAIN34P/K5sh1wANwoHftrKZT@TtcuegP@u0SaaoKqDCtQUmmardggYp6qIlrtZuPSwA59OURu72Ywd2zs3h6AVXAu9r2OceQqPKcjVQ@mH6HjYm@EbSWfzolD/EPR06FoaKejM8/Gi3H3CsJHSH13NpOVrbhVzmRC3PPzuTyi@OUQhyyOLu@IFcfYgGZOgrRUi8sJyVfN5pHfPFbQ7MEy4O1K71vDPE/jIBucqsjY9y1t/2m//bwzaRbRMC7Np@BQhX1r3xp@5TTz8yZeQ0ivUK/abynbbcNdjepaN4M0rYq@VZjlIaVMQ7woZkJTFhcVZWYaZw/s0fpSS7/nvvUM/DuM6ro@Ccpa8238pYc2dx6dFyQIH6ECbZ8HRWSIPR36VltEkWkQsiMXA0g0@aEaIJ311unAObM00zhjmoD26j9oTkPLoCzjCEHM6wdoEtCUr2rg4NCTJ3FA6DVR50bVd/XpHw)
**Explanation:**
First, merge the original and transposed board. In each row, find all words longer than 1 letter and for all of them, check their presence in the dictionary.
]