/////////////////////////////////////////////////////////////////////////////// // // http://mathsforeurope.digibel.be/magic.htm // // Ultra Super Magic Squares 5x5 // /////////////////////////////////////////////////////////////////////////////// // // An Ultra Super Magic Square is a Magic square that is complete and // symmetrical. // // (1) Complete property // In the squares, not only the major but also the minor diagonals add up to // the number 65. For example: // // A * * * * // * B * * * // * * C * * // * * * D * A + B + C + D + E = 65 (Major diagonal) // * * * * E // // * A * * * // * * B * * // * * * C * // * * * * D A + B + C + D + E = 65 // E * * * * // // * * A * * // * * * B * // * * * * C // D * * * * A + B + C + D + E = 65 // * E * * * // // ... // ... and so on. // // (2) Self complement // The square is invariant for the complemental transform. If we change each // number "n" of the square by "26-n" , we get the same square rotated. // Also called self-similar or self-joined square. // // (3) Five-star constellation patterns; // Sum of the five numbers of all small squares and the centers sum to the same // number 65. // // 1 * * * 9 1 * 22 * * * 15 * 18 * * * 22 * 9 // * * * * * * 19 * * * * * 6 * * * * * 5 * // * * 13 * * 10 * 13 * * * 2 * 24 * * * 13 * 16 // * * * * * * * * * * * * * * * * * * * * // 17 * * * 25 * * * * * * * * * * * * * * * // .... // .... // * * * * * // * * * * * // * * 13 * 16 // .... .... .... .... .... * * * 7 * // * * 4 * 25 // (4) Rhonbohedral patterns // Furthermore, five numbers of all small rhonbohedrons add up to // the same number 65. // // * 15 * * * * * 22 * * // 23 19 6 * * * 19 6 5 * // * 2 * * * * * 13 * * // * * * * * * * * * * // * * * * * * * * * * ...... // // ...... // ...... // // * * * * * * * 22 * * // * * * * * * * * * * // * * * 24 * 10 * 13 * 16 // * * 20 7 3 * * * * * // * * * 11 * * * 4 * * // // The F1 code below will calculate all 16 Ultra Super Magic Squares 5x5. // The code itself is quite straightforward and can be easily adapted to calculate // Ultra Super Magic Squares of other dimensions. // // To execute the code, run the query // // all UltraSuperMS5x5q() // // The program will generate and print all solutions in the following format: // // +---------------+ // | 1 15 22 18 9| // | 23 19 6 5 12| // | 10 2 13 24 16| // | 14 21 20 7 3| // | 17 8 4 11 25| // +---------------+ // // ___ Solution: 1 __________________________________ // // .... // .... // .... // // +---------------+ // | 5 23 16 14 7| // | 11 9 2 25 18| // | 22 20 13 6 4| // | 8 1 24 17 15| // | 19 12 10 3 21| // +---------------+ // // ___ Solution: 16 __________________________________ // // Number of solutions: 16 Number of backtracks: 3085 // Elapsed time: 00:00:01 // // /////////////////////////////////////////////////////////////////////////////// MS5 = [0..24]->>L[1..25] // an array of 25 numbers 1..25 pred UltraSuperMS5x5q() iff UltraSuperMS5x5(ms) & PrintFormattedSolution(ms) /////////////////////////////////////////////////////////////////////////////// // This is the main workhorse code. Explicitely specify all constraints // (mentioned above) required for Ultra Super Magic Square 5x5. // pred UltraSuperMS5x5(ms::MS5) iff ms = [ a1, a2, a3, a4, a5, b1, b2, b3, b4, b5, c1, c2, c3, c4, c5, d1, d2, d3, d4, d5, e1, e2, e3, e4, e5] & // set constraints to avoid generating solutions with // rotational/mirror symetries. a1 < a5 & a1 < e5 & a1 < e1 & a5 < e1 & // constraints for rows a1 + a2 + a3 + a4 + a5 = 65 & b1 + b2 + b3 + b4 + b5 = 65 & c1 + c2 + c3 + c4 + c5 = 65 & d1 + d2 + d3 + d4 + d5 = 65 & e1 + e2 + e3 + e4 + e5 = 65 & // constraints for columns a1 + b1 + c1 + d1 + e1 = 65 & a2 + b2 + c2 + d2 + e2 = 65 & a3 + b3 + c3 + d3 + e3 = 65 & a4 + b4 + c4 + d4 + e4 = 65 & a5 + b5 + c5 + d5 + e5 = 65 & // major + minor diagonals a1 + b2 + c3 + d4 + e5 = 65 & a2 + b3 + c4 + d5 + e1 = 65 & a3 + b4 + c5 + d1 + e2 = 65 & a4 + b5 + c1 + d2 + e3 = 65 & a5 + b1 + c2 + d3 + e4 = 65 & // reversed major + minor digonals a5 + b4 + c3 + d2 + e1 = 65 & a4 + b3 + c2 + d1 + e5 = 65 & a3 + b2 + c1 + d5 + e4 = 65 & a2 + b1 + c5 + d4 + e3 = 65 & a1 + b5 + c4 + d3 + e2 = 65 & // five star constellations patterns a1 + a5 + c3 + e1 + e5 = 65 & a1 + a3 + b2 + c1 + c3 = 65 & a2 + a4 + b3 + c2 + c4 = 65 & a3 + a5 + b4 + c3 + c5 = 65 & b1 + b3 + c2 + d1 + d3 = 65 & b2 + b4 + c3 + d2 + d4 = 65 & b3 + b5 + c4 + d3 + d5 = 65 & c1 + c3 + d2 + e1 + e3 = 65 & c2 + c4 + d3 + e2 + e4 = 65 & c3 + c5 + d4 + e3 + e5 = 65 & // Rhonbohedral patterns a2 + b1 + b2 + b3 + c2 = 65 & a3 + b2 + b3 + b4 + c3 = 65 & a4 + b3 + b4 + b5 + c4 = 65 & b2 + c1 + c2 + c3 + d2 = 65 & b3 + c2 + c3 + c4 + d3 = 65 & b4 + c3 + c4 + c5 + d4 = 65 & c2 + d1 + d2 + d3 + e2 = 65 & c3 + d2 + d3 + d4 + e3 = 65 & c4 + d3 + d4 + d5 + e4 = 65 & a3 + c1 + c3 + c5 + e3 = 65 & // Create a joint square "msj" JointSquare(ms,msj,0) & // If the joint square after some rotations is the same as // the "magic" square, we have an self-joined (or symmetrical) square. (Rotated180(msj,msr) | Rotated90(msj,msr) | Rotated270(msj,msr)) & msr = ms /////////////////////////////////////////////////////////////////////////////// // If we substitute each number x of a Magic square of order n by n**2 + 1 - x // (the x from the formula signifies the number in the original square), then // it can be proved that we get another Magic square. We call them joined // squares. local pred JointSquare(msa::MS5,msj::MS5,i:<I) iff if i < Len(msj) then msj(i) = 26 - msa(i) & JointSquare(msa,msj,i+1) end /////////////////////////////////////////////////////////////////////////////// // Rotate a square clockwise by 90 degrees: // // 0 1 2 3 4 20 15 10 5 0 // 5 6 7 8 9 21 16 11 6 1 // 10 11 12 13 14 -> 22 17 12 7 2 // 15 16 17 18 19 23 18 13 8 3 // 20 21 22 23 24 24 19 14 9 4 // local pred Rotated90(ms::MS5,msr::MS5) iff msr( 0) = ms(20) & msr( 1) = ms(15) & msr( 2) = ms(10) & msr( 3) = ms( 5) & msr( 4) = ms( 0) & msr( 5) = ms(21) & msr( 6) = ms(16) & msr( 7) = ms(11) & msr( 8) = ms( 6) & msr( 9) = ms( 1) & msr(10) = ms(22) & msr(11) = ms(17) & msr(12) = ms(12) & msr(13) = ms( 7) & msr(14) = ms( 2) & msr(15) = ms(23) & msr(16) = ms(18) & msr(17) = ms(13) & msr(18) = ms( 8) & msr(19) = ms( 3) & msr(20) = ms(24) & msr(21) = ms(19) & msr(22) = ms(14) & msr(23) = ms( 9) & msr(24) = ms( 4) /////////////////////////////////////////////////////////////////////////////// // Rotate a square by 180 degrees. This is done by two successive rotations // by 90 degrees. // local pred Rotated180(ms::MS5,msr::MS5) iff Rotated90(ms,ms90) & Rotated90(ms90,msr) /////////////////////////////////////////////////////////////////////////////// // Rotate a square by 270 degrees. This is done by successive rotations // by 180 and by 90 degrees. // local pred Rotated270(ms::MS5,msr::MS5) iff Rotated180(ms,ms180) & Rotated90(ms180,msr) /////////////////////////////////////////////////////////////////////////////// // Print the one dimensional array of 25 elements in a form of a 5x5 matrix // local proc PrintFormattedSolution(ms:<MS5) iff Print('\n+---------------+\n') & PrintRows(ms,0) & Print('+---------------+\n') local proc PrintRows(ms:<MS5,row:<I) iff if row < 5 then Print('|') & PrintCols(ms,row,0) & Print('|\n') & PrintRows(ms,row+1) end local proc PrintCols(ms:<MS5, row:<I,col:<I) iff if col < 5 then PrintNum3(ms(row*5+col)) & PrintCols(ms,row,col+1) end /////////////////////////////////////////////////////////////////////////////// // Print each number 1..25 as three characters, by prepending blank spaces // where neccessary. // local proc PrintNum3(i:<L) iff if i < 10 then Print(' ') end & Print(' ') & Print(i)
This page was created by F1toHTML