Generate Random Boggle Board

Generate a 4x12 grid of letters / spaces:

Each die should appear precisely once, location randomly chosen. Locations should be approximate a uniform random permutation of the dice. Display a random (again, approximately uniform) face of each die. Left-justify the face in the 3-character window. For example,

A  E  A  A
E  C  D  E
D  A  Qu E
E  A  H  D


Is a non-randomized board in the format I want. Trailing space is allowed.

The dice:

A  A  E  E  G  N
E  L  R  T  T  Y
A  O  O  T  T  W
A  B  B  J  O  O
E  H  R  T  V  W
C  I  M  O  T  U
D  I  S  T  T  Y
E  I  O  S  S  T
D  E  L  R  V  Y
A  C  H  O  P  S
H  I  M  N  Qu U
E  E  I  N  S  U
E  E  G  H  N  W
A  F  F  K  P  S
H  L  N  N  R  Z
D  E  I  L  R  X


Amusing fact: there is only 1 K in the set. What other letter exclusively shares that die?

This is so the program with the shortest bytecount wins!

• there can't be F's if there are K's. this means you can't spell f...iretruck! :P Feb 7, 2012 at 2:54
• @Blazer: Yeah, and you can't spell f...olk either. :P
– Ry-
Feb 7, 2012 at 5:13
• @Ry- or f......lock May 13, 2021 at 14:01

GolfScript, 116 bytes

Since the scoring is in bytes, I figure that means we can use all bytes in the solution. Going outside the printable ASCII set allows a somewhat shorter solution than Peter Taylor's, at the cost of making the code harder to display here. Without the unprintable data, my code looks like this:

'57 BYTES OF BINARY DATA HERE'256base 26base 6/{;9.?rand}${6rand=65+.81=' u '2/=}%8/n*  It's pretty similar to Peter Taylor's solution, and I admit to shamelessly borrowing bits of it (such as the .81=' u '2/= trick), although I think I managed to shorten his shuffle slightly, even after spending an extra char byte for better randomness. The binary string in the beginning of the script contains unprintable characters, and so cannot be directly pasted here. Instead, I'll provide the script as a hex dump: 0000000: 2701 8302 7c56 97d5 ec9c 52e3 462e 44d7 '...|V....R.F.D. 0000010: a8d2 81c9 6115 fc80 4da4 6cd3 b06f a6d8 ....a...M.l..o.. 0000020: 4e7e 2029 12a9 f331 0b83 3481 de36 81e2 N~ )...1..4..6.. 0000030: 41b4 534d dee8 13f7 ccfd 2732 3536 6261 A.SM......'256ba 0000040: 7365 2032 3662 6173 6520 362f 7b3b 392e se 26base 6/{;9. 0000050: 3f72 616e 647d 247b 3672 616e 643d 3635 ?rand}${6rand=65
0000060: 2b2e 3831 3d27 2020 7520 2732 2f3d 7d25  +.81='  u '2/=}%
0000070: 382f 6e2a                                8/n*


On Linux, or any system with the xxd utility installed, this hex dump can be turned back into a working 116-byte GolfScript program by passing it through xxd -r.

Edit: Replaced 999rand with 9.?rand for much better randomness. The shuffle should now be about as close to perfect as the underlying RNG allows.

• Ah - I'd forgotten that you can sort by a mapping. Feb 7, 2012 at 14:05

Python 2.7, 253 229 215 chars

from random import*
j=0
for x in map(choice,sample("AAEEGN ELRTTY AOOTTW ABBJOO EHRTVW CIMOTU DISTTY EIOSST DELRVY ACHOPS HIMNQU EEINSU EEGHNW AFFKPS HLNNRZ DEILRX".split(),16)):j+=1;print x+' u'[x=='Q']+'\n'[j%4:],


Most of the characters are just the dice themselves. I didnt want to spend too much time trying to reduce it too much

minor edit: removed 2 unnecessary bytes (extra spaces)

edit2: down to 229

edit3: down to 215

