# Generate a Graeco-Latin square

## 05AB1E, 2623 22 bytes

-3 bytes thanks to Emigna

-1 byte thanks to Kevin Cruijssen

Lãœ.ΔIôDζ«D€í«ε€нÙgQ}P


Try it online!

## R, 164 148 bytes

-many bytes thanks to Giuseppe.

n=scan()
!=function(x)sd(colSums(2^x))
m=function()matrix(sample(n,n^2,1),n)
while(T)T=!(l=m())|!(g=m())|!t(l)|!t(g)|1-all(1:n^2%in%(n*l+g-n))
l
g


Try it online!

Dramatically inefficient - I think it's even worse than other brute force approaches. Even for n=3, it will probably time out on TIO. Here is an alternate version (155 bytes) which works for n=3 in about 1 second.

Works by rejection. The function m draws a random matrix of integers between $$\1\$$ and $$\n\$$ (without forcing each integer to appear exactly $$\n\$$ times, or in different columns - this explains the slowness of the code, and is the only thing changed in the faster version). Call this function twice, to get the "latin" and "greek" squares l and g. Then we check:

1. all(1:n^2%in%(n*l+g-n)): are there $$\n^2\$$ different pairs of values in l $$\\times\$$ g?
2. are l and g latin squares?

To check that a matrix is a latin square, use the function !. Since point 1. above has been validated, we know that each integer appears $$\n\$$ times in each of l and g. Compute the column-wise sums of 2^l: these sums are all equal if and only if each integer appears once in each column (and the value of the sum is then $$\2^{n+1}-2\$$). If this is true for both l and its transpose t(l), then l is a latin square; same for g. The function sd, which computes the standard deviation, is an easy way to check whether all values of a vector are equal. Note that it doesn't work for the trivial cases $$\n=0\$$ and $$\n=1\$$ , which is OK according to the OP.

A final note: as often in R code golf, I used the variable T, which is initialized as TRUE, to gain a few bytes. But this means that when I needed the actual value TRUE in the definition of m (parameter replace in sample), I had to use 1 instead of T. Similarly, since I am redefining ! as a function different from negation, I had to use 1-all(...) instead of !all(...).

## JavaScript (ES6),  159 147  140 bytes

Returns a flat array of $$\n\times n\$$ pairs of non-negative integers.

This is a simple brute force search, and therefore very slow.

n=>(g=(m,j=0,X=n*n)=>j<n*n?!X--||m.some(([x,y],i)=>(X==x)+(Y==y)>(j/n^i/n&&j%n!=i%n),g(m,j,X),Y=X/n|0,X%=n)?o:g([...m,[X,Y]],j+1):o=m)(o=[])


Try it online! (with prettified output)

### Commented

n => (                      // n = input
g = (                     // g is the recursive search function taking:
m,                      //   m[] = flattened matrix
j = 0,                  //   j   = current position in m[]
X = n * n               //   X   = counter used to compute the current pair
) =>                      //
j < n * n ?             // if j is less than n²:
!X-- ||               //   abort right away if X is equal to 0; decrement X
m.some(([x, y], i) => //   for each pair [x, y] at position i in m[]:
(X == x) +          //     yield 1 if X is equal to x OR Y is equal to y
(Y == y)            //     yield 2 if both values are equal
//     or yield 0 otherwise
>                   //     test whether the above result is greater than:
( j / n ^ i / n &&  //       - 1 if i and j are neither on the same row
j % n != i % n    //         nor the same column
),                  //       - 0 otherwise
//     initialization of some():
g(m, j, X),         //       do a recursive call with all parameters unchanged
Y = X / n | 0,      //       start with Y = floor(X / n)
X %= n              //       and X = X % n
) ?                   //   end of some(); if it's falsy (or X was equal to 0):
o                   //     just return o[]
:                     //   else:
g(                  //     do a recursive call:
[...m, [X, Y]],   //       append [X, Y] to m[]
j + 1             //       increment j
)                   //     end of recursive call
:                       // else:
o = m                 //   success: update o[] to m[]
)(o = [])                   // initial call to g with m = o = []