Generating Word Grids
Jelly, 67 65 64 66 64 63 bytes
”?;ØAx“³Ċu~Ṿr¥rṇ⁽ȦƑ’ḃ12¤µŒl⁾?!yW,WKF€
H3ṬṚ¤ṁ‘1¦ṚŒḄ0,0j«þ`ị¢X€€Y
A monadic link taking a number and returning a list of characters, or a full program printing the result.
Try it online! (I prefer it using G
rather than Y
since that's more square)
How?
”?;ØAx“³Ċu~Ṿr¥rṇ⁽ȦƑ’ḃ12¤µŒl⁾?!yW,WKF€ - Link 1, getLetterSets: no arguments
”? - literal '?'
ØA - yield uppercase alphabet
; - concatenate
¤ - nilad followed by link(s) as a nilad:
“³Ċu~Ṿr¥rṇ⁽ȦƑ’ - base 250 number
ḃ12 - converted to bijective base 12 (frequencies)
x - times (repeat each)
µ - start a new monadic chain, call that uppers
Œl - to lower-case
⁾?! - literal ['?','!']
y - translate (change '?'s to '!'s)
W - wrap (that) in a list
W - wrap (uppers) in a list
, - pair
K - join with a space, ' '
F€ - flatten €ach (both flattens the wrapped lists
- AND makes the lone ' ' into [' '])
H3ṬṚ¤ṁ‘1¦ṚŒḄ0,0j«þ`ị¢X€€Y - Main link: number, n e.g. 13
H - halve 6.5
¤ - nilad followed by link(s) as a nilad:
3 - literal three 3
Ṭ - untruth [0,0,1]
Ṛ - reverse [1,0,0]
ṁ - mould like (implicit range(int(right))) [1,0,0,1,0,0]
¦ - sparse application:
1 - ...to indices: 1
‘ - ...action: increment [2,0,0,1,0,0]
Ṛ - reverse [0,0,1,0,0,2]
ŒḄ - bounce [0,0,1,0,0,2,0,0,1,0,0]
0,0 - literal [0,0] [0,0]
j - join [0,0,0,1,0,0,2,0,0,1,0,0,0]
` - repeat left argument as right argument with:
þ - outer product using: [[0,0,0,0,0,0,0,0,0,0,0,0,0],
« - minimum [0,0,0,0,0,0,0,0,0,0,0,0,0],
- [0,0,0,0,0,0,0,0,0,0,0,0,0],
- [0,0,0,1,0,0,1,0,0,1,0,0,0],
- [0,0,0,0,0,0,0,0,0,0,0,0,0],
- [0,0,0,0,0,0,0,0,0,0,0,0,0],
- [0,0,0,1,0,0,2,0,0,1,0,0,0],
- [0,0,0,0,0,0,0,0,0,0,0,0,0],
- [0,0,0,0,0,0,0,0,0,0,0,0,0],
- [0,0,0,1,0,0,1,0,0,1,0,0,0],
- [0,0,0,0,0,0,0,0,0,0,0,0,0],
- [0,0,0,0,0,0,0,0,0,0,0,0,0],
- [0,0,0,0,0,0,0,0,0,0,0,0,0]]
¢ - call the last link (1) as a nilad (the letter sets)
ị - index into - gets the correct letter sets for each cell
X€€ - random-choice for €ach cell in €ach row
Y - join with newlines
- if running as a full program: implicit print
R, 288 281 267 257 225 214 bytes
thanks to @cole for -1 byte, reordering the ?
to collapse the 2 into rep(2,10)
-10 bytes realizing that row(m) == t(col(m))
-41 bytes thanks to user2390246 for reconfiguring the weights, golfing down the indexing, and some more usual R tips
function(n){m=matrix(sample(el(strsplit("EOAINRTLSUDGBCMPFHVW?YKJXQZ","")),n^2,T,rep(c(12,8,9,6,4:1),c(1,1:4,1,10,5))),,n)
K=n/2+.5
L=col(m)
m[i]=chartr("A-Z?","a-z!",m[i<-(x=!(L-K)%%3&L-1&L-n)&t(x)])
m[K,K]=" "
m}
Try it online!
Returns a matrix. Fairly simple implementation; samples n^2 values with the proper distribution, stores as an nxn
matrix.
K
is the index of the center.
L=col(m)
is a matrix indicating the column number of each element in the matrix. Hence we compute !(L-K)%%3
to get the possible columns (including the edges), i.e., those a multiple of 3 away from the center column. To remove the edges, we consider L-1
and L-n
. L-1
is 0
(false) for the first column and L-n
is 0
for the last column. Applying &
(element-wise boolean AND
) to these three yields a matrix with TRUE
in those columns a multiple of three away from the center, excluding the edges. We store this result as x
.
If we take the transpose of x
, t(x)
, we get the same matrix, but for the rows, hence x&t(x)
is a matrix we save as i
containing: TRUE
indices for the required cells, and FALSE
everywhere else.
Then we use chartr
to perform the required transformation on m[i]
and save the result as m[i]
, change the center cell to a space, and return the matrix.
Importantly as user2390246 pointed out, we don't need to test n>=9
because for n<7
, there aren't any cells a multiple of 3 away from the center (apart from the center which is changed to a space anyway), and for n==7
, the only cells a multiple of 3 from the center are on the edge so they are excluded. Neat!
JavaScript (ES6), 247 242 bytes
-5 bytes with help from @Shaggy
n=>[...Array(p=n*n)].map((_,i)=>i==p>>1?" ":g(i/n|0)&g(i%n,c="AI9O8NRTEE6LSUD4G3BCMPFHVWY?2KJXQZ".replace(/(\D+)(\d)/g,(_,c,i)=>c.repeat(i))[Math.random()*100|0])?c<"A"?"!":c.toLowerCase():++i%n?c:c+`
`,g=x=>x&&x<n-1&((n>>1)-x)%n%3==0).join``
Test Snippet
let f=
n=>[...Array(p=n*n)].map((_,i)=>i==p>>1?" ":g(i/n|0)&g(i%n,c="AI9O8NRTEE6LSUD4G3BCMPFHVWY?2KJXQZ".replace(/(\D+)(\d)/g,(_,c,i)=>c.repeat(i))[Math.random()*100|0])?c<"A"?"!":c.toLowerCase():++i%n?c:c+`
`,g=x=>x&&x<n-1&((n>>1)-x)%n%3==0).join``
;(R.onclick=L.onchange=I.oninput=function(){let n=+I.value,res=f(n);O.innerText=n+"\n"+(L.checked?res.replace(/[A-Z\?]/g,".").replace(/[a-z!]/g,"#"):res);})()
<label><input id=L type=checkbox> Layout only</label> <button id=R>Rerun</button><br><input id=I type=range min=9 max=53 step=2 value=9 style="width:100%">
<pre id=O></pre>