Random Latin squares: Difference between revisions

From Rosetta Code
Content added Content deleted
(added RPL)
 
(33 intermediate revisions by 15 users not shown)
Line 2: Line 2:


A Latin square of size <code>n</code> is an arrangement of <code>n</code> symbols in an <code>n-by-n</code> square in such a way that each row and column has each symbol appearing exactly once.<br>
A Latin square of size <code>n</code> is an arrangement of <code>n</code> symbols in an <code>n-by-n</code> square in such a way that each row and column has each symbol appearing exactly once.<br>
For the purposes of this task, a random Latin square of size <code>n</code> is a Latin square constructed or generated by a probabilistic procedure such that the probability of any particular Latin square of size <code>n</code> being produced is non-zero.
A randomised Latin square generates random configurations of the symbols for any given <code>n</code>.


;Example n=4 randomised Latin square:
;Example n=4 randomised Latin square:
Line 15: Line 15:


;Note:
;Note:
Strict ''Uniformity'' in the random generation is a hard problem and '''not''' a requirement of the task.
Strict ''uniformity'' in the random generation is a hard problem and '''not''' a requirement of the task.

;Related tasks:
* [[Latin Squares in reduced form/Randomizing using Jacobson and Matthews’ Technique]]
* [[Latin Squares in reduced form]]


;Reference:
;Reference:
Line 25: Line 29:
{{trans|Python}}
{{trans|Python}}


<lang 11l>F _transpose(matrix)
<syntaxhighlight lang="11l">F _transpose(matrix)
assert(matrix.len == matrix[0].len)
assert(matrix.len == matrix[0].len)
V r = [[0] * matrix.len] * matrix.len
V r = [[0] * matrix.len] * matrix.len
Line 70: Line 74:
print(square.map(row -> row.join(‘ ’)).join("\n"))
print(square.map(row -> row.join(‘ ’)).join("\n"))
_check(square)
_check(square)
print()</lang>
print()</syntaxhighlight>


{{out}}
{{out}}
Line 93: Line 97:
1 0 4 3 2
1 0 4 3 2
0 3 1 2 4
0 3 1 2 4
</pre>

=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE PTR="CARD"
DEFINE DIMENSION="5"

TYPE Matrix=[
PTR data ;BYTE ARRAY
BYTE dim]

PTR FUNC GetPtr(Matrix POINTER mat BYTE x,y)
RETURN (mat.data+x+y*mat.dim)

PROC PrintMatrix(Matrix POINTER mat)
BYTE x,y
BYTE POINTER d

d=GetPtr(mat,0,0)
FOR y=0 TO mat.dim-1
DO
FOR x=0 TO mat.dim-1
DO
PrintB(d^) Put(32)
d==+1
OD
PutE()
OD
RETURN

PROC KnuthShuffle(BYTE ARRAY tab BYTE size)
BYTE i,j,tmp

i=size-1
WHILE i>0
DO
j=Rand(i+1)
tmp=tab(i)
tab(i)=tab(j)
tab(j)=tmp
i==-1
OD
RETURN

PROC LatinSquare(Matrix POINTER mat)
BYTE x,y,yy,shuffled
BYTE POINTER ptr1,ptr2
BYTE ARRAY used(DIMENSION)

ptr1=GetPtr(mat,0,0)
FOR y=0 TO mat.dim-1
DO
FOR x=0 TO mat.dim-1
DO
ptr1^=x
ptr1==+1
OD
OD

;first row
ptr1=GetPtr(mat,0,0)
KnuthShuffle(ptr1,mat.dim)

;middle rows
FOR y=1 TO mat.dim-2
DO
shuffled=0
WHILE shuffled=0
DO
ptr1=GetPtr(mat,0,y)
KnuthShuffle(ptr1,mat.dim)

shuffled=1
yy=0
WHILE shuffled=1 AND yy<y
DO
x=0
WHILE shuffled=1 AND x<mat.dim
DO
ptr1=GetPtr(mat,x,yy)
ptr2=GetPtr(mat,x,y)
IF ptr1^=ptr2^ THEN
shuffled=0
FI
x==+1
OD
yy==+1
OD
OD
OD

;last row
FOR x=0 TO mat.dim-1
DO
Zero(used,mat.dim)

FOR y=0 TO mat.dim-2
DO
ptr1=GetPtr(mat,x,y)
yy=ptr1^ used(yy)=1
OD

FOR y=0 TO mat.dim-1
DO
IF used(y)=0 THEN
ptr1=GetPtr(mat,x,mat.dim-1)
ptr1^=y
EXIT
FI
OD
OD
RETURN

PROC Main()
BYTE ARRAY d(25)
BYTE i
Matrix mat

mat.data=d
mat.dim=DIMENSION

FOR i=1 TO 2
DO
LatinSquare(mat)
PrintMatrix(mat)
PutE()
OD
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Random_Latin_squares.png Screenshot from Atari 8-bit computer]
<pre>
3 1 2 4 0
1 4 0 2 3
4 0 3 1 2
2 3 1 0 4
0 2 4 3 1

2 1 3 4 0
3 0 4 2 1
4 3 1 0 2
1 2 0 3 4
0 4 2 1 3
</pre>

=={{header|ALGOL 68}}==
{{Trans|Nim}}
Uses the Knuth Shuffle routine from the Algol 68 sample in the Knuth Shuffle task - modified to shuffle a row in a CHAR matrix.
<br>
Generating largish squares can take some time...
<syntaxhighlight lang="algol68">
BEGIN # generate random latin squares #

# Knuth Shuffle routine from the Knuth Shuffle Task #
# modified to shufflw a row of a [,]CHAR array #
PROC knuth shuffle = (REF[,]CHAR a, INT row)VOID:
(
PROC between = (INT a, b)INT :
(
ENTIER (random * ABS (b-a+1) + (a<b|a|b))
);
FOR i FROM LWB a TO UPB a DO
INT j = between(LWB a, UPB a);
CHAR t = a[row, i];
a[row, i] := a[row, j];
a[row, j] := t
OD
);

# generates a random latin square #
PROC latin square = ( INT n )[,]CHAR:
BEGIN
[ 1 : n ]CHAR letters;
[ 1 : n, 1 : n ]CHAR result;
FOR col TO n DO
letters[ col ] := REPR ( ABS "A" + ( col - 1 ) )
OD;
FOR row TO n DO
result[ row, : ] := letters
OD;
knuth shuffle( result, 1 );
FOR row FROM 2 TO n - 1 DO
BOOL ok := FALSE;
WHILE
knuth shuffle( result, row );
BOOL all different := TRUE;
FOR prev TO row - 1 WHILE all different DO
FOR col TO n
WHILE all different :=
result[ row, col ] /= result[ prev, col ]
DO SKIP OD
OD;
NOT all different
DO SKIP OD
OD;
# the final row, there is only one possibility for each column #
FOR col TO n DO
[ 1 : n ]CHAR free := letters;
FOR row TO n - 1 DO
free[ ( ABS result[ row, col ] - ABS "A" ) + 1 ] := REPR 0
OD;
BOOL found := FALSE;
FOR row FROM 1 LWB result TO 1 UPB result WHILE NOT found DO
IF free[ row ] /= REPR 0 THEN
found := TRUE;
result[ n, col ] := free[ row ]
FI
OD
OD;
result
END # latin suare # ;

# prints a latin square #
PROC print square = ( [,]CHAR square )VOID:
FOR row FROM 1 LWB square TO 1 UPB square DO
IF 2 LWB square <= 2 UPB square THEN
print( ( square[ row, 2 LWB square ] ) );
FOR col FROM 2 LWB square + 1 TO 2 UPB square DO
print( ( " ", square[ row, col ] ) )
OD;
print( ( newline ) )
FI
OD # print square # ;

next random;
print square( latin square( 5 ) );
print( ( newline ) );
print square( latin square( 5 ) );
print( ( newline ) );
print square( latin square( 10 ) )

END
</syntaxhighlight>
{{out}}
<pre>
A C D B E
C A B E D
D E A C B
E B C D A
B D E A C

A B E C D
B E D A C
E C B D A
D A C E B
C D A B E

A C D J F G I B E H
D F H G E A B J C I
H E C I B J A F G D
B I G A C H J D F E
E J I F H C D G B A
I D B C G F H E A J
C H F B J I E A D G
G B J D A E F I H C
J G A E D B C H I F
F A E H I D G C J B
</pre>
</pre>


=={{header|Arturo}}==
=={{header|Arturo}}==


<lang rebol>latinSquare: function [n][
<syntaxhighlight lang="rebol">latinSquare: function [n][
square: new []
square: new []
variants: shuffle permutate 0..n-1
variants: shuffle permutate 0..n-1
Line 120: Line 379:
print row
print row
print "---------"
print "---------"
]</lang>
]</syntaxhighlight>


{{out}}
{{out}}
Line 138: Line 397:
=={{header|C}}==
=={{header|C}}==
{{trans|C++}}
{{trans|C++}}
<lang c>#include <stdbool.h>
<syntaxhighlight lang="c">#include <stdbool.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
Line 255: Line 514:


return 0;
return 0;
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>[1, 4, 3, 0, 2]
<pre>[1, 4, 3, 0, 2]
Line 282: Line 541:
=={{header|C++}}==
=={{header|C++}}==
{{trans|Java}}
{{trans|Java}}
<lang cpp>#include <algorithm>
<syntaxhighlight lang="cpp">#include <algorithm>
#include <chrono>
#include <chrono>
#include <iostream>
#include <iostream>
Line 375: Line 634:
latinSquare(10);
latinSquare(10);
return 0;
return 0;
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>[4, 3, 1, 2, 0]
<pre>[4, 3, 1, 2, 0]
Line 402: Line 661:
=={{header|C sharp|C#}}==
=={{header|C sharp|C#}}==
{{trans|Kotlin}}
{{trans|Kotlin}}
<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Collections.Generic;


Line 506: Line 765:
}
}
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>[3, 0, 1, 4, 2]
<pre>[3, 0, 1, 4, 2]
Line 533: Line 792:
=={{header|D}}==
=={{header|D}}==
{{trans|C#}}
{{trans|C#}}
<lang d>import std.array;
<syntaxhighlight lang="d">import std.array;
import std.random;
import std.random;
import std.stdio;
import std.stdio;
Line 605: Line 864:


latinSquare(10);
latinSquare(10);
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>[2, 4, 3, 1, 0]
<pre>[2, 4, 3, 1, 0]
Line 629: Line 888:
[7, 0, 6, 2, 5, 4, 3, 8, 1, 9]
[7, 0, 6, 2, 5, 4, 3, 8, 1, 9]
[9, 7, 5, 4, 1, 3, 0, 6, 2, 8]</pre>
[9, 7, 5, 4, 1, 3, 0, 6, 2, 8]</pre>

=={{header|EasyLang}}==
{{trans|Kotlin}}
<syntaxhighlight>
proc shuffle . a[] .
for i = len a[] downto 2
r = randint i
swap a[r] a[i]
.
.
proc prsquare . lat[][] .
n = len lat[][]
for i to n
for j to n
write lat[i][j] & " "
.
print ""
.
print ""
.
proc square n . .
for i to n
lat[][] &= [ ]
for j to n
lat[i][] &= j
.
.
shuffle lat[1][]
for i = 2 to n - 1
repeat
shuffle lat[i][]
for k to i - 1
for j to n
if lat[k][j] = lat[i][j]
break 2
.
.
.
until k = i
.
.
len used0[] n
for j to n
used[] = used0[]
for i to n - 1
used[lat[i][j]] = 1
.
for k to n
if used[k] = 0
lat[n][j] = k
break 1
.
.
.
prsquare lat[][]
.
square 5
square 5
</syntaxhighlight>

{{out}}
<pre>
1 5 4 2 3
3 4 2 1 5
2 1 5 3 4
5 3 1 4 2
4 2 3 5 1

3 5 1 4 2
2 1 4 3 5
5 2 3 1 4
4 3 2 5 1
1 4 5 2 3
</pre>


=={{header|F_Sharp|F#}}==
=={{header|F_Sharp|F#}}==
This solution uses functions from [[Factorial_base_numbers_indexing_permutations_of_a_collection#F.23]] and [[Latin_Squares_in_reduced_form#F.23]]. This solution generates completely random uniformly distributed Latin Squares from all possible Latin Squares of order 5. It takes 5 thousandths of a second can that really be called hard?
This solution uses functions from [[Factorial_base_numbers_indexing_permutations_of_a_collection#F.23]] and [[Latin_Squares_in_reduced_form#F.23]]. It has been alleged that this solution generates completely random uniformly distributed Latin Squares from all possible Latin Squares of order 5. It takes 5 thousandths of a second to do so.
<lang fsharp>
<syntaxhighlight lang="fsharp">
// Generate 2 Random Latin Squares of order 5. Nigel Galloway: July 136th., 2019
// Generate 2 Random Latin Squares of order 5. Nigel Galloway: July 136th., 2019
let N=let N=System.Random() in (fun n->N.Next(n))
let N=let N=System.Random() in (fun n->N.Next(n))
let rc()=let β=lN2p [|0;N 4;N 3;N 2|] [|0..4|] in Seq.item (N 56) (normLS 5) |> List.map(lN2p [|N 5;N 4;N 3;N 2|]) |> List.permute(fun n->β.[n]) |> List.iter(printfn "%A")
let rc()=let β=lN2p [|0;N 4;N 3;N 2|] [|0..4|] in Seq.item (N 56) (normLS 5) |> List.map(lN2p [|N 5;N 4;N 3;N 2|]) |> List.permute(fun n->β.[n]) |> List.iter(printfn "%A")
rc(); printfn ""; rc()
rc(); printfn ""; rc()
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 678: Line 1,011:


=={{header|Factor}}==
=={{header|Factor}}==
A brute force method for generating uniformly random Latin squares. Repeatedly select a random permutation of (0, 1,...n-1) and add it as the next row of the square. If at any point the rules for being a Latin square are violated, start the entire process over again from the beginning.
A brute force method for generating Latin squares with uniform randomness from the relevant population. Repeatedly select a random permutation of (0, 1,...n-1) and add it as the next row of the square. If at any point the rules for being a Latin square are violated, start the entire process over again from the beginning.
<lang factor>USING: arrays combinators.extras fry io kernel math.matrices
<syntaxhighlight lang="factor">USING: arrays combinators.extras fry io kernel math.matrices
prettyprint random sequences sets ;
prettyprint random sequences sets ;
IN: rosetta-code.random-latin-squares
IN: rosetta-code.random-latin-squares
Line 689: Line 1,022:
: random-latin-squares ( -- ) [ 5 ls simple-table. nl ] twice ;
: random-latin-squares ( -- ) [ 5 ls simple-table. nl ] twice ;


MAIN: random-latin-squares</lang>
MAIN: random-latin-squares</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 704: Line 1,037:
3 1 2 4 0
3 1 2 4 0
</pre>
</pre>

=={{header|FreeBASIC}}==
{{trans|Wren}}
====Restarting Row method====
<syntaxhighlight lang="vbnet">Randomize Timer

Sub printSquare(latin() As Integer, n As Integer)
For i As Integer = 0 To n - 1
Print "[";
For j As Integer = 0 To n - 1
Print latin(i, j); ",";
Next j
Print Chr(8); " ]"
Next i
Print
End Sub

Sub latinSquare(n As Integer)
Dim As Integer i, j, k
If n <= 0 Then
Print "[]"
Exit Sub
End If
Dim latin(n - 1, n - 1) As Integer
For i = 0 To n - 1
For j = 0 To n - 1
latin(i, j) = j
Next j
Next i
' first row
For i = 0 To n - 1
Dim j As Integer = Int(Rnd * n)
Swap latin(0, i), latin(0, j)
Next i
' middle row(s)
For i = 1 To n - 2
Dim shuffled As Integer = 0
While shuffled = 0
For j = 0 To n - 1
Dim k As Integer = Int(Rnd * n)
Swap latin(i, j), latin(i, k)
Next j
shuffled = 1
For k As Integer = 0 To i - 1
For j = 0 To n - 1
If latin(k, j) = latin(i, j) Then
shuffled = 0
Exit For
End If
Next j
If shuffled = 0 Then Exit For
Next k
Wend
Next i
' last row
For j = 0 To n - 1
Dim used(n - 1) As Integer
For i = 0 To n - 2
used(latin(i, j)) = 1
Next i
For k = 0 To n - 1
If used(k) = 0 Then
latin(n - 1, j) = k
Exit For
End If
Next k
Next j
printSquare(latin(), n)
End Sub

latinSquare(5)
latinSquare(5)
latinSquare(10) ' for good measure

Sleep</syntaxhighlight>


=={{header|Go}}==
=={{header|Go}}==
===Restarting Row method===
===Restarting Row method===
As the task is not asking for large squares to be generated and even n = 10 is virtually instant, we use a simple brute force approach here known as the 'Restarting Row' method (see Talk page). However, whilst easy to understand, this method does not produce uniformly random squares.
As the task is not asking for large squares to be generated and even n = 10 is virtually instant, we use a simple brute force approach here known as the 'Restarting Row' method (see Talk page). However, whilst easy to understand, this method does not produce uniformly random squares.
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 787: Line 1,199:
latinSquare(5)
latinSquare(5)
latinSquare(10) // for good measure
latinSquare(10) // for good measure
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 818: Line 1,230:
===Latin Squares in Reduced Form method===
===Latin Squares in Reduced Form method===
Unlike the "Restarting Row" method, this method does produce uniformly random Latin squares for n <= 6 (see Talk page) but is more involved and therefore slower. It reuses some (suitably adjusted) code from the [https://rosettacode.org/wiki/Latin_Squares_in_reduced_form#Go Latin Squares in Reduced Form] and [https://rosettacode.org/wiki/Permutations#non-recursive.2C_lexicographical_order Permutations] tasks.
Unlike the "Restarting Row" method, this method does produce uniformly random Latin squares for n <= 6 (see Talk page) but is more involved and therefore slower. It reuses some (suitably adjusted) code from the [https://rosettacode.org/wiki/Latin_Squares_in_reduced_form#Go Latin Squares in Reduced Form] and [https://rosettacode.org/wiki/Permutations#non-recursive.2C_lexicographical_order Permutations] tasks.
<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 1,070: Line 1,482:
fmt.Println("\nA randomly generated latin square of order 6 is:\n")
fmt.Println("\nA randomly generated latin square of order 6 is:\n")
generateLatinSquares(6, 1, 1)
generateLatinSquares(6, 1, 1)
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 1,114: Line 1,526:
given first row and first column.
given first row and first column.


<syntaxhighlight lang="haskell">import Data.List (permutations, (\\))
<lang haskell>latinSquare :: Eq a => [a] -> [a] -> [[a]]

latinSquare :: Eq a => [a] -> [a] -> [[a]]
latinSquare [] [] = []
latinSquare [] [] = []
latinSquare c r | head r /= head c = []
latinSquare c r
| head r /= head c = []
| otherwise = reverse <$> foldl addRow firstRow perms
| otherwise = reverse <$> foldl addRow firstRow perms
where
where
-- permutations grouped by the first element
-- permutations grouped by the first element
perms =
perms = tail $ (\x -> (x :) <$> permutations (r \\ [x])) <$> c
tail $
fmap
(fmap . (:) <*> (permutations . (r \\) . return))
c
firstRow = pure <$> r
firstRow = pure <$> r
addRow tbl rows = head [ zipWith (:) row tbl
addRow tbl rows =
head
| row <- rows
, and $ different (tail row) (tail tbl) ]
[ zipWith (:) row tbl
| row <- rows,
and $ different (tail row) (tail tbl)
]
different = zipWith $ (not .) . elem
different = zipWith $ (not .) . elem


printTable :: Show a => [[a]] -> IO ()
printTable :: Show a => [[a]] -> IO ()
printTable tbl = putStrLn $ unlines $ unwords . map show <$> tbl</lang>
printTable tbl =
putStrLn $
unlines $
unwords . map show <$> tbl</syntaxhighlight>


<pre>λ> printTable $ latinSquare [1,2,3,4,5] [1,3,2,5,4]
<pre>λ> printTable $ latinSquare [1,2,3,4,5] [1,3,2,5,4]
Line 1,140: Line 1,565:
the deterministic algorithm.
the deterministic algorithm.


<lang haskell>randomLatinSquare :: Eq a => [a] -> Random [[a]]
<syntaxhighlight lang="haskell">randomLatinSquare :: Eq a => [a] -> Random [[a]]
randomLatinSquare set = do
randomLatinSquare set = do
r <- randomPermutation set
r <- randomPermutation set
c <- randomPermutation (tail r)
c <- randomPermutation (tail r)
return $ latinSquare r (head r:c)</lang>
return $ latinSquare r (head r:c)</syntaxhighlight>


For examples a naive linear congruent method in a State monad is used.
For examples a naive linear congruent method in a State monad is used.


<lang haskell>import Control.Monad.State
<syntaxhighlight lang="haskell">import Control.Monad.State


type Random a = State Int a
type Random a = State Int a
Line 1,168: Line 1,593:


randomSample :: [a] -> Random a
randomSample :: [a] -> Random a
randomSample lst = (lst !!) <$> random (length lst)</lang>
randomSample lst = (lst !!) <$> random (length lst)</syntaxhighlight>


<pre>λ> printTable $ randomLatinSquare [0..4] `evalState` 42
<pre>λ> printTable $ randomLatinSquare [0..4] `evalState` 42
Line 1,189: Line 1,614:
4 8 9 5 0 6 1 2 3 7
4 8 9 5 0 6 1 2 3 7
</pre>
</pre>

=={{header|J}}==
<syntaxhighlight lang="j">rls=: 3 : 0
s=. ?~ y NB. "deal" y unique integers from 0 to y
for_ijk. i.<:y do.
NB. deal a new row. subtract it from all previous rows
NB. if you get a 0, some column has a matching integer, deal again
whilst. 0 = */ */ s -"1 r do.
r=. ?~ y
end.
s=. s ,,: r NB. "laminate" successful row to the square
end.
)
</syntaxhighlight>
{{out}}
<pre> rls 5
4 0 1 2 3
3 1 4 0 2
2 3 0 4 1
0 2 3 1 4
1 4 2 3 0
rls 5
0 4 2 1 3
4 1 3 2 0
1 0 4 3 2
2 3 1 0 4
3 2 0 4 1</pre>


=={{header|Java}}==
=={{header|Java}}==
{{trans|Kotlin}}
{{trans|Kotlin}}
<lang java>import java.util.ArrayList;
<syntaxhighlight lang="java">import java.util.ArrayList;
import java.util.Collections;
import java.util.Collections;
import java.util.Iterator;
import java.util.Iterator;
Line 1,277: Line 1,729:
latinSquare(10);
latinSquare(10);
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>[1, 3, 4, 0, 2]
<pre>[1, 3, 4, 0, 2]
Line 1,303: Line 1,755:


=={{header|Javascript}}==
=={{header|Javascript}}==
<lang javascript>
<syntaxhighlight lang="javascript">
class Latin {
class Latin {
constructor(size = 3) {
constructor(size = 3) {
Line 1,356: Line 1,808:
}
}
new Latin(5);
new Latin(5);
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 1,370: Line 1,822:
1 2 3 5 4
1 2 3 5 4
2 3 5 4 1
2 3 5 4 1
</pre>

=={{header|jq}}==
{{works with|jq}}
'''Also works with gojq, the Go implementation of jq.'''

This entry presents two jq programs for generating Latin Squares of order n
(LS(n)) in accordance with the requirements.

The first program uses a "brute-force" algorithm (with simple optimizations) to
generate Latin Squares of order n as though drawing with
replacement from the population of all such Latin Squares.
The chi-squared statistics show good agreement
with the theoretical uniformity.

The second program uses a much faster algorithm for generating Latin Squares
in accordance with the requirements, but with bias away from
uniformity, as also illustrated by chi-squared statistics.

Both algorithms use /dev/random as a source of entropy. They also
both use the Knuth shuffle to generate the first row, and rely on
backtracking using the jq idiom:

`first( repeat( _) )`

The first algorithm incrementally adds rows, backtracking to the
point immediately after the selection of the first row. For n larger
than about 4, this algorithm is quite slow, though in a fairly predictable way.

The second algorithm incrementally adds cells, backtracking to the
last cell. It is much faster but the running time can be quite
variable, as suggested by this table:
<pre>
n Typical range of u+s times on 3GHz machine
10 0.11 to 0.14 s
15 0.15 to 0.21 s
20 0.36 to 0.94 s
30 0.5 to 29 seconds
40 80 seconds to 21 minutes
45 8 to 39 minutes
</pre>

An interesting variant of the second algorithm can be obtained by
a trivial modification of just one line (see the comment with "n.b."):
backtracking to the last full row is slightly faster while maintaining
randomness, at the cost of a greater departure from uniform
randomness, as confirmed by these two runs using the same `stats`
function as defined in the first program.

<pre>
# Using `ext` (i.e., backtrack to point after selection of first row)
Number of LS(4): 5760
Of 576 possibilities, only 575 were generated.
Chi-squared statistic (df=575): 2128.6
# u+s 5.5s

# Using `extend` (i.e. backtrack to point of most recent row extension - faster but more biased)
Number of LS(4): 5760
All 576 possibilities have been generated.
Chi-squared statistic (df=575): 3055.8
# u+s 4.7s
</pre>

<syntaxhighlight lang=sh>
#!/bin/bash
< /dev/random tr -cd '0-9' | fold -w 1 | jq -Mcnr -f random-latin-squares.jq
</syntaxhighlight>

=== Common Functions ===
<syntaxhighlight lang=sh>

'''Generic Utility Functions'''
# For inclusion using jq's `include` directive:
# Output: a PRN in range(0;$n) where $n is .
def prn:
if . == 1 then 0
else . as $n
| (($n-1)|tostring|length) as $w
| [limit($w; inputs)] | join("") | tonumber
| if . < $n then . else ($n | prn) end
end;

def knuthShuffle:
length as $n
| if $n <= 1 then .
else {i: $n, a: .}
| until(.i == 0;
.i += -1
| (.i + 1 | prn) as $j
| .a[.i] as $t
| .a[.i] = .a[$j]
| .a[$j] = $t)
| .a
end;

def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;

# If the input array is not rectangular, let nulls fall where they may
def column($j):
[.[] | .[$j]];

# Emit a stream of [value, frequency] pairs
def histogram(stream):
reduce stream as $s ({};
($s|type) as $t
| (if $t == "string" then $s else ($s|tojson) end) as $y
| .[$t][$y][0] = $s
| .[$t][$y][1] += 1 )
| .[][] ;

def ss(s): reduce s as $x (0; . + ($x * $x));

def chiSquared($expected): ss( .[] - $expected ) / $expected;
</syntaxhighlight>

===Latin Squares selected at random uniformly===
<syntaxhighlight lang=sh>
# Include the utilities e.g. by
# include "random-latin-squares.utilities" {search: "."};

# Determine orthogonality of two arrays, confining attention
# to the first $n elements in each:
def orthogonal($a; $b; $n):
first( (range(0; $n) | if $a[.] == $b[.] then 0 else empty end) // 1) | . == 1;

# Are the two arrays orthogonal up to the length of the shorter?
def orthogonal($a; $b):
([$a, $b | length] | min) as $min
| orthogonal($a; $b; $min);

# Is row $i orthogonal to all the previous rows?
def orthogonal($i):
. as $in
| .[$i] as $row
| all(range(0;$i); orthogonal($row; $in[.]));

# verify columnwise orthogonality
def columnwise:
length as $n
| transpose as $t
| all( range(1;$n); . as $i | $t | orthogonal($i)) ;

def addLast:
(.[0] | length) as $n
| [range(0; $n)] as $range
| [range(0; $n) as $i
| ($range - column($i))[0] ] as $last
| . + [$last] ;

# input: an array being a permutation of [range(0;$n)] for some $n
# output: a Latin Square selected at random from all the candidates
def extend:
(.[0] | length) as $n
| if length >= $n then .
elif length == $n - 1 then addLast
else ([range(0; $n)] | knuthShuffle) as $row
| (. + [$row] )
| if orthogonal(length - 1) and columnwise then extend else empty end
end ;

# Generate a Latin Square.
# The input should be an integer specifying its size.
def latinSquare:
. as $n
| if $n <= 0 then []
else
[ [range(0; $n)] | knuthShuffle]
| first(repeat(extend))
# | (if columnwise then . else debug end) # internal check
end ;

# If the input is a positive integer, $n, generate and print an $n x $n Latin Square.
# If it is not number, echo it.
def printLatinSquare:
if type == "number"
then latinSquare
| .[] | map(lpad(3)) | join(" ")
else .
end;

# $order should be in 1 .. 5 inclusive
# If $n is null, then use 10 * $counts[$order]
def stats($order; $n):
# table of counts:
[0,1,2,12,576,161280] as $counts
| $counts[$order] as $possibilities
| (if $n then $n else 10 * $possibilities end) as $n
| reduce range(0;$n) as $i ({};
($order|latinSquare|flatten|join("")) as $row
| .[$row] += 1)
| # ([histogram(.[])] | sort[] | join(" ")),
"Number of LS(\($order)): \($n)",
(if length == $possibilities
then "All \($possibilities) possibilities have been generated."
else "Of \($possibilities) possibilities, only \(length) were generated."
end),
"Chi-squared statistic (df=\($possibilities-1)): \( [.[]] | chiSquared( $n / $possibilities))";


stats(3;null), "",
stats(4;5760), ""
stats(4;5760)
</syntaxhighlight>
{{output}}
<pre>
Number of LS(3): 120
All 12 possibilities have been generated.
Chi-squared statistic (df=11): 18.8

Number of LS(4): 5760
All 576 possibilities have been generated.
Chi-squared statistic (df=575): 572.2

Number of LS(4): 5760
All 576 possibilities have been generated.
Chi-squared statistic (df=575): 517.2
</pre>

=== Random Latin Squares ===
This is the (much) faster program that meets the task
requirements while deviating from uniform randomness
as suggested by the Chi-squared statistics presented in the preamble.

<syntaxhighlight lang=sh>
# Include the utilities e.g. by
# include "random-latin-squares.utilities" {search: "."};

# Select an element at random from [range(0;$n)] - column($j)
def candidate($j):
(.[0] | length) as $n
| [range(0;$n)] - column($j)
| .[length|prn];

# Input: the first row or rows of a Latin Square
def extend:
# The input to ext should be several rows of a Latin Square
# optionally followed by a candidate for an additional row.
def ext:
.[0] as $first
| length as $length
| ($first|length) as $n
| .[-1] as $last
| if ($last|length) < $n # then extend the last row
then ( ([range(0;$n)] - column($last|length)) - $last) as $candidates
| .[:$length-1] as $good
| ($candidates|length) as $cl

# if we can complete the row, then there is no need for another backtrack point!
| if $cl == 1 and ($last|length) == $n - 1
then ($good + [ $last + $candidates]) | ext # n.b. or use `extend` to speed things up at the cost of more bias
else
if $cl == 1 then ($good + [ $last + $candidates]) | ext
elif $cl == 0
then empty
else ($candidates[$cl | prn] as $add
| ($good + [$last + [$add]]) | ext)
end
end
elif length < $n then ((. + [[candidate(0)]]) | ext)
else .
end;
# If at first you do not succeed ...
first( repeat( ext ));

# Generate a Latin Square.
# The input should be an integer specifying its size.
def latinSquare:
. as $n
| if $n <= 0 then []
else
[ [range(0; $n)] | knuthShuffle]
| extend
end ;

# If the input is a positive integer, $n, generate and print an $n x $n Latin Square.
# Otherwise, simply echo it.
def printLatinSquare:
if type == "number"
then latinSquare
| .[] | map(lpad(3)) | join(" ")
else .
end;

"Five", 5, "\nFive", 5, "\nTen", 10, "\nForty", 40
| printLatinSquare
'
</syntaxhighlight>
{{output}}
<pre style="font-size: xx-small">
Five
2 1 3 4 0
1 4 0 2 3
4 3 2 0 1
3 0 4 1 2
0 2 1 3 4

Five
1 0 2 3 4
4 3 0 1 2
0 4 3 2 1
2 1 4 0 3
3 2 1 4 0

Ten
0 4 9 1 5 3 8 7 2 6
5 8 7 9 3 6 0 2 4 1
8 7 2 6 0 1 4 5 3 9
9 3 1 2 7 4 5 6 0 8
7 2 5 4 6 0 9 8 1 3
6 9 0 8 4 5 1 3 7 2
3 0 8 7 9 2 6 1 5 4
4 1 6 3 2 8 7 0 9 5
1 5 3 0 8 9 2 4 6 7
2 6 4 5 1 7 3 9 8 0

Forty
30 29 36 1 37 23 27 33 22 32 38 20 5 13 25 35 16 18 19 24 11 6 4 12 3 10 21 26 34 39 14 28 31 2 8 7 9 17 0 15
16 30 21 32 24 6 25 17 35 12 26 10 19 33 18 31 29 34 4 13 15 28 0 3 5 11 9 23 14 2 20 38 37 8 39 27 1 22 36 7
21 4 27 11 5 12 9 13 30 20 3 36 31 0 24 16 28 1 8 33 38 2 23 22 29 32 18 34 6 7 15 17 25 26 10 35 19 14 39 37
2 13 18 36 15 19 17 32 27 24 9 3 26 21 1 0 10 39 38 16 20 14 34 6 28 22 12 7 11 8 5 23 33 37 30 4 29 31 25 35
35 39 10 0 3 15 1 37 7 4 6 2 27 9 29 38 34 16 33 28 32 30 24 14 18 23 31 12 19 17 21 36 8 13 20 25 22 5 11 26
13 27 34 25 17 1 21 5 23 39 2 8 0 38 22 7 32 9 29 26 18 4 36 19 30 16 14 20 31 28 3 6 35 11 15 12 33 10 37 24
36 31 26 3 25 2 11 38 13 18 24 35 17 10 20 1 7 15 6 19 22 0 12 32 33 27 4 30 37 9 8 29 14 28 34 39 23 16 5 21
26 25 35 31 6 34 5 8 11 19 30 1 20 15 33 10 23 38 0 21 37 29 2 39 14 17 28 27 32 18 24 7 12 3 36 13 4 9 22 16
18 14 4 30 33 38 8 2 1 28 21 27 13 36 37 22 15 3 20 31 7 25 6 0 12 29 26 32 17 35 23 34 11 9 19 5 16 24 10 39
14 21 5 34 8 29 0 10 20 9 28 39 35 4 17 30 26 11 25 38 16 19 31 15 32 1 6 24 13 37 7 27 36 33 23 18 2 12 3 22
15 28 24 2 34 7 3 35 29 30 0 4 38 25 6 27 11 12 17 37 26 20 21 5 1 14 10 8 33 16 36 9 13 32 22 19 39 18 31 23
38 3 23 7 39 37 13 20 21 25 33 5 6 32 14 4 8 35 12 9 24 17 11 34 27 36 16 22 26 0 31 18 2 29 1 15 28 19 30 10
11 19 30 5 31 18 10 21 6 23 34 33 4 12 2 14 37 22 39 1 25 8 16 38 24 28 36 13 3 27 29 26 32 35 7 20 0 15 9 17
0 9 12 20 16 30 38 11 18 14 4 17 10 7 19 36 3 27 37 35 29 22 26 28 21 8 13 39 23 33 34 31 24 6 2 32 25 1 15 5
29 2 16 18 35 17 37 25 10 27 39 31 3 6 23 34 9 19 30 4 13 38 1 21 8 0 22 5 36 24 12 33 28 15 26 14 11 32 7 20
22 35 29 38 23 8 7 6 9 36 14 0 18 34 27 3 12 33 5 39 21 11 30 31 10 26 15 17 1 4 37 16 20 19 13 24 32 2 28 25
32 16 25 4 26 22 36 1 28 3 27 7 14 19 39 5 33 21 9 2 23 31 13 20 11 37 30 0 15 34 35 10 17 24 29 38 18 8 12 6
33 20 32 13 30 21 35 7 24 2 19 16 11 37 4 23 14 31 36 15 1 39 22 9 25 38 27 6 0 26 10 8 29 5 17 3 34 28 18 12
5 0 28 26 22 39 30 27 33 31 12 24 21 35 11 20 4 32 34 8 9 16 15 17 19 25 3 1 10 6 18 2 38 7 14 37 13 29 23 36
25 5 17 37 11 13 4 18 36 34 23 32 9 20 12 19 21 2 3 0 30 10 35 26 38 24 39 28 22 15 16 1 27 14 31 6 8 7 33 29
10 32 1 17 12 31 39 30 15 26 25 11 33 27 13 29 6 37 2 3 8 24 18 4 7 21 35 16 20 5 9 19 34 23 38 22 36 0 14 28
31 37 33 27 4 20 14 9 34 29 32 26 22 30 28 12 5 25 24 17 10 7 39 11 23 2 1 36 18 38 13 35 21 16 0 8 15 6 19 3
4 34 11 15 27 33 19 14 37 0 8 29 28 5 3 18 2 10 31 12 39 23 20 35 13 30 24 21 25 1 6 22 26 17 16 36 7 38 32 9
1 38 14 21 7 4 34 16 2 22 13 12 29 31 15 28 25 36 32 10 27 3 37 33 17 5 0 9 30 23 11 20 39 18 6 26 24 35 8 19
28 26 20 10 14 35 29 4 16 8 37 38 7 17 9 32 19 6 23 30 5 36 27 2 15 13 25 11 12 22 0 39 3 34 24 33 31 21 1 18
20 10 6 29 21 24 32 19 39 16 31 15 36 23 34 37 17 13 1 25 14 18 9 27 0 7 8 38 35 12 30 5 4 22 3 28 26 11 2 33
24 7 9 8 18 5 26 0 19 15 1 30 2 22 36 21 35 17 27 29 3 33 38 10 4 39 11 25 16 20 28 12 23 31 32 34 37 13 6 14
37 33 3 19 10 25 20 26 17 13 11 34 23 1 30 8 22 5 28 14 2 12 7 18 36 15 29 35 21 32 27 4 16 38 9 0 6 39 24 31
39 1 31 9 29 14 15 3 26 17 36 25 30 11 38 24 27 28 18 32 6 5 33 37 2 19 7 10 4 13 22 21 0 20 12 23 35 34 16 8
34 17 15 24 28 16 6 22 8 7 5 14 25 29 35 2 30 26 11 27 12 1 19 36 39 20 23 4 9 21 38 32 18 10 37 31 3 33 13 0
12 24 22 39 19 28 18 15 32 33 7 23 16 26 8 11 36 14 13 34 0 9 29 30 6 35 2 31 38 25 4 3 5 27 21 10 17 37 20 1
8 23 7 28 9 27 12 39 31 6 18 21 34 16 10 25 20 24 15 11 35 37 3 1 22 4 19 29 2 14 26 13 30 0 33 17 5 36 38 32
9 36 2 23 32 11 33 12 25 38 16 18 8 14 0 39 31 7 10 6 28 21 5 29 34 3 17 37 24 19 1 15 22 4 27 30 20 26 35 13
17 22 0 6 36 3 31 23 12 1 20 9 37 28 32 33 13 30 7 5 19 26 14 24 35 18 34 15 8 29 2 11 10 39 25 16 21 4 27 38
19 18 38 35 13 0 22 28 4 5 15 6 12 39 16 26 1 23 14 20 17 34 10 8 37 31 32 3 29 30 33 24 7 36 11 9 27 25 21 2
7 6 19 12 20 36 2 24 3 21 17 22 32 18 31 9 0 8 35 23 34 13 25 16 26 33 5 14 28 10 39 37 15 30 4 1 38 27 29 11
27 8 39 33 38 9 23 36 0 11 29 19 15 24 5 13 18 20 26 22 31 35 32 25 16 12 37 2 7 3 17 14 6 1 28 21 10 30 4 34
23 15 8 16 1 32 24 34 14 10 22 37 39 2 7 17 38 29 21 36 33 27 28 13 9 6 20 18 5 31 25 0 19 12 35 11 30 3 26 4
3 11 13 14 2 10 16 31 38 37 35 28 24 8 26 6 39 0 22 18 4 15 17 7 20 9 33 19 27 36 32 25 1 21 5 29 12 23 34 30
6 12 37 22 0 26 28 29 5 35 10 13 1 3 21 15 24 4 16 7 36 32 8 23 31 34 38 33 39 11 19 30 9 25 18 2 14 20 17 27
</pre>
</pre>


=={{header|Julia}}==
=={{header|Julia}}==
Using the Python algorithm as described in the discussion section.
Using the Python algorithm as described in the discussion section.
<lang julia>using Random
<syntaxhighlight lang="julia">using Random


shufflerows(mat) = mat[shuffle(1:end), :]
shufflerows(mat) = mat[shuffle(1:end), :]
Line 1,405: Line 2,213:


printlatinsquare(5), println("\n"), printlatinsquare(5)
printlatinsquare(5), println("\n"), printlatinsquare(5)
</lang>{{out}}
</syntaxhighlight>{{out}}
<pre>
<pre>
1 3 0 4 2
1 3 0 4 2
Line 1,423: Line 2,231:
=={{header|Kotlin}}==
=={{header|Kotlin}}==
{{trans|Go}}
{{trans|Go}}
<lang scala>typealias matrix = MutableList<MutableList<Int>>
<syntaxhighlight lang="scala">typealias matrix = MutableList<MutableList<Int>>


fun printSquare(latin: matrix) {
fun printSquare(latin: matrix) {
Line 1,480: Line 2,288:
latinSquare(5)
latinSquare(5)
latinSquare(10) // for good measure
latinSquare(10) // for good measure
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>[4, 1, 2, 3, 0]
<pre>[4, 1, 2, 3, 0]
Line 1,513: Line 2,321:
We use the stack of values, a linked list, for pushing to top (Push) or to bottom (Data), and we can pop from top using Number or by using Read A to read A from stack. Also we can shift from a chosen position to top using Shift, or using shiftback to move an item from top to chosen position. So we shuffle items by shifting them.
We use the stack of values, a linked list, for pushing to top (Push) or to bottom (Data), and we can pop from top using Number or by using Read A to read A from stack. Also we can shift from a chosen position to top using Shift, or using shiftback to move an item from top to chosen position. So we shuffle items by shifting them.


<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module FastLatinSquare {
Module FastLatinSquare {
n=5
n=5
Line 1,564: Line 2,372:
End Sub
End Sub
}
}
FastLatinSquare</lang>
FastLatinSquare</syntaxhighlight>


===Hard Way===
===Hard Way===
Line 1,573: Line 2,381:
for 20X20 need 22 min (as for 9.8 version)
for 20X20 need 22 min (as for 9.8 version)


<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module LatinSquare (n, z=1, f$="latin.dat", NewFile As Boolean=False) {
Module LatinSquare (n, z=1, f$="latin.dat", NewFile As Boolean=False) {
If Not Exist(f$) Or NewFile Then
If Not Exist(f$) Or NewFile Then
Line 1,648: Line 2,456:
LatinSquare 16
LatinSquare 16


</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre style="height:30ex;overflow:scroll">
<pre style="height:30ex;overflow:scroll">
Line 1,681: Line 2,489:
14 1 9 6 10 5 11 3 16 2 4 13 12 15 8 7
14 1 9 6 10 5 11 3 16 2 4 13 12 15 8 7
</pre >
</pre >

=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">Clear[RandomLatinSquare]
RandomLatinSquare[n_] := Module[{out, ord},
out = Table[RotateLeft[Range[n], i], {i, n}];
out = RandomSample[out];
ord = RandomSample[Range[n]];
out = out[[All, ord]];
out
]
RandomLatinSquare[5] // Grid</syntaxhighlight>
{{out}}
<pre>5 2 4 1 3
2 4 1 3 5
4 1 3 5 2
3 5 2 4 1
1 3 5 2 4</pre>


=={{header|Nim}}==
=={{header|Nim}}==
Line 1,688: Line 2,513:
Starting at n = 11, the execution time will be very variable as the program proceeds by trial and error. At least, the algorithm will be able to produce all the possible Latin squares but not in a uniform way.
Starting at n = 11, the execution time will be very variable as the program proceeds by trial and error. At least, the algorithm will be able to produce all the possible Latin squares but not in a uniform way.


<lang Nim>import random, sequtils, strutils
<syntaxhighlight lang="nim">import random, sequtils, strutils


type LatinSquare = seq[seq[char]]
type LatinSquare = seq[seq[char]]
Line 1,731: Line 2,556:
echo latinSquare(5)
echo latinSquare(5)
echo latinSquare(5)
echo latinSquare(5)
echo latinSquare(10)</lang>
echo latinSquare(10)</syntaxhighlight>


{{out}}
{{out}}
Line 1,756: Line 2,581:
J A I C G B D H E F
J A I C G B D H E F
E G F D C J B A H I</pre>
E G F D C J B A H I</pre>


=={{header|Pascal}}==

Jacobson-Matthews algorithm. Generates uniformly distributed random Latin squares (if used PRNG is good - Delphi/Pascal built-in PRNG is '''not''').

Slightly modified translation of C code from https://brainwagon.org/2016/05/17/code-for-generating-a-random-latin-square/

Algorithm source:
Jacobson, M. T.; Matthews, P. (1996). "Generating uniformly distributed random latin squares". Journal of Combinatorial Designs. 4 (6): 405–437.

<syntaxhighlight lang="pascal">

{$APPTYPE CONSOLE}

const
Alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';


Type
IncidenceCube = Array of Array Of Array of Integer;

Var
Cube : IncidenceCube;
DIM : Integer;


Procedure InitIncidenceCube(Var c:IncidenceCube; const Size:Integer);
var i, j, k : integer;
begin
DIM := Size;
SetLength(c,DIM,DIM,DIM);
for i := 0 to DIM-1 do
for j := 0 to DIM-1 do
for k := 0 to DIM-1 do c[i,j,k] := 0 ;

for i := 0 to DIM-1 do
for j := 0 to DIM-1 do c[i,j,(i+j) mod DIM] := 1;
end;


Procedure FreeIncidenceCube(Var c:IncidenceCube);
begin
Finalize(c);
end;


procedure PrintIncidenceCube(var c:IncidenceCube);
var i, j, k : integer;
begin
for i := 0 to DIM-1 do begin
for j := 0 to DIM-1 do begin
for k := 0 to DIM-1 do begin
if (c[i,j,k]=1) then begin
write(Alpha[k+1],' ');
break;
end;
end;
end;
Writeln;
end;
Writeln;
WriteLn;
end;


procedure ShuffleIncidenceCube(var c:IncidenceCube);
var i, j, rx, ry, rz, ox, oy, oz : integer;
begin

for i := 0 to (DIM*DIM*DIM)-1 do begin

repeat
rx := Random(DIM);
ry := Random(DIM);
rz := Random(DIM);
until (c[rx,ry,rz]=0);

for j := 0 to DIM-1 do begin
if (c[j,ry,rz]=1) then ox := j;
if (c[rx,j,rz]=1) then oy := j;
if (c[rx,ry,j]=1) then oz := j;
end;

Inc(c[rx,ry,rz]);
Inc(c[rx,oy,oz]);
Inc(c[ox,ry,oz]);
Inc(c[ox,oy,rz]);

Dec(c[rx,ry,oz]);
Dec(c[rx,oy,rz]);
Dec(c[ox,ry,rz]);
Dec(c[ox,oy,oz]);

while (c[ox,oy,oz] < 0) do begin

rx := ox ;
ry := oy ;
rz := oz ;

if (random(2)=0) then begin
for j := 0 to DIM-1 do begin
if (c[j,ry,rz]=1) then ox := j;
end;
end else begin
for j := DIM-1 downto 0 do begin
if (c[j,ry,rz]=1) then ox := j;
end;
end;

if (random(2)=0) then begin
for j := 0 to DIM-1 do begin
if (c[rx,j,rz]=1) then oy := j;
end;
end else begin
for j := DIM-1 downto 0 do begin
if (c[rx,j,rz]=1) then oy := j;
end;
end;

if (random(2)=0) then begin
for j := 0 to DIM-1 do begin
if (c[rx,ry,j]=1) then oz := j;
end;
end else begin
for j := DIM-1 downto 0 do begin
if (c[rx,ry,j]=1) then oz := j;
end;
end;

Inc(c[rx,ry,rz]);
Inc(c[rx,oy,oz]);
Inc(c[ox,ry,oz]);
Inc(c[ox,oy,rz]);

Dec(c[rx,ry,oz]);
Dec(c[rx,oy,rz]);
Dec(c[ox,ry,rz]);
Dec(c[ox,oy,oz]);
end;
end;
end;
begin
Randomize;
InitIncidenceCube(cube, 5); ShuffleIncidenceCube(cube); PrintIncidenceCube(cube); FreeIncidenceCube(Cube);
InitIncidenceCube(cube, 5); ShuffleIncidenceCube(cube); PrintIncidenceCube(cube); FreeIncidenceCube(Cube);
InitIncidenceCube(cube,10); ShuffleIncidenceCube(cube); PrintIncidenceCube(cube); FreeIncidenceCube(Cube);
InitIncidenceCube(cube,26); ShuffleIncidenceCube(cube); PrintIncidenceCube(cube); FreeIncidenceCube(Cube);
end.

</syntaxhighlight>

{{out}}

<pre>

B A E D C
D B C A E
C D A E B
A E B C D
E C D B A

A C D B E
B E C D A
D A B E C
E D A C B
C B E A D

E F G C D A H B I J
B J A H F D C E G I
F I J A C E G H D B
J A E D G F B I C H
C E D I H G A J B F
I D H E A B F C J G
H G B J E C I D F A
G C F B J I D A H E
D H I F B J E G A C
A B C G I H J F E D

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

</pre>



=={{header|Perl}}==
=={{header|Perl}}==
{{trans|Raku}}
{{trans|Raku}}
<lang perl>use strict;
<syntaxhighlight lang="perl">use strict;
use warnings;
use warnings;
use feature 'say';
use feature 'say';
Line 1,791: Line 2,827:
}
}


say display random_ls($_) for 2..5, 5;</lang>
say display random_ls($_) for 2..5, 5;</syntaxhighlight>
{{out}}
{{out}}
<pre>B A
<pre>B A
Line 1,819: Line 2,855:
=={{header|Phix}}==
=={{header|Phix}}==
Brute force, begins to struggle above 42.
Brute force, begins to struggle above 42.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>string aleph = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>

<span style="color: #004080;">string</span> <span style="color: #000000;">aleph</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"</span>
function ls(integer n)
if n>length(aleph) then ?9/0 end if -- too big...
<span style="color: #008080;">function</span> <span style="color: #000000;">ls</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
atom t1 = time()+1
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">aleph</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- too big...</span>
sequence tn = tagset(n), -- {1..n}
<span style="color: #004080;">atom</span> <span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()+</span><span style="color: #000000;">1</span>
vcs = repeat(tn,n), -- valid for cols
<span style="color: #004080;">sequence</span> <span style="color: #000000;">tn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- {1..n}</span>
res = {}
<span style="color: #000000;">vcs</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- valid for cols</span>
integer clashes = 0
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
while length(res)<n do
<span style="color: #004080;">integer</span> <span style="color: #000000;">clashes</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
sequence rn = {}, -- next row
<span style="color: #008080;">while</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
vr = tn, -- valid for row (ie all)
<span style="color: #004080;">sequence</span> <span style="color: #000000;">rn</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000080;font-style:italic;">-- next row</span>
vc = vcs -- copy (in case of clash)
<span style="color: #000000;">vr</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- valid for row (ie all)</span>
bool clash = false
<span style="color: #000000;">vc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vcs</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- copy (in case of clash)</span>
for c=1 to n do
<span style="color: #004080;">bool</span> <span style="color: #000000;">clash</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
sequence v = {}
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
for k=1 to n do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
-- collect all still valid options
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
if vr[k] and vc[c][k] then v &= k end if
<span style="color: #000080;font-style:italic;">-- collect all still valid options</span>
end for
<span style="color: #008080;">if</span> <span style="color: #000000;">vr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">and</span> <span style="color: #000000;">vc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">k</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if v={} then
clash = true
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">={}</span> <span style="color: #008080;">then</span>
exit
<span style="color: #000000;">clash</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
end if
integer z = v[rand(length(v))]
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
rn &= z
<span style="color: #004080;">integer</span> <span style="color: #000000;">z</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">[</span><span style="color: #7060A8;">rand</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v</span><span style="color: #0000FF;">))]</span>
vr[z] = 0 -- no longer valid
<span style="color: #000000;">rn</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">z</span>
vc[c][z] = 0 -- ""
<span style="color: #000000;">vr</span><span style="color: #0000FF;">[</span><span style="color: #000000;">z</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- no longer valid</span>
end for
<span style="color: #000000;">vc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">][</span><span style="color: #000000;">z</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> <span style="color: #000080;font-style:italic;">-- ""</span>
if not clash then
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
res = append(res,rn)
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">clash</span> <span style="color: #008080;">then</span>
vcs = vc
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rn</span><span style="color: #0000FF;">)</span>
else
<span style="color: #000000;">vcs</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">vc</span>
clashes += 1
if time()>t1 then
<span style="color: #008080;">else</span>
<span style="color: #000000;">clashes</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
printf(1,"rows completed:%d/%d, clashes:%d\n",
<span style="color: #008080;">if</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()></span><span style="color: #000000;">t1</span> <span style="color: #008080;">then</span>
{length(res),n,clashes})
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"rows completed:%d/%d, clashes:%d\n"</span><span style="color: #0000FF;">,</span>
t1 = time()+1
<span style="color: #0000FF;">{</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">),</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">clashes</span><span style="color: #0000FF;">})</span>
end if
<span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()+</span><span style="color: #000000;">1</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end while
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
for i=1 to n do
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
string line = ""
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
for j=1 to n do
<span style="color: #004080;">string</span> <span style="color: #000000;">line</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
line &= aleph[res[i][j]]
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
end for
<span style="color: #000000;">line</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">aleph</span><span style="color: #0000FF;">[</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]]</span>
res[i] = line
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">line</span>
return res
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end function
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>

<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
procedure latin_square(integer n)
atom t0 = time()
<span style="color: #008080;">procedure</span> <span style="color: #000000;">latin_square</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
string res = join(ls(n),"\n"),
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
e = elapsed(time()-t0)
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ls</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">),</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">),</span>
printf(1,"Latin square of order %d (%s):\n%s\n",{n,e,res})
<span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
end procedure
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Latin square of order %d (%s):\n%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})</span>
latin_square(3)
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
latin_square(5)
<span style="color: #000000;">latin_square</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
latin_square(5)
<span style="color: #000000;">latin_square</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
latin_square(10)
<span style="color: #000000;">latin_square</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
latin_square(42)</lang>
<span style="color: #000000;">latin_square</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">latin_square</span><span style="color: #0000FF;">(</span><span style="color: #000000;">42</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 1,956: Line 2,997:
ZL6K5NFVMCYbXfA8Oe43g7dUcDa9JTEQGSWB1PR2IH
ZL6K5NFVMCYbXfA8Oe43g7dUcDa9JTEQGSWB1PR2IH
</pre>
</pre>

=={{header|Picat}}==
Using constraint modelling.

The used labeling (search strategy) is:
* <code>ff</code>: select a variable to label using the first fail strategy
* <code>rand_val</code>: select a random (but valid) value.


Normally a non-random value strategy is preferred such as <code>up</code>, <code>split</code>, or <code>updown</code>, but the task requires random solutions.

<syntaxhighlight lang="picat">main =>
_ = random2(), % random seed
N = 5,
foreach(_ in 1..2)
latin_square(N, X),
pretty_print(X)
end,
% A larger random instance
latin_square(62,X),
pretty_print(X).

% Latin square
latin_square(N, X) =>
X = new_array(N,N),
X :: 1..N,
foreach(I in 1..N)
all_different([X[I,J] : J in 1..N]),
all_different([X[J,I] : J in 1..N])
end,
% rand_val for randomness
solve($[ff,rand_val],X).

pretty_print(X) =>
N = X.len,
Alpha = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
foreach(I in 1..N)
foreach(J in 1..N)
if N > 20 then
printf("%w",Alpha[X[I,J]])
else
printf("%2w ",X[I,J])
end
end,
nl
end,
nl.</syntaxhighlight>

{{out}}
<pre> 5 1 3 4 2
1 2 4 3 5
4 5 2 1 3
2 3 1 5 4
3 4 5 2 1

5 2 3 4 1
3 4 5 1 2
2 5 1 3 4
4 1 2 5 3
1 3 4 2 5

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

CPU time 0.048 seconds.</pre>

===Number of solutions===
The number of solutions for a Latin square of size N is the OEIS sequence [https://oeis.org/A002860 A002860: Number of Latin squares of order n; or labeled quasigroups]. Here we check N = 1..6 which took 18min54s.
<syntaxhighlight lang="picat">main =>
foreach(N in 1..6)
Count = count_all(latin_square(N,_)),
println(N=Count)
end.</syntaxhighlight>

{{out}}
<pre>1 = 1
2 = 2
3 = 12
4 = 576
5 = 161280
6 = 812851200

CPU time 1134.36 seconds.
</pre>



=={{header|Python}}==
=={{header|Python}}==
<lang python>from random import choice, shuffle
<syntaxhighlight lang="python">from random import choice, shuffle
from copy import deepcopy
from copy import deepcopy


Line 2,018: Line 3,204:
print(_to_text(square))
print(_to_text(square))
_check(square)
_check(square)
print()</lang>
print()</syntaxhighlight>


{{out}}
{{out}}
Line 2,053: Line 3,239:
4 10 9 0 3 7 2 5 1 11 6 8
4 10 9 0 3 7 2 5 1 11 6 8
0 6 11 9 1 3 5 10 2 7 8 4</pre>
0 6 11 9 1 3 5 10 2 7 8 4</pre>

=={{header|Quackery}}==

<code>transpose</code> is defined at [[Matrix transposition#Quackery]].

<syntaxhighlight lang="Quackery"> [ [] []
rot times
[ i join ]
dup size times
[ tuck
nested join
swap
behead join ]
drop
shuffle
transpose
shuffle ] is rls ( n --> [ )

2 times
[ 5 rls
witheach
[ witheach
[ echo sp ]
cr ]
cr ]</syntaxhighlight>

{{out}}

<pre>2 4 0 1 3
0 2 3 4 1
1 3 4 0 2
4 1 2 3 0
3 0 1 2 4

1 2 3 0 4
3 4 0 2 1
2 3 4 1 0
0 1 2 4 3
4 0 1 3 2
</pre>


=={{header|Raku}}==
=={{header|Raku}}==
Line 2,059: Line 3,285:
{{trans|Python}}
{{trans|Python}}


<lang perl6>sub latin-square { [[0],] };
<syntaxhighlight lang="raku" line>sub latin-square { [[0],] };


sub random ( @ls, :$size = 5 ) {
sub random ( @ls, :$size = 5 ) {
Line 2,093: Line 3,319:


# Or, if you'd prefer:
# Or, if you'd prefer:
display random latin-square, :size($_) for 12, 2, 1;</lang>
display random latin-square, :size($_) for 12, 2, 1;</syntaxhighlight>
{{out|Sample output}}
{{out|Sample output}}
<pre> V Z M J U
<pre> V Z M J U
Line 2,143: Line 3,369:


The symbols could be any characters (except those that contain a blank), &nbsp; but the numbers from &nbsp; '''0''' ──► '''N-1''' &nbsp; are used.
The symbols could be any characters (except those that contain a blank), &nbsp; but the numbers from &nbsp; '''0''' ──► '''N-1''' &nbsp; are used.
<lang rexx>/*REXX program generates and displays a randomized Latin square. */
<syntaxhighlight lang="rexx">/*REXX program generates and displays a randomized Latin square. */
parse arg N seed . /*obtain the optional argument from CL.*/
parse arg N seed . /*obtain the optional argument from CL.*/
if N=='' | N=="," then N= 5 /*Not specified? Then use the default.*/
if N=='' | N=="," then N= 5 /*Not specified? Then use the default.*/
Line 2,158: Line 3,384:
do j=1 for N /* [↓] display rows of random Latin sq*/
do j=1 for N /* [↓] display rows of random Latin sq*/
say translate(subword(zz, j, N), , '_') /*translate leading underbar to blank. */
say translate(subword(zz, j, N), , '_') /*translate leading underbar to blank. */
end /*j*/ /*stick a fork in it, we're all done. */</lang>
end /*j*/ /*stick a fork in it, we're all done. */</syntaxhighlight>
{{out|output|text=&nbsp; for 1<sup>st</sup> run when using the default inputs:}}
{{out|output|text=&nbsp; for 1<sup>st</sup> run when using the default inputs:}}
<pre>
<pre>
Line 2,177: Line 3,403:


=={{header|Ring}}==
=={{header|Ring}}==
<lang ring>
<syntaxhighlight lang="ring">
load "stdlib.ring"
load "stdlib.ring"
load "guilib.ring"
load "guilib.ring"
Line 2,523: Line 3,749:
###====================================================================================
###====================================================================================


</syntaxhighlight>
</lang>


[https://www.mediafire.com/file/6fruvfgydnbmtyj/RandomLatinSquares.jpg/file Random Latin Squares - image]
[https://www.mediafire.com/file/6fruvfgydnbmtyj/RandomLatinSquares.jpg/file Random Latin Squares - image]

=={{header|RPL}}==
{{trans|Quackery}}
{{works with|RPL|HP49-C}}
<code>SHUFL</code> is defined at [[Knuth shuffle#RPL|Knuth shuffle]]
« → n
« « k » 'k' 0 n 1 - 1 SEQ
2 n '''START'''
DUP TAIL LASTARG HEAD +
'''NEXT'''
n →LIST
<span style="color:blue">SHUFL</span> AXL
TRAN AXL
<span style="color:blue">SHUFL</span> AXL
» '<span style="color:blue">RLS</span>' STO

5 <span style="color:blue">RLS</span>
{{out}}
<pre>
1: [[ 3 1 4 2 0 ]
[ 4 2 0 3 1 ]
[ 2 0 3 1 4 ]
[ 0 3 1 4 2 ]
[ 1 4 2 0 3 ]]
</pre>


=={{header|Ruby}}==
=={{header|Ruby}}==
This crude algorithm works fine up to a square size of 10; higher values take too much time and memory. It creates an array of all possible permutations, picks a random one as first row an weeds out all permutations which cannot appear in the remaining square. Repeat picking and weeding until there is a square.
This crude algorithm works fine up to a square size of 10; higher values take too much time and memory. It creates an array of all possible permutations, picks a random one as first row an weeds out all permutations which cannot appear in the remaining square. Repeat picking and weeding until there is a square.
<lang ruby>N = 5
<syntaxhighlight lang="ruby">N = 5


def generate_square
def generate_square
Line 2,548: Line 3,799:


2.times{print_square( generate_square)}
2.times{print_square( generate_square)}
</syntaxhighlight>
</lang>
{{out}}<pre>
{{out}}<pre>
3 4 2 1 5
3 4 2 1 5
Line 2,567: Line 3,818:
{{trans|Go}}
{{trans|Go}}
===Restarting Row method===
===Restarting Row method===
<lang ecmascript>import "random" for Random
<syntaxhighlight lang="wren">import "random" for Random


var rand = Random.new()
var rand = Random.new()
Line 2,626: Line 3,877:
latinSquare.call(5)
latinSquare.call(5)
latinSquare.call(5)
latinSquare.call(5)
latinSquare.call(10) // for good measure</lang>
latinSquare.call(10) // for good measure</syntaxhighlight>


{{out}}
{{out}}
Line 2,659: Line 3,910:
{{libheader|Wren-fmt}}
{{libheader|Wren-fmt}}
{{libheader|Wren-math}}
{{libheader|Wren-math}}
<lang ecmascript>import "random" for Random
<syntaxhighlight lang="wren">import "random" for Random
import "/sort" for Sort
import "./sort" for Sort
import "/fmt" for Fmt
import "./fmt" for Fmt
import "/math" for Int
import "./math" for Int


var rand = Random.new()
var rand = Random.new()
Line 2,874: Line 4,125:
for (i in 0..3) System.print("%(testSquares[i]) : %(counts[i])")
for (i in 0..3) System.print("%(testSquares[i]) : %(counts[i])")
System.print("\nA randomly generated latin square of order 6 is:\n")
System.print("\nA randomly generated latin square of order 6 is:\n")
generateLatinSquares.call(6, 1, 1)</lang>
generateLatinSquares.call(6, 1, 1)</syntaxhighlight>


{{out}}
{{out}}
Line 2,913: Line 4,164:


=={{header|zkl}}==
=={{header|zkl}}==
<lang zkl>fcn randomLatinSquare(n,symbols=[1..]){ //--> list of lists
<syntaxhighlight lang="zkl">fcn randomLatinSquare(n,symbols=[1..]){ //--> list of lists
if(n<=0) return(T);
if(n<=0) return(T);
square,syms := List(), symbols.walker().walk(n);
square,syms := List(), symbols.walker().walk(n);
Line 2,920: Line 4,171:
T.zip(square.shuffle().xplode()).shuffle();
T.zip(square.shuffle().xplode()).shuffle();
}
}
fcn rls2String(square){ square.apply("concat"," ").concat("\n") }</lang>
fcn rls2String(square){ square.apply("concat"," ").concat("\n") }</syntaxhighlight>
<lang zkl>foreach n in (T(1,2,5)){ randomLatinSquare(n) : rls2String(_).println("\n") }
<syntaxhighlight lang="zkl">foreach n in (T(1,2,5)){ randomLatinSquare(n) : rls2String(_).println("\n") }
randomLatinSquare(5, ["A".."Z"]) : rls2String(_).println("\n");
randomLatinSquare(5, ["A".."Z"]) : rls2String(_).println("\n");
randomLatinSquare(10,"!@#$%^&*()") : rls2String(_).println("\n");</lang>
randomLatinSquare(10,"!@#$%^&*()") : rls2String(_).println("\n");</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>

Latest revision as of 08:43, 17 March 2024

Task
Random Latin squares
You are encouraged to solve this task according to the task description, using any language you may know.

A Latin square of size n is an arrangement of n symbols in an n-by-n square in such a way that each row and column has each symbol appearing exactly once.
For the purposes of this task, a random Latin square of size n is a Latin square constructed or generated by a probabilistic procedure such that the probability of any particular Latin square of size n being produced is non-zero.

Example n=4 randomised Latin square
0 2 3 1
2 1 0 3
3 0 1 2
1 3 2 0
Task
  1. Create a function/routine/procedure/method/... that given n generates a randomised Latin square of size n.
  2. Use the function to generate and show here, two randomly generated squares of size 5.
Note

Strict uniformity in the random generation is a hard problem and not a requirement of the task.

Related tasks
Reference


11l

Translation of: Python
F _transpose(matrix)
   assert(matrix.len == matrix[0].len)
   V r = [[0] * matrix.len] * matrix.len
   L(i) 0 .< matrix.len
      L(j) 0 .< matrix.len
         r[i][j] = matrix[j][i]
   R r

F _shuffle_transpose_shuffle(matrix)
   V square = copy(matrix)
   random:shuffle(&square)
   V trans = _transpose(square)
   random:shuffle(&trans)
   R trans

F _rls(&symbols)
   V n = symbols.len
   I n == 1
      R [symbols]
   E
      V sym = random:choice(symbols)
      symbols.remove(sym)
      V square = _rls(&symbols)
      square.append(copy(square[0]))
      L(i) 0 .< n
         square[i].insert(i, sym)
      R square

F rls(n)
   V symbols = Array(0 .< n)
   V square = _rls(&symbols)
   R _shuffle_transpose_shuffle(square)

F _check_rows(square)
   V set_row0 = Set(square[0])
   R all(square.map(row -> row.len == Set(row).len & Set(row) == @set_row0))

F _check(square)
   V transpose = _transpose(square)
   assert(_check_rows(square) & _check_rows(transpose), ‘Not a Latin square’)

L(i) [3, 3, 5, 5]
   V square = rls(i)
   print(square.map(row -> row.join(‘ ’)).join("\n"))
   _check(square)
   print()
Output:
0 2 1
2 1 0
1 0 2

1 0 2
0 2 1
2 1 0

1 2 0 4 3
4 0 3 2 1
2 3 1 0 4
3 4 2 1 0
0 1 4 3 2

2 4 3 1 0
4 1 2 0 3
3 2 0 4 1
1 0 4 3 2
0 3 1 2 4

Action!

DEFINE PTR="CARD"
DEFINE DIMENSION="5"

TYPE Matrix=[
  PTR data ;BYTE ARRAY
  BYTE dim]

PTR FUNC GetPtr(Matrix POINTER mat BYTE x,y)
RETURN (mat.data+x+y*mat.dim)

PROC PrintMatrix(Matrix POINTER mat)
  BYTE x,y
  BYTE POINTER d

  d=GetPtr(mat,0,0)
  FOR y=0 TO mat.dim-1
  DO
    FOR x=0 TO mat.dim-1
    DO
      PrintB(d^) Put(32)
      d==+1
    OD
    PutE()
  OD
RETURN

PROC KnuthShuffle(BYTE ARRAY tab BYTE size)
  BYTE i,j,tmp

  i=size-1
  WHILE i>0
  DO
    j=Rand(i+1)
    tmp=tab(i)
    tab(i)=tab(j)
    tab(j)=tmp
    i==-1
  OD
RETURN

PROC LatinSquare(Matrix POINTER mat)
  BYTE x,y,yy,shuffled
  BYTE POINTER ptr1,ptr2
  BYTE ARRAY used(DIMENSION)

  ptr1=GetPtr(mat,0,0)
  FOR y=0 TO mat.dim-1
  DO
    FOR x=0 TO mat.dim-1
    DO
      ptr1^=x
      ptr1==+1
    OD
  OD

  ;first row
  ptr1=GetPtr(mat,0,0)
  KnuthShuffle(ptr1,mat.dim)

  ;middle rows
  FOR y=1 TO mat.dim-2
  DO
    shuffled=0
    WHILE shuffled=0
    DO
      ptr1=GetPtr(mat,0,y)
      KnuthShuffle(ptr1,mat.dim)

      shuffled=1
      yy=0
      WHILE shuffled=1 AND yy<y
      DO
        x=0
        WHILE shuffled=1 AND x<mat.dim
        DO
          ptr1=GetPtr(mat,x,yy)
          ptr2=GetPtr(mat,x,y)
          IF ptr1^=ptr2^ THEN
            shuffled=0
          FI
          x==+1
        OD
        yy==+1
      OD
    OD
  OD

  ;last row
  FOR x=0 TO mat.dim-1
  DO
    Zero(used,mat.dim)

    FOR y=0 TO mat.dim-2
    DO
      ptr1=GetPtr(mat,x,y)
      yy=ptr1^ used(yy)=1
    OD

    FOR y=0 TO mat.dim-1
    DO
      IF used(y)=0 THEN
        ptr1=GetPtr(mat,x,mat.dim-1)
        ptr1^=y
        EXIT
      FI
    OD
  OD
RETURN

PROC Main()
  BYTE ARRAY d(25)
  BYTE i
  Matrix mat

  mat.data=d
  mat.dim=DIMENSION

  FOR i=1 TO 2
  DO
    LatinSquare(mat)
    PrintMatrix(mat)
    PutE()
  OD
RETURN
Output:

Screenshot from Atari 8-bit computer

3 1 2 4 0
1 4 0 2 3
4 0 3 1 2
2 3 1 0 4
0 2 4 3 1

2 1 3 4 0
3 0 4 2 1
4 3 1 0 2
1 2 0 3 4
0 4 2 1 3

ALGOL 68

Translation of: Nim

Uses the Knuth Shuffle routine from the Algol 68 sample in the Knuth Shuffle task - modified to shuffle a row in a CHAR matrix.
Generating largish squares can take some time...

BEGIN # generate random latin squares #

    # Knuth Shuffle routine from the Knuth Shuffle Task  #
    #       modified to shufflw a row of a [,]CHAR array #
    PROC knuth shuffle = (REF[,]CHAR a, INT row)VOID:
    (
      PROC between = (INT a, b)INT :
      (
        ENTIER (random * ABS (b-a+1) + (a<b|a|b))
      );
      FOR i FROM LWB a TO UPB a DO
        INT  j = between(LWB a, UPB a);
        CHAR t = a[row, i];
        a[row, i] := a[row, j];
        a[row, j] := t
      OD
    );

    # generates a random latin square #
    PROC latin square = ( INT n )[,]CHAR:
         BEGIN
            [ 1 : n ]CHAR letters;
            [ 1 : n, 1 : n ]CHAR result;
            FOR col TO n DO
                letters[ col ] := REPR ( ABS "A" + ( col - 1 ) )
            OD;
            FOR row TO n DO
                result[ row, : ] := letters
            OD;
            knuth shuffle( result, 1 );
            FOR row FROM 2 TO n - 1 DO
                BOOL ok := FALSE;
                WHILE
                    knuth shuffle( result, row );
                    BOOL all different := TRUE;
                    FOR prev TO row - 1 WHILE all different DO
                        FOR col TO n
                        WHILE all different :=
                                result[ row, col ] /= result[ prev, col ]
                        DO SKIP OD
                    OD;
                    NOT all different
                DO SKIP OD
            OD;
            # the final row, there is only one possibility for each column #
            FOR col TO n DO
                [ 1 : n ]CHAR free := letters;
                FOR row TO n - 1 DO
                    free[ ( ABS result[ row, col ] - ABS "A" ) + 1 ] := REPR 0
                OD;
                BOOL found := FALSE;
                FOR row FROM 1 LWB result TO 1 UPB result WHILE NOT found DO
                    IF free[ row ] /= REPR 0 THEN
                        found := TRUE;
                        result[ n, col ] := free[ row ]
                    FI
                OD
            OD;
            result
         END # latin suare # ;

    # prints a latin square #
    PROC print square = ( [,]CHAR square )VOID:
         FOR row FROM 1 LWB square TO 1 UPB square DO
             IF 2 LWB square <= 2 UPB square THEN
                 print( ( square[ row, 2 LWB square ] ) );
                 FOR col FROM 2 LWB square + 1 TO 2 UPB square DO
                     print( ( " ", square[ row, col ] ) )
                 OD;
                 print( ( newline ) )
             FI
         OD # print square # ;

    next random;
    print square( latin square(  5 ) );
    print( ( newline ) );
    print square( latin square(  5 ) );
    print( ( newline ) );
    print square( latin square( 10 ) )

END
Output:
A C D B E
C A B E D
D E A C B
E B C D A
B D E A C

A B E C D
B E D A C
E C B D A
D A C E B
C D A B E

A C D J F G I B E H
D F H G E A B J C I
H E C I B J A F G D
B I G A C H J D F E
E J I F H C D G B A
I D B C G F H E A J
C H F B J I E A D G
G B J D A E F I H C
J G A E D B C H I F
F A E H I D G C J B

Arturo

latinSquare: function [n][
    square: new []
    variants: shuffle permutate 0..n-1
    while -> n > size square [
        row: sample variants
        'square ++ @[row]
        filter 'variants 'variant [
            reject: false
            loop.with:'i variant 'col [
                if col = row\[i] ->
                    reject: true
            ]
            reject
        ]
    ]
    return square
]

loop 2 'x [
    ls: latinSquare 5
    loop ls 'row ->
        print row
    print "---------"
]
Output:
2 4 0 1 3 
3 0 2 4 1 
4 3 1 0 2 
1 2 4 3 0 
0 1 3 2 4 
---------
3 2 1 4 0 
2 1 4 0 3 
4 3 0 2 1 
1 0 2 3 4 
0 4 3 1 2

C

Translation of: C++
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// low <= num < high
int randInt(int low, int high) {
    return (rand() % (high - low)) + low;
}

// shuffle an array of n elements
void shuffle(int *const array, const int n) {
    if (n > 1) {
        int i;
        for (i = 0; i < n - 1; i++) {
            int j = randInt(i, n);

            int t = array[i];
            array[i] = array[j];
            array[j] = t;
        }
    }
}

// print an n * n array
void printSquare(const int *const latin, const int n) {
    int i, j;
    for (i = 0; i < n; i++) {
        printf("[");
        for (j = 0; j < n; j++) {
            if (j > 0) {
                printf(", ");
            }
            printf("%d", latin[i * n + j]);
        }
        printf("]\n");
    }
    printf("\n");
}

void latinSquare(const int n) {
    int *latin, *used;
    int i, j, k;

    if (n <= 0) {
        printf("[]\n");
        return;
    }

    // allocate
    latin = (int *)malloc(n * n * sizeof(int));
    if (!latin) {
        printf("Failed to allocate memory.");
        return;
    }

    // initialize
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            latin[i * n + j] = j;
        }
    }

    // first row
    shuffle(latin, n);

    // middle row(s)
    for (i = 1; i < n - 1; i++) {
        bool shuffled = false;

        while (!shuffled) {
            shuffle(&latin[i * n], n);

            for (k = 0; k < i; k++) {
                for (j = 0; j < n; j++) {
                    if (latin[k * n + j] == latin[i * n + j]) {
                        goto shuffling;
                    }
                }
            }
            shuffled = true;

        shuffling: {}
        }
    }

    //last row
    used = (int *)malloc(n * sizeof(int));
    for (j = 0; j < n; j++) {
        memset(used, 0, n * sizeof(int));
        for (i = 0; i < n - 1; i++) {
            used[latin[i * n + j]] = 1;
        }
        for (k = 0; k < n; k++) {
            if (used[k] == 0) {
                latin[(n - 1) * n + j] = k;
                break;
            }
        }
    }
    free(used);

    // print the result
    printSquare(latin, n);
    free(latin);
}

int main() {
    // initialze the random number generator
    srand((unsigned int)time((time_t)0));

    latinSquare(5);
    latinSquare(5);
    latinSquare(10);

    return 0;
}
Output:
[1, 4, 3, 0, 2]
[3, 1, 0, 2, 4]
[2, 3, 4, 1, 0]
[4, 0, 2, 3, 1]
[0, 2, 1, 4, 3]

[0, 2, 4, 1, 3]
[1, 3, 0, 4, 2]
[4, 0, 3, 2, 1]
[3, 1, 2, 0, 4]
[2, 4, 1, 3, 0]

[6, 8, 2, 1, 4, 7, 3, 9, 5, 0]
[8, 7, 3, 2, 0, 1, 6, 5, 4, 9]
[1, 3, 5, 6, 7, 9, 4, 0, 2, 8]
[2, 5, 1, 9, 8, 0, 7, 4, 3, 6]
[4, 9, 8, 5, 6, 2, 0, 1, 7, 3]
[9, 6, 7, 8, 2, 4, 1, 3, 0, 5]
[7, 2, 9, 0, 3, 6, 5, 8, 1, 4]
[3, 1, 0, 4, 5, 8, 2, 6, 9, 7]
[5, 0, 4, 7, 9, 3, 8, 2, 6, 1]
[0, 4, 6, 3, 1, 5, 9, 7, 8, 2]

C++

Translation of: Java
#include <algorithm>
#include <chrono>
#include <iostream>
#include <random>
#include <vector>

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    auto it = v.cbegin();
    auto end = v.cend();

    os << '[';
    if (it != end) {
        os << *it;
        it = std::next(it);
    }
    while (it != end) {
        os << ", ";
        os << *it;
        it = std::next(it);
    }
    return os << ']';
}

void printSquare(const std::vector<std::vector<int>> &latin) {
    for (auto &row : latin) {
        std::cout << row << '\n';
    }
    std::cout << '\n';
}

void latinSquare(int n) {
    if (n <= 0) {
        std::cout << "[]\n";
        return;
    }

    // obtain a time-based seed:
    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
    auto g = std::default_random_engine(seed);

    std::vector<std::vector<int>> latin;
    for (int i = 0; i < n; ++i) {
        std::vector<int> inner;
        for (int j = 0; j < n; ++j) {
            inner.push_back(j);
        }
        latin.push_back(inner);
    }
    // first row
    std::shuffle(latin[0].begin(), latin[0].end(), g);

    // middle row(s)
    for (int i = 1; i < n - 1; ++i) {
        bool shuffled = false;

        while (!shuffled) {
            std::shuffle(latin[i].begin(), latin[i].end(), g);
            for (int k = 0; k < i; ++k) {
                for (int j = 0; j < n; ++j) {
                    if (latin[k][j] == latin[i][j]) {
                        goto shuffling;
                    }
                }
            }
            shuffled = true;

        shuffling: {}
        }
    }

    // last row
    for (int j = 0; j < n; ++j) {
        std::vector<bool> used(n, false);
        for (int i = 0; i < n - 1; ++i) {
            used[latin[i][j]] = true;
        }
        for (int k = 0; k < n; ++k) {
            if (!used[k]) {
                latin[n - 1][j] = k;
                break;
            }
        }
    }

    printSquare(latin);
}

int main() {
    latinSquare(5);
    latinSquare(5);
    latinSquare(10);
    return 0;
}
Output:
[4, 3, 1, 2, 0]
[1, 0, 3, 4, 2]
[3, 2, 0, 1, 4]
[2, 1, 4, 0, 3]
[0, 4, 2, 3, 1]

[2, 4, 0, 3, 1]
[0, 3, 4, 1, 2]
[3, 0, 1, 2, 4]
[1, 2, 3, 4, 0]
[4, 1, 2, 0, 3]

[9, 3, 5, 0, 8, 2, 7, 1, 6, 4]
[0, 9, 4, 6, 1, 8, 5, 3, 7, 2]
[4, 1, 9, 7, 3, 5, 2, 0, 8, 6]
[2, 6, 8, 3, 4, 0, 9, 7, 1, 5]
[6, 5, 3, 4, 7, 9, 1, 8, 2, 0]
[1, 8, 6, 5, 2, 4, 0, 9, 3, 7]
[7, 2, 0, 8, 9, 1, 4, 6, 5, 3]
[3, 0, 7, 1, 5, 6, 8, 2, 4, 9]
[8, 4, 2, 9, 6, 7, 3, 5, 0, 1]
[5, 7, 1, 2, 0, 3, 6, 4, 9, 8]

C#

Translation of: Kotlin
using System;
using System.Collections.Generic;

namespace RandomLatinSquares {
    using Matrix = List<List<int>>;

    // Taken from https://stackoverflow.com/a/1262619
    static class Helper {
        private static readonly Random rng = new Random();

        public static void Shuffle<T>(this IList<T> list) {
            int n = list.Count;
            while (n > 1) {
                n--;
                int k = rng.Next(n + 1);
                T value = list[k];
                list[k] = list[n];
                list[n] = value;
            }
        }
    }

    class Program {
        static void PrintSquare(Matrix latin) {
            foreach (var row in latin) {
                Console.Write('[');

                var it = row.GetEnumerator();
                if (it.MoveNext()) {
                    Console.Write(it.Current);
                }
                while (it.MoveNext()) {
                    Console.Write(", ");
                    Console.Write(it.Current);
                }

                Console.WriteLine(']');
            }
            Console.WriteLine();
        }

        static void LatinSquare(int n) {
            if (n <= 0) {
                Console.WriteLine("[]");
                return;
            }

            var latin = new Matrix();
            for (int i = 0; i < n; i++) {
                List<int> temp = new List<int>();
                for (int j = 0; j < n; j++) {
                    temp.Add(j);
                }
                latin.Add(temp);
            }
            // first row
            latin[0].Shuffle();

            // middle row(s)
            for (int i = 1; i < n - 1; i++) {
                bool shuffled = false;

                while (!shuffled) {
                    latin[i].Shuffle();
                    for (int k = 0; k < i; k++) {
                        for (int j = 0; j < n; j++) {
                            if (latin[k][j] == latin[i][j]) {
                                goto shuffling;
                            }
                        }
                    }
                    shuffled = true;

                shuffling: { }
                }
            }

            // last row
            for (int j = 0; j < n; j++) {
                List<bool> used = new List<bool>();
                for (int i = 0; i < n; i++) {
                    used.Add(false);
                }

                for (int i = 0; i < n-1; i++) {
                    used[latin[i][j]] = true;
                }
                for (int k = 0; k < n; k++) {
                    if (!used[k]) {
                        latin[n - 1][j] = k;
                        break;
                    }
                }
            }

            PrintSquare(latin);
        }

        static void Main() {
            LatinSquare(5);
            LatinSquare(5);
            LatinSquare(10); // for good measure
        }
    }
}
Output:
[3, 0, 1, 4, 2]
[4, 2, 3, 1, 0]
[2, 1, 4, 0, 3]
[0, 4, 2, 3, 1]
[1, 3, 0, 2, 4]

[4, 0, 2, 3, 1]
[2, 1, 4, 0, 3]
[0, 4, 3, 1, 2]
[3, 2, 1, 4, 0]
[1, 3, 0, 2, 4]

[5, 9, 4, 2, 0, 3, 8, 6, 1, 7]
[7, 1, 3, 9, 6, 2, 4, 0, 8, 5]
[1, 8, 6, 3, 4, 0, 9, 5, 7, 2]
[9, 0, 1, 4, 2, 7, 3, 8, 5, 6]
[6, 7, 8, 0, 5, 1, 2, 3, 9, 4]
[8, 2, 7, 5, 3, 4, 1, 9, 6, 0]
[2, 4, 5, 6, 8, 9, 0, 7, 3, 1]
[4, 5, 9, 8, 1, 6, 7, 2, 0, 3]
[0, 3, 2, 7, 9, 5, 6, 1, 4, 8]
[3, 6, 0, 1, 7, 8, 5, 4, 2, 9]

D

Translation of: C#
import std.array;
import std.random;
import std.stdio;

alias Matrix = int[][];

void latinSquare(int n) {
    if (n <= 0) {
        writeln("[]");
        return;
    }

    Matrix latin = uninitializedArray!Matrix(n, n);
    foreach (row; latin) {
        for (int i = 0; i < n; i++) {
            row[i] = i;
        }
    }
    // first row
    latin[0].randomShuffle;

    // middle row(s)
    for (int i = 1; i < n - 1; i++) {
        bool shuffled = false;

        shuffling:
        while (!shuffled) {
            latin[i].randomShuffle;
            for (int k = 0; k < i; k++) {
                for (int j = 0; j < n; j++) {
                    if (latin[k][j] == latin[i][j]) {
                        continue shuffling;
                    }
                }
            }
            shuffled = true;
        }
    }

    // last row
    for (int j = 0; j < n; j++) {
        bool[] used = uninitializedArray!(bool[])(n);
        used[] = false;

        for (int i = 0; i < n - 1; i++) {
            used[latin[i][j]] = true;
        }
        for (int k = 0; k < n; k++) {
            if (!used[k]) {
                latin[n - 1][j] = k;
                break;
            }
        }
    }

    printSquare(latin);
}

void printSquare(Matrix latin) {
    foreach (row; latin) {
        writeln(row);
    }
}

void main() {
    latinSquare(5);
    writeln;

    latinSquare(5);
    writeln;

    latinSquare(10);
}
Output:
[2, 4, 3, 1, 0]
[1, 0, 2, 3, 4]
[0, 1, 4, 2, 3]
[3, 2, 0, 4, 1]
[4, 3, 1, 0, 2]

[4, 1, 0, 3, 2]
[3, 4, 1, 2, 0]
[0, 2, 3, 1, 4]
[1, 0, 2, 4, 3]
[2, 3, 4, 0, 1]

[3, 5, 1, 9, 4, 2, 7, 0, 8, 6]
[6, 2, 7, 8, 3, 9, 1, 4, 5, 0]
[0, 4, 3, 6, 7, 8, 2, 5, 9, 1]
[8, 3, 0, 5, 9, 7, 4, 1, 6, 2]
[2, 8, 9, 0, 6, 1, 5, 3, 7, 4]
[5, 6, 8, 1, 2, 0, 9, 7, 4, 3]
[4, 1, 2, 3, 8, 5, 6, 9, 0, 7]
[1, 9, 4, 7, 0, 6, 8, 2, 3, 5]
[7, 0, 6, 2, 5, 4, 3, 8, 1, 9]
[9, 7, 5, 4, 1, 3, 0, 6, 2, 8]

EasyLang

Translation of: Kotlin
proc shuffle . a[] .
   for i = len a[] downto 2
      r = randint i
      swap a[r] a[i]
   .
.
proc prsquare . lat[][] .
   n = len lat[][]
   for i to n
      for j to n
         write lat[i][j] & " "
      .
      print ""
   .
   print ""
.
proc square n . .
   for i to n
      lat[][] &= [ ]
      for j to n
         lat[i][] &= j
      .
   .
   shuffle lat[1][]
   for i = 2 to n - 1
      repeat
         shuffle lat[i][]
         for k to i - 1
            for j to n
               if lat[k][j] = lat[i][j]
                  break 2
               .
            .
         .
         until k = i
      .
   .
   len used0[] n
   for j to n
      used[] = used0[]
      for i to n - 1
         used[lat[i][j]] = 1
      .
      for k to n
         if used[k] = 0
            lat[n][j] = k
            break 1
         .
      .
   .
   prsquare lat[][]
.
square 5
square 5
Output:
1 5 4 2 3 
3 4 2 1 5 
2 1 5 3 4 
5 3 1 4 2 
4 2 3 5 1 

3 5 1 4 2 
2 1 4 3 5 
5 2 3 1 4 
4 3 2 5 1 
1 4 5 2 3 

F#

This solution uses functions from Factorial_base_numbers_indexing_permutations_of_a_collection#F.23 and Latin_Squares_in_reduced_form#F.23. It has been alleged that this solution generates completely random uniformly distributed Latin Squares from all possible Latin Squares of order 5. It takes 5 thousandths of a second to do so.

// Generate 2 Random Latin Squares of order 5. Nigel Galloway: July 136th., 2019
let N=let N=System.Random() in (fun n->N.Next(n))
let rc()=let β=lN2p [|0;N 4;N 3;N 2|] [|0..4|] in Seq.item (N 56) (normLS 5) |> List.map(lN2p [|N 5;N 4;N 3;N 2|]) |> List.permute(fun n->β.[n]) |> List.iter(printfn "%A")
rc(); printfn ""; rc()
Output:
[|5; 3; 1; 4; 2|]
[|1; 4; 5; 2; 3|]
[|4; 1; 2; 3; 5|]
[|2; 5; 3; 1; 4|]
[|3; 2; 4; 5; 1|]

[|4; 1; 2; 5; 3|]
[|3; 5; 1; 2; 4|]
[|2; 4; 5; 3; 1|]
[|1; 2; 3; 4; 5|]
[|5; 3; 4; 1; 2|]

I thought some statistics might be interesting so I generated 1 million Latin Squares of order 5. There are 161280 possible Latin Squares of which 3174 were not generated. The remainder were generated:

Times Generated    Number of Latin Squares
     1                       1776
     2                       5669
     3                      11985
     4                      19128
     5                      24005
     6                      25333
     7                      22471
     8                      18267
     9                      12569
    10                       7924
    11                       4551
    12                       2452
    13                       1130
    14                        483
    15                        219
    16                         93
    17                         37
    18                          5
    19                          7
    20                          2

Factor

A brute force method for generating Latin squares with uniform randomness from the relevant population. Repeatedly select a random permutation of (0, 1,...n-1) and add it as the next row of the square. If at any point the rules for being a Latin square are violated, start the entire process over again from the beginning.

USING: arrays combinators.extras fry io kernel math.matrices
prettyprint random sequences sets ;
IN: rosetta-code.random-latin-squares

: rand-permutation ( n -- seq ) <iota> >array randomize ;
: ls? ( n -- ? ) [ all-unique? ] column-map t [ and ] reduce ;
: (ls) ( n -- m ) dup '[ _ rand-permutation ] replicate ;
: ls ( n -- m ) dup (ls) dup ls? [ nip ] [ drop ls ] if ;
: random-latin-squares ( -- ) [ 5 ls simple-table. nl ] twice ;

MAIN: random-latin-squares
Output:
0 4 3 2 1
3 0 2 1 4
4 2 1 3 0
2 1 4 0 3
1 3 0 4 2

4 0 1 3 2
0 2 4 1 3
1 3 0 2 4
2 4 3 0 1
3 1 2 4 0

FreeBASIC

Translation of: Wren

Restarting Row method

Randomize Timer

Sub printSquare(latin() As Integer, n As Integer)
    For i As Integer = 0 To n - 1
        Print "[";
        For j As Integer = 0 To n - 1
            Print latin(i, j); ",";
        Next j
        Print Chr(8); " ]"
    Next i
    Print
End Sub

Sub latinSquare(n As Integer)
    Dim As Integer i, j, k
    
    If n <= 0 Then
        Print "[]"
        Exit Sub
    End If
    Dim latin(n - 1, n - 1) As Integer
    For i = 0 To n - 1
        For j = 0 To n - 1
            latin(i, j) = j
        Next j
    Next i
    
    ' first row
    For i = 0 To n - 1
        Dim j As Integer = Int(Rnd * n)
        Swap latin(0, i), latin(0, j)
    Next i
    
    ' middle row(s)
    For i = 1 To n - 2
        Dim shuffled As Integer = 0
        While shuffled = 0
            For j = 0 To n - 1
                Dim k As Integer = Int(Rnd * n)
                Swap latin(i, j), latin(i, k)
            Next j
            shuffled = 1
            For k As Integer = 0 To i - 1
                For j = 0 To n - 1
                    If latin(k, j) = latin(i, j) Then
                        shuffled = 0
                        Exit For
                    End If
                Next j
                If shuffled = 0 Then Exit For
            Next k
        Wend
    Next i
    
    ' last row
    For j = 0 To n - 1
        Dim used(n - 1) As Integer
        For i = 0 To n - 2
            used(latin(i, j)) = 1
        Next i
        For k = 0 To n - 1
            If used(k) = 0 Then
                latin(n - 1, j) = k
                Exit For
            End If
        Next k
    Next j
    printSquare(latin(), n)
End Sub

latinSquare(5)
latinSquare(5)
latinSquare(10) ' for good measure

Sleep

Go

Restarting Row method

As the task is not asking for large squares to be generated and even n = 10 is virtually instant, we use a simple brute force approach here known as the 'Restarting Row' method (see Talk page). However, whilst easy to understand, this method does not produce uniformly random squares.

package main

import (
    "fmt"
    "math/rand"
    "time"
)

type matrix [][]int

func shuffle(row []int, n int) {
    rand.Shuffle(n, func(i, j int) {
        row[i], row[j] = row[j], row[i]
    })
}

func latinSquare(n int) {
    if n <= 0 {
        fmt.Println("[]\n")
        return
    }
    latin := make(matrix, n)
    for i := 0; i < n; i++ {
        latin[i] = make([]int, n)
        if i == n-1 {
            break
        }
        for j := 0; j < n; j++ {
            latin[i][j] = j
        }
    }
    // first row
    shuffle(latin[0], n)

    // middle row(s)
    for i := 1; i < n-1; i++ {
        shuffled := false
    shuffling:
        for !shuffled {
            shuffle(latin[i], n)
            for k := 0; k < i; k++ {
                for j := 0; j < n; j++ {
                    if latin[k][j] == latin[i][j] {
                        continue shuffling
                    }
                }
            }
            shuffled = true
        }
    }

    // last row
    for j := 0; j < n; j++ {
        used := make([]bool, n)
        for i := 0; i < n-1; i++ {
            used[latin[i][j]] = true
        }
        for k := 0; k < n; k++ {
            if !used[k] {
                latin[n-1][j] = k
                break
            }
        }
    }
    printSquare(latin, n)
}

func printSquare(latin matrix, n int) {
    for i := 0; i < n; i++ {
        fmt.Println(latin[i])
    }
    fmt.Println()
}

func main() {
    rand.Seed(time.Now().UnixNano())
    latinSquare(5)
    latinSquare(5)
    latinSquare(10) // for good measure
}
Output:

Sample run:

[3 2 1 0 4]
[0 3 2 4 1]
[4 1 0 3 2]
[2 4 3 1 0]
[1 0 4 2 3]

[3 1 0 4 2]
[1 0 2 3 4]
[2 4 3 0 1]
[4 3 1 2 0]
[0 2 4 1 3]

[9 2 8 4 6 1 7 5 0 3]
[4 3 7 6 0 8 5 9 2 1]
[2 1 9 7 3 4 6 0 5 8]
[8 6 0 5 7 2 3 1 9 4]
[5 0 6 8 1 3 9 2 4 7]
[7 5 4 9 2 0 1 3 8 6]
[3 9 2 1 5 6 8 4 7 0]
[1 4 5 2 8 7 0 6 3 9]
[6 8 3 0 4 9 2 7 1 5]
[0 7 1 3 9 5 4 8 6 2]

Latin Squares in Reduced Form method

Unlike the "Restarting Row" method, this method does produce uniformly random Latin squares for n <= 6 (see Talk page) but is more involved and therefore slower. It reuses some (suitably adjusted) code from the Latin Squares in Reduced Form and Permutations tasks.

package main

import (
    "fmt"
    "math/rand"
    "sort"
    "time"
)

type matrix [][]int

// generate derangements of first n numbers, with 'start' in first place.
func dList(n, start int) (r matrix) {
    start-- // use 0 basing
    a := make([]int, n)
    for i := range a {
        a[i] = i
    }
    a[0], a[start] = start, a[0]
    sort.Ints(a[1:])
    first := a[1]
    // recursive closure permutes a[1:]
    var recurse func(last int)
    recurse = func(last int) {
        if last == first {
            // bottom of recursion.  you get here once for each permutation.
            // test if permutation is deranged.
            for j, v := range a[1:] { // j starts from 0, not 1
                if j+1 == v {
                    return // no, ignore it
                }
            }
            // yes, save a copy
            b := make([]int, n)
            copy(b, a)
            for i := range b {
                b[i]++ // change back to 1 basing
            }
            r = append(r, b)
            return
        }
        for i := last; i >= 1; i-- {
            a[i], a[last] = a[last], a[i]
            recurse(last - 1)
            a[i], a[last] = a[last], a[i]
        }
    }
    recurse(n - 1)
    return
}

func reducedLatinSquares(n int) []matrix {
    var rls []matrix
    if n < 0 {
        n = 0
    }
    rlatin := make(matrix, n)
    for i := 0; i < n; i++ {
        rlatin[i] = make([]int, n)
    }
    if n <= 1 {
        return append(rls, rlatin)
    }
    // first row
    for j := 0; j < n; j++ {
        rlatin[0][j] = j + 1
    }
    // recursive closure to compute reduced latin squares
    var recurse func(i int)
    recurse = func(i int) {
        rows := dList(n, i) // get derangements of first n numbers, with 'i' first.
    outer:
        for r := 0; r < len(rows); r++ {
            copy(rlatin[i-1], rows[r])
            for k := 0; k < i-1; k++ {
                for j := 1; j < n; j++ {
                    if rlatin[k][j] == rlatin[i-1][j] {
                        if r < len(rows)-1 {
                            continue outer
                        } else if i > 2 {
                            return
                        }
                    }
                }
            }
            if i < n {
                recurse(i + 1)
            } else {
                rl := copyMatrix(rlatin)
                rls = append(rls, rl)
            }
        }
        return
    }

    // remaining rows
    recurse(2)
    return rls
}

func copyMatrix(m matrix) matrix {
    le := len(m)
    cpy := make(matrix, le)
    for i := 0; i < le; i++ {
        cpy[i] = make([]int, le)
        copy(cpy[i], m[i])
    }
    return cpy
}

func printSquare(latin matrix, n int) {
    for i := 0; i < n; i++ {
        for j := 0; j < n; j++ {
            fmt.Printf("%d ", latin[i][j]-1)
        }
        fmt.Println()
    }
    fmt.Println()
}

func factorial(n uint64) uint64 {
    if n == 0 {
        return 1
    }
    prod := uint64(1)
    for i := uint64(2); i <= n; i++ {
        prod *= i
    }
    return prod
}

// generate permutations of first n numbers, starting from 0.
func pList(n int) matrix {
    fact := factorial(uint64(n))
    perms := make(matrix, fact)
    a := make([]int, n)
    for i := 0; i < n; i++ {
        a[i] = i
    }
    t := make([]int, n)
    copy(t, a)
    perms[0] = t
    n--
    var i, j int
    for c := uint64(1); c < fact; c++ {
        i = n - 1
        j = n
        for a[i] > a[i+1] {
            i--
        }
        for a[j] < a[i] {
            j--
        }
        a[i], a[j] = a[j], a[i]
        j = n
        i++
        for i < j {
            a[i], a[j] = a[j], a[i]
            i++
            j--
        }
        t := make([]int, n+1)
        copy(t, a)
        perms[c] = t
    }
    return perms
}

func generateLatinSquares(n, tests, echo int) {   
    rls := reducedLatinSquares(n)
    perms := pList(n)
    perms2 := pList(n - 1)
    for test := 0; test < tests; test++ {
        rn := rand.Intn(len(rls))
        rl := rls[rn] // select reduced random square at random
        rn = rand.Intn(len(perms))
        rp := perms[rn] // select a random permuation of 'rl's columns
        // permute columns
        t := make(matrix, n)
        for i := 0; i < n; i++ {
            t[i] = make([]int, n)
        }
        for i := 0; i < n; i++ {
            for j := 0; j < n; j++ {
                t[i][j] = rl[i][rp[j]]
            }
        }
        rn = rand.Intn(len(perms2))
        rp = perms2[rn] // select a random permutation of 't's rows 2 to n
        // permute rows 2 to n
        u := make(matrix, n)
        for i := 0; i < n; i++ {
            u[i] = make([]int, n)
        }
        for i := 0; i < n; i++ {
            for j := 0; j < n; j++ {
                if i == 0 {
                    u[i][j] = t[i][j]
                } else {
                    u[i][j] = t[rp[i-1]+1][j]
                }
            }
        }
        if test < echo {
            printSquare(u, n)
        }
        if n == 4 {
            for i := 0; i < 4; i++ {
                for j := 0; j < 4; j++ {
                    u[i][j]--
                }
            }
            for i := 0; i < 4; i++ {
                copy(a[4*i:], u[i])
            }
            for i := 0; i < 4; i++ {
                if testSquares[i] == a {
                    counts[i]++
                    break
                }
            }
        }
    }
}

var testSquares = [4][16]int{
    {0, 1, 2, 3, 1, 0, 3, 2, 2, 3, 0, 1, 3, 2, 1, 0},
    {0, 1, 2, 3, 1, 0, 3, 2, 2, 3, 1, 0, 3, 2, 0, 1},
    {0, 1, 2, 3, 1, 2, 3, 0, 2, 3, 0, 1, 3, 0, 1, 2},
    {0, 1, 2, 3, 1, 3, 0, 2, 2, 0, 3, 1, 3, 2, 1, 0},
}

var (
    counts [4]int
    a      [16]int
)

func main() {
    rand.Seed(time.Now().UnixNano())
    fmt.Println("Two randomly generated latin squares of order 5 are:\n")
    generateLatinSquares(5, 2, 2)

    fmt.Println("Out of 1,000,000 randomly generated latin squares of order 4, ")
    fmt.Println("of which there are 576 instances ( => expected 1736 per instance),")
    fmt.Println("the following squares occurred the number of times shown:\n")
    generateLatinSquares(4, 1e6, 0)
    for i := 0; i < 4; i++ {
        fmt.Println(testSquares[i][:], ":", counts[i])
    }

    fmt.Println("\nA randomly generated latin square of order 6 is:\n")
    generateLatinSquares(6, 1, 1)
}
Output:

Sample run:

Two randomly generated latin squares of order 5 are:

2 1 3 4 0 
4 3 0 1 2 
1 0 2 3 4 
0 4 1 2 3 
3 2 4 0 1 

1 2 3 4 0 
0 3 4 2 1 
2 4 0 1 3 
4 0 1 3 2 
3 1 2 0 4 

Out of 1,000,000 randomly generated latin squares of order 4, 
of which there are 576 instances ( => expected 1736 per instance),
the following squares occurred the number of times shown:

[0 1 2 3 1 0 3 2 2 3 0 1 3 2 1 0] : 1737
[0 1 2 3 1 0 3 2 2 3 1 0 3 2 0 1] : 1736
[0 1 2 3 1 2 3 0 2 3 0 1 3 0 1 2] : 1726
[0 1 2 3 1 3 0 2 2 0 3 1 3 2 1 0] : 1799

A randomly generated latin square of order 6 is:

3 5 1 0 4 2 
2 0 5 4 1 3 
0 4 2 5 3 1 
1 3 4 2 0 5 
5 1 0 3 2 4 
4 2 3 1 5 0 

Haskell

Pure functional Haskell encourages programmer to separate randomness and deterministic business logic. So first we determine a function which returns a Latin square which is built according to given first row and first column.

import Data.List (permutations, (\\))

latinSquare :: Eq a => [a] -> [a] -> [[a]]
latinSquare [] [] = []
latinSquare c r
  | head r /= head c = []
  | otherwise = reverse <$> foldl addRow firstRow perms
  where
    -- permutations grouped by the first element
    perms =
      tail $
        fmap
          (fmap . (:) <*> (permutations . (r \\) . return))
          c
    firstRow = pure <$> r
    addRow tbl rows =
      head
        [ zipWith (:) row tbl
          | row <- rows,
            and $ different (tail row) (tail tbl)
        ]
    different = zipWith $ (not .) . elem

printTable :: Show a => [[a]] -> IO ()
printTable tbl =
  putStrLn $
    unlines $
      unwords . map show <$> tbl
λ> printTable $ latinSquare [1,2,3,4,5] [1,3,2,5,4]
1 2 3 4 5
3 4 1 5 2
2 5 4 3 1
5 3 2 1 4

Now whatever random generator is used, the construction of a random Latin square may be done by feeding two appropriate random permutations to the deterministic algorithm.

randomLatinSquare :: Eq a => [a] -> Random [[a]]
randomLatinSquare set = do
  r <- randomPermutation set
  c <- randomPermutation (tail r)
  return $ latinSquare r (head r:c)

For examples a naive linear congruent method in a State monad is used.

import Control.Monad.State

type Random a = State Int a

random :: Integral a => a -> Random a
random k = rescale <$> modify iter 
  where
    iter x = (x * a + c) `mod` m
    (a, c, m) = (1103515245, 12345, 2^31-1)
    rescale x = fromIntegral x `mod` k

randomPermutation :: Eq a => [a] -> Random [a]
randomPermutation = go
  where
    go [] = pure []
    go lst = do
      x <- randomSample lst
      (x :) <$> go (lst \\ [x])

randomSample :: [a] -> Random a
randomSample lst = (lst !!) <$> random (length lst)
λ> printTable $ randomLatinSquare [0..4] `evalState` 42
3 2 0 1 4
0 1 4 3 2
1 4 3 2 0
2 0 1 4 3
4 3 2 0 1

λ> printTable $ randomLatinSquare [0..9] `evalState` 42
8 5 6 1 7 2 4 0 9 3
5 9 4 0 6 8 3 1 7 2
6 0 8 2 3 5 9 7 1 4
7 1 5 3 8 4 0 9 2 6
3 2 7 8 9 0 5 4 6 1
2 4 3 9 5 1 7 6 8 0
1 3 2 7 4 9 6 8 0 5
0 7 1 6 2 3 8 5 4 9
9 6 0 4 1 7 2 3 5 8
4 8 9 5 0 6 1 2 3 7

J

rls=: 3 : 0
  s=. ?~ y             NB. "deal" y unique integers from 0 to y
  for_ijk. i.<:y do.
    NB. deal a new row. subtract it from all previous rows
    NB. if you get a 0, some column has a matching integer, deal again
    whilst. 0 = */ */ s -"1 r do. 
      r=. ?~ y 
    end.
    s=. s ,,: r        NB. "laminate" successful row to the square 
  end.
)
Output:
   rls 5
4 0 1 2 3
3 1 4 0 2
2 3 0 4 1
0 2 3 1 4
1 4 2 3 0
   rls 5
0 4 2 1 3
4 1 3 2 0
1 0 4 3 2
2 3 1 0 4
3 2 0 4 1

Java

Translation of: Kotlin
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

public class RandomLatinSquares {
    private static void printSquare(List<List<Integer>> latin) {
        for (List<Integer> row : latin) {
            Iterator<Integer> it = row.iterator();

            System.out.print("[");
            if (it.hasNext()) {
                Integer col = it.next();
                System.out.print(col);
            }
            while (it.hasNext()) {
                Integer col = it.next();
                System.out.print(", ");
                System.out.print(col);
            }
            System.out.println("]");
        }
        System.out.println();
    }

    private static void latinSquare(int n) {
        if (n <= 0) {
            System.out.println("[]");
            return;
        }

        List<List<Integer>> latin = new ArrayList<>(n);
        for (int i = 0; i < n; ++i) {
            List<Integer> inner = new ArrayList<>(n);
            for (int j = 0; j < n; ++j) {
                inner.add(j);
            }
            latin.add(inner);
        }
        // first row
        Collections.shuffle(latin.get(0));

        // middle row(s)
        for (int i = 1; i < n - 1; ++i) {
            boolean shuffled = false;
            shuffling:
            while (!shuffled) {
                Collections.shuffle(latin.get(i));
                for (int k = 0; k < i; ++k) {
                    for (int j = 0; j < n; ++j) {
                        if (Objects.equals(latin.get(k).get(j), latin.get(i).get(j))) {
                            continue shuffling;
                        }
                    }
                }
                shuffled = true;
            }
        }

        // last row
        for (int j = 0; j < n; ++j) {
            List<Boolean> used = new ArrayList<>(n);
            for (int i = 0; i < n; ++i) {
                used.add(false);
            }
            for (int i = 0; i < n - 1; ++i) {
                used.set(latin.get(i).get(j), true);
            }
            for (int k = 0; k < n; ++k) {
                if (!used.get(k)) {
                    latin.get(n - 1).set(j, k);
                    break;
                }
            }
        }

        printSquare(latin);
    }

    public static void main(String[] args) {
        latinSquare(5);
        latinSquare(5);
        latinSquare(10);
    }
}
Output:
[1, 3, 4, 0, 2]
[4, 0, 2, 1, 3]
[0, 2, 1, 3, 4]
[2, 1, 3, 4, 0]
[3, 4, 0, 2, 1]

[4, 2, 1, 3, 0]
[2, 1, 3, 0, 4]
[0, 3, 2, 4, 1]
[3, 4, 0, 1, 2]
[1, 0, 4, 2, 3]

[8, 7, 9, 0, 1, 2, 6, 5, 4, 3]
[4, 6, 3, 8, 0, 5, 2, 9, 1, 7]
[2, 1, 0, 4, 8, 9, 7, 3, 5, 6]
[6, 4, 8, 1, 9, 7, 3, 0, 2, 5]
[7, 9, 2, 6, 5, 3, 4, 8, 0, 1]
[9, 5, 1, 3, 2, 6, 8, 4, 7, 0]
[5, 0, 4, 9, 6, 8, 1, 7, 3, 2]
[3, 8, 5, 2, 7, 1, 0, 6, 9, 4]
[1, 3, 6, 7, 4, 0, 5, 2, 8, 9]
[0, 2, 7, 5, 3, 4, 9, 1, 6, 8]

JavaScript

class Latin {
  constructor(size = 3) {
    this.size = size;
    this.mst = [...Array(this.size)].map((v, i) => i + 1);
    this.square = Array(this.size).fill(0).map(() => Array(this.size).fill(0));

    if (this.create(0, 0)) {
      console.table(this.square);
    }
  }

  create(c, r) {
    const d = [...this.mst];
    let s;
    while (true) {
      do {
        s = d.splice(Math.floor(Math.random() * d.length), 1)[0];
        if (!s) return false;
      } while (this.check(s, c, r));

      this.square[c][r] = s;
      if (++c >= this.size) {
        c = 0;
        if (++r >= this.size) {
          return true;
        }
      }
      if (this.create(c, r)) return true;
      if (--c < 0) {
        c = this.size - 1;
        if (--r < 0) {
          return false;
        }
      }
    }
  }

  check(d, c, r) {
    for (let a = 0; a < this.size; a++) {
      if (c - a > -1) {
        if (this.square[c - a][r] === d)
          return true;
      }
      if (r - a > -1) {
        if (this.square[c][r - a] === d)
          return true;
      }
    }
    return false;
  }
}
new Latin(5);
Output:
3 5 4 1 2
4 3 1 2 5
1 2 3 5 4
5 1 2 4 3
2 4 5 3 1
 
4 5 1 3 2
3 1 4 2 5
5 4 2 1 3
1 2 3 5 4
2 3 5 4 1

jq

Works with: jq

Also works with gojq, the Go implementation of jq.

This entry presents two jq programs for generating Latin Squares of order n (LS(n)) in accordance with the requirements.

The first program uses a "brute-force" algorithm (with simple optimizations) to generate Latin Squares of order n as though drawing with replacement from the population of all such Latin Squares. The chi-squared statistics show good agreement with the theoretical uniformity.

The second program uses a much faster algorithm for generating Latin Squares in accordance with the requirements, but with bias away from uniformity, as also illustrated by chi-squared statistics.

Both algorithms use /dev/random as a source of entropy. They also both use the Knuth shuffle to generate the first row, and rely on backtracking using the jq idiom:

   `first( repeat( _) )`

The first algorithm incrementally adds rows, backtracking to the point immediately after the selection of the first row. For n larger than about 4, this algorithm is quite slow, though in a fairly predictable way.

The second algorithm incrementally adds cells, backtracking to the last cell. It is much faster but the running time can be quite variable, as suggested by this table:

n     Typical range of u+s times on 3GHz machine
10   0.11 to 0.14 s
15   0.15 to 0.21 s
20   0.36 to 0.94 s
30   0.5 to 29 seconds
40   80 seconds to 21 minutes
45   8 to 39 minutes

An interesting variant of the second algorithm can be obtained by a trivial modification of just one line (see the comment with "n.b."): backtracking to the last full row is slightly faster while maintaining randomness, at the cost of a greater departure from uniform randomness, as confirmed by these two runs using the same `stats` function as defined in the first program.

# Using `ext` (i.e., backtrack to point after selection of first row)
Number of LS(4): 5760
Of 576 possibilities, only 575 were generated.
Chi-squared statistic (df=575): 2128.6
# u+s 5.5s

# Using `extend` (i.e. backtrack to point of most recent row extension - faster but more biased)
Number of LS(4): 5760
All 576 possibilities have been generated.
Chi-squared statistic (df=575): 3055.8
# u+s 4.7s
#!/bin/bash
< /dev/random tr -cd '0-9' | fold -w 1 | jq -Mcnr -f random-latin-squares.jq

Common Functions

'''Generic Utility Functions'''
# For inclusion using jq's `include` directive:
# Output: a PRN in range(0;$n) where $n is .
def prn:
  if . == 1 then 0
  else . as $n
  | (($n-1)|tostring|length) as $w
  | [limit($w; inputs)] | join("") | tonumber
  | if . < $n then . else ($n | prn) end
  end;

def knuthShuffle:
  length as $n
  | if $n <= 1 then .
    else {i: $n, a: .}
    | until(.i ==  0;
        .i += -1
        | (.i + 1 | prn) as $j
        | .a[.i] as $t
        | .a[.i] = .a[$j]
        | .a[$j] = $t)
    | .a 
    end;

def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;

# If the input array is not rectangular, let nulls fall where they may
def column($j):
   [.[] | .[$j]];

# Emit a stream of [value, frequency] pairs
def histogram(stream):
  reduce stream as $s ({};
    ($s|type) as $t
     | (if $t == "string" then $s else ($s|tojson) end) as $y
     | .[$t][$y][0] = $s
     | .[$t][$y][1] += 1 )
  | .[][] ;

def ss(s): reduce s as $x (0; . + ($x * $x));

def chiSquared($expected): ss( .[] - $expected ) / $expected;

Latin Squares selected at random uniformly

# Include the utilities e.g. by
# include "random-latin-squares.utilities" {search: "."};

# Determine orthogonality of two arrays, confining attention 
# to the first $n elements in each:
def orthogonal($a; $b; $n):
   first( (range(0; $n) | if $a[.] == $b[.] then 0 else empty end) // 1) | . == 1;

# Are the two arrays orthogonal up to the length of the shorter?
def orthogonal($a; $b):
   ([$a, $b | length] | min) as $min
   | orthogonal($a; $b; $min);

# Is row $i orthogonal to all the previous rows?
def orthogonal($i): 
  . as $in
  | .[$i] as $row
  | all(range(0;$i); orthogonal($row; $in[.])); 

# verify columnwise orthogonality
def columnwise: 
  length as $n
  | transpose as $t
  | all( range(1;$n); . as $i | $t | orthogonal($i)) ;

def addLast:
  (.[0] | length) as $n
  | [range(0; $n)] as $range
  | [range(0; $n) as $i
     | ($range - column($i))[0]  ] as $last
  | . + [$last] ;

# input: an array being a permutation of [range(0;$n)] for some $n
# output: a Latin Square selected at random from all the candidates
def extend:
  (.[0] | length) as $n
  | if length >= $n then .
    elif length == $n - 1 then addLast
    else ([range(0; $n)] | knuthShuffle) as $row
    | (. + [$row] )
    | if orthogonal(length - 1) and columnwise then extend else empty end
    end ;

# Generate a Latin Square.
# The input should be an integer specifying its size.
def latinSquare:
  . as $n
  | if $n <= 0 then []
    else
    [ [range(0; $n)] | knuthShuffle]
    | first(repeat(extend))
    # | (if columnwise then . else debug end)  # internal check
    end ;

# If the input is a positive integer, $n, generate and print an $n x $n Latin Square.
# If it is not number, echo it.
def printLatinSquare:
  if type == "number"
  then latinSquare
  | .[] | map(lpad(3)) | join(" ")
  else .
  end;

# $order should be in 1 .. 5 inclusive
# If $n is null, then use 10 * $counts[$order]
def stats($order; $n):
  # table of counts:
  [0,1,2,12,576,161280] as $counts  
  | $counts[$order] as $possibilities
  | (if $n then $n else 10 * $possibilities end) as $n
  | reduce range(0;$n) as $i ({};
      ($order|latinSquare|flatten|join("")) as $row
      | .[$row] += 1)
  | # ([histogram(.[])] | sort[] | join(" ")),
    "Number of LS(\($order)): \($n)",
    (if length == $possibilities
     then "All \($possibilities) possibilities have been generated." 
     else "Of \($possibilities) possibilities, only \(length) were generated."
     end),
    "Chi-squared statistic (df=\($possibilities-1)): \( [.[]] | chiSquared( $n / $possibilities))";


stats(3;null), "",
stats(4;5760), ""
stats(4;5760)
Output:
Number of LS(3): 120
All 12 possibilities have been generated.
Chi-squared statistic (df=11): 18.8

Number of LS(4): 5760
All 576 possibilities have been generated.
Chi-squared statistic (df=575): 572.2

Number of LS(4): 5760
All 576 possibilities have been generated.
Chi-squared statistic (df=575): 517.2

Random Latin Squares

This is the (much) faster program that meets the task requirements while deviating from uniform randomness as suggested by the Chi-squared statistics presented in the preamble.

# Include the utilities e.g. by
# include "random-latin-squares.utilities" {search: "."};

# Select an element at random from [range(0;$n)] - column($j)
def candidate($j):
  (.[0] | length) as $n
  | [range(0;$n)] - column($j)
  | .[length|prn];

# Input: the first row or rows of a Latin Square
def extend:
  # The input to ext should be several rows of a Latin Square
  # optionally followed by a candidate for an additional row.
  def ext:
  .[0] as $first
  | length as $length
  | ($first|length) as $n
  | .[-1] as $last
  | if ($last|length) < $n # then extend the last row
    then ( ([range(0;$n)] - column($last|length)) - $last) as $candidates
    | .[:$length-1] as $good
    | ($candidates|length) as $cl

    # if we can complete the row, then there is no need for another backtrack point!
    | if $cl == 1 and ($last|length) == $n - 1
      then ($good + [ $last + $candidates]) | ext # n.b. or use `extend` to speed things up at the cost of more bias
      else
         if $cl == 1 then ($good + [ $last + $candidates]) | ext
         elif $cl == 0 
         then empty
         else ($candidates[$cl | prn] as $add
            | ($good + [$last + [$add]]) | ext)
         end
      end
    elif length < $n then ((. + [[candidate(0)]]) | ext)
    else .
    end;
    # If at first you do not succeed ...
    first( repeat( ext ));

# Generate a Latin Square.
# The input should be an integer specifying its size.
def latinSquare:
  . as $n
  | if $n <= 0 then []
    else
    [ [range(0; $n)] | knuthShuffle]
    | extend
    end ;

# If the input is a positive integer, $n, generate and print an $n x $n Latin Square.
# Otherwise, simply echo it.
def printLatinSquare:
  if type == "number"
  then latinSquare
  | .[] | map(lpad(3)) | join(" ")
  else .
  end;

"Five", 5, "\nFive", 5, "\nTen", 10, "\nForty", 40
| printLatinSquare
'
Output:
Five
  2   1   3   4   0
  1   4   0   2   3
  4   3   2   0   1
  3   0   4   1   2
  0   2   1   3   4

Five
  1   0   2   3   4
  4   3   0   1   2
  0   4   3   2   1
  2   1   4   0   3
  3   2   1   4   0

Ten
  0   4   9   1   5   3   8   7   2   6
  5   8   7   9   3   6   0   2   4   1
  8   7   2   6   0   1   4   5   3   9
  9   3   1   2   7   4   5   6   0   8
  7   2   5   4   6   0   9   8   1   3
  6   9   0   8   4   5   1   3   7   2
  3   0   8   7   9   2   6   1   5   4
  4   1   6   3   2   8   7   0   9   5
  1   5   3   0   8   9   2   4   6   7
  2   6   4   5   1   7   3   9   8   0

Forty
 30  29  36   1  37  23  27  33  22  32  38  20   5  13  25  35  16  18  19  24  11   6   4  12   3  10  21  26  34  39  14  28  31   2   8   7   9  17   0  15
 16  30  21  32  24   6  25  17  35  12  26  10  19  33  18  31  29  34   4  13  15  28   0   3   5  11   9  23  14   2  20  38  37   8  39  27   1  22  36   7
 21   4  27  11   5  12   9  13  30  20   3  36  31   0  24  16  28   1   8  33  38   2  23  22  29  32  18  34   6   7  15  17  25  26  10  35  19  14  39  37
  2  13  18  36  15  19  17  32  27  24   9   3  26  21   1   0  10  39  38  16  20  14  34   6  28  22  12   7  11   8   5  23  33  37  30   4  29  31  25  35
 35  39  10   0   3  15   1  37   7   4   6   2  27   9  29  38  34  16  33  28  32  30  24  14  18  23  31  12  19  17  21  36   8  13  20  25  22   5  11  26
 13  27  34  25  17   1  21   5  23  39   2   8   0  38  22   7  32   9  29  26  18   4  36  19  30  16  14  20  31  28   3   6  35  11  15  12  33  10  37  24
 36  31  26   3  25   2  11  38  13  18  24  35  17  10  20   1   7  15   6  19  22   0  12  32  33  27   4  30  37   9   8  29  14  28  34  39  23  16   5  21
 26  25  35  31   6  34   5   8  11  19  30   1  20  15  33  10  23  38   0  21  37  29   2  39  14  17  28  27  32  18  24   7  12   3  36  13   4   9  22  16
 18  14   4  30  33  38   8   2   1  28  21  27  13  36  37  22  15   3  20  31   7  25   6   0  12  29  26  32  17  35  23  34  11   9  19   5  16  24  10  39
 14  21   5  34   8  29   0  10  20   9  28  39  35   4  17  30  26  11  25  38  16  19  31  15  32   1   6  24  13  37   7  27  36  33  23  18   2  12   3  22
 15  28  24   2  34   7   3  35  29  30   0   4  38  25   6  27  11  12  17  37  26  20  21   5   1  14  10   8  33  16  36   9  13  32  22  19  39  18  31  23
 38   3  23   7  39  37  13  20  21  25  33   5   6  32  14   4   8  35  12   9  24  17  11  34  27  36  16  22  26   0  31  18   2  29   1  15  28  19  30  10
 11  19  30   5  31  18  10  21   6  23  34  33   4  12   2  14  37  22  39   1  25   8  16  38  24  28  36  13   3  27  29  26  32  35   7  20   0  15   9  17
  0   9  12  20  16  30  38  11  18  14   4  17  10   7  19  36   3  27  37  35  29  22  26  28  21   8  13  39  23  33  34  31  24   6   2  32  25   1  15   5
 29   2  16  18  35  17  37  25  10  27  39  31   3   6  23  34   9  19  30   4  13  38   1  21   8   0  22   5  36  24  12  33  28  15  26  14  11  32   7  20
 22  35  29  38  23   8   7   6   9  36  14   0  18  34  27   3  12  33   5  39  21  11  30  31  10  26  15  17   1   4  37  16  20  19  13  24  32   2  28  25
 32  16  25   4  26  22  36   1  28   3  27   7  14  19  39   5  33  21   9   2  23  31  13  20  11  37  30   0  15  34  35  10  17  24  29  38  18   8  12   6
 33  20  32  13  30  21  35   7  24   2  19  16  11  37   4  23  14  31  36  15   1  39  22   9  25  38  27   6   0  26  10   8  29   5  17   3  34  28  18  12
  5   0  28  26  22  39  30  27  33  31  12  24  21  35  11  20   4  32  34   8   9  16  15  17  19  25   3   1  10   6  18   2  38   7  14  37  13  29  23  36
 25   5  17  37  11  13   4  18  36  34  23  32   9  20  12  19  21   2   3   0  30  10  35  26  38  24  39  28  22  15  16   1  27  14  31   6   8   7  33  29
 10  32   1  17  12  31  39  30  15  26  25  11  33  27  13  29   6  37   2   3   8  24  18   4   7  21  35  16  20   5   9  19  34  23  38  22  36   0  14  28
 31  37  33  27   4  20  14   9  34  29  32  26  22  30  28  12   5  25  24  17  10   7  39  11  23   2   1  36  18  38  13  35  21  16   0   8  15   6  19   3
  4  34  11  15  27  33  19  14  37   0   8  29  28   5   3  18   2  10  31  12  39  23  20  35  13  30  24  21  25   1   6  22  26  17  16  36   7  38  32   9
  1  38  14  21   7   4  34  16   2  22  13  12  29  31  15  28  25  36  32  10  27   3  37  33  17   5   0   9  30  23  11  20  39  18   6  26  24  35   8  19
 28  26  20  10  14  35  29   4  16   8  37  38   7  17   9  32  19   6  23  30   5  36  27   2  15  13  25  11  12  22   0  39   3  34  24  33  31  21   1  18
 20  10   6  29  21  24  32  19  39  16  31  15  36  23  34  37  17  13   1  25  14  18   9  27   0   7   8  38  35  12  30   5   4  22   3  28  26  11   2  33
 24   7   9   8  18   5  26   0  19  15   1  30   2  22  36  21  35  17  27  29   3  33  38  10   4  39  11  25  16  20  28  12  23  31  32  34  37  13   6  14
 37  33   3  19  10  25  20  26  17  13  11  34  23   1  30   8  22   5  28  14   2  12   7  18  36  15  29  35  21  32  27   4  16  38   9   0   6  39  24  31
 39   1  31   9  29  14  15   3  26  17  36  25  30  11  38  24  27  28  18  32   6   5  33  37   2  19   7  10   4  13  22  21   0  20  12  23  35  34  16   8
 34  17  15  24  28  16   6  22   8   7   5  14  25  29  35   2  30  26  11  27  12   1  19  36  39  20  23   4   9  21  38  32  18  10  37  31   3  33  13   0
 12  24  22  39  19  28  18  15  32  33   7  23  16  26   8  11  36  14  13  34   0   9  29  30   6  35   2  31  38  25   4   3   5  27  21  10  17  37  20   1
  8  23   7  28   9  27  12  39  31   6  18  21  34  16  10  25  20  24  15  11  35  37   3   1  22   4  19  29   2  14  26  13  30   0  33  17   5  36  38  32
  9  36   2  23  32  11  33  12  25  38  16  18   8  14   0  39  31   7  10   6  28  21   5  29  34   3  17  37  24  19   1  15  22   4  27  30  20  26  35  13
 17  22   0   6  36   3  31  23  12   1  20   9  37  28  32  33  13  30   7   5  19  26  14  24  35  18  34  15   8  29   2  11  10  39  25  16  21   4  27  38
 19  18  38  35  13   0  22  28   4   5  15   6  12  39  16  26   1  23  14  20  17  34  10   8  37  31  32   3  29  30  33  24   7  36  11   9  27  25  21   2
  7   6  19  12  20  36   2  24   3  21  17  22  32  18  31   9   0   8  35  23  34  13  25  16  26  33   5  14  28  10  39  37  15  30   4   1  38  27  29  11
 27   8  39  33  38   9  23  36   0  11  29  19  15  24   5  13  18  20  26  22  31  35  32  25  16  12  37   2   7   3  17  14   6   1  28  21  10  30   4  34
 23  15   8  16   1  32  24  34  14  10  22  37  39   2   7  17  38  29  21  36  33  27  28  13   9   6  20  18   5  31  25   0  19  12  35  11  30   3  26   4
  3  11  13  14   2  10  16  31  38  37  35  28  24   8  26   6  39   0  22  18   4  15  17   7  20   9  33  19  27  36  32  25   1  21   5  29  12  23  34  30
  6  12  37  22   0  26  28  29   5  35  10  13   1   3  21  15  24   4  16   7  36  32   8  23  31  34  38  33  39  11  19  30   9  25  18   2  14  20  17  27

Julia

Using the Python algorithm as described in the discussion section.

using Random

shufflerows(mat) = mat[shuffle(1:end), :]
shufflecols(mat) = mat[:, shuffle(1:end)]

function addatdiagonal(mat)
    n = size(mat)[1] + 1
    newmat = similar(mat, size(mat) .+ 1)
    for j in 1:n, i in 1:n
        newmat[i, j] = (i == n && j < n) ? mat[1, j] : (i == j) ? n - 1 :
            (i < j) ? mat[i, j - 1] : mat[i, j]
    end
    newmat
end

function makelatinsquare(N)
    mat = [0 1; 1 0]
    for i in 3:N
        mat = addatdiagonal(mat)
    end
    shufflecols(shufflerows(mat))
end

function printlatinsquare(N)
    mat = makelatinsquare(N)
    for i in 1:N, j in 1:N
        print(rpad(mat[i, j], 3), j == N ? "\n" : "")
    end
end

printlatinsquare(5), println("\n"), printlatinsquare(5)
Output:
1  3  0  4  2
3  0  4  2  1
0  4  2  1  3
2  1  3  0  4
4  2  1  3  0


2  0  1  3  4
4  3  2  1  0
3  2  0  4  1
1  4  3  0  2
0  1  4  2  3

Kotlin

Translation of: Go
typealias matrix = MutableList<MutableList<Int>>

fun printSquare(latin: matrix) {
    for (row in latin) {
        println(row)
    }
    println()
}

fun latinSquare(n: Int) {
    if (n <= 0) {
        println("[]")
        return
    }

    val latin = MutableList(n) { MutableList(n) { it } }
    // first row
    latin[0].shuffle()

    // middle row(s)
    for (i in 1 until n - 1) {
        var shuffled = false
        shuffling@
        while (!shuffled) {
            latin[i].shuffle()
            for (k in 0 until i) {
                for (j in 0 until n) {
                    if (latin[k][j] == latin[i][j]) {
                        continue@shuffling
                    }
                }
            }
            shuffled = true
        }
    }

    // last row
    for (j in 0 until n) {
        val used = MutableList(n) { false }
        for (i in 0 until n - 1) {
            used[latin[i][j]] = true
        }
        for (k in 0 until n) {
            if (!used[k]) {
                latin[n - 1][j] = k
                break
            }
        }
    }

    printSquare(latin)
}

fun main() {
    latinSquare(5)
    latinSquare(5)
    latinSquare(10) // for good measure
}
Output:
[4, 1, 2, 3, 0]
[1, 3, 0, 2, 4]
[3, 2, 4, 0, 1]
[0, 4, 3, 1, 2]
[2, 0, 1, 4, 3]

[2, 0, 3, 1, 4]
[0, 4, 1, 3, 2]
[1, 3, 2, 4, 0]
[3, 2, 4, 0, 1]
[4, 1, 0, 2, 3]

[7, 8, 4, 6, 5, 2, 9, 3, 1, 0]
[1, 5, 8, 2, 3, 0, 7, 9, 4, 6]
[6, 9, 5, 8, 7, 1, 3, 4, 0, 2]
[0, 6, 9, 4, 8, 3, 1, 2, 7, 5]
[4, 1, 3, 0, 6, 5, 8, 7, 2, 9]
[5, 0, 1, 7, 9, 4, 2, 6, 3, 8]
[2, 3, 6, 9, 4, 7, 0, 8, 5, 1]
[3, 7, 2, 5, 0, 9, 6, 1, 8, 4]
[8, 2, 0, 3, 1, 6, 4, 5, 9, 7]
[9, 4, 7, 1, 2, 8, 5, 0, 6, 3]

M2000 Interpreter

Easy Way

One row shuffled to be used as the destination row. One more shuffled and then n times rotated by one and stored to array

for 40x40 need 2~3 sec, including displaying to screen

We use the stack of values, a linked list, for pushing to top (Push) or to bottom (Data), and we can pop from top using Number or by using Read A to read A from stack. Also we can shift from a chosen position to top using Shift, or using shiftback to move an item from top to chosen position. So we shuffle items by shifting them.

Module FastLatinSquare {
	n=5
	For k=1 To 2
		latin()
	Next
	n=40
	latin()
	Sub latin()
		Local i,a, a(1 To n), b, k
		Profiler
		flush
		Print "latin square ";n;" by ";n
		For i=1 To n
			Push i
		Next i
		For i=1 To n div 2
			Shiftback random(2, n)
		Next i
		a=[]
		Push ! stack(a)
		a=array(a)  ' change a from stack to array
		For i=1 To n*10
			Shiftback random(2, n)
		Next i
		For i=0 To n-1
			Data number  ' rotate by one the stack items
			b=[]    ' move stack To b, leave empty stack
			a(a#val(i))=b
			Push ! stack(b)  ' Push from a copy of b all items To stack
		Next i
		flush
		For k=1 To  n div 2
			z=random(2, n)
			For i=1 To n
				a=a(i)
				stack a {
					shift z
				}
			Next
		Next
		For i=1 To n
			a=a(i)
			a(i)=array(a)  ' change To array from stack
		Next i
		For i=1 To n
			Print a(i)
		Next i
		Print TimeCount
	End Sub
}
FastLatinSquare

Hard Way

for 5x5 need some miliseconds

for 16X16 need 56 seconds

for 20X20 need 22 min (as for 9.8 version)

Module LatinSquare (n, z=1, f$="latin.dat", NewFile As Boolean=False) {
	If Not Exist(f$)  Or NewFile Then
		Open f$ For Wide Output As f
	Else
		Open f$ For Wide Append As f
	End If
	ArrayToString=Lambda -> {
		Shift 2  ' swap two top values in stack
		Push Letter$+Str$(Number)
	}
	Dim line(1 to n)
	flush   ' erase current stack of value
	z=if(z<1->1, z)
	newColumn()
	For j=1 To z
		Profiler
		ResetColumns()
		For i=1 To n
			placeColumn()
		Next
		Print "A latin square of ";n;" by ";n
		For i=1 To n
			Print line(i)
			Print #f, line(i)#Fold$(ArrayToString)
		Next 
		Print TimeCount
		Refresh
	Next 
	close #f
	Flush  ' empty stack again
	End
	Sub ResetColumns()
		Local i
		For i=1 To n:line(i)=(,):Next
	End Sub
	Sub newColumn()
		Local i
		For i=1 To n : Push i: Next
	End Sub
	Sub shuffle()
		Local i
		For i=1 To n div 2: Shift Random(2, n): Next
	End Sub
	Sub shuffleLocal(x)
		If Stack.size<=x Then Exit Sub
		Shift Random(x+1, Stack.size)
		Shiftback x
	End Sub
	Sub PlaceColumn()
		Local i, a, b, k
		shuffle()
		Do
			data number   ' rotate one position
			k=0
			For i=1 To n
				a=line(i)  ' get the pointer
				Do
				If a#Pos(Stackitem(i))=-1 Then k=0 :Exit Do
				shuffleLocal(i)
				k++
				Until k>Stack.size-i
				If k>0 Then Exit For
			Next
		Until k=0
		For i=1 To n
			a=line(i) 
			Append a, (Stackitem(i),)
		Next
	End Sub
}
Form 100,50
LatinSquare 5, 2, True
LatinSquare 16
Output:
A latin square of 5 by 5
 4 5 3 1 2
 5 4 2 3 1
 2 1 5 4 3
 1 3 4 2 5
 3 2 1 5 4
A latin square of 5 by 5
 4 3 5 1 2
 2 4 3 5 1
 1 2 4 3 5
 5 1 2 4 3
 3 5 1 2 4
A latin square of 16 by 16
12 14 5 16 1 2 7 15 9 11 10 8 13 3 6 4
 3 13 16 12 7 4 1 11 5 6 15 2 8 14 10 9
 13 2 8 3 4 12 5 9 14 7 16 10 6 1 15 11
 8 3 13 9 2 10 16 1 15 14 5 4 11 7 12 6
 4 12 2 7 5 3 6 10 1 9 11 16 14 8 13 15
 16 8 3 4 14 6 13 7 11 10 9 15 1 12 2 5
 15 4 14 1 16 8 2 13 6 12 7 9 10 11 5 3
 11 16 12 10 15 9 4 5 7 1 8 6 3 13 14 2
 10 15 4 5 12 16 3 6 8 13 1 11 7 2 9 14
 9 11 15 8 3 1 14 12 13 4 6 5 2 16 7 10
 7 10 11 13 9 14 15 4 3 5 2 12 16 6 1 8
 6 7 10 2 8 13 9 16 12 15 14 3 5 4 11 1
 5 6 1 14 13 11 8 2 10 3 12 7 15 9 4 16
 2 5 6 15 11 7 12 14 4 8 3 1 9 10 16 13
 1 9 7 11 6 15 10 8 2 16 13 14 4 5 3 12
 14 1 9 6 10 5 11 3 16 2 4 13 12 15 8 7

Mathematica/Wolfram Language

Clear[RandomLatinSquare]
RandomLatinSquare[n_] := Module[{out, ord},
  out = Table[RotateLeft[Range[n], i], {i, n}];
  out = RandomSample[out];
  ord = RandomSample[Range[n]];
  out = out[[All, ord]];
  out
  ]
RandomLatinSquare[5] // Grid
Output:
5	2	4	1	3
2	4	1	3	5
4	1	3	5	2
3	5	2	4	1
1	3	5	2	4

Nim

Translation of: Kotlin

Not a straight translation of Kotlin version. There are many differences but the algorithm is the same.

Starting at n = 11, the execution time will be very variable as the program proceeds by trial and error. At least, the algorithm will be able to produce all the possible Latin squares but not in a uniform way.

import random, sequtils, strutils

type LatinSquare = seq[seq[char]]

proc get[T](s: set[T]): T =
  ## Return the first element of a set.
  for n in s:
    return n

proc letterAt(n: Natural): char {.inline.} = chr(ord('A') - 1 + n)


proc latinSquare(n: Positive): LatinSquare =
  result = newSeqWith(n, toSeq(letterAt(1)..letterAt(n)))
  result[0].shuffle()

  for row in 1..(n - 2):
    var ok = false
    while not ok:
      block shuffling:
        result[row].shuffle()
        for prev in 0..<row:
          for col in 0..<n:
            if result[row][col] == result[prev][col]:
              break shuffling
        ok = true

  for col in 0..<n:
    var s = {letterAt(1)..letterAt(n)}
    for row in 0..(n - 2):
      s.excl result[row][col]
    result[^1][col] = s.get()


proc `$`(s: LatinSquare): string =
  let n = s.len
  for row in 0..<n:
    result.add s[row].join(" ") & '\n'


randomize()
echo latinSquare(5)
echo latinSquare(5)
echo latinSquare(10)
Output:
D A C E B
A D B C E
B E D A C
E C A B D
C B E D A

E C D A B
B A C E D
C B A D E
A D E B C
D E B C A

D I J B H F G E A C
H E C G A I F D B J
I J G A F E C B D H
C D H J E A I G F B
G B A F I H E C J D
B F D E J C H I G A
F C B H D G A J I E
A H E I B D J F C G
J A I C G B D H E F
E G F D C J B A H I


Pascal

Jacobson-Matthews algorithm. Generates uniformly distributed random Latin squares (if used PRNG is good - Delphi/Pascal built-in PRNG is not).

Slightly modified translation of C code from https://brainwagon.org/2016/05/17/code-for-generating-a-random-latin-square/

Algorithm source: Jacobson, M. T.; Matthews, P. (1996). "Generating uniformly distributed random latin squares". Journal of Combinatorial Designs. 4 (6): 405–437.

{$APPTYPE CONSOLE}

const
  Alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';


Type
IncidenceCube = Array of Array Of Array of Integer;

Var
Cube : IncidenceCube;
DIM  : Integer;


Procedure InitIncidenceCube(Var c:IncidenceCube; const Size:Integer);
var i, j, k : integer;
begin
DIM := Size;
SetLength(c,DIM,DIM,DIM);
for i := 0 to DIM-1 do
for j := 0 to DIM-1 do
for k := 0 to DIM-1 do c[i,j,k] := 0 ;

for i := 0 to DIM-1 do
for j := 0 to DIM-1 do c[i,j,(i+j) mod DIM] := 1;
end;


Procedure FreeIncidenceCube(Var c:IncidenceCube);
begin
Finalize(c);
end;


procedure PrintIncidenceCube(var c:IncidenceCube);
var i, j, k : integer;
begin
    for i := 0 to DIM-1 do begin
        for j := 0 to DIM-1 do begin
            for k := 0 to DIM-1 do begin
                if (c[i,j,k]=1) then begin
                    write(Alpha[k+1],' ');
                    break;
                end;
            end;
        end;
        Writeln;
    end;
    Writeln;
	WriteLn;
end;


procedure ShuffleIncidenceCube(var c:IncidenceCube);
var i, j, rx, ry, rz, ox, oy, oz : integer;
begin

    for i := 0 to (DIM*DIM*DIM)-1 do begin

        repeat
            rx := Random(DIM);
            ry := Random(DIM);
            rz := Random(DIM);
        until (c[rx,ry,rz]=0);

        for j := 0 to DIM-1 do begin
            if (c[j,ry,rz]=1) then ox := j;
            if (c[rx,j,rz]=1) then oy := j;
            if (c[rx,ry,j]=1) then oz := j;
        end;

        Inc(c[rx,ry,rz]);
        Inc(c[rx,oy,oz]);
        Inc(c[ox,ry,oz]);
        Inc(c[ox,oy,rz]);

        Dec(c[rx,ry,oz]);
        Dec(c[rx,oy,rz]);
        Dec(c[ox,ry,rz]);
        Dec(c[ox,oy,oz]);

        while (c[ox,oy,oz] < 0) do begin

            rx := ox ;
            ry := oy ;
            rz := oz ;

            if (random(2)=0) then begin
                for j := 0 to DIM-1 do begin
                    if (c[j,ry,rz]=1) then ox := j;
                end;
            end else begin
                for j := DIM-1 downto 0 do begin
                    if (c[j,ry,rz]=1) then ox := j;
                end;
            end;

            if (random(2)=0) then begin
                for j := 0 to DIM-1 do begin
                    if (c[rx,j,rz]=1) then oy := j;
                end;
            end else begin
                for j := DIM-1 downto 0 do begin
                    if (c[rx,j,rz]=1) then oy := j;
                end;
            end;

            if (random(2)=0) then begin
                for j := 0 to DIM-1 do begin
                    if (c[rx,ry,j]=1) then oz := j;
                end;
            end else begin
                for j := DIM-1 downto 0 do begin
                    if (c[rx,ry,j]=1) then oz := j;
                end;
            end;

            Inc(c[rx,ry,rz]);
            Inc(c[rx,oy,oz]);
            Inc(c[ox,ry,oz]);
            Inc(c[ox,oy,rz]);

            Dec(c[rx,ry,oz]);
            Dec(c[rx,oy,rz]);
            Dec(c[ox,ry,rz]);
            Dec(c[ox,oy,oz]);
        end;
 
    end;
end;
 
begin
    Randomize;
    InitIncidenceCube(cube, 5); ShuffleIncidenceCube(cube); PrintIncidenceCube(cube); FreeIncidenceCube(Cube);
    InitIncidenceCube(cube, 5); ShuffleIncidenceCube(cube); PrintIncidenceCube(cube); FreeIncidenceCube(Cube);
    InitIncidenceCube(cube,10); ShuffleIncidenceCube(cube); PrintIncidenceCube(cube); FreeIncidenceCube(Cube);	
    InitIncidenceCube(cube,26); ShuffleIncidenceCube(cube); PrintIncidenceCube(cube); FreeIncidenceCube(Cube);
end.
Output:

B A E D C 
D B C A E 
C D A E B 
A E B C D 
E C D B A 

A C D B E 
B E C D A 
D A B E C 
E D A C B 
C B E A D 

E F G C D A H B I J 
B J A H F D C E G I 
F I J A C E G H D B 
J A E D G F B I C H 
C E D I H G A J B F 
I D H E A B F C J G 
H G B J E C I D F A 
G C F B J I D A H E 
D H I F B J E G A C 
A B C G I H J F E D 

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


Perl

Translation of: Raku
use strict;
use warnings;
use feature 'say';
use List::Util 'shuffle';

sub random_ls {
    my($n) = @_;
    my(@cols,@symbols,@ls_sym);

    # build n-sized latin square
    my @ls = [0,];
    for my $i (1..$n-1) {
        @{$ls[$i]} = @{$ls[0]};
        splice(@{$ls[$_]}, $_, 0, $i) for 0..$i;
    }

    # shuffle rows and columns
    @cols = shuffle 0..$n-1;
    @ls = map [ @{$_}[@cols] ], @ls[shuffle 0..$n-1];

    # replace numbers with symbols
    @symbols = shuffle( ('A'..'Z')[0..$n-1] );
    push @ls_sym, [@symbols[@$_]] for @ls;
    @ls_sym
}

sub display {
    my $str;
    $str .= join(' ', @$_) . "\n" for @_;
    $str
}

say display random_ls($_) for 2..5, 5;
Output:
B A
A B

A B C
B C A
C A B

A B D C
B D C A
C A B D
D C A B

C E A B D
E A D C B
B C E D A
D B C A E
A D B E C

E D C B A
C E B A D
A B D E C
B C A D E
D A E C B

Phix

Brute force, begins to struggle above 42.

with javascript_semantics
string aleph = "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
 
function ls(integer n)
    if n>length(aleph) then ?9/0 end if -- too big...
    atom t1 = time()+1
    sequence tn = tagset(n),     -- {1..n}
             vcs = repeat(tn,n), -- valid for cols
             res = {}
    integer clashes = 0
    while length(res)<n do
        sequence rn = {},               -- next row
                 vr = tagset(n),        -- valid for row (ie all)
                 vc = deep_copy(vcs)    -- copy (in case of clash)
        bool clash = false
        for c=1 to n do
            sequence v = {}
            for k=1 to n do
                -- collect all still valid options
                if vr[k] and vc[c][k] then v &= k end if
            end for
            if v={} then
                clash = true
                exit
            end if
            integer z = v[rand(length(v))]
            rn &= z
            vr[z] = 0           -- no longer valid
            vc[c][z] = 0        --      ""
        end for
        if not clash then
            res = append(res,rn)
            vcs = vc
        else
            clashes += 1
            if time()>t1 then
                printf(1,"rows completed:%d/%d, clashes:%d\n",
                         {length(res),n,clashes})
                t1 = time()+1
            end if
        end if
    end while
    for i=1 to n do
        string line = ""
        for j=1 to n do
            line &= aleph[res[i][j]]
        end for
        res[i] = line
    end for
    return res
end function
 
procedure latin_square(integer n)
    atom t0 = time()
    string res = join(ls(n),"\n"),
           e = elapsed(time()-t0)
    printf(1,"Latin square of order %d (%s):\n%s\n",{n,e,res})
end procedure
latin_square(3)
latin_square(5)
latin_square(5)
latin_square(10)
if platform()!=JS then
    latin_square(42)
end if
Output:
Latin square of order 3 (0s):
231
123
312
Latin square of order 5 (0s):
15423
53142
24315
42531
31254
Latin square of order 5 (0s):
32514
21453
43125
15342
54231
Latin square of order 10 (0s):
3258A69417
9314275A86
586312479A
19A2753864
61294873A5
267194A538
473A618952
85973A6241
7A45831629
A486592173
rows completed:40/42, clashes:49854
rows completed:40/42, clashes:104051
Latin square of order 42 (2.1s):
5CMOgPTHbDBKGLU9d1aIREFNV8cQYeZ62AJXW3Sf74
VQEaBOIL2GefUYXbZWKP5cRDd3C4HS89MF7Jg6A1NT
LIRc1AXPWKJH4bTNFC2VS935g6ZEDfaeOGdYQ8B7MU
QPZ1LcN8O4I96dKRATfEWHaJUSM5e37GXBbDYFCV2g
ATIZD2VY8gGRNHBO6P35QaEM1fS79dKFbCX4JWcUeL
eE9Q7CJZ3VP254YMLHGOIBcdf1AbgXFKUR8WaTDNS6
7FfJdWGg4ZDC1UaVIcH9A5XLSb63MBTNPOQEKe2Y8R
DMa53QWdB9bPSeEZJg6GK2A7YR1C4VLcIXTUFO8HfN
G8d2eaARUPNEI6HCKQZSO4b1BM5g3L9VcTYFfXWJD7
9OHSGIRDEMf3YKb2cU1WVdNeTL8XA64gQPC57JZaBF
634YR52FINaeDQPKCXBAEZ8S7dgUG9OHJcfLMVTWb1
aVgXP7EO5f8JdFQ1RY9BHW42eTNGSUb3LMKZIC6AcD
YBWLbFUAP1T8JSZ6N2gMeIQfHc3DC75d9EVOG4aKRX
TXUBHe62JSCNA7WPfGLdYbOc9VRZ1IgD3aMQ5KEF48
dU1IS9D362V5cR8WTZCKfNPYA4OebQXJ7HBMLEFGga
3aDTUf5SCY6g8GOJbVIHZ1KWMNXBFPd7AQRc924LEe
1e2bJBHUDa9dTCRLYAWNXOMZFIK6QgfPE5S38G74Vc
F786NJP1Gb4BLXVdUaAfcTgQC2eWKHYZ53D9ERISOM
U1cRQGOeFBXWag6IPdVJ2Mf8L7YSNCHETK4bDZ539A
2DbgW6MfVAQY9acUX35ZNRBPIOJL81CSe4EHd7GTFK
8bNE2U7XTWHVBZJ5QMcePY9g6Ad1OaIf4DFKRSLC3G
g5L8AbKN7JF6MD1SBEQU3fTXWHVdR2P4ZY9aCceIGO
W2K9FHa5dT1OZ8C3gLScGVI4JB7YPDUbfe6RNAXMQE
X6QdY49JZ7E1fB5THFD2MeGAPaI8VRSWNgUCcLbOK3
EASPTVLWRe7I35Mc24FX9gHO8KbJdN1aB6GfZQUDCY
cSFM9ECbY65DW3GA17RTBQUVOg4K2ZNXadLPeIH8Jf
O9GFf8QEXdAMVN47SRUD13ZB5PH26cWTCJaebYKgLI
RcJUI319KFMXH2fea8dCL6WTG5EO74DYSNZAVgQBPb
M4CHOZdIQUgGE9DB7KJaTLeF2WfN5A38V1c6XbPRYS
IJBCad3cSQ27OEegM6XFb8LK4YDfTWGR1ZHNA59PUV
SRXA4D8GeHUQ7c2aVbNgJP1E3FTILOMBKf5d69YZWC
fNAeKMS7gR34bWIF5BEYDX69QCUTaGV28LO1HdJcZP
PfOD6SeKaXcF2Id4W9bQCU73RZLMBYA5g81GTNVEHJ
JZ5VMTcQfLRaP1SG8DOb4CYHNEFAXKeIW7g2BU36d9
4HVNEgbTLcKUCA7Y95eRFGJIaXBPZ8QMDW3SO1fd62
bgT7VKfBH5dLQJ3E4N86aSCRZUGFcM21Y9eIPDOXAW
CW3fXRg6NOSTKV9HEJYL8D5GbQPcIFBUd2A74M1eaZ
KGY3ZX4CA8OcFPNfeSM17JDbE92aW56LRVIgUHdQTB
NYP4C1ZM9EWSROLDGI786KVaXeQHfJcAFU2T3Bgb5d
HdeGcYB413LZgTFQDfP7UASCKJWVEbRO6IN82aM9X5
BK7W8LYacIZAeMgX3OT4dF26DG9RUEJCHbPVSfN51Q
ZL6K5NFVMCYbXfA8Oe43g7dUcDa9JTEQGSWB1PR2IH

Picat

Using constraint modelling.

The used labeling (search strategy) is:

  • ff: select a variable to label using the first fail strategy
  • rand_val: select a random (but valid) value.


Normally a non-random value strategy is preferred such as up, split, or updown, but the task requires random solutions.

main =>
  _ = random2(), % random seed
  N = 5,
  foreach(_ in 1..2)
    latin_square(N, X),
    pretty_print(X)
  end,
  % A larger random instance
  latin_square(62,X),
  pretty_print(X).

% Latin square
latin_square(N, X) =>
  X = new_array(N,N),
  X :: 1..N,
  foreach(I in 1..N)
    all_different([X[I,J] : J in 1..N]),
    all_different([X[J,I] : J in 1..N])
  end,
  % rand_val for randomness
  solve($[ff,rand_val],X).

pretty_print(X) =>
  N = X.len,
  Alpha = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
  foreach(I in 1..N)
    foreach(J in 1..N)
      if N > 20 then
        printf("%w",Alpha[X[I,J]])
      else
        printf("%2w ",X[I,J])      
      end
    end,
    nl
  end,
  nl.
Output:
 5  1  3  4  2 
 1  2  4  3  5 
 4  5  2  1  3 
 2  3  1  5  4 
 3  4  5  2  1 

 5  2  3  4  1 
 3  4  5  1  2 
 2  5  1  3  4 
 4  1  2  5  3 
 1  3  4  2  5 

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

CPU time 0.048 seconds.

Number of solutions

The number of solutions for a Latin square of size N is the OEIS sequence A002860: Number of Latin squares of order n; or labeled quasigroups. Here we check N = 1..6 which took 18min54s.

main =>
  foreach(N in 1..6)
    Count = count_all(latin_square(N,_)),
    println(N=Count)
  end.
Output:
1 = 1
2 = 2
3 = 12
4 = 576
5 = 161280
6 = 812851200

CPU time 1134.36 seconds.


Python

from random import choice, shuffle
from copy import deepcopy

def rls(n):
    if n <= 0:
        return []
    else:
        symbols = list(range(n))
        square = _rls(symbols)
        return _shuffle_transpose_shuffle(square)


def _shuffle_transpose_shuffle(matrix):
    square = deepcopy(matrix)
    shuffle(square)
    trans = list(zip(*square))
    shuffle(trans)
    return trans


def _rls(symbols):
    n = len(symbols)
    if n == 1:
        return [symbols]
    else:
        sym = choice(symbols)
        symbols.remove(sym)
        square = _rls(symbols)
        square.append(square[0].copy())
        for i in range(n):
            square[i].insert(i, sym)
        return square

def _to_text(square):
    if square:
        width = max(len(str(sym)) for row in square for sym in row)
        txt = '\n'.join(' '.join(f"{sym:>{width}}" for sym in row)
                        for row in square)
    else:
        txt = ''
    return txt

def _check(square):
    transpose = list(zip(*square))
    assert _check_rows(square) and _check_rows(transpose), \
        "Not a Latin square"

def _check_rows(square):
    if not square:
        return True
    set_row0 = set(square[0])
    return all(len(row) == len(set(row)) and set(row) == set_row0
               for row in square)


if __name__ == '__main__':
    for i in [3, 3,  5, 5, 12]:
        square = rls(i)
        print(_to_text(square))
        _check(square)
        print()
Output:
2 1 0
0 2 1
1 0 2

1 0 2
0 2 1
2 1 0

1 0 3 2 4
3 4 2 0 1
4 2 1 3 0
2 1 0 4 3
0 3 4 1 2

2 1 0 4 3
0 4 3 2 1
3 2 1 0 4
4 3 2 1 0
1 0 4 3 2

 6  2  4  8 11  9  3  1  7  0  5 10
 1 11  5  2  8  6  0  9  4 10  7  3
 2  7 10  5  4  8  9 11  0  6  3  1
 8  5  0  4  7 11  1  2  3  9 10  6
11  4  3  7  5  2  6  8 10  1  0  9
10  1  8  6  9  0  7  3 11  4  2  5
 7  0  1  3 10  5  8  4  6  2  9 11
 9  8  7 11  2  1 10  6  5  3  4  0
 3  9  2  1  6 10  4  0  8  5 11  7
 5  3  6 10  0  4 11  7  9  8  1  2
 4 10  9  0  3  7  2  5  1 11  6  8
 0  6 11  9  1  3  5 10  2  7  8  4

Quackery

transpose is defined at Matrix transposition#Quackery.

    [ [] []
      rot times
        [ i join ]
      dup size times
        [ tuck
          nested join
          swap
          behead join ]
      drop
      shuffle
      transpose
      shuffle ]         is rls ( n --> [ )

  2 times
    [ 5 rls
      witheach
        [ witheach
            [ echo sp ]
           cr ]
      cr ]
Output:
2 4 0 1 3 
0 2 3 4 1 
1 3 4 0 2 
4 1 2 3 0 
3 0 1 2 4 

1 2 3 0 4 
3 4 0 2 1 
2 3 4 1 0 
0 1 2 4 3 
4 0 1 3 2 

Raku

(formerly Perl 6)

Works with: Rakudo version 2019.03
Translation of: Python
sub latin-square { [[0],] };

sub random ( @ls, :$size = 5 ) {

    # Build
    for 1 ..^ $size -> $i {
        @ls[$i] = @ls[0].clone;
        @ls[$_].splice($_, 0, $i) for 0 .. $i;
    }

    # Shuffle
    @ls = @ls[^$size .pick(*)];
    my @cols = ^$size .pick(*);
    @ls[$_] = @ls[$_][@cols] for ^@ls;

    # Some random Latin glyphs
    my @symbols = ('A' .. 'Z').pick($size);

    @ls.deepmap: { $_ = @symbols[$_] };

}

sub display ( @array ) { $_.fmt("%2s ").put for |@array, '' }


# The Task

# Default size 5
display random latin-square;

# Specified size
display random :size($_), latin-square for 5, 3, 9;

# Or, if you'd prefer:
display random latin-square, :size($_) for 12, 2, 1;
Sample output:
 V   Z   M   J   U 
 Z   M   U   V   J 
 U   J   V   M   Z 
 J   V   Z   U   M 
 M   U   J   Z   V 
   
 B   H   K   U   D 
 H   D   U   B   K 
 K   U   H   D   B 
 U   B   D   K   H 
 D   K   B   H   U 
   
 I   P   Y 
 P   Y   I 
 Y   I   P 
   
 Y   J   K   E   Z   B   I   W   H 
 E   Y   B   W   K   H   J   Z   I 
 B   K   Y   H   J   E   Z   I   W 
 I   H   W   J   E   Z   B   Y   K 
 J   I   Z   Y   W   K   H   E   B 
 W   E   H   Z   B   I   Y   K   J 
 H   B   E   I   Y   W   K   J   Z 
 K   Z   J   B   I   Y   W   H   E 
 Z   W   I   K   H   J   E   B   Y 
   
 L   Q   E   M   A   T   Z   C   N   Y   R   D 
 Q   R   Y   L   N   D   C   E   M   T   A   Z 
 E   Y   M   C   D   Q   A   N   Z   L   T   R 
 M   L   C   N   R   Y   D   Z   A   E   Q   T 
 N   M   Z   A   Q   E   T   D   R   C   L   Y 
 T   D   Q   Y   C   A   M   L   E   R   Z   N 
 R   A   T   Q   M   Z   E   Y   L   D   N   C 
 D   Z   R   T   E   N   L   Q   Y   A   C   M 
 Y   T   L   E   Z   R   N   M   C   Q   D   A 
 A   N   D   R   L   C   Y   T   Q   Z   M   E 
 Z   C   A   D   Y   M   Q   R   T   N   E   L 
 C   E   N   Z   T   L   R   A   D   M   Y   Q 
   
 Y   G 
 G   Y 
   
 I

REXX

This REXX version produces a randomized Latin square similar to the   Julia   program.

The symbols could be any characters (except those that contain a blank),   but the numbers from   0 ──► N-1   are used.

/*REXX program generates and displays a randomized Latin square.                        */
parse arg N seed .                               /*obtain the optional argument from CL.*/
if N=='' | N==","  then N= 5                     /*Not specified?  Then use the default.*/
if datatype(seed, 'W')  then call random ,,seed  /*Seed numeric?   Then use it for seed.*/
w= length(N - 1)                                 /*get the length of the largest number.*/
$=                                               /*initialize  $  string to null.       */
         do i=0  for N;    $= $ right(i, w, '_') /*build a string of numbers (from zero)*/
         end   /*i*/                             /* [↑]  $ string is (so far)  in order.*/
z=                                               /*Z:  will be the 1st row of the square*/
         do N;             ?= random(1,words($)) /*gen a random number from the $ string*/
         z= z word($, ?);  $= delword($, ?, 1)   /*add the number to string; del from $.*/
         end   /*r*/
zz= z||z                                         /*build a double-length string of  Z.  */
         do j=1  for N                           /* [↓]  display rows of random Latin sq*/
         say translate(subword(zz, j, N), , '_') /*translate leading underbar to blank. */
         end   /*j*/                             /*stick a fork in it,  we're all done. */
output   for 1st run when using the default inputs:
4 1 3 0 2
1 3 0 2 4
3 0 2 4 1
0 2 4 1 3
2 4 1 3 0
output   for 2nd run when using the default inputs:
2 1 0 4 3
1 0 4 3 2
0 4 3 2 1
4 3 2 1 0
3 2 1 0 4

Ring

load "stdlib.ring"
load "guilib.ring"

###====================================================================================

size      = 10

time1     = 0
bwidth    = 0
bheight   = 0	
				
a2DSquare = newlist(size,size)
a2DFinal  = newlist(size,size)

aList  = 1:size
aList2 = RandomList(aList)

GenerateRows(aList2)
ShuffleCols(a2DSquare, a2DFinal)

C_SPACING           = 1
Button              = newlist(size,size)
LayoutButtonRow     = list(size)
C_ButtonOrangeStyle = 'border-radius:1x;color:black; background-color: orange'

###====================================================================================

MyApp = New qApp {

	StyleFusion()

	win = new qWidget() {

		workHeight = win.height()
		fontSize = 8 + (300/size)

	    wwidth = win.width()
	    wheight = win.height()
	    bwidth = wwidth/size
	    bheight = wheight/size

		setwindowtitle("Random Latin Squares")
		move(555,0)
		setfixedsize(1000,1000)

		myfilter = new qallevents(win) 
		myfilter.setResizeEvent("resizeBoard()")
		installeventfilter(myfilter)

		LayoutButtonMain = new QVBoxLayout() {
			setSpacing(C_SPACING)
			setContentsmargins(50,50,50,50) 
		}

		LayoutButtonStart = new QHBoxLayout() {
			setSpacing(C_SPACING)
			setContentsmargins(0,0,0,0)
		}

		btnStart = new qPushButton(win) {
			setFont(new qFont("Calibri",fontsize,2100,0))
			resize(bwidth,bheight)
			settext(" Start ")
			setstylesheet(C_ButtonOrangeStyle)
			setclickevent("gameSolution()")
		}

		sizeBtn = new qlabel(win) 
		{
			setFont(new qFont("Calibri",fontsize,2100,0))
			resize(bwidth,bheight)
			setStyleSheet("background-color:rgb(255,255,204)")  
			setText(" Size: ")
		}	

		lineSize = new qLineEdit(win) 
		{
			setFont(new qFont("Calibri",fontsize,2100,0))
			resize(bwidth,bheight)
			setStyleSheet("background-color:rgb(255,255,204)")
			setAlignment( Qt_AlignHCenter)
			setAlignment( Qt_AlignVCenter)
			setreturnPressedEvent("newBoardSize()")
			setText(string(size))
		}

		btnExit = new qPushButton(win) {
			setFont(new qFont("Calibri",fontsize,2100,0))
			resize(bwidth,bheight)
			settext(" Exit ")
			setstylesheet(C_ButtonOrangeStyle)
			setclickevent("pExit()")
		}

		LayoutButtonStart.AddWidget(btnStart)
		LayoutButtonStart.AddWidget(sizeBtn)
		LayoutButtonStart.AddWidget(lineSize)
		LayoutButtonStart.AddWidget(btnExit)
	
		LayoutButtonMain.AddLayout(LayoutButtonStart)

		for Row = 1 to size

			LayoutButtonRow[Row] = new QHBoxLayout() {
				setSpacing(C_SPACING)
				setContentsmargins(0,0,0,0)
			}

			for Col = 1 to size
				Button[Row][Col] = new qlabel(win) {
					setFont(new qFont("Calibri",fontsize,2100,0))
					resize(bwidth,bheight)
				} 
				LayoutButtonRow[Row].AddWidget(Button[Row][Col])
			next
			LayoutButtonMain.AddLayout(LayoutButtonRow[Row])

		next

		setLayout(LayoutButtonMain)

		 show()

	}

	exec()
}

###====================================================================================

func newBoardSize()

	nrSize = number(lineSize.text())

	if nrSize = 1
		? "Enter: Size > 1"
		return
	ok

	for Row = 1 to size
		for Col = 1 to size
			Button[Row][Col].settext("")
		next
	next

	newWindow(nrSize)

###====================================================================================

func newWindow(newSize)

	time1 = clock()

	for Row = 1 to size
		for Col = 1 to size
			Button[Row][Col].delete()
		next
	next

	size = newSize

	bwidth  = ceil((win.width() - 8) / size)   
	bheight = ceil((win.height() - 32) / size)

	fontSize = 8 + (300/size)

	if size > 16 
		fontSize = 8 + (150/size)
	ok

	if size < 8
		fontSize = 30 + (150/size)
	ok

	if size = 2
		fontSize = 10 + (100/size)
	ok

	btnStart.setFont(new qFont("Calibri",fontsize,2100,0))
	sizeBtn.setFont(new qFont("Calibri",fontsize,2100,0))
	lineSize.setFont(new qFont("Calibri",fontsize,2100,0))
	btnExit.setFont(new qFont("Calibri",fontsize,2100,0))

	LayoutButtonStart = new QHBoxLayout() {
		setSpacing(C_SPACING)
		setContentsmargins(0,0,0,0)
	}

	Button = newlist(size,size)
	LayoutButtonRow = list(size)

	for Row = 1 to size

		LayoutButtonRow[Row] = new QHBoxLayout() {
			setSpacing(C_SPACING)
			setContentsmargins(0,0,0,0)
		}

		for Col = 1 to size

			Button[Row][Col] = new qlabel(win) {
				setFont(new qFont("Calibri",fontsize,2100,0))
				resize(bwidth,bheight)
			}
			LayoutButtonRow[Row].AddWidget(Button[Row][Col])

		next

		LayoutButtonMain.AddLayout(LayoutButtonRow[Row])

	next

	win.setLayout(LayoutButtonMain)

	return

###====================================================================================

func resizeBoard

	bwidth  = ceil((win.width() - 8) / size)   
	bheight = ceil((win.height() - 32) / size) 

	for Row = 1 to size
		for Col = 1 to size
			Button[Row][Col].resize(bwidth,bheight)
		next
	next

###====================================================================================

Func pExit

	MyApp.quit()

###====================================================================================

func gameSolution()

	a2DSquare = newlist(size,size)
	a2DFinal  = newlist(size,size)

	aList  = 1:size
	aList2 = RandomList(aList)

	GenerateRows(aList2)
	ShuffleCols(a2DSquare, a2DFinal)

	for nRow = 1 to size 
		for nCol = 1 to size
			Button[nRow][nCol].settext("-")
		next 
	next

	for nRow = 1 to size
		for nCol = 1 to size
			Button[nRow][nCol].resize(bwidth,bheight)
			Button[nRow][nCol].settext(string(a2DSquare[nRow][nCol]))
		next
	next

	time2 = clock()
	time3 = (time2 - time1)/1000
	? "Elapsed time: " + time3 + " ms at size = " + size + nl

###====================================================================================

// Scramble the numbers in the List
// Uniq random picks, then shorten list by each pick

Func RandomList(aInput)

    aOutput = []

    while len(aInput) > 1
        nIndex = random(len(aInput)-1)
        nIndex++

        aOutput + aInput[nIndex]
        del(aInput,nIndex)
    end

    aOutput + aInput[1]

return aOutput

###====================================================================================
// Generate Rows of data. Put them in the 2DArray

Func GenerateRows(aInput)

	aOutput = []
	size  = len(aInput)
    shift = 1

	for k = 1 to size									// Make 8 Rows of lists
		aOutput = []
		
		for i = 1 to size           					// make a list
			   pick = i + shift     					// shift every Row by +1 more
			if pick > size   pick = pick - size  ok
	
			aOutput + aInput[pick]
		next
	
		a2DSquare[k] = aOutput							// Row of Output to a2DSquare

		shift++                    						// shift next line by +1 more
		if shift > size  shift = 1 ok
	next

	return

###====================================================================================
// Shift random Rows into a2DFinal, then random Cols

Func ShuffleCols(a2DSquare, a2DFinal)

	aSuffle  = 1:size
    aSuffle2 = RandomList(aSuffle)	// Pick random Col to insert in a2DFinal
	
	for i = 1 to size           	// Row		
		pick = aSuffle2[i]

        for j = 1 to size			// Col
			a2DFinal[i][j] =  a2DSquare[pick][j]  // i-Row-Col j-Horz-Vert
		next
	next

	a2DSquare = a2DFinal			// Now do the verticals
	aSuffle  = 1:size
	aSuffle2 = RandomList(aSuffle)

	for i = 1 to size           	// Row		
		pick = aSuffle2[i]

        for j = 1 to size			// Col
			a2DFinal[j][i] =  a2DSquare[j][pick]  //Reverse i-j , i-Row-Col j-Horz-Vert
		next
	next

	return

###====================================================================================

Random Latin Squares - image

RPL

Translation of: Quackery
Works with: RPL version HP49-C

SHUFL is defined at Knuth shuffle

« → n
  « « k » 'k' 0 n 1 - 1 SEQ
    2 n START 
       DUP TAIL LASTARG HEAD + 
    NEXT
    n →LIST
    SHUFL AXL 
    TRAN AXL 
    SHUFL AXL
» 'RLS' STO
5 RLS
Output:
1: [[ 3 1 4 2 0 ]
    [ 4 2 0 3 1 ]
    [ 2 0 3 1 4 ]
    [ 0 3 1 4 2 ]
    [ 1 4 2 0 3 ]]

Ruby

This crude algorithm works fine up to a square size of 10; higher values take too much time and memory. It creates an array of all possible permutations, picks a random one as first row an weeds out all permutations which cannot appear in the remaining square. Repeat picking and weeding until there is a square.

N = 5

def generate_square
  perms  =  (1..N).to_a.permutation(N).to_a.shuffle
  square = []
  N.times do
    square << perms.pop
    perms.reject!{|perm| perm.zip(square.last).any?{|el1, el2| el1 == el2} }
  end
  square
end

def print_square(square)
  cell_size = N.digits.size + 1
  strings = square.map!{|row| row.map!{|el| el.to_s.rjust(cell_size)}.join }
  puts strings, "\n"
end

2.times{print_square( generate_square)}
Output:

3 4 2 1 5
2 3 4 5 1
1 2 5 3 4
5 1 3 4 2
4 5 1 2 3
1 2 5 4 3
2 3 4 1 5
5 4 2 3 1
3 5 1 2 4
4 1 3 5 2

Wren

Translation of: Go

Restarting Row method

import "random" for Random

var rand = Random.new()

var printSquare = Fn.new { |latin|
    for (row in latin) System.print(row)
    System.print()
}

var latinSquare = Fn.new { |n|
    if (n <= 0) {
        System.print("[]\n")
        return
    }
    var latin = List.filled(n, null)
    for (i in 0...n) {
        latin[i] = List.filled(n, 0)
        if (i == n - 1) break
        for (j in 0...n) latin[i][j] = j
    }

    // first row
    rand.shuffle(latin[0])

    // middle row(s)
    for (i in 1...n-1) {
        var shuffled = false
        while (!shuffled) {
            rand.shuffle(latin[i])
            var shuffling = false
            for (k in 0...i) {
                for (j in 0...n) {
                    if (latin[k][j] == latin[i][j]) {
                        shuffling = true
                        break
                    }
                }
                if (shuffling) break 
            }
            if (!shuffling) shuffled = true
        }
    }

    // last row
    for (j in 0...n) {
        var used = List.filled(n, false)
        for (i in 0...n-1) used[latin[i][j]] = true
        for (k in 0...n) {
            if (!used[k]) {
                latin[n-1][j] = k
                break
            }
        }
    }
    printSquare.call(latin)
}

latinSquare.call(5)
latinSquare.call(5)
latinSquare.call(10) // for good measure
Output:

Sample run:

[4, 1, 2, 0, 3]
[3, 2, 0, 1, 4]
[1, 0, 3, 4, 2]
[0, 3, 4, 2, 1]
[2, 4, 1, 3, 0]

[1, 2, 0, 4, 3]
[2, 4, 3, 0, 1]
[4, 3, 1, 2, 0]
[0, 1, 2, 3, 4]
[3, 0, 4, 1, 2]

[5, 3, 0, 6, 8, 2, 1, 7, 4, 9]
[6, 5, 9, 8, 7, 1, 3, 4, 0, 2]
[7, 6, 8, 4, 2, 0, 9, 1, 3, 5]
[0, 1, 7, 2, 4, 6, 5, 8, 9, 3]
[1, 0, 2, 3, 9, 5, 8, 6, 7, 4]
[3, 7, 5, 0, 1, 9, 4, 2, 8, 6]
[2, 4, 1, 5, 3, 8, 7, 9, 6, 0]
[9, 2, 3, 7, 6, 4, 0, 5, 1, 8]
[8, 9, 4, 1, 5, 3, 6, 0, 2, 7]
[4, 8, 6, 9, 0, 7, 2, 3, 5, 1]

Latin Squares in Reduced Form method

Library: Wren-sort
Library: Wren-fmt
Library: Wren-math
import "random" for Random
import "./sort" for Sort
import "./fmt" for Fmt
import "./math" for Int

var rand = Random.new()
var counts = List.filled(4, 0)
var aa = List.filled(16, 0)

var testSquares = [
    [0, 1, 2, 3, 1, 0, 3, 2, 2, 3, 0, 1, 3, 2, 1, 0],
    [0, 1, 2, 3, 1, 0, 3, 2, 2, 3, 1, 0, 3, 2, 0, 1],
    [0, 1, 2, 3, 1, 2, 3, 0, 2, 3, 0, 1, 3, 0, 1, 2],
    [0, 1, 2, 3, 1, 3, 0, 2, 2, 0, 3, 1, 3, 2, 1, 0]
]

// Checks whether two lists contain the same elements in the same order
var areSame = Fn.new { |l1, l2|
    if (l1.count != l2.count) return false
    for (i in 0...l1.count) {
        if (l1[i] != l2[i]) return false
    }
    return true
}

// generate derangements of first n numbers, with 'start' in first place.
var dList = Fn.new { |n, start|
    var r = []
    start = start - 1  // use 0 basing
    var a = List.filled(n, 0)
    for (i in 0...n) a[i] = i
    var t = a[0]
    a[0] = start
    a[start] = t
    Sort.quick(a, 1, a.count-1, null)
    var first = a[1]
    var recurse  // recursive closure permutes a[1..-1]
    recurse = Fn.new { |last|
        if (last == first) {
            // bottom of recursion.  you get here once for each permutation.
            // test if permutation is deranged.
            var j = 0  // j starts from 0, not 1
            for (v in a.skip(1)) {
                if (j+1 == v) return r  // no, ignore it
                j = j + 1
            }
            // yes, save a copy
            var b = a.toList
            for (i in 0...b.count) b[i] = b[i] + 1  // change back to 1 basing
            r.add(b)
            return r
        }
        var i = last
        while (i >= 1) {
            a.swap(i, last)
            recurse.call(last - 1)
            a.swap(i, last)
            i = i - 1
        }
    }
    recurse.call(n - 1)
    return r
}

var copyMatrix = Fn.new { |m|
    var le = m.count
    var cpy = List.filled(le, null)
    for (i in 0...le) cpy[i] = m[i].toList
    return cpy
}

var reducedLatinSquares = Fn.new { |n|
    var rls = []
    if (n < 0) n = 0
    var rlatin = List.filled(n, null)
    for (i in 0...n) rlatin[i] = List.filled(n, 0)
    if (n <= 1) {
        rls.add(rlatin)
        return rls
    }

    // first row
    for (j in 0...n) rlatin[0][j] = j + 1

    // recursive closure to compute reduced latin squares
    var recurse
    recurse = Fn.new { |i|
        var rows = dList.call(n, i) // get derangements of first n numbers, with 'i' first.
        for (r in 0...rows.count) {
            var outer = false
            rlatin[i-1] = rows[r].toList
            for (k in 0...i-1) {
                for (j in 1...n) {
                    if (rlatin[k][j] == rlatin[i-1][j]) {
                        if (r < rows.count-1) {
                            outer = true
                            break
                        } else if (i > 2) {
                            return
                        }
                    }
                }
                if (outer) break
            }
            if (outer) continue
            if (i < n) {
                recurse.call(i + 1)
            } else {
                var rl = copyMatrix.call(rlatin)
                rls.add(rl)
            }
        }
        return
    }
 
    // remaining rows
    recurse.call(2)
    return rls
}

var printSquare = Fn.new { |latin, n|
    for (i in 0...n) {
        for (j in 0...n) Fmt.write("$d ", latin[i][j]-1)
        System.print()
    }
    System.print()
}

// generate permutations of first n numbers, starting from 0.
var pList = Fn.new { |n|
    var fact  = Int.factorial(n)
    var perms = List.filled(fact, null)
    var a = List.filled(n, 0)
    for (i in 0...n) a[i] = i
    var t = a.toList
    perms[0] = t
    n = n - 1
    for (c in 1...fact) {
        var i = n - 1
        var j = n
        while (a[i] > a[i+1]) i = i - 1
        while (a[j] < a[i])   j = j - 1
        a.swap(i, j)
        j = n
        i = i + 1
        while (i < j) {
            a.swap(i, j)
            i = i + 1
            j = j - 1
        }
        var t = a.toList
        t.add(0)    
        perms[c] = t
    }
    return perms
}

var generateLatinSquares = Fn.new { |n, tests, echo|  
    var rls = reducedLatinSquares.call(n)
    var perms  = pList.call(n)
    var perms2 = pList.call(n - 1)
    for (test in 0...tests) {
        var rn = rand.int(rls.count)
        var rl = rls[rn] // select reduced random square at random
        rn = rand.int(perms.count)
        var rp = perms[rn] // select a random permuation of 'rl's columns
        // permute columns
        var t = List.filled(n, null)
        for (i in 0...n) {
            t[i] = List.filled(n, 0)
            for (j in 0...n) t[i][j] = rl[i][rp[j]]
        }
        rn = rand.int(perms2.count)
        rp = perms2[rn] // select a random permutation of 't's rows 2 to n
        // permute rows 2 to n
        var u = List.filled(n, null)
        for (i in 0...n) {
            u[i] = List.filled(n, 0)
            for (j in 0...n) {
                if (i == 0) {
                    u[i][j] = t[i][j]
                } else {
                    u[i][j] = t[rp[i-1]+1][j]
                }
            }
        }
        if (test < echo) printSquare.call(u, n)
        if (n == 4) {
            for (i in 0..3) {
                for (j in 0..3) u[i][j] = u[i][j] - 1
            }
            for (i in 0..3) {
                for (j in 4*i...4*i+4) {
                    aa[j] = u[i][j - 4*i]
                }
            }
            for (i in 0..3) {
                if (areSame.call(testSquares[i], aa)) {
                    counts[i] = counts[i] + 1
                    break
                }
            }
        }
    }
}

System.print("Two randomly generated latin squares of order 5 are:\n")
generateLatinSquares.call(5, 2, 2)

System.print("Out of 1,000,000 randomly generated latin squares of order 4, ")
System.print("of which there are 576 instances ( => expected 1736 per instance),")
System.print("the following squares occurred the number of times shown:\n")
generateLatinSquares.call(4, 1e6, 0)
for (i in 0..3) System.print("%(testSquares[i]) : %(counts[i])")
System.print("\nA randomly generated latin square of order 6 is:\n")
generateLatinSquares.call(6, 1, 1)
Output:

Sample run:

Two randomly generated latin squares of order 5 are:

1 3 2 4 0 
0 1 3 2 4 
2 4 1 0 3 
3 0 4 1 2 
4 2 0 3 1 

0 2 3 4 1 
3 1 4 2 0 
4 0 2 1 3 
1 4 0 3 2 
2 3 1 0 4 

Out of 1,000,000 randomly generated latin squares of order 4, 
of which there are 576 instances ( => expected 1736 per instance),
the following squares occurred the number of times shown:

[0, 1, 2, 3, 1, 0, 3, 2, 2, 3, 0, 1, 3, 2, 1, 0] : 1749
[0, 1, 2, 3, 1, 0, 3, 2, 2, 3, 1, 0, 3, 2, 0, 1] : 1686
[0, 1, 2, 3, 1, 2, 3, 0, 2, 3, 0, 1, 3, 0, 1, 2] : 1702
[0, 1, 2, 3, 1, 3, 0, 2, 2, 0, 3, 1, 3, 2, 1, 0] : 1764

A randomly generated latin square of order 6 is:

4 5 2 0 1 3 
1 4 5 3 0 2 
3 0 4 5 2 1 
2 1 3 4 5 0 
5 2 0 1 3 4 
0 3 1 2 4 5 

zkl

fcn randomLatinSquare(n,symbols=[1..]){  //--> list of lists
   if(n<=0) return(T);
   square,syms := List(), symbols.walker().walk(n);
   do(n){ syms=syms.copy(); square.append(syms.append(syms.pop(0))) }
   // shuffle rows, transpose & shuffle columns
   T.zip(square.shuffle().xplode()).shuffle();
}
fcn rls2String(square){ square.apply("concat"," ").concat("\n") }
foreach n in (T(1,2,5)){ randomLatinSquare(n) : rls2String(_).println("\n") }
randomLatinSquare(5, ["A".."Z"])   : rls2String(_).println("\n");
randomLatinSquare(10,"!@#$%^&*()") : rls2String(_).println("\n");
Output:
1

1 2
2 1

3 1 4 5 2
4 2 5 1 3
1 4 2 3 5
5 3 1 2 4
2 5 3 4 1

E D A B C
D C E A B
B A C D E
A E B C D
C B D E A

& % # ! * @ ) $ ( ^
@ ) * ^ # & % ( $ !
( & % # ) $ @ ^ ! *
! ( & % @ ^ $ * # )
% # ! ( ^ ) * @ & $
^ $ @ ) & ! ( # * %
# ! ( & $ * ^ ) % @
$ @ ) * % ( & ! ^ #
) * ^ $ ! % # & @ (
* ^ $ @ ( # ! % ) &