• you can make your code tighter with indexing, print a+' u'[a=='Q'] and print'\n'[j%4:] Feb 7, 2012 at 5:45
• @keith thanks! I made it even tighter by combining those two tricks :) Feb 7, 2012 at 6:22
• I managed to get it down to 218 without killing it (I think?): 1) Change the import statement to from random import* and remove all r.. 2) Change separators in string to   (space) and take advantage of str.split's default argument. 3) Get rid of anything to do with j and use '\n'[len(d)%4:]. 4) Use list.pop's default argument. 5) ... 6) Profit! Feb 8, 2012 at 0:50
• @D C ahh thanks! I'm surprised I overlooked them. but I guess that's what I get for writing it in a few minutes :P Feb 8, 2012 at 3:13
• And I reduced it even more by 3 chars using a little map trick, but I had to keep the j=0...+'\n'[j%4:] for it to work Feb 8, 2012 at 3:35

GolfScript (141 139 137 charsbytes)

Of which 94 expand to the string containing the dice. Figure doesn't include the unnecessary newline inserted to make it wrap so that the code can be seen without scrolling:

'Y
ISY
XIAOOW
VYAAEEGNABBJOOEHRTVWCIMOTUEIOSSTACHOPSHIMNQUEEINSUEEGHNWAFFKPSHLNNRZ'n/'TTELRD'*
6/{[6rand=99rand\]}%${1=.81=' u '2/=}%8/n*  • If my (by hand) analysis is correct there aren't any other strings which are both long enough and frequent enough to compress the data by simple replacement, regardless of ordering of dice and within dice. Feb 7, 2012 at 11:38 • I was able to get the table down from 96 to 84 characters by interleaving the dice and using run-length encoding. Decoding that might make up the difference... it sure does for python. Feb 8, 2012 at 8:24 • You can encode 6 letters in 30 bits, then in 5 printable characters , saving 16 bytes. But you'll need some shift/mask to extract them. Feb 8, 2012 at 13:29 • @ugoren, Ilmari already did that. Feb 8, 2012 at 14:43 • @PeterTaylor, if you say he did, I believe you (I never bothered to learn Golfscript). But he seems to be using 57 unprintable characters, while I suggested 80 printable. Feb 8, 2012 at 19:11 Ruby, 201 197 chars %W(AAEEGN ELRTTY AOOTTW ABBJOO EHRTVW CIMOTU DISTTY EIOSST DELRVY ACHOPS HIMNQU EEINSU EEGHNW AFFKPS HLNNRZ DEILRX).sample(16).map{|c|c[rand 6]}.each_slice(4){|x|puts x.join(" ").gsub(/Q ?/,"Qu")}  (and it's a one-liner) Edit 1: Used %W() to avoid the .split and a pair of quotes. Edit 2: Made it to spec (two spaces between each output column) • I just approved an edit by "an anonymous user" to this answer; I assume that was you, Mark, and you just forgot to log in. (Ps. You output doesn't seem to be exactly to spec; using x.join(" ").gsub(/Q ?/,"Qu") would fix that at the cost of three extra chars.) Feb 10, 2012 at 13:48 • (That's one extra space in the join string and an extra space and question mark in the regex, in case the SE software mangles the spaces...) Feb 10, 2012 at 13:54 • @IlmariKaronen Thanks, I didn't notice the two spaces between columns. It should be to spec now. Feb 10, 2012 at 17:31 Powershell, 234 characters $d=(0..15|%{@{'AAEEGNELRTTYAOOTTWABBJOOEHRTVWCIMOTUDISTTYEIOSSTDELRVYACHOPSHIMNQUEEINSUEEGHNWAFFKPSHLNNRZDEILRX'[6*$_+(random)%6]=random}.GetEnumerator()}|sort Value|%{$_.Key})
0..3|%{($d[($_*4)..($_*4+3)])-join" "-replace'Q ','Qu'}  Here's the same code with extra whitespace, in an attempt at improving readability :-) ######################################### # roll the 16 dice and shuffle them # #########################################$d=(
0..15 | % {
@{
'AAEEGNELRTTYAOOTTWABBJOOEHRTVWCIMOTUDISTTYEIOSSTDELRVYACHOPSHIMNQUEEINSUEEGHNWAFFKPSHLNNRZDEILRX'[6*$_+(random)%6]=random }.GetEnumerator() } | sort Value | % {$_.Key
}
)

############################################
# add the 16 results to the 4 by 4 grid    #
############################################

