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


C#: using System;
using System.Collections.Generic;

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

    
    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);
            }
            
            latin[0].Shuffle();

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

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