[Question]
  [
I like to play [(*The Settlers of*) *Catan*](https://en.wikipedia.org/wiki/Catan) on [Board Game Arena](https://boardgamearena.com) with totally random number tokens. These tokens determine the production rate of the terrain tiles beneath:
![](https://i.stack.imgur.com/VWCy7.jpg)
There are 18 number tokens, two each of 3, 4, 5, 6, 8, 9, 10, 11 and one each of 2 and 12. A valid arrangement of these tokens on the board (19 hexes in a side-3 hexagon) has each token placed in exactly one hex, leaving one empty hex (the desert), *and none of the 6 and 8 tokens adjacent*. So a 6 cannot be adjacent to the other 6, an 8 cannot be adjacent to the other 8 and a 6 cannot be adjacent to an 8.
## Task
Output a valid random arrangement of the number tokens. Each possible arrangement only needs a nonzero probability of being output.
You may output in any reasonable format, which may be 2D (like the valid and invalid outputs below) or 1D (e.g. mapping the hexes to a 19-character string in a fixed and consistent order). In either case it must be specified how the different positions in the output map to the hexagon. You may use any set of 11 different symbols to denote the number tokens or lack thereof.
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"); fewest bytes wins.
## Valid outputs
These use `A B C` for `10 11 12` respectively and `.` for the empty desert hex.
```
  6 3 8
 2 4 5 A
5 9 . 6 9
 A B 3 C
  8 4 B
```
```
  B 9 A
 5 6 C 8
6 4 B 5 3
 2 8 9 3
  A . 4
```
```
  B B C
 3 3 A A
2 4 6 . 6
 4 5 9 9
  8 5 8
```
## Invalid outputs
This one has three 5s and only one 4:
```
  6 A 2
 C 5 9 3
8 B 3 6 A
 . 9 4 5
  5 B 8
```
The two 6s are adjacent here:
```
  5 2 4
 3 8 B 4
9 B 3 5 8
 A 6 9 C
  . 6 A
```
A 6 and an 8 are adjacent here:
```
  4 3 A
 . 8 2 5
4 6 A 8 B
 5 C 3 9
  B 6 9
```
  
[Answer]
# JavaScript (ES6), 162 bytes
```
f=(s=`  . 2 3  
 3 4 4 5 
5 6 6 8 8
 9 9 A A 
  B B C`,a=s.match(e=/\S/g).sort(_=>Math.random()-.5))=>/[68](.|[^]{8,10})[68]/.exec(s)?f(s.replace(e,_=>a.pop())):s
```
[Try it online!](https://tio.run/##FcxNC4JAFIXhvb/iLu8FvfZlWDBGtW7V0iyHcdRCHXEkguq328QDZ/EuzkM@pVXDvR@DzhR6mkqBVuQADAtYAnhuVk4EXgRrJ4bYg42zdzyAg3PMfSkst3JUNWoRXs5hRWzNMOJNJCc51jzIrjAtUsARkUjCdB1nyJ/0mr1jfz770j@ErF9aoaVdiZYH3TdSadS@O5Hcmx6JaGsnZTprGs2NqbB0bfoB "JavaScript (Node.js) – Try It Online")
### Uniform distribution, 163 bytes
The ways the grid is shuffled in the above version, some patterns have a higher probability than others -- which is fine as per the challenge rules. But getting a uniform distribution just costs one extra byte.
```
f=(s=`  . 2 3  
 3 4 4 5 
5 6 6 8 8
 9 9 A A 
  B B C`,a=s.match(e=/\S/g))=>/[68](.|[^]{8,10})[68]/.exec(s)?f(s.replace(e,_=>a.splice(Math.random()*n--,1),n=19)):s
```
[Try it online!](https://tio.run/##FcjLCsIwEIXhfZ9iljOSptZLaYUo6tqVy1o1xPQiNSlNEUF99hr54Idz7vIpneqbbgiNvelxLAU6cQXgMIM5QOCz8JYQLCHxUkgDyLytFwDsvP2VSeH4Qw6qRi2i0zGqiMQ6ypO0QP7Jz8U7ZfH0S/8j4vqlFTralOh4r7tWKo2aXcRacte1jV8HOdS8l@ZmH0gTE4YsJmZEnBGt3KiscbbVvLUVlkg0/gA "JavaScript (Node.js) – Try It Online")
### Commented
```
f = (                    // f is a recursive function taking:
  s = `...`,             //   s = initial 2D grid, with an invalid pattern
  a =                    //   a[] = array of
    s.match(e = /\S/g)   //         non-space characters
    .sort(_ =>           //         shuffled
      Math.random() - .5 //         using a random sort() callback
    )                    //
) =>                     //
/[68](.|[^]{8,10})[68]/  // test the validity of the grid by detecting
.exec(s)                 // 6's or 8's separated by 1, 8 or 10 characters
                         // (line-break included)
?                        // if it's not valid:
  f(                     //   try again with another grid:
    s.replace(           //     replace in s:
      e,                 //       each non-space character with
      _ => a.pop()       //       the next character taken from a[]
    )                    //     end of replace()
  )                      //   end of recursive call
:                        // else:
  s                      //   success: return s
```
[Answer]
# [Retina](https://github.com/m-ender/retina/wiki/The-Language), 79 bytes
```
  . 2 3  ¶ 3 4 4 5 ¶5 6 6 8 8¶ 9 9 A A ¶  B B C
/[68](?s:.|.{8,10})[68]/+O?`\S
```
[Try it online!](https://tio.run/##K0otycxLNPz/n0tBQU/BSMFYQeHQNiBpAoSmQKapghkQWihYAEUtgdARCIFMBScgdObSjzaziNWwL7bSq9GrttAxNKjVBInoa/vbJ8QE//8PAA "Retina – Try It Online") Explanation: Based on @Arnauld's JavaScript answer.
```
  . 2 3  ¶ 3 4 4 5 ¶5 6 6 8 8¶ 9 9 A A ¶  B B C
```
Insert the tokens in an invalid layout.
```
/[68](?s:.|.{8,10})[68]/+`
```
Repeat while the layout is invalid...
```
O?`\S
```
... shuffle the tokens.
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 39 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
ỊTḤ>þ“©©©Çð   ‘S+Ɗạþ`Ff“£µ¿‘
17Ż%⁵⁵;ẊÇ¿
```
A niladic Link that yields a flat list of the tokens to be placed in row-major order.
The mapping from question values to the outputted tokens is:
```
Catan (Question):  2   3   4   5   6   8   9  10  11  12   .
    Token (code):  9   3   4   5   0   1   2   6   7   8  10
```
[Try it online!](https://tio.run/##y0rNyan8///h7q6QhzuW2B3e96hhzqGVIHi4/fAGBQWFRw0zgrWPdT3ctfDwvgS3NJD04kNbD@0HinMZmh/drfqocSsQWT/c1XW4/dD@//8B "Jelly – Try It Online") Or see a **[formatted version](https://tio.run/##y0rNyan8///h7q6QhzuW2B3e96hhzqGVIHi4/fAGBQWFRw0zgrWPdT3ctfDwvgS3NJD04kNbD@0HinMZmh/drfqocSsQWT/c1XW4/dD@/4cWPdzdDVRlYWlsYuro5GykZ/aoYS5I29JD6w63HZ4O1Hh08sOd07wfNa2xdlB61Lg34NB@l4e7uh0eNW47tCTyPwA "Jelly – Try It Online")** (translates tokens to Catan values and pretty-prints as a hexagon).
(Also [here](https://tio.run/##y0rNyan8///h7q6QhzuW2B3e96hhzqGVIHi4/fAGBQWFRw0zgrWPdT3ctfDwvgS3NJD04kNbD@0HinMZmh/drfqocSsQWT/c1XW4/dD@/4cWPdzdDVRloQcDZo8a5oK0LT207nDb4elAjUcnP9w5zftR0xprB6VHjXsDDu13ebir2@FR47ZDSyL/AwA) is version that only prints the sixes and eights.)
### How?
```
ỊTḤ>þ“©©©Çð   ‘S+Ɗạþ`Ff“£µ¿‘ - Helper Link, is invalid?: list of tokens
Ị                            - insignificant? (abs(x)<=1 - i.e. is Catan 6 or 8?) (vectorises)
 T                           - truthy, 1-indexed indices
  Ḥ                          - double (vectorises)
                 Ɗ           - last three links as a monad f(X=that):
     “©©©Çð   ‘              -   code-page indices = [6,6,6,14,24,32,32,32]
    þ                        -   (X) table with (that) using:
   >                         -     greater than?
               S             -   (column-wise) sum
                +            -   add (X) (vectorises)
                    `        - use (that) as both arguments of:
                   þ         -   table using:
                  ạ          -     absolute difference
                     F       - flatten
                       “£µ¿‘ - code-page indices = [2,9,11]
                      f      - filter keep
                               -> nonempty list (truthy) if invalid
                                  empty list (falsey) if valid
17Ż%⁵⁵;ẊÇ¿ - Link, get random Catan Distribution: no arguments
17         - seventeen
  Ż        - zero range -> [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
    ⁵      - ten
   %       - modulo -> [0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7]
     ⁵     - ten
      ;    - concatenate ->  [10,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7]
         ¿ - while...
        Ç  - ...condition: call the Helper Link (above)
       Ẋ   - ...action: shuffle
```
[Answer]
# Excel VBA, ~~408~~ ~~361~~ 352 bytes
Saved 9 bytes thanks to [Taylor Raine](https://codegolf.stackexchange.com/questions/255009/totally-random-catan-number-distributions/255067?noredirect=1#comment572655_255067)
**Golfed code:** (Note: VBA will autoformat this code by adding spaces in many places and a few other niceties.)
```
Sub z
Set g=[C4:E6,F2:G4,D3:E3,E2,F5]
x:
Set c=New Collection
c.Add 2
c.Add 12
For i=1To 2
For j=3To 11
c.Add j
Next j,i
c.Remove 7
For Each s In g
k=CInt(1+Int(Rnd*c.Count))
s.Value=c(k)
c.Remove k
Next
For Each s In g
u=0
For Each t In Union(s.Offset(-1,0).Resize(2,2),s.Offset(0,-1).Resize(2,2))
If t=6Or t=8Then u=u+1
Next
If u>2GoTo x
Next
End Sub
```
**Formatted and commented code:**
```
Sub z()
    ' Define our game board
    Set g = [C4:E6,F2:G4,D3:E3,E2,F5]
    
    ' Setup a label so we can loop back here and start over as needed
    ' I know this uses GoTo which is [bad] but it's the shortest way to loop
x:
    
    ' Create a list of all the numbers we want to populate into the grid
    ' We need to recreate this on each loop because it'll be emptied later in this process
    Set c = New Collection
    c.Add 2
    c.Add 12
    For i = 1 To 2  'Add all the numbers 3-11 twice
        For j = 3 To 11
            c.Add j
        Next
    Next
    c.Remove 7  ' As it happens, the 7th term will be one of the "7" values and we only need one of those.
    
    ' Populate the grid with a random entry from that list and then remove it from the list.
    For Each s In g
        k = CInt(1 + Int(Rnd * c.Count))
        s.Value = c(k)
        c.Remove k
    Next
    
    ' Look for more than one instance of 6 or 8 in each set of adjacent hexes
    For Each s In g
        u = 0
        ' Check a rotated hexagonal-ish shape centered on the current cell
        For Each t In Union(s.Offset(-1, 0).Resize(2, 2), s.Offset(0, -1).Resize(2, 2))
            ' This is less bytes than something like "If Abs(s-7)=1Then" because this has more spaces than can be removed
            If t = 6 Or t = 8 Then u = u + 1
        Next
        If u > 2 Then GoTo x     ' Loop if you found more than two (since we check the center cell twice)
    Next
End Sub
```
**Output format:**
Output is in a spaced out grid spanning the range `C2:G6` in the active sheet. The values are 2-12 with 7 being the desert. It is a rotated and compressed version of the hexagonal grid. If you translated the first example in the question into Excel, you may want it to look like image below. I've added colors for clarity later and outlined all the cells that would be considered adjacent to the desert in the middle of the board.
[![Spaced Out Grid](https://i.stack.imgur.com/a0idk.png)](https://i.stack.imgur.com/a0idk.png)
However, that spaced out thing is not very byte-friendly. We're going to rotate it 45° and compress it. Here's the same board with the same colors and the same cells outlined in a border showing they're adjacent to the desert:
[![Rotated and Compressed Grid](https://i.stack.imgur.com/wpMqF.png)](https://i.stack.imgur.com/wpMqF.png)
To better show how this looks like the original board, I'm going to rotate the text 45°. Tilt your head to the left and you should see a perfectly normal Catan board.
[![Rotated Text](https://i.stack.imgur.com/e2EJg.png)](https://i.stack.imgur.com/e2EJg.png)
**Example board generation:**
With the colors and borders back in place, here's a video showing the generation of some random boards. The top left board is where the code is outputting data. The bottom left board is full of formulas show it shows the same data as the top left but in the more expanded layout. The diamond shape to the right is a snapshot of the same results (again linked by formulas) but with the text rotated 45° CCW and then the whole snapshot rotated 45° CW so it looks like a normal board. The places where it pauses is where a good board was found, I waited, then ran the script again.
[![Board Generation GIF](https://i.stack.imgur.com/X1ftN.gif)](https://i.stack.imgur.com/X1ftN.gif)
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 73 bytes
```
Ｗ¬ＫＡ«⎚Ｐ→↙×ψ³‖Ｃ‖Ｏ↓≔⟦⟧υＷ⁻…³¦²²υ⊞υ‽κ¤⭆υ⁺§…α¹¹κ Ｆ⁵Ｆ⁹«Ｊ⁻λ²κ¿‹IＫＫ¿‹I⌈⊞ＯＫＭ⊟ＫＤ³→⎚
```
[Try it online!](https://tio.run/##VVDLasMwEDw7XyF8WoF7SEIPTU/BoZASNybNrfQgnLUtIktGkvOg5NvdlRpoKxDSPmZ2dqpW2MoINY7nVipk8GY8lIjHpVLAOWdfkyRXKCzw50lSDMrL3krtYbGTTesztliZs95gTd@97NDBNWNzHpp3WCusfG76K/yJtye0SvQQgSG/dE42Gj4@MzaE@C6kkHpwsBO6QZhnbDbjoc5ZObgWhoxR5WA6OMZZL5LkvntS1hTETeVSEXrp1/qAF8ivlcK8NT2IjE2nxHSkm7KUR3RtLINHzuL7FHdOXoeu35u7CkXzI4iaE1kz2KBzkK5TmkNeRaP@pwtxkd3QQVC77dEKb2z0tTDGIhBZSWpCYiUtuSKNDlv@uMrjYb@@3ya3cRwfTuob "Charcoal – Try It Online") Link is to verbose version of code. Uses `A`, `B` and `C` to represent `2`, `12` and the desert, `J` and `K` to represent `6` and `8` and intervening letters for the remaining tokens. Explanation:
```
Ｗ¬ＫＡ«
```
Repeat while the canvas is empty.
```
⎚Ｐ→↙×ψ³‖Ｃ‖Ｏ↓
```
Outline a hexagon. (The extra `Clear();` at the beginning ensures that the cursor is at the origin, as it is not there at the end of the loop.)
```
≔⟦⟧υＷ⁻…³¦²²υ⊞υ‽κ¤⭆υ⁺§…α¹¹κ 
```
Shuffle the tokens and fill in the hexagon.
```
Ｆ⁵Ｆ⁹«Ｊ⁻λ²κ
```
Loop over the canvas.
```
¿‹IＫＫ¿‹I⌈⊞ＯＫＭ⊟ＫＤ³→⎚
```
If an adjacent pair of `J` and/or `K` are found then clear the canvas.
[Answer]
# [Python](https://www.python.org), 184 bytes
```
from random import*
f=lambda s=".2C"+2*"345#%9AB":any((x:=(*s[:3],"_",*s[3:-3],"_",*s[-3:],*"___"))[i]<'.'>min(x[i+4:i+6]+~-~-i%5*(x[i+1],))for i in range(20))and f(sample(s,k=19))or s
```
[Attempt This Online!](https://ato.pxeger.com/run?1=lVFRTsMwDP3vKaKganabTmu7IRZRJOAYXVUVtYGIJY2SIm0_uwg_-4EzcBVuQ7apYsAXliXbz7b8bL--m-3w1Ov9_u1lEMnV54ewvSK20a03UpneDlEginWjHtqGuIJOs3saZxHN54uLcHl7R3mjtwAbXkDkSp5XjNaUeTfnyXeQ5LxiEa3rmiKWsrqeTCc3SmrYlDKecxlfVvEu2SUyXERHLK0YougtkUTqA5_HDrIZoidGBLhGmXUHjj0X6RLRl7mRf9sJYsAhD4gXY6UeAFbH4CCUkNCddKVpfIaP8J_MWeIfXT_mYOiP4xcKgl8rpTPkBgQgnviPf_gC)
`#` and `$` represent tiles 6 and 8 respectively; the rest of the encoding are the same as in the example.
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), ~~56~~ 54 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
12L7Kû¨¨[.rD18Ýü2ZÝ3LÌû£ü2εé`δ‚εND>‚è}}˜2ô«èJ€ê68æδÊß#
```
Uses `1` for the empty desert hex. The other numbers are the same.  
Outputs as a flat list.
[Try it online](https://tio.run/##AV4Aof9vc2FiaWX//zEyTDdLw7vCqMKoWy5yRDE4w53DvDJaw50zTMOMw7vCo8O8Ms61w6lgzrTigJrOtU5EPuKAmsOofX3LnDLDtMKrw6hK4oKsw6o2OMOmzrTDisOfI///) or [try it with pretty-print](https://tio.run/##yy9OTMpM/f/f0MjH3Pvw7kMrDq2I1ityMbQ4PPfwHqOow3ONfQ73AMUXA3nnth5emXBuy6OGWee2@rnYAenDK2prT88xOrzl0OrDK7weNa05vMrM4vCyc1sOdx2er/y/1ujw3BBtw0Orju4LUtc7tPpRw0KYcYd26yX/BwA).
**Explanation:**
```
12L7Kû¨¨  # Get a list of the numbers:
12L       #  Push a list in the range [1,12]
   7K     #  Remove the 7
     û    #  Palindromize it
      ¨¨  #  Remove the trailing [2,1]
[         # Start an infinite loop:
 .r       #  Randomly shuffle the list
   D      #  Duplicate this list
 18Ýü2ZÝ3LÌû£ü2εé`δ‚εND>‚è}}˜2ô«èJ€ê68æδÊß#
          #  Pop the copy, and check whether it's valid (see below)
  #       #  If it is valid: stop the infinite loop
          #  (after which the valid shuffled list is output implicitly as result)
```
```
18Ý       # Push a list in the range [0,18]
   ü2     # Get its overlapping pairs: [[0,1],[1,2],...,[16,17],[17,18]]
Z         # Push its flattened maximum (18), without popping the list
 Ý        # Push a list in the range [0,18] again
  3L      # Push list [1,2,3]
    Ì     # Increase each by 2 to [3,4,5]
     û    # Palindromize it to [3,4,5,4,3]
      £   # Split the [0,18] list into parts of those sizes
ü2        # Get overlapping pairs of these lists
  ε       # Map over each pair of lists:
   é      #  Sort the lists by length
    `     #  Pop and push both lists separated to the stack
     δ    #  Apply double-vectorized:
      ‚   #   Pair values together
   ε      #  Inner map over these lists of pairs:
    N  ‚  #   Pair the current index
     D>   #   With the index+1
        è #   Use this [index,index+1] to get the pairs at those indices
  }}      # Close the nested maps
    ˜2ô   # Flatten it two levels down to a single list of pairs:
    ˜     #  Flatten the list of lists of pairs
     2ô   #  Split the flattened list back into parts of size 2
«         # Merge it to the list of overlapping pairs of [0,18]
 è        # Get the values at those indices from the shuffled list
  J       # Join each inner pair together to a string
   €ê     # Sorted-uniquify the digits of each inner string
68        # Push 68
  æ       # Pop and push its powerset: ["",6,8,68]
   δ      # Apply double-vectorized:
    Ê     #  Not equals check
     ß    # Get the flattened minimum to verify none are falsey
```
The index-pairs to check each adjacent hex, generated by `18Ýü2ZÝ3LÌû£ü2εé`δ‚εND>‚è}}˜2ô«`, are:
```
[[0,1],[1,2],[2,3],[3,4],[4,5],[5,6],[6,7],[7,8],[8,9],[9,10],[10,11],[11,12],[12,13],[13,14],[14,15],[15,16],[16,17],[17,18],[0,3],[0,4],[1,4],[1,5],[2,5],[2,6],[3,7],[3,8],[4,8],[4,9],[5,9],[5,10],[6,10],[6,11],[7,12],[8,12],[8,13],[9,13],[9,14],[10,14],[10,15],[11,15],[12,16],[13,16],[13,17],[14,17],[14,18],[15,18]]
     0   1   2
   3   4   5   6
 7   8   9  10  11
  12  13  14  15
    16  17  18
```
[Try it online.](https://tio.run/##yy9OTMpM/f/f0OLw3MN7jKIOzzX2OdxzePehxUDeua2HVyac2/KoYda5rX4udkD68Ira2tNzjA5vObT6/38A)
[Answer]
# Python 3, 391 bytes:
```
from random import*
R=range
P=lambda i:' '*int((9-(i*2-1))/2)
def b():
 while 1:
  t=[*'2C.'+'345689AB'*2];shuffle(t)
  B,f=[P(i)+' '.join(t.pop(0)for _ in R(i))+P(i)for i in[3,4,5,4,3]],1
  for x in R(5):
   for y in R(9):
    for X,Y in[(1,1),(-1,1),(1,-1),(-1,-1),(0,2),(-2,0)]:
     if 0<=(j:=x+X)<5 and 0<=(k:=y+Y)<9 and {'6','8'}&{B[x][y],B[j][k]}=={B[x][y],B[j][k]}:f=0
  if f:yield B
```
[Try it online!](https://tio.run/##ZZDPboMwDMbP4yl8WhIIHX9KVVhzGHuBaqdWUTS1gqxpKSCWaaCqz84S2E47RI5//mzZXzvoU1PH67YbR9k1V@gOdWGCurZNp13njRnwUTpbVh2ux@IAKkOAXFVrjFMfKzfyQ0KeIuIUpYQjJpkD3ydVlRCaH2jGXRS9LpCH4mWyWqcvOXIj8fx5@pKyKrEmRpRTyfgWK@KZ0Ytzo2qsF23T4oDIpoN3UDW8mTLxrMgiZRCP6ZIm5sVC0NCMsYV@1iZ2jZkMM0lnMqEd3dt@HNKQUOzPIaT@bzbFgEY2i2hAxNwJSkKwYficsd7bkU0CxqmJXDI2eHuySSdyQytE0RrdH2857wUfBM35WfCLuDP2D2WSBc40W2aDKqsC8vHvQqjLXmPjqdn9oe2s54qMPw)
[Answer]
# JavaScript (ES6), 157 bytes
The output format for this version was inspired by [Jonathan Allan's answer](https://codegolf.stackexchange.com/a/255022/58563).
Returns a flat array with the following mapping:
```
-1 0 1 2 3 4 5 6 7 8 9
 . 6 8 9 3 4 5 A B C 2
```
```
f=_=>(a=[...s="8889999_____0000111"].map((_,i)=>~-i%10).sort(_=>Math.random()-.5)).some((v,i)=>227259>>i&(g=k=>3>>a[i+k]&3>>v&1)(1)|g(q=s[i]-5)|g(q+1))?f():a
```
[Try it online!](https://tio.run/##TZDLboJAGIX3PMUJSc0/QUYHi8UmM43ae2tvLinRCSJSL1AgrJq@Oh1d9VudnMvmfOlGV3GZFbV7yFdJ267lQirSMuScV9IOgmBkWBzpG4QQdsT3uiBadDMm1a@bnYk@41Ve1mSmM11veKkPq3xPzOU@O0b7hKg51T3vwvNHSmUdSuVWqoFSOsycbdQxqukIRoL9pPQtqzCLXP@kHcHY1ZrYpW7j/FDlu4Tv8pQ0JIzLrP/m0gLGmGAKWLjGDW5xB@seD3jEE54tzPCCV7yZFO/4wHzJy6TY6Tih3ue8l3YRQyrYfBiMBuf@eDL17FCHMY83upyah8Y1MbgY@hEciIix9g8 "JavaScript (Node.js) – Try It Online")
[Answer]
# [Ruby](https://www.ruby-lang.org/), 132 bytes
```
f=->{a=([*0..10]*2)[i=0,q=19].shuffle
"&&X,,,^1,,,]+&&WKK".bytes{|b|q&&=a[i]/2+[a[i+=1]|b&64,a[b/5%5+i],a[b%5+i]].min/2>0}
q ?a:f[]}
```
[Try it online!](https://tio.run/##ZYzhCsIgFIX/7ylEmNQ0p6MFBa4H2AMUiIHCJKGitQ0a257drKCCDod7vsvlnltneu@tWBSDFjOZMEo5U0k2l04wUgu@VrQ5dtaeqggitCeEHHgYCiO0K0tITd9WzTCasUZIaOlUmmEZEguuRoNWS6KlSfM4x0498QWKnt0lzQo2RTXY6o2VavLXrm0ABCC@vx196Ln88N/t@wPjUAWC/AM "Ruby – Try It Online")
Outputs a flat array. Uses the same tokenization as Jonathan Allen.
(the footer of the TIO link converts `10` to hexadecimal `A` for better presentation.)
```
Catan (Question):  2   3   4   5   6   8   9  10  11  12   .
    Token (code):  9   3   4   5   0   1   2   6   7   8  10
```
**Explanation**
We generate a flat array of all 11 tokens, duplicate it to 22 elements, truncate to 19 elements to discard the extra `8 9 10`, then shuffle. We check if the arrangement is valid, and if so, return it. Otherwise we call recursively to try again.
For each element (except the last one) we check if any of the (up to 3) adjacent elements following it are incompatible. The elements to be checked (to the right, below, and diagonally) are shown as an offset in the table below.
```
134 134 .34
145 145 145 .45
1.5 145 145 145 .4.
    1.4 134 134 .3.
        1.. 1.. ...
```
This was encoded in a magic string as follows. For the below and diagonal offsets, we subtract 1 from each and encode as a two-digit base 5 number. Thus `.45` becomes `34` becomes 3x5 + 4 = decimal 19. If a below or diagonal check is NOT required, we pick a number that gives a duplicate check in one of the other directions.
We then add a multiple of 25 to it to bring it into the printable ASCII range. If checking of an element to the right is NOT required, we add a further multiple of 25 to increase the value above 64.
Decoding should be apparent from the code, but I will add commented code later when I have time.
]