0..3 | % {
($d[($_*4)..($_*4+3)]) -join " " -replace 'Q ','Qu' }  I'm not aware of a built in shuffle feature in powershell, so I turned each result into a key-value pair - the key equalling a dice result and the value equalling a random number. Then it was just a case of sorting these pairs by the value then outputting the keys. • maybe you could use the last digits in the current time in ms as a sorting value? Feb 7, 2012 at 4:17 • @Blazer - possibly, but "random" only takes six characters :-) Feb 7, 2012 at 4:43 Perl, 179 chars @d=(Qu,map"$_ ",HIMNUAAEEGNELRTTYAOOTTWABBJOOEHRTVWCIMOTUDISTTYEIOSSTDELRVYACHOPSEEINSUEEGHNWAFFKPSHLNNRZDEILRX
=~/./g);print+(splice@d,6*int rand@d/6,6)[rand 6],@d%24?$":$/while@d


Here's a verbose version of the program:

my $fullset = "HIMNUAAEEGNELRTTYAOOTTWABBJOOEHRTVWCIMOTUDISTTY" . "EIOSSTDELRVYACHOPSEEINSUEEGHNWAFFKPSHLNNRZDEILRX"; my @dice = ("Qu"); push @dice, "$_ " for split //, $fullset; while (@dice) { my @die = splice @dice, 6 * (int rand @dice / 6), 6; print$die[rand 6];
print @dice % 24 ? " " : "\n";
}


Vyxal, 85 bytes

«3꘍Ẋʀɖ>¯ɖ\4ȧḊ#⅛F>ẇ#₂⟑†ql~-ṡ²<vŻ%)∆₆U÷↵ʁʀeµṘbD{⇧½⁰ṙ⟩ĊI3≥⁰?λ«16/v℅Ṗ℅4ẇƛ÷W‛  j;⁋⇧‛Q ‛QuV


Don't try it Online! Because it breaks the interpreter trying to handle 16! permutations of the dice at once. Would work given enough memory + time though. Try this one that doesn't shuffle online!

«...«                           # Compressed string
16/                        # Into 16 pieces
v℅                      # Random choice from each
Ṗ℅                    # Shuffle
4ẇ                  # Split into four pieces
ƛ      ;          # Foreach...
÷W               # To list of characters
‛  j           # Joined by double spaces
⁋⇧        # Joined by newlines and uppercased
‛Q ‛QuV # Replace Q  with Qu


Perl 5, 157 bytes

@d{JobaotwHTVErHnZlRIXDeLtYrDELVyDItsHOPCafKPsIeUneagWeHnQUHImCIOUtEOsI=~s/[a-z]/\U$&$&/gr=~/.{6}/g}++;print$_=(/./g)[rand 6],/Q/?u:$",++$-%4?$":$/for keys%d  Try it online! Explanation This solution builds up the dice from the long string, replacing occurrences of lowercase letters with two of their uppercase companions (s/[a-z]/\U$&$&/gr) resulting in an ordering of 16 sets of 6 characters (/.{6}/g) which are then used as hash keys and set to 1 (@d{...}++). Since keys aren't stored in a particular order in Perl, this gives the ordering of the dice the required randomness. Then for each of the keys in %d, print a randomly selected char from the list, either u or $" (which defaults to space) depending on whether or not the randomly selected letter was Q, and either $" or $/ (which defaults to newline) depending on whether or not we're working on a multiple of 4.

I quite enjoyed playing with the ordering to maximise saved characters, making sure that each dice ends with a letter that the next starts with and keeping other doubles in the middles of each set of 6. 68 bytes of data, but the decoding is a little expensive. Maybe it'll help someone else though!

Batch 252 bytes

Note: script = 243 bytes + 9 bytes required to invoke script with Delayed expansion enabled from cmd.exe:

Cmd/Von/Cboggle.bat


boggle.bat

@Set c=0&For %%G in (AAEEGN ELRTTY AOOTTW ABBJOO EHRTVW CIMOTU DISTTY EIOSST DELRVY ACHOPS HIMNQU EEINSU EEGHNW AFFKPS HLNNRZ DEILRX)Do @Set D=%%G&Set/ac+=1&For /f %%i in ('Set/A!random!%%6')Do @<nul Set/p=!D:~%%i,1! &If !c!==4 (Echo(&Set c=0)