Using serpentine matrices and reflections on their columns of even order we present a computer program that generates a large class of semi-magic squares and magic squares.
Computation of Semi-Magic Squares Generated by Serpentine Matrices
1. Computation of Semi-Magic Squares
Generated by Serpentine Matrices
L’hau˜ Barbosa Pereira de Miranda, Coordena¸ao de ADS, IFPI, Pra¸a da
a c˜ c
Liberdade, 1597, Teresina, PI, Brasil, l4u4n.00@gmail.com
Liuhan Oliveira de Miranda, Coordena¸ao Pedag´gica, Instituto Antoine
c˜ o
Lavoisier de Ensino, Rua Firmino Pires, 787 Sul, Teresina, PI, Brasil,
liuhan− 100@hotmail.com
Lohans de Oliveira Miranda, Coordena¸ao Pedag´gica, Instituto Antoine
c˜ o
Lavoisier de Ensino, Rua Firmino Pires, 787 Sul, Teresina, PI, Brasil,
snahol@hotmail.com.
Lossian Barbosa Bacelar Miranda, Coordena¸˜o de Matem´tica, IFPI,
ca a
Pra¸a da Liberdade, 1597, 64000-040, Teresina, PI, Brasil,
c
lossian@oi.com.br.
Abstract. Using serpentine matrices and reflections on their columns of even
order we present a computer program that generates a large class of semi-
magic squares and magic squares.
Keywords: semi-magic squares, snake-shaped matrices, arithmetic progres-
sions, java language.
1. Introduction
Methods have been developed for the construction of magic rectangles
from snake-shaped matrices (see reference [1]), which consist of two steps.
In this paper we present an alternative method, which also makes use of
snake-shaped matrices, consisting of three steps. The first step is the same
as established in the literature and the second, slightly different. The third
is a problem of combining the solution of which provides a variety of semi-
magic squares. Our approach is restricted to the squares of even order, but
applies to any rectangles with even numbers of rows and columns. To make
the construction three procedures (steps) can be used on the lines instead
of columns. Similar result is achieved by making it the second procedure
(reflection) on the columns of odd order.
1
2. 2. Definitions and notations
Consider a square matrix of even order A = (aij ) , n > 2, with aij ∈
I = {1, 2, 3, ..., n2 } and such that aij = akl ⇔ i = k ∧ j = l. The aij
n2
elements are called entries. We denote the row of order k by (akj )j=1,2,...,n =
[ak1 , ak2 , ..., akn ] and the column of order k by (ajk )j=1,2,...,n = [a1k , a2k , ..., ank ]t .
n n n(n2 +1)
If j=1 akj = i=1 ail = 2
, ∀k, l ∈ In2 , we say that A is a semi-magic
n(n2 +1)
square with the magic constant c(n) = 2
. The columns [a1k , a2k , ..., ank ]t
t
and ank , a(n−1)k , ..., a1k are said reflected from each other and we call re-
flection the procedure for changing aik by a(n−i+1)k for any i ∈ I n . We call
2
the snake-shaped matrix the square matrix A = (aij )n×n defined by
n(i − 1) + j if i = 1, 3, 5, ..., (n − 1)
aij = (1)
ni − (j − 1) if i = 2, 4, 6, ..., n
Using (1) it is noticed that the sum of all the elements of any column of
a snake-shaped matrix is equal to the magic constant. If all n columns of
2
an even order snake-shaped matrix suffer a reflection, we will have a snake-
shaped matrix with reflected columns of even orders.
3. Main Results
The following are the main results.
PROPOSITION 1. If A = (aij )n×n , n > 2 , is snake-shaped matrix with re-
flected columns of even orders, then: (i) n a[(2k−1)+2s]j = n a(2k−1)j =
j=1 j=1
c(n) − n , k ∈ I( n −1) , s ∈ I( n −k) ; (ii) n a(2k+2s)j = n a(2k)j =
2 2 2 j=1 j=1
c(n) + n , k ∈ I( n −1) , s ∈ I( n −k) .
2 2 2
Proof. See reference [6]
PROPOSITION 2. Every snake-shaped matrix with reflected columns of
even orders A = (aij )n×n can be transformed into a semi-magic square from
the swap of entries with the forms a(2k−1)j and a(2k)j , k ∈ I n , j ∈ In .
2
Proof. See reference [6].
4. Computer Program
Proposition 2 generates the following problem: If n > 2 is even, find all
sums (without repetition of plots) of the elements of the set Ω = {3, 7, 11, ..., (2n − 1)}∪
2
3. {−1, −5, −9, ..., −(2n − 3)} that are equal to n .
2
To schedule a resolution of the above problem we use the programming
language Java. We also use IDE Eclipse e Netbeans.
The following are the source codes of the program. This program may be
seen in reference [4].
4.1. Classe Combinacao
import java.util.ArrayList;
class Combinacao {
private ArrayList<Integer> parcelas = new ArrayList<Integer>();
private int soma;
public Combinacao() { }
public Combinacao(ArrayList<Integer> array) {
addArray(array);
calculaSomatorio();
}
public ArrayList<Integer> getParcelas() { return parcelas; }
public int getSoma() { return soma; }
public void setSoma(int valor) { soma = valor; }
public void calculaSomatorio() {
int resultado = 0;
for (int i = 0; i < parcelas.size();i++) {
resultado += parcelas.get(i);
}
soma = resultado;
}
public void addArray(ArrayList<Integer> array) {
for (int i = 0; i < array.size(); i++) {
parcelas.add(array.get(i));
}
}
public ArrayList<Integer> addParcela(int numero) {
parcelas.add(numero);
return parcelas;
}
public String toString() {
return "" + parcelas;
}
}
4.2. Classe Solucao
public class Solucao {
private Combinacao combinacao1 = new Combinacao();
3
4. private Combinacao combinacao2 = new Combinacao();
public Solucao(Combinacao c1, Combinacao c2) {
this.combinacao1.addArray(c1.getParcelas());
this.combinacao1.setSoma(c1.getSoma());
this.combinacao2.addArray(c2.getParcelas());
this.combinacao2.setSoma(c2.getSoma());
}
public Combinacao getCombinacao1() { return this.combinacao1; }
public Combinacao getCombinacao2() { return this.combinacao2; }
}
4.3. Classe Listas
import java.util.ArrayList;
public class Listas {
private int numeroPar;
private ArrayList<Integer> listaA = new ArrayList<Integer>();
private ArrayList<Integer> listaB = new ArrayList<Integer>();
private ArrayList<Combinacao> combinacoesListaA = new ArrayList<Combinacao>();
private ArrayList<Combinacao> combinacoesListaB = new ArrayList<Combinacao>();
private ArrayList<Solucao> listaDeSolucoes = new ArrayList<Solucao>();
private ArrayList<ArrayList<Integer>> listaPermutaSolucao =
new ArrayList<ArrayList<Integer>>();
private int vetorOmega[];
public Listas(int num) {
numeroPar = num;
geraListaAeB();
geraCombinacoes();
geraSolucoes();
geraVetorOmega();
geraListaPermutaSolucao();
}
public ArrayList<Integer> getListaA() {
return listaA;
}
public ArrayList<Integer> getListaB() {
return listaB;
}
public int[] getVetorOmega() {
return vetorOmega;
}
public ArrayList<ArrayList<Integer>> getListaPermutaSolucao() {
return listaPermutaSolucao;
}
public ArrayList<Solucao> getListaDeSolucoes() {
return listaDeSolucoes;
}
public void geraListaAeB() {
for (int i = 2, cont = 0; cont != numeroPar / 2; i = i + 2, cont++) {
listaA.add((2 * i) - 1);
listaB.add((2 * i) - 3);
4
5. }
}
public void geraListaPermutaSolucao() {
ArrayList<Integer> arrayVazio = new ArrayList<Integer>();
ArrayList<Integer> array = new ArrayList<Integer>();
for (int i = 0; i < listaDeSolucoes.size(); i++) {
array.add(i);
}
geraListaPermutaSolucao(arrayVazio, array);
}
private void geraListaPermutaSolucao(ArrayList<Integer> arrayInicial,
ArrayList<Integer> array) {
int N = numeroPar / 2;
if (arrayInicial.size() == N) {
listaPermutaSolucao.add(arrayInicial);
} else {
for (int i = 0; i < array.size(); i++) {
geraListaPermutaSolucao(adicionaNumero(arrayInicial, array.get(i)), array);
}
}
}
public void geraVetorOmega() {
vetorOmega = new int[numeroPar];
vetorOmega[numeroPar-1] = 1;
vetorOmega[numeroPar-2] = 3;
if (numeroPar >= 4) {
for (int i = numeroPar-3, cont = 0; cont != (numeroPar-2)/2; i = i-2, cont++) {
vetorOmega[i] = vetorOmega[i + 2] + 4;
}
for (int i = numeroPar-4, cont = 0; cont != (numeroPar-2)/2; i = i-2, cont++) {
vetorOmega[i] = vetorOmega[i+2]+4;
}
}
}
public void geraCombinacoes() {
ArrayList<Integer> arrayVazio = new ArrayList<Integer>();
geraCombinacoesListaA(arrayVazio, listaA);
geraCombinacoesListaB(arrayVazio, listaB);
}
public void geraCombinacoesListaA(ArrayList<Integer> arrayInicial,
ArrayList<Integer> lista) {
Combinacao p = new Combinacao(arrayInicial);
if (!arrayInicial.isEmpty()) {
combinacoesListaA.add(p);
}
for (int i = 0; i < lista.size(); i++) {
geraCombinacoesListaA(adicionaNumero(
arrayInicial, lista.get(i)), cortaArray(lista, i+1));
}
}
public void geraCombinacoesListaB(ArrayList<Integer> arrayInicial,
ArrayList<Integer> lista) {
Combinacao p = new Combinacao(arrayInicial);
combinacoesListaB.add(p);
for (int i = 0; i < lista.size(); i++) {
geraCombinacoesListaB(adicionaNumero(
5
6. arrayInicial, lista.get(i)), cortaArray(lista, i+1));
}
}
public ArrayList<Integer> adicionaNumero(ArrayList<Integer> array, int numero) {
ArrayList<Integer> arrayAuxiliar = new ArrayList<Integer>(array);
arrayAuxiliar.add(numero);
return arrayAuxiliar;
}
public ArrayList<Integer> cortaArray(ArrayList<Integer> array, int indice) {
ArrayList<Integer> arrayAuxiliar = new ArrayList<Integer>(array);
for (int i = 0; i < indice; i++) {
arrayAuxiliar.remove(0);
}
return arrayAuxiliar;
}
public void geraSolucoes() {
for (int i = 0; i < combinacoesListaA.size(); i++) {
for (int j = 0; j < combinacoesListaB.size(); j++) {
if (combinacoesListaA.get(i).getSoma()
- combinacoesListaB.get(j).getSoma() == numeroPar/2) {
Solucao s = new Solucao(combinacoesListaA.get(i),
combinacoesListaB.get(j));
listaDeSolucoes.add(s);
}
}
}
}
public void imprimeListaA() {
System.out.println(listaA);
}
public void imprimeListaB() {
System.out.println(listaB);
}
public void imprimeCombinacaoesListaA() {
for (int i = 0; i < combinacoesListaA.size(); i++) {
System.out.println(combinacoesListaA.get(i).getParcelas());
}
}
public void imprimeCombinacaoesListaB() {
for (int i = 0; i < combinacoesListaB.size(); i++) {
System.out.println(combinacoesListaB.get(i).getParcelas());
}
}
public void imprimeListaDeSolucoes() {
for (int i = 0; i < listaDeSolucoes.size(); i++) {
System.out.println("nSolucao " + (i + 1) + ":n"
+ listaDeSolucoes.get(i).getCombinacao1() + " - "
+ listaDeSolucoes.get(i).getCombinacao2() + " "
+ listaDeSolucoes.get(i).getCombinacao1().getSoma()
+ " - " + listaDeSolucoes.get(i).getCombinacao2().getSoma());
}
}
}
6
7. 4.4. Classe Matriz
import java.text.DecimalFormat;
import java.util.ArrayList;
public class Matriz {
private int linhas;
private int colunas;
private int[][] matriz;
private Listas listas;
public Matriz(int n) {
linhas = n;
colunas = n;
matriz = new int[linhas][colunas];
listas = new Listas(n);
}
public int[][] copiaMatriz(int matr[][]) {
int matriz_aux[][] = new int[linhas][colunas];
for (int i = 0; i < linhas; i++) {
for (int j = 0; j < colunas; j++) {
matriz_aux[i][j] = matr[i][j];
}
}
return matriz_aux;
}
public void constroiMatrizSerpentiforme() {
for (int i = 0; i < linhas; i = i + 2) {
for (int j = 0; j < colunas; j++) {
matriz[i][j] = i * linhas + j + 1;
}
}
for (int i = 1, cont = 1; i < linhas; i = i + 2, cont++) {
for (int j = 0; j < colunas; j++) {
matriz[i][j] = cont * (linhas * 2) - j;
}
}
}
public void refleteEmColunasPares() {
int aux;
for (int j = 1; j < colunas; j = j + 2) {
for (int i = 0, cont = (linhas - 1); i < linhas / 2; i++, cont--) {
aux = matriz[i][j];
matriz[i][j] = matriz[cont][j];
matriz[cont][j] = aux;
}
}
}
public void permutaElemento(int lin, int col, int matriz_aux[][]) {
int aux;
aux = matriz_aux[lin][col];
matriz_aux[lin][col] = matriz_aux[lin + 1][col];
matriz_aux[lin + 1][col] = aux;
}
public int[][] geraQuadrado(int numeroMetodo, int indiceLinha, int matriz_aux[][]) {
int vetor1[] = retornaIndicesColuna(listas.getListaDeSolucoes().get(numeroMetodo).
getCombinacao1().getParcelas());
7
8. int vetor2[] = retornaIndicesColuna(listas.getListaDeSolucoes().get(numeroMetodo).
getCombinacao2().getParcelas());
for (int j = 0; j < vetor1.length; j++) {
permutaElemento(indiceLinha, vetor1[j], matriz_aux);
}
for (int j = 0; j < vetor2.length; j++) {
permutaElemento(indiceLinha, vetor2[j], matriz_aux);
}
return matriz_aux;
}
public void geraVariosQuadrados() {
for (int i = 0; i < listas.getListaPermutaSolucao().size(); i++) {
int[][] matriz_aux = copiaMatriz(matriz);
for (int j = 0; j < listas.getListaPermutaSolucao().get(i).size(); j++) {
geraQuadrado(listas.getListaPermutaSolucao().get(i).
get(j), j * 2, matriz_aux);
}
System.out.println("Quadrado semi-magico " + (i + 1) + ":");
imprimeMatriz(matriz_aux);
}
}
public int[] retornaIndicesColuna(ArrayList<Integer> array) {
int vetor[] = new int[array.size()];
for (int i = 0; i < array.size(); i++) {
for (int j = 0; j < listas.getVetorOmega().length; j++) {
if (array.get(i) == listas.getVetorOmega()[j]) {
vetor[i] = j;
}
}
}
return vetor;
}
public void imprimeMatriz() {
DecimalFormat formatter = new DecimalFormat("000");
for (int i = 0; i < linhas; i++) {
for (int j = 0; j < colunas; j++) {
System.out.print(formatter.format(matriz[i][j]) + " ");
}
System.out.println();
}
System.out.println();
}
public void imprimeMatriz(int matriz_aux[][]) {
DecimalFormat formatter = new DecimalFormat("000");
for (int i = 0; i < linhas; i++) {
for (int j = 0; j < colunas; j++) {
System.out.print(formatter.format(matriz_aux[i][j]) + " ");
}
System.out.println();
}
System.out.println();
}
}
4.5. Classe Principal
import java.io.BufferedReader;
import java.io.IOException;
8
9. import java.io.InputStreamReader;
public class Principal {
public static void main(String[] args) throws IOException {
System.out.println("Digite um numero inteiro par:");
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
String texto = buf.readLine();
try {
int numeroPar = Integer.parseInt(texto);
if (numeroPar % 2 == 0) {
Matriz m = new Matriz(numeroPar);
m.constroiMatrizSerpentiforme();
System.out.println("Matriz serpentiforme:");
m.imprimeMatriz();
m.refleteEmColunasPares();
System.out.println("Matriz serpentiforme espelhada em colunas pares:");
m.imprimeMatriz();
System.out.println();
m.geraVariosQuadrados();
} else {
System.out.println("Numero digitado nao ´ par.");
e
}
} catch (NumberFormatException e) {
System.out.println("O valor digitado nao e um numero inteiro.");
´
}
}
}
.
Conclusion
From snake-shaped matrix (procedure 1) we can construct a wide class of
semi-magic squares of any even orders disposing the numbers 1, 2, 3, · · · , n2
in the same sequence with orders increasing in n rows of odd order and de-
2
scending order in the n rows of even order and then effecting two procedures
2
are as follows: 2) make reflection (rotation of π radians) in each of columns
of even order (after procedures 1 and 2 rows of all odd orders have equal
sums c(n) − n ) and the rows of even orders sums equal to c(n) + n ); 3) swap
2 2
of elements with forms a(2k−1)j and a(2k)j , transferring n units of n a(2k)j
2 j=1
for the sum n a(2k−1)j .
j=1
Acknowledgments
We thank the student Oannes de Oliveira Miranda for discussions and
suggestions.
9
10. References
[1] J. P. De Los Reyes, Ashish Das, Chand K. Midha and P. Vellaisamy.
On a method to construct magic Rectangles of even order. New
Delhi: Indian Statistical Institute, Delhi Centre, 2007. Available at
http://www.isid.ac.in/∼statmath/2007/isid200709.pdf. 17/02/2012.
[2] Leonhard Euler. On magic squares. Originally published as De
quadratis magicis, Commentationes arithmeticae 2 (1849), 593-602.
Translated from the Latin by Jordan Bell, 2004. Available at
http://arxiv.org/pdf/math/0408230.pdf. 18/02/2012.
[3] La Loubere, Simon de. A new historical relation of the king-
dom of Siam. Ithaca, New York: Cornell University Li-
brary. Print source: London, Tho. Horne. . . [and 2 others],
1693. Available at http://dlxs.library.cornell.edu/cgi/t/text/text-
idx?c=sea;idno=sea130;view=toc;cc=sea. 29/2/2012.
[4] DE MIRANDA, L’hau˜ B. P.; DE MIRANDA, Liuhan O.; MIRANDA,
a
Lohans de O.; MIRANDA, Lossian B. B.; Computa¸˜o de Quadrados
ca
Semi-M´gicos Gerados por Matrizes Serpentiformes. Pˆster submetido
a o
e aceito no IV Congresso Latinoamericano de Matem´ticos, C´rdoba,
a o
Argentina, 2012.
[5] DE MIRANDA, L’hau˜ B. P.; DE MIRANDA, Liuhan O.; MIRANDA,
a
Lohans de O.; MIRANDA, Lossian B. B.; Quadrados Semi-M´gicos a
a
partir de ”Subset Sum”. Pˆster apresentado na 64a Reuni˜o Anual da
o a
Sociedade Brasileira para o Progresso da Ciˆncia, S˜o Lu´ 2012.
e a ıs,
[6] MIRANDA, Lohans de O.; MIRANDA, Lossian B. B. Semi-
Magic Squares From Snake-Shaped Matrices. Available at
http://www.slideshare.net/lossian/semimagic-squares-from-snakeshape
d-matrices.
[7] SEDGEWICK, R.; WAYNE, K. Introduction to Programming in Java:
An Interdisciplinary Approach. Addison-Wesley, 2008. Available at
<http://introcs.cs.princeton.edu/java/23recursion/Combinations.java.ht
ml>. 15/03/2012.
10