C #, 520 506 494 484 байта
class P{static void Main(string[]a){int n=int.Parse(a[0]);int[,,]m=new int[n,n,2];int i=n,j,k,p,I,J;R:for(;i-->0;)for(j=n;j-->0;)for(k=2;k-->0;)if((m[i,j,k]=(m[i,j,k]+ 1) % n)!=0)goto Q;Q:for(i=n;i-->0;)for(j=n;j-->0;){for(k=2;k-->0;)for(p=n;p-->0;)if(p!=i&&m[i,j,k]==m[p,j,k]||p!=j&&m[i,j,k]==m[i,p,k])goto R;for(I=i;I<n;I++)for(J=0;J<n;J++)if(I!=i&&J!=j&&m[i,j,0]==m[I,J,0]&&m[i,j,1]==m[I,J,1])goto R;}for(i=n;i-->0;)for(j=n;j-->0;)System.Console.Write(m[i,j,0]+"-"+m[i,j,1]+" ");}}
Алгоритм поиска квадрата очень прост. Это ... грубая сила. Да, это глупо, но код-гольф не связан со скоростью программы, верно?
Код перед тем, как сделать его короче:
using System;
public class Program
{
static int[,,] Next(int[,,] m, int n){
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
for (int k = 0; k < 2; k++)
{
if ((m[i, j, k] = (m[i, j, k] + 1) % n) != 0)
{
return m;
}
}
}
}
return m;
}
static bool Check(int[,,] m, int n)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
for (int k = 0; k < 2; k++)
{
for (int p = 0; p < n; p++)
{
if (p != i)
if (m[i, j, k] == m[p, j, k])
return false;
}
for (int p = 0; p < n; p++)
{
if (p != j)
if (m[i, j, k] == m[i, p, k])
return false;
}
}
}
}
for (int i_1 = 0; i_1 < n; i_1++)
{
for (int j_1 = 0; j_1 < n; j_1++)
{
int i_2 = i_1;
for (int j_2 = j_1 + 1; j_2 < n; j_2++)
{
if (m[i_1, j_1, 0] == m[i_2, j_2, 0] && m[i_1, j_1, 1] == m[i_2, j_2, 1])
return false;
}
for (i_2 = i_1 + 1; i_2 < n; i_2++)
{
for (int j_2 = 0; j_2 < n; j_2++)
{
if (m[i_1, j_1, 0] == m[i_2, j_2, 0] && m[i_1, j_1, 1] == m[i_2, j_2, 1])
return false;
}
}
}
}
return true;
}
public static void Main()
{
int n = 3;
Console.WriteLine(n);
int maxi = (int)System.Math.Pow((double)n, (double)n*n*2);
int[,,] m = new int[n, n, 2];
Debug(m, n);
do
{
m = Next(m, n);
if (m == null)
{
Console.WriteLine("!");
return;
}
Console.WriteLine(maxi--);
} while (!Check(m, n));
Debug(m, n);
}
static void Debug(int[,,] m, int n)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
Console.Write(m[i, j, 0] + "-" + m[i, j, 1] + " ");
}
Console.WriteLine();
}
Console.WriteLine();
}
}
Теперь, если вы хотите проверить это с n = 3, вам придется ждать как час, так что вот другая версия:
public static void Main()
{
int n = 3;
Console.WriteLine(n);
int maxi = (int)System.Math.Pow((double)n, (double)n*n*2);
int[,,] result = new int[n, n, 2];
Parallel.For(0, n, (I) =>
{
int[,,] m = new int[n, n, 2];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
{
m[i, j, 0] = I;
m[i, j, 1] = I;
}
while (true)
{
m = Next(m, n);
if (Equals(m, n, I + 1))
{
break;
}
if (Check(m, n))
{
Debug(m, n);
}
}
});
}
Обновление: забыл удалить "публичный".
Обновление: используется «Система». вместо «использования системы»; Также, благодаря Кевину Круйссену , использовали «а» вместо «args».
Обновление: спасибо гастропнеру и кому-то .