А верно же, что имея элементы группы в виде произведения образующих можно восстановить всю таблицу умножения группы всего лишь по столбцам, соответствующим умножению на эти образующие?
На самом деле даже имена элементов не нужны. Достаточно только столбцов с результатом умножения на образующие. В случае групп, получаемых из двух образующих, достаточно всего двух столбцов, даже если в группе тысяча элементов. Забавно, как много излишней информации содержится в таблице умножения. Ниже процедура, выполняющая восстановление таблицы умножения:
int[][] restoreTable(int[][] arg) {
int k, l, m, size, number;
int[][] references, result;
size = arg.length;
number = arg[0].length;
references = new int[size][number];
result = new int[size][size];
for (k = 0; size > k; ++k) {
result[k][0] = k;
for (l = 1; number >= l; ++l) {
m = arg[k][l - 1];
result[k][l] = m;
if (0 == references[m][1]) {
references[m][0] = k;
references[m][1] = l;
}
}
}
for (k = number + 1; size > k; ++k) {
for (l = 0; size > l; ++l) {
result[l][k] = result[result[l][references[k][0]]][references[k][1]];
}
}
return result;
}
Таблица умножения группы восстанавливается по массиву
arg, содержащим результаты умножения элементов группы на образующие группы, которые являются элементами с номерами от 1 до
number включительно. Всего в группе
size элементов и они нумеруются от нуля. При этом в исходном массиве
arg номера умножаемых элементов совпадают с номером строки, а элементы со старшими номерами всегда можно получить произведением элементов с младшими номерами. Последнее требование необходимо для того, чтобы второй внешний цикл мог перебирать элементы просто один за одним в порядка возрастания номера, и оно автоматически выполняется при построении списка элементов в виде дерева, как в моих предыдущих программах.
Каждый элемент
группы можно представить как другой элемент
группы, умноженный на одну из образующих
. Поэтому столбец умножения на элемент
получается из столбца умножения на элемент
перестановкой, задаваемой умножением на образующую
. Программа выше заполняет столбец умножения на единичный элемент (тривиальная перестановка), столбцы умножения на образующие, беря их из исходного массива
arg, а затем — все остальные столбцы, применяя это правило.