Random Latin squares: Difference between revisions

added RPL
(added RPL)
 
(26 intermediate revisions by 9 users not shown)
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>
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:
Line 15:
 
;Note:
Strict ''Uniformityuniformity'' 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:
Line 25 ⟶ 29:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">F _transpose(matrix)
assert(matrix.len == matrix[0].len)
V r = [[0] * matrix.len] * matrix.len
Line 70 ⟶ 74:
print(square.map(row -> row.join(‘ ’)).join("\n"))
_check(square)
print()</langsyntaxhighlight>
 
{{out}}
Line 96 ⟶ 100:
 
=={{header|Action!}}==
<langsyntaxhighlight Actionlang="action!">DEFINE PTR="CARD"
DEFINE DIMENSION="5"
 
Line 219 ⟶ 223:
PutE()
OD
RETURN</langsyntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Random_Latin_squares.png Screenshot from Atari 8-bit computer]
Line 234 ⟶ 238:
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>
 
=={{header|Arturo}}==
 
<langsyntaxhighlight lang="rebol">latinSquare: function [n][
square: new []
variants: shuffle permutate 0..n-1
Line 261 ⟶ 379:
print row
print "---------"
]</langsyntaxhighlight>
 
{{out}}
Line 279 ⟶ 397:
=={{header|C}}==
{{trans|C++}}
<langsyntaxhighlight lang="c">#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
Line 396 ⟶ 514:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>[1, 4, 3, 0, 2]
Line 423 ⟶ 541:
=={{header|C++}}==
{{trans|Java}}
<langsyntaxhighlight lang="cpp">#include <algorithm>
#include <chrono>
#include <iostream>
Line 516 ⟶ 634:
latinSquare(10);
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>[4, 3, 1, 2, 0]
Line 543 ⟶ 661:
=={{header|C sharp|C#}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
 
Line 647 ⟶ 765:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>[3, 0, 1, 4, 2]
Line 674 ⟶ 792:
=={{header|D}}==
{{trans|C#}}
<langsyntaxhighlight lang="d">import std.array;
import std.random;
import std.stdio;
Line 746 ⟶ 864:
 
latinSquare(10);
}</langsyntaxhighlight>
{{out}}
<pre>[2, 4, 3, 1, 0]
Line 770 ⟶ 888:
[7, 0, 6, 2, 5, 4, 3, 8, 1, 9]
[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#}}==
This solution uses functions from [[Factorial_base_numbers_indexing_permutations_of_a_collection#F.23]] and [[Latin_Squares_in_reduced_form#F.23]]. ThisIt 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 canto thatdo really be called hard?so.
<langsyntaxhighlight lang="fsharp">
// 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()
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 819 ⟶ 1,011:
 
=={{header|Factor}}==
A brute force method for generating uniformly random 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.
<langsyntaxhighlight lang="factor">USING: arrays combinators.extras fry io kernel math.matrices
prettyprint random sequences sets ;
IN: rosetta-code.random-latin-squares
Line 830 ⟶ 1,022:
: random-latin-squares ( -- ) [ 5 ls simple-table. nl ] twice ;
 
MAIN: random-latin-squares</langsyntaxhighlight>
{{out}}
<pre>
Line 845 ⟶ 1,037:
3 1 2 4 0
</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}}==
===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.
<langsyntaxhighlight lang="go">package main
 
import (
Line 928 ⟶ 1,199:
latinSquare(5)
latinSquare(10) // for good measure
}</langsyntaxhighlight>
 
{{out}}
Line 959 ⟶ 1,230:
===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.
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,211 ⟶ 1,482:
fmt.Println("\nA randomly generated latin square of order 6 is:\n")
generateLatinSquares(6, 1, 1)
}</langsyntaxhighlight>
 
{{out}}
Line 1,255 ⟶ 1,526:
given first row and first column.
 
<langsyntaxhighlight lang="haskell">import Data.List (permutations, (\\))
 
latinSquare :: Eq a => [a] -> [a] -> [[a]]
Line 1,282 ⟶ 1,553:
putStrLn $
unlines $
unwords . map show <$> tbl</langsyntaxhighlight>
 
<pre>λ> printTable $ latinSquare [1,2,3,4,5] [1,3,2,5,4]
Line 1,294 ⟶ 1,565:
the deterministic algorithm.
 
<langsyntaxhighlight lang="haskell">randomLatinSquare :: Eq a => [a] -> Random [[a]]
randomLatinSquare set = do
r <- randomPermutation set
c <- randomPermutation (tail r)
return $ latinSquare r (head r:c)</langsyntaxhighlight>
 
For examples a naive linear congruent method in a State monad is used.
 
<langsyntaxhighlight lang="haskell">import Control.Monad.State
 
type Random a = State Int a
Line 1,322 ⟶ 1,593:
 
randomSample :: [a] -> Random a
randomSample lst = (lst !!) <$> random (length lst)</langsyntaxhighlight>
 
<pre>λ> printTable $ randomLatinSquare [0..4] `evalState` 42
Line 1,345 ⟶ 1,616:
 
=={{header|J}}==
<langsyntaxhighlight lang="j">rls=: 3 : 0
s=. ?~ y NB. "deal" y unique integers from 0 to y
for_ijk. i.<:y do.
Line 1,356 ⟶ 1,627:
end.
)
</syntaxhighlight>
</lang>
{{out}}
<pre> rls 5
Line 1,373 ⟶ 1,644:
=={{header|Java}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="java">import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
Line 1,458 ⟶ 1,729:
latinSquare(10);
}
}</langsyntaxhighlight>
{{out}}
<pre>[1, 3, 4, 0, 2]
Line 1,484 ⟶ 1,755:
 
=={{header|Javascript}}==
<langsyntaxhighlight lang="javascript">
class Latin {
constructor(size = 3) {
Line 1,537 ⟶ 1,808:
}
new Latin(5);
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 1,551 ⟶ 1,822:
1 2 3 5 4
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>
 
=={{header|Julia}}==
Using the Python algorithm as described in the discussion section.
<langsyntaxhighlight lang="julia">using Random
 
shufflerows(mat) = mat[shuffle(1:end), :]
Line 1,586 ⟶ 2,213:
 
printlatinsquare(5), println("\n"), printlatinsquare(5)
</langsyntaxhighlight>{{out}}
<pre>
1 3 0 4 2
Line 1,604 ⟶ 2,231:
=={{header|Kotlin}}==
{{trans|Go}}
<langsyntaxhighlight lang="scala">typealias matrix = MutableList<MutableList<Int>>
 
fun printSquare(latin: matrix) {
Line 1,661 ⟶ 2,288:
latinSquare(5)
latinSquare(10) // for good measure
}</langsyntaxhighlight>
{{out}}
<pre>[4, 1, 2, 3, 0]
Line 1,694 ⟶ 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.
 
<syntaxhighlight lang="m2000 interpreter">
<lang M2000 Interpreter>
Module FastLatinSquare {
n=5
Line 1,745 ⟶ 2,372:
End Sub
}
FastLatinSquare</langsyntaxhighlight>
 
===Hard Way===
Line 1,754 ⟶ 2,381:
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) {
If Not Exist(f$) Or NewFile Then
Line 1,829 ⟶ 2,456:
LatinSquare 16
 
</syntaxhighlight>
</lang>
{{out}}
<pre style="height:30ex;overflow:scroll">
Line 1,864 ⟶ 2,491:
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">Clear[RandomLatinSquare]
RandomLatinSquare[n_] := Module[{out, ord},
out = Table[RotateLeft[Range[n], i], {i, n}];
Line 1,872 ⟶ 2,499:
out
]
RandomLatinSquare[5] // Grid</langsyntaxhighlight>
{{out}}
<pre>5 2 4 1 3
Line 1,886 ⟶ 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.
 
<langsyntaxhighlight Nimlang="nim">import random, sequtils, strutils
 
type LatinSquare = seq[seq[char]]
Line 1,929 ⟶ 2,556:
echo latinSquare(5)
echo latinSquare(5)
echo latinSquare(10)</langsyntaxhighlight>
 
{{out}}
Line 1,954 ⟶ 2,581:
J A I C G B D H E F
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}}==
{{trans|Raku}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
Line 1,989 ⟶ 2,827:
}
 
