For a recent experiment I used the method presented here to generate a balanced latin square for selecting participant condition orders. Rather than do this manually, I wrote a couple of functions to do this automatically for squares of any size. Here’s an implementation in both C# and R!
C#
public static int[,] GetLatinSquare(int n) { // 1. Create initial square. int[,] latinSquare = new int[n, n]; // 2. Initialise first row. latinSquare[0, 0] = 1; latinSquare[0, 1] = 2; for (int i = 2, j = 3, k = 0; i < n; i++) { if (i % 2 == 1) latinSquare[0, i] = j++; else latinSquare[0, i] = n - (k++); } // 3. Initialise first column. for (int i = 1; i <= n; i++) { latinSquare[i - 1, 0] = i; } // 4. Fill in the rest of the square. for (int row = 1; row < n; row++) { for (int col = 1; col < n; col++) { latinSquare[row, col] = (latinSquare[row - 1, col] + 1) % n; if (latinSquare[row, col] == 0) latinSquare[row, col] = n; } } return latinSquare; }
R
LatinSquare <- function(n) { # 1. Create initial square. sq <- matrix(0, n, n) # 2. Initialise first row. sq[1, 1] <- 1 sq[1, 2] <- 2 j <- 3 k <- 0 for (i in 3:n) { if (i %% 2 == 0) { sq[1, i] <- j j <- j + 1 } else { sq[1, i] <- n - k k <- k + 1 } } # 3. Initialise first column. for (i in 2:(n+1)) { sq[i - 1, 1] <- i - 1 } # 4. Fill in the rest of the square. for (row in 2:n) { for (col in 2:n) { sq[row, col] <- (sq[row - 1, col] + 1) %% n if (sq[row, col] == 0) { sq[row, col] = n } } } return (sq) }