幻方解法之Merzirac法生成奇阶幻方

/*

程序思想参考百度百科上"幻方法则" 2015-01-27

http://baike.baidu.com/link?url=7ynfkLYfGv4f7PtQkuH4PSn_8IFr_QFAN-Bnsk0hmd2uk6WITW7r1d8o7IQJ1IL3bNRHbpHYbVXpDAvNbyJBDK


其实在维基百科上有更全面的,搜索Magic square即可查到,可惜太英语了,有点难,留着以后看^*^


代码环境xcode6.1 playground


几个公用函数只在第一篇显示,后面的篇章不在重复

func isMagic(s:[[Int]])->[Int]?

func printMagic(s:[[Int]])

func signed(aint: Int)->Int

func correction(k: Int, step: Int) ->Int

*/



/*

一、Merzirac法生成奇阶幻方

在第一行居中的方格内放1,依次向右上方填入234…,如果右上方已有数字,则向下移一格继续填写。如下图用Merziral法生成的5阶幻方:

17 24 18 15

23 5 714 16

4 6 1320 22

10 12 1921 3

11 18 252 9

*/

func JJMerzirac(#step:Int) -> ([[Int]])?{

   if (step < 3) {returnnil}

   if (step % 2 ==0) {return nil}

    

   let aRow = [Int](count: step, repeatedValue:0)

   var solution = [[Int]](count: step, repeatedValue: aRow)

    

    //要赋值的位置,初始化为第一行居中的位置

   var row = 0 //第一行

   var col = step/2 //中间列

   var iPut = 1 //放这个数

    //第一行居中的方格内放1

    solution[row][col] = iPut++

   var time = step * step - 1

   do{

        //下一个赋值的位置

       var nextcol = col + 1

       var nextrow = row - 1

        

        nextcol =correction(nextcol,step)

        nextrow =correction(nextrow,step)

        

       if solution[nextrow][nextcol] != 0{

            nextrow = row +1

            nextrow =correction(nextrow,step)

            nextcol = col

           if solution[nextrow][col] != 0{

               return solution

            }

        }

        

        row = nextrow

        col = nextcol

        solution[row][col] = iPut++

        

    }while(time-- >0)


    return nil

}


//测试过程

func testJJMerzirac(){

   func testAStep(step: Int){

       let s = JJMerzirac(step: step)

       if let s1 = s{

           printMagic(s1)

           let k = isMagic(s1)

           if let k1 = k{

               println("这个不是幻方 k=\(k1)")

            }


        }else{

            println("s is not a magic square step =\(step)")

        }

    }

    

    testAStep(3)

    testAStep(5)

    testAStep(7)

    testAStep(9)

}

//testJJMerzirac()//打开即可打印


/*3579阶幻方打印如下

[8, 1, 6]

[3, 5, 7]

[4, 9, 2]

经检查,行的和都是相等的

经检查,列的和都是相等的

经检查,左对角线的和都是相等的

经检查,右对角线的和都是相等的

[17, 24, 1, 8, 15]

[23, 5, 7, 14, 16]

[4, 6, 13, 20, 22]

[10, 12, 19, 21, 3]

[11, 18, 25, 2, 9]

经检查,行的和都是相等的

经检查,列的和都是相等的

经检查,左对角线的和都是相等的

经检查,右对角线的和都是相等的

[30, 39, 48, 1, 10, 19, 28]

[38, 47, 7, 9, 18, 27, 29]

[46, 6, 8, 17, 26, 35, 37]

[5, 14, 16, 25, 34, 36, 45]

[13, 15, 24, 33, 42, 44, 4]

[21, 23, 32, 41, 43, 3, 12]

[22, 31, 40, 49, 2, 11, 20]

经检查,行的和都是相等的

经检查,列的和都是相等的

经检查,左对角线的和都是相等的

经检查,右对角线的和都是相等的

[47, 58, 69, 80, 1, 12, 23, 34, 45]

[57, 68, 79, 9, 11, 22, 33, 44, 46]

[67, 78, 8, 10, 21, 32, 43, 54, 56]

[77, 7, 18, 20, 31, 42, 53, 55, 66]

[6, 17, 19, 30, 41, 52, 63, 65, 76]

[16, 27, 29, 40, 51, 62, 64, 75, 5]

[26, 28, 39, 50, 61, 72, 74, 4, 15]

[36, 38, 49, 60, 71, 73, 3, 14, 25]

[37, 48, 59, 70, 81, 2, 13, 24, 35]

经检查,行的和都是相等的

经检查,列的和都是相等的

经检查,左对角线的和都是相等的

经检查,右对角线的和都是相等的

*/


/*

Merzirac法,有人也叫楼梯法,我管它叫斜步法,即走X+Y斜步(数字按右上方顺序填入),-Y跳步(如果右上方已有数字或出了对角线,则向下移一格继续填写)。

其实斜步法可以向4个方向依次填写数字,即右上、右下、左上、左下4个方向,每种斜步都可有2种跳步,即左(右)跳步、上(下)跳步。

对于X+Y斜步相应的跳步可以为-X-Y【记住,跳步是X+Y斜步的X(或Y)相反方向即可。如右上方向斜步,跳步就为向左(或向下)一步;左下方向斜步,跳步就为向右(或向上)一步;等等等等】

*/

/*

step表示幻方阶数

deltaX,deltaY表示X方向,Y方向步长

jumpX表示跳步时是X方向,否则y方向

经测试并不是上面说的对于X+Y斜步相应的跳步可以为-X-Y”

可我的测试结果却发现这个扩展不对

下面是我写的程序以及测试结果

若有对原文理解不对的地方,请指正

*/

