Task: Random Latin squares


C++: #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;
    }

    
    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);
    }
    
    std::shuffle(latin[0].begin(), latin[0].end(), g);

    
    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: {}
        }
    }

    
    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;
}






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()