Original post: http://anothermysqldba.blogspot.com/2014/05/mysql-magic-square-4x4-routines-loop.html
Eu tenho desviado hoje jogando com quadrados mágicos e pensei que poderia ser uma boa oportunidade para dar um exemplo de utilização do MySQL rotinas, loops e se cheques.
Então, se você não tem conhecimento do que é um quadrado mágico é que eu incluí alguns links. Pode poupar uma pesquisa no Google, mas caso contrário acho Sudoku como exemplo.
Estou passando o valor de 4 para a rotina para mostrar como fazê-lo. É uma etapa desnecessária uma vez que estou codificação duro da praça a 4, mas mesmo assim ele funciona para o exemplo.
Agora que eu construí fora da rotina, posso obter resultados válidos? Tenha em mente que esta não é todas as possíveis opções, apenas opções que podem funcionar. 924 opções para um quadrado 4x4 existir.
Não! Eles trabalham para as linhas, mas não as colunas. Enquanto isto mostra como usar rotinas, loops e uma instrução IF, a exemplo falhar, ele não fornece o que eu queria. Então eu tive que refazer a inserção com mais de uma verificação IF, bem como troca de alguns números no final.
Agora isso funciona?
OK eu enganei um pouco, apenas movendo as colunas ao redor, mas você começa a idéia.
Eu tenho desviado hoje jogando com quadrados mágicos e pensei que poderia ser uma boa oportunidade para dar um exemplo de utilização do MySQL rotinas, loops e se cheques.
Então, se você não tem conhecimento do que é um quadrado mágico é que eu incluí alguns links. Pode poupar uma pesquisa no Google, mas caso contrário acho Sudoku como exemplo.
- http://en.wikipedia.org/wiki/Melencolia_I
- http://en.wikipedia.org/wiki/File:Albrecht_D% C3% BCrer_-_Melencolia_I_% 28detail% 29.jpg
- http://www.mathematische-basteleien.de/magsquare.htm
- http://mathworld.wolfram.com/MagicSquare.html
- http://quasistoic.org/fun/magicsquare/all.html
Estou passando o valor de 4 para a rotina para mostrar como fazê-lo. É uma etapa desnecessária uma vez que estou codificação duro da praça a 4, mas mesmo assim ele funciona para o exemplo.
DROP PROCEDURE IF EXISTS magic_sq;
DROP TABLE IF EXISTS `magic_sq` ;
delimiter //
CREATE PROCEDURE magic_sq( N int(11))
BEGIN
DECLARE nXn INT;
DECLARE SQ_SUM INT;
DECLARE _passfail_ INT;
DECLARE min INT;
DECLARE max INT;
-- DRAW THE TEMPLATE FOR THE SQUARE MAX of 8 FOR NOW
DROP TABLE IF EXISTS `magic_sq` ;
CREATE TABLE `magic_sq` (
`xy_id` int(11) NOT NULL AUTO_INCREMENT,
`1` int(11) NULL DEFAULT NULL,
`2` int(11) NULL DEFAULT NULL,
`3` int(11) NULL DEFAULT NULL,
`4` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`xy_id`) ,
UNIQUE KEY `Y1` (`1`),
UNIQUE KEY `Y2` (`2`),
UNIQUE KEY `Y3` (`3`),
UNIQUE KEY `Y4` (`4`)
) ENGINE= MEMORY;
-- n X n
SET @nXn = N + N;
-- SQ_SUM This is the formula for what the total should equal
SET @SQ_SUM = ( N * (POW(N,2) + 1) ) / 2;
-- MIN Value
SET @min=1;
-- MAX Value
SET @max=POW(N,2);
-- BUILD THE SQUARE
WHILE ( @min <= @nXn )
DO
-- TEST VALUES
SET _passfail_ = IF ( (@min + (@min +1) + ( @max - 1) +@max) = @SQ_SUM ,1 , 0 ) ;
-- IF VALID RESULTS THEN SAVE THEM
IF _passfail_ = 1 THEN
INSERT INTO magic_sq VALUES (NULL,@min ,(@min +1),( @max - 1) , @max );
END IF;
-- CONTINUE
SET @min= @min +2;
SET @max= @max -2;
END WHILE;
END//
delimiter ;
Agora que eu construí fora da rotina, posso obter resultados válidos? Tenha em mente que esta não é todas as possíveis opções, apenas opções que podem funcionar. 924 opções para um quadrado 4x4 existir.
CALL magic_sq(4);
select * from magic_sq;
+-------+------+------+------+------+
| xy_id | 1 | 2 | 3 | 4 |
+-------+------+------+------+------+
| 1 | 1 | 2 | 15 | 16 |
| 2 | 3 | 4 | 13 | 14 |
| 3 | 5 | 6 | 11 | 12 |
| 4 | 7 | 8 | 9 | 10 |
+-------+------+------+------+------+
+-------+---------+
| xy_id | per_row |
+-------+---------+
| 1 | 34 |
| 2 | 34 |
| 3 | 34 |
| 4 | 34 |
+-------+---------+
DROP PROCEDURE IF EXISTS magic_sq;
DROP TABLE IF EXISTS `magic_sq` ;
delimiter //
CREATE PROCEDURE magic_sq( N int(11))
BEGIN
DECLARE nXn INT;
DECLARE SQ_SUM INT;
DECLARE _passfail_ INT;
DECLARE _io_ INT;
DECLARE min INT;
DECLARE max INT;
-- DRAW THE TEMPLATE FOR THE SQUARE MAX of 8 FOR NOW
DROP TABLE IF EXISTS `magic_sq` ;
CREATE TABLE `magic_sq` (
`xy_id` int(11) NOT NULL AUTO_INCREMENT,
`1` int(11) NULL DEFAULT NULL,
`2` int(11) NULL DEFAULT NULL,
`3` int(11) NULL DEFAULT NULL,
`4` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`xy_id`) ,
UNIQUE KEY `Y1` (`1`),
UNIQUE KEY `Y2` (`2`),
UNIQUE KEY `Y3` (`3`),
UNIQUE KEY `Y4` (`4`)
) ENGINE= MEMORY;
-- n X n
SET @nXn = N + N;
-- SQ_SUM This is the formula for what the total should equal
SET @SQ_SUM = ( N * (POW(N,2) + 1) ) / 2;
-- MIN Value
SET @min=1;
-- MAX Value
SET @max=POW(N,2);
-- insert_options
SET _io_ =0;
-- BUILD THE SQUARE
WHILE ( @min <= @nXn )
DO
-- TEST VALUES
SET _passfail_ = IF ( (@min + (@min +1) + ( @max - 1) +@max) = @SQ_SUM ,1 , 0 ) ;
-- IF VALID RESULTS THEN SAVE THEM
IF _passfail_ = 1 THEN
IF _io_ = 0 THEN
INSERT INTO magic_sq VALUES (NULL,@min ,(@min +1),( @max - 1) , @max );
SET _io_ =1;
ELSEIF _io_ = 1 THEN
INSERT INTO magic_sq VALUES (NULL,( @max - 1),@max , @min , (@min +1) );
SET _io_ =2;
ELSEIF _io_ = 2 THEN
INSERT INTO magic_sq VALUES (NULL,@max ,(@min +1) , ( @max - 1) , @min );
SET _io_ =4;
ELSEIF _io_ = 4 THEN
INSERT INTO magic_sq VALUES (NULL, (@min +1) , @max , @min ,( @max - 1) );
SET _io_ =0;
END IF;
END IF;
-- CONTINUE
SET @min= @min +2;
SET @max= @max -2;
END WHILE;
SELECT @x3y2 := `2` FROM magic_sq WHERE xy_id = 3;
SELECT @x3y3 := `3` FROM magic_sq WHERE xy_id = 3;
SELECT @x4y2 := `2` FROM magic_sq WHERE xy_id = 4;
SELECT @x4y3 := `3` FROM magic_sq WHERE xy_id = 4;
UPDATE magic_sq SET `2` = @x4y3 , `3` = @x4y2 WHERE xy_id = 3;
UPDATE magic_sq SET `2` = @x3y3 , `3` = @x3y2 WHERE xy_id = 4;
select * from magic_sq;
select SUM(`1`),SUM(`2`),SUM(`3`),SUM(`4`) from magic_sq;
select xy_id, SUM(`1` +`2` +`3` + `4`) as per_row from magic_sq GROUP BY xy_id;
END//
delimiter ;
Agora isso funciona?
CALL magic_sq(4);
+-------+------+------+------+------+
| xy_id | 1 | 2 | 3 | 4 |
+-------+------+------+------+------+
| 1 | 1 | 2 | 15 | 16 |
| 2 | 13 | 14 | 3 | 4 |
| 3 | 12 | 7 | 10 | 5 |
| 4 | 8 | 11 | 6 | 9 |
+-------+------+------+------+------+
4 rows in set (0.22 sec)
+----------+----------+----------+----------+
| SUM(`1`) | SUM(`2`) | SUM(`3`) | SUM(`4`) |
+----------+----------+----------+----------+
| 34 | 34 | 34 | 34 |
+----------+----------+----------+----------+
1 row in set (0.22 sec)
+-------+---------+
| xy_id | per_row |
+-------+---------+
| 1 | 34 |
| 2 | 34 |
| 3 | 34 |
| 4 | 34 |
+-------+---------+