func JJMerziracExtend(#step:Int, #deltaX: Int, #deltaY:Int, jumpX: Bool =false) -> ([[Int]])?{

   if (step < 3) {returnnil}

   if (step % 2 ==0) {return nil}


   let aRow = [Int](count: step, repeatedValue:0)

   var solution = [[Int]](count: step, repeatedValue: aRow)



    //要赋值的位置,初始化为第一行居中的位置

   var row = 0 //第一行

   var col = step/2 //中间列

   var iPut = 1 //放这个数

    //第一行居中的方格内放1

    solution[row][col] = iPut++

   var time = step * step - 1

   do{

        //下一个赋值的位置

       var nextcol = col + deltaX

       var nextrow = row - deltaY

        

        nextcol =correction(nextcol,step)

        nextrow =correction(nextrow,step)

        

       if solution[nextrow][nextcol] != 0{

           if jumpX{//x轴上跳步

                

                nextcol = col +signed(deltaX) * signed(deltaY) *abs(deltaX) //右上,左下,x右跳步;左上,右下,x左跳步

                nextcol =correction(nextcol,step)

                nextrow = row

               if solution[row][nextcol] != 0{

                   return solution

                }

            }else{//y轴上跳步

                nextrow = row +abs(deltaY)//1在上面,y方向跳步肯定是向下的

                nextrow =correction(nextrow,step)

                nextcol = col

               if solution[nextrow][col] != 0{

                   return solution

                }

            }

        }

        row = nextrow

        col = nextcol

        solution[row][col] = iPut++

       

        

    

    }while(time-- >0)

    

    

    return nil

}



//测试过程

func testJJMerziracExtend(){

   func testAStep(#step: Int, #deltaX: Int, #deltaY: Int, jumpX: Bool = false){

       let s = JJMerziracExtend(step: step, deltaX: deltaX, deltaY: deltaY, jumpX: jumpX)

       if let s1 = s{

           printMagic(s1)

           let k = isMagic(s1)

           if let k1 = k{

               println("这个不是幻方 k=\(k1)")

            }

        }else{

            println("s is not a magic square step =\(step)")

        }

    }

    println("右上下跳")

   testAStep(step: 5,deltaX:1,deltaY: 1)//右上

    println("右上右跳")

   testAStep(step: 5,deltaX:1,deltaY: 1,jumpX:true)//右上

    println("右下下跳")

   testAStep(step: 5,deltaX:1,deltaY: -1)//右下

    println("右下左跳")

   testAStep(step: 5,deltaX:1,deltaY: -1,jumpX:true)//右下

    println("左上下跳")

   testAStep(step: 5,deltaX: -1,deltaY:1)//左上

    println("左上左跳")

   testAStep(step: 5,deltaX: -1,deltaY:1,jumpX:true)//左上

    println("左下下跳")

   testAStep(step: 5,deltaX: -1,deltaY: -1)//左下

    println("左下右跳")

   testAStep(step: 5,deltaX: -1,deltaY: -1,jumpX:true)//左下


}

//testJJMerziracExtend()//打开即可打印


/*

右上下跳

[17, 24, 1, 8, 15]

[23, 5, 7, 14, 16]

[4, 6, 13, 20, 22]

[10, 12, 19, 21, 3]

[11, 18, 25, 2, 9]

经检查,行的和都是相等的

经检查,列的和都是相等的

经检查,左对角线的和都是相等的

经检查,右对角线的和都是相等的

右上右跳

[19, 25, 1, 7, 13]

[24, 5, 6, 12, 18]

[4, 10, 11, 17, 23]

[9, 15, 16, 22, 3]

[14, 20, 21, 2, 8]

经检查,行的和都是相等的

这个不是幻方 k=[0, 0]

右下下跳

[11, 6, 1, 21, 16]

[17, 12, 7, 2, 22]

[23, 18, 13, 8, 3]

[4, 24, 19, 14, 9]

[10, 5, 25, 20, 15]

这个不是幻方 k=[1, 0]

右下左跳

[13, 7, 1, 25, 19]

[20, 14, 8, 2, 21]

[22, 16, 15, 9, 3]

[4, 23, 17, 11, 10]

[6, 5, 24, 18, 12]

经检查,行的和都是相等的

经检查,列的和都是相等的

经检查,左对角线的和都是相等的

经检查,右对角线的和都是相等的

左上下跳

[15, 8, 1, 24, 17]

[16, 14, 7, 5, 23]

[22, 20, 13, 6, 4]

[3, 21, 19, 12, 10]

[9, 2, 25, 18, 11]

经检查,行的和都是相等的

经检查,列的和都是相等的

经检查,左对角线的和都是相等的

经检查,右对角线的和都是相等的

左上左跳

[13, 7, 1, 25, 19]

[18, 12, 6, 5, 24]

[23, 17, 11, 10, 4]

[3, 22, 16, 15, 9]

[8, 2, 21, 20, 14]

经检查,行的和都是相等的

这个不是幻方 k=[0, 1]

左下下跳

[16, 21, 1, 6, 11]

[22, 2, 7, 12, 17]

[3, 8, 13, 18, 23]

[9, 14, 19, 24, 4]

[15, 20, 25, 5, 10]

这个不是幻方 k=[1, 0]

左下右跳

[19, 25, 1, 7, 13]

[21, 2, 8, 14, 20]

[3, 9, 15, 16, 22]

[10, 11, 17, 23, 4]

[12, 18, 24, 5, 6]

经检查,行的和都是相等的

经检查,列的和都是相等的

经检查,左对角线的和都是相等的

经检查,右对角线的和都是相等的

*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值