HomeHome More SamplesMore Samples
///////////////////////////////////////////////////////////////////////////////
//
// 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