say display random_ls($_) for 2..5, 5;</langsyntaxhighlight>
{{out}}
<pre>B A
Line 2,017 ⟶ 2,855:
=={{header|Phix}}==
Brute force, begins to struggle above 42.
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<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>
Line 2,083 ⟶ 2,921:
<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>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 2,170 ⟶ 3,008:
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.
 
<langsyntaxhighlight Picatlang="picat">main =>
_ = random2(), % random seed
N = 5,
Line 2,205 ⟶ 3,043:
nl
end,
nl.</langsyntaxhighlight>
 
{{out}}
Line 2,287 ⟶ 3,125:
===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.
<langsyntaxhighlight Picatlang="picat">main =>
foreach(N in 1..6)
Count = count_all(latin_square(N,_)),
println(N=Count)
end.</langsyntaxhighlight>
 
{{out}}
Line 2,306 ⟶ 3,144:
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">from random import choice, shuffle
from copy import deepcopy
 
Line 2,366 ⟶ 3,204:
print(_to_text(square))
_check(square)
print()</langsyntaxhighlight>
 
{{out}}
Line 2,401 ⟶ 3,239:
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>
 
=={{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}}==
Line 2,407 ⟶ 3,285:
{{trans|Python}}
 
<syntaxhighlight lang="raku" perl6line>sub latin-square { [[0],] };
 
sub random ( @ls, :$size = 5 ) {
Line 2,441 ⟶ 3,319:
 
# Or, if you'd prefer:
display random latin-square, :size($_) for 12, 2, 1;</langsyntaxhighlight>
{{out|Sample output}}
<pre> V Z M J U
Line 2,491 ⟶ 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.
<langsyntaxhighlight lang="rexx">/*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.*/
Line 2,506 ⟶ 3,384:
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. */</langsyntaxhighlight>
{{out|output|text=&nbsp; for 1<sup>st</sup> run when using the default inputs:}}
<pre>
Line 2,525 ⟶ 3,403:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
load "stdlib.ring"
load "guilib.ring"
Line 2,871 ⟶ 3,749:
###====================================================================================
 
</syntaxhighlight>
</lang>
 
[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}}==
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.
<langsyntaxhighlight lang="ruby">N = 5
 
def generate_square
Line 2,896 ⟶ 3,799:
 
2.times{print_square( generate_square)}
</syntaxhighlight>
</lang>
{{out}}<pre>
3 4 2 1 5
Line 2,915 ⟶ 3,818:
{{trans|Go}}
===Restarting Row method===
<langsyntaxhighlight ecmascriptlang="wren">import "random" for Random
 
var rand = Random.new()
Line 2,974 ⟶ 3,877:
latinSquare.call(5)
latinSquare.call(5)
latinSquare.call(10) // for good measure</langsyntaxhighlight>
 
{{out}}
Line 3,007 ⟶ 3,910:
{{libheader|Wren-fmt}}
{{libheader|Wren-math}}
<langsyntaxhighlight ecmascriptlang="wren">import "random" for Random
import "./sort" for Sort
import "./fmt" for Fmt
import "./math" for Int
 
var rand = Random.new()
Line 3,222 ⟶ 4,125:
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)</langsyntaxhighlight>
 
{{out}}
Line 3,261 ⟶ 4,164:
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">fcn randomLatinSquare(n,symbols=[1..]){ //--> list of lists
if(n<=0) return(T);
square,syms := List(), symbols.walker().walk(n);
Line 3,268 ⟶ 4,171:
T.zip(square.shuffle().xplode()).shuffle();
}
fcn rls2String(square){ square.apply("concat"," ").concat("\n") }</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">foreach n in (T(1,2,5)){ randomLatinSquare(n) : rls2String(_).println("\n") }
randomLatinSquare(5, ["A".."Z"]) : rls2String(_).println("\n");
randomLatinSquare(10,"!@#$%^&*()") : rls2String(_).println("\n");</langsyntaxhighlight>
{{out}}
<pre>
1,150

edits