This is inspired by HennSarv and draws upon that work.
What I have tried to do is go flat out for a functional programming style rather than creating a formula.
= GenerateBoardλ()
"GenerateBoardλ()"
= LET(
dealt, Dealλ(),
hands, BYCOL(dealt, SortHandλ),
board, Tableλ(hands),
board
)
"Dealλ()"
= LET(
deck, SEQUENCE(52,,0),
shuffle, RANDARRAY(52),
dealt, SORTBY(deck, shuffle),
WRAPCOLS(dealt, 13)
)
"SortHandλ(cards)"
= LET(
cardID, VSTACK({"A";"K";"Q";"J"},SEQUENCE(9,,10,-1)&""),
suits, UNICHAR(SEQUENCE(4,,9824)),
cdIdx, VSTACK({0;0;0;0}, 1 + MOD(+cards,13)),
sIdx, VSTACK(suits, INDEX(suits, 1 + QUOTIENT(+cards,13))),
sorted, SORT(HSTACK(cdIdx, sIdx), {2,1}),
vIdx, TAKE(sorted,,1),
suit, TAKE(sorted,,-1),
value, IF(vIdx, INDEX(cardID, vIdx), ¶ & suit),
TEXTJOIN(" ",, value)
)
"Tableλ(hands)"
= LET(
name, " " & {"North","East","South","West"},
spaced, VSTACK({"","","",""}, name & hand),
reorder, CHOOSECOLS(spaced, 1,4,2,3),
WRAPROWS(TOCOL(reorder,,1),3,"")
)
I have used array shaping functions as the first option, for example the WRAPCOLS to split the dealt deck into hands.
The Pilcrow sign, "¶", is used as a defined name to hold the formula
= CHAR(10)