Латинские квадраты, или Квадратно-гнездовой посев чисел в Delphi

Латинскими квадратами называют таблицы, в которых каждая строка и каждый столбец содержат по 1 разу все латинские буквы, начиная с А. Об­щее количество разных букв определяется размерами квадрата. Например, для квадрата 4 х 4 клетки в каждом столбце и строке будут расположены буквы A, B, C, D.

Важно отметить, что в диагоналях буквы могут и повторяться.

Хотя первоначально таблицы заполнялись латинскими буквами (что и да­ло название квадрату), гораздо удобнее расставлять в клетках числа от 1 до размерности квадрата.

 

Теорию построения латинских квадратов разработал великий швейцарский учёный Леонард Эйлер. Сейчас латинские квадраты используют при планировании экспериментов (например, при исследовании урожайности различных сортов злаков), в теории кодирования, в секретной связи. Бо­лее «легкомысленное» применение латинских квадратов мы найдём в го­ловоломках - сквэрвордах, футошики, диаго и всем известных судоку.

 

 

Но нас интересуют сейчас латинские квадраты не сами по себе, а только как таблицы, заполненные числами, то есть двумерные массивы.

Интерфейс программы нам уже хорошо знаком, поэтому сразу нажмём кнопку с волшебной палочкой, которая всё за нас и решит:

 


procedure TfrmMain.sbtSolveClick(Sender: TObject);
begin
generate(speNum.Value);

Delphi

Конечно, никакое чудо не произойдёт, если его заранее не подготовить:


//ГЕНЕРИРОВАТЬ 1 ЛАТИНСКИЙ КВАДРАТ procedure generate(number: integer); var i,j,k,n,x: integer;
B,C,D: array[1..20] of integer;
s: string; time,time0: single;
field: array[0..20,0..20] of integer;
begin
Randomize;
frmMain.lstProtokol.Clear; time0:=GetTickCount(); //засечь начало
for i:= 1 to number do begin B:= i; C:= i; D:= i; end;
n:= number;
//формируем «случайный» столбец: for i:= 1 to number do begin x:= random(n)+1;
B:= C[x]; dec(n);
for k:= x to n do C[k]:= C[k+1];
end;
n:= number;
//формируем «случайную» строку: for i:= 1 to number do begin x:= random(n)+1;
 
C:= D[x]; dec(n);
for k:= x to n do D[k]:= D[k+1];
end;
//составляем случайный латинский квадрат: for j:= 1 to number do
for i:= 1 to number do begin n:= B[j]+C;
if n > number then n:= n - number; field[j,i]:= n; end;
for j:= 1 to number do begin s: = ’’;
for i := 1 to number do begin
if field[i,j] < 10 then s:= s + ’   ’
else s:= s + ’ ’;
s:= s + inttostr(field[i,j]); end;
frmMain.lstProtokol.Items.Add(s);
end;
time:=(GetTickCount()-time0)/1000; str(time:6:3,s);
frmMain.lstProtokol.Items.Add('');
 
frmMain.lstProtokol.Items.Add(’Time ’ + s + ’ s’); application.ProcessMessages; end;

Хитроумный алгоритм, по которому генерируется случайный латинский квадрат, мы разбирать не будем, однако заметим, что для его реализации нам потребовались 3 вспомогательных одномерных массива B, C, D:

B,C,D: array[1..20] of integer;

Для самого латинского квадрата мы подготовим двумерный массив:

field: array[1..20,1..20] of integer;

 

После заполнения и перемешивания массивов B и C в двух циклах for из них составляется латинский квадрат: 


for j:= 1 to number do
for i:= 1 to number do begin n:= B[j]+C; 
if n > number then n:= n - number; field[j,i]:= n; end;

Ну, а дальше остаётся только вывести результат в окно списка.

 

Нажимая волшебную кнопку вновь и вновь, вы будете получать каждый раз новый латинский квадрат, который вы легко сможете сохранить на диске.

Программа благодаря хорошему алгоритму генерирует латинские квадра­ты практически мгновенно, хотя это не так просто - попробуйте сами со­ставить хотя бы маленький квадрат!

������� ������ ��� dle ������� ��������� ������

Помоги проекту! Расскажи друзьям об этом сайте: