幻方解法之Strachey法生成双偶幻方

来源:互联网 发布:淘宝京东比价插件 编辑:程序博客网 时间:2024/04/30 04:41

/*

程序思想参考百度百科上"幻方法则" 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

*/


/*

2Strachey法生成双偶幻方

第一步,将n阶双偶幻方表示为4m阶幻方。将其等分为四分,成为如下图所示ABCD四个2m阶偶数幻方。

A C

D B

A1(2m)^2填写成2m阶幻方;B(2m)^2+12*(2m)^2填写成2m阶幻方;C2*(2m)^2+13*(2m)^2填写成2m阶幻方;D3*(2m^)2+14*(2m)^2填写成2m阶幻方;

8阶双偶幻方表示为4×2阶幻方。将其等分为四个2×2阶偶数幻方,即4阶偶数幻方。

16 2 3 13 48 34 35 45

5 11 10 8 37 43 42 40

9 7 6 12 41 39 38 44

4 14 15 1 36 46 47 33

64 50 51 61 32 18 19 29

53 59 58 56 21 27 26 24

57 55 54 60 25 23 22 28

52 62 63 49 20 30 31 17

第三步,在A每行取m个小格(一侧对角线格为必换格,其余m-1格只要不是另一侧对角线格即可),将其与D相应方格内交换;BC以相同方法进行。

对于8阶幻方,A每行取2个小格(一侧对角线格为必换格,其余1格只要不是另一侧对角线格即可),要与D相应方格内交换;CB以相同方法进行。

最简单的方法就是:A任意2列,与D相对应的2列互换,C任意2列,与B相对应的2列互换即可。

64 50 3 13 48 34 19 29

53 59 10 8 37 43 26 24

57 55 6 12 41 39 22 28

52 62 15 1 36 46 31 17

16 2 51 61 32 18 35 45

5 11 58 56 21 27 42 40

9 7 54 60 25 23 38 44

4 14 63 49 20 30 47 33

64 50 3 13 32 18 35 45

53 59 10 8 21 27 42 40

57 55 6 12 25 23 38 44

52 62 15 1 20 30 47 33

16 2 51 61 48 34 19 29

5 11 58 56 37 43 26 24

9 7 54 60 41 39 22 28

4 14 63 49 36 46 31 17

等等完成幻方,幻和值260

*/


func SOStrachey(#subMagic:[[Int]])->([[Int]])?{

   let subStep = subMagic.count

   let step = subStep * 2

    

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

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

    

    

    //填充s中一块区域,使之成为幻方,起点为row,col 边长为substep

   func fillSubMagic(inout s:[[Int]], #row0:Int, #col0: Int, #subMagic: [[Int]],var #iPut0:Int){

       for var row =0; row < subMagic.count; ++row{

           for var col =0; col < subMagic.count; ++col{

                s[row0 + row][col0 + col] = subMagic[row][col] + iPut0

            }

        }

    }

    

    //第一步,初始化ABCD

   fillSubMagic(&solution, row0: 0, col0: 0, subMagic: subMagic, iPut0: 1)

   fillSubMagic(&solution, row0: step/2, col0: step/2, subMagic: subMagic, iPut0: step*step+1)

   fillSubMagic(&solution, row0: 0, col0: step/2, subMagic: subMagic, iPut0: step*step*2+1)

   fillSubMagic(&solution, row0: step/2, col0:0, subMagic: subMagic, iPut0: step*step*3+1)

    

    

    //第二步,在A每行取m个小格(一侧对角线格为必换格,其余m-1格只要不是另一侧对角线格即可),将其与D相应方格内交换;BC以相同方法进行。

    //row0,col0第一个子区域的起点, row1,col1第二个子区域的起点, subStep边长

   func swapColumnDataInSubMagic(inout s:[[Int]], #row0:Int, #col0: Int, #row1:Int, #col1: Int, #subStep:Int){

       for var row =0; row < subStep; ++row{

           for var col =0; col < subStep/2; ++col{

               let swaprow0 = row + row0

               let swapcol0 = col + col0

               let swaprow1 = row + row1

               let swapcol1 = col + col1

                

               let tmp = s[swaprow0][swapcol0]

                s[swaprow0][swapcol0] = s[swaprow1][swapcol1]

                s[swaprow1][swapcol1] = tmp

            }

        }

    }

    

    //AD换前m列, BC换前m

   swapColumnDataInSubMagic(&solution, row0: 0, col0: 0, row1: step/2, col1:0, subStep: step/2)

   swapColumnDataInSubMagic(&solution, row0: 0, col0: step/2, row1: step/2, col1: step/2, subStep: step/2)

    

   return solution

}



//测试过程

func testSOStrachey(){

   func checkMagic(magic:[[Int]]){

       printMagic(magic)

       let k = isMagic(magic)

       if let k1 = k{

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

        }

    }

    

    println("来个8阶的")

   let magic4 = SOSpring1(step:4, swap00: true)

   let magic8 = SOStrachey(subMagic: magic4!)

   checkMagic(magic8!)

    

    println("来个12阶的")

   let magic3 = JJMerzirac(step:3)

   let magic6 = DOStrachey(subMagic: magic3!)

   let magic12 = SOStrachey(subMagic: magic6!)

   checkMagic(magic12!)

    

    println("16阶的来一个")

   let magic16 = SOStrachey(subMagic: magic8!)

   checkMagic(magic16!)

}

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



/*

来个8阶的

[209, 195, 4, 14, 81, 67, 132, 142]

[198, 204, 11, 9, 70, 76, 139, 137]

[202, 200, 7, 13, 74, 72, 135, 141]

[197, 207, 16, 2, 69, 79, 144, 130]

[17, 3, 196, 206, 145, 131, 68, 78]

[6, 12, 203, 201, 134, 140, 75, 73]

[10, 8, 199, 205, 138, 136, 71, 77]

[5, 15, 208, 194, 133, 143, 80, 66]

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

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

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

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

来个12阶的

[550, 435, 440, 82, 75, 80, 262, 147, 152, 370, 363, 368]

[437, 547, 441, 77, 79, 81, 149, 259, 153, 365, 367, 369]

[546, 443, 436, 78, 83, 76, 258, 155, 148, 366, 371, 364]

[442, 543, 548, 46, 39, 44, 154, 255, 260, 334, 327, 332]

[545, 439, 549, 41, 43, 45, 257, 151, 261, 329, 331, 333]

[438, 551, 544, 42, 47, 40, 150, 263, 256, 330, 335, 328]

[118, 3, 8, 514, 507, 512, 406, 291, 296, 226, 219, 224]

[5, 115, 9, 509, 511, 513, 293, 403, 297, 221, 223, 225]

[114, 11, 4, 510, 515, 508, 402, 299, 292, 222, 227, 220]

[10, 111, 116, 478, 471, 476, 298, 399, 404, 190, 183, 188]

[113, 7, 117, 473, 475, 477, 401, 295, 405, 185, 187, 189]

[6, 119, 112, 474, 479, 472, 294, 407, 400, 186, 191, 184]

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

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

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

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

16阶的来一个

[978, 964, 773, 783, 82, 68, 133, 143, 466, 452, 261, 271, 594, 580, 645, 655]

[967, 973, 780, 778, 71, 77, 140, 138, 455, 461, 268, 266, 583, 589, 652, 650]

[971, 969, 776, 782, 75, 73, 136, 142, 459, 457, 264, 270, 587, 585, 648, 654]

[966, 976, 785, 771, 70, 80, 145, 131, 454, 464, 273, 259, 582, 592, 657, 643]

[786, 772, 965, 975, 146, 132, 69, 79, 274, 260, 453, 463, 658, 644, 581, 591]

[775, 781, 972, 970, 135, 141, 76, 74, 263, 269, 460, 458, 647, 653, 588, 586]

[779, 777, 968, 974, 139, 137, 72, 78, 267, 265, 456, 462, 651, 649, 584, 590]

[774, 784, 977, 963, 134, 144, 81, 67, 262, 272, 465, 451, 646, 656, 593, 579]

[210, 196, 5, 15, 850, 836, 901, 911, 722, 708, 517, 527, 338, 324, 389, 399]

[199, 205, 12, 10, 839, 845, 908, 906, 711, 717, 524, 522, 327, 333, 396, 394]

[203, 201, 8, 14, 843, 841, 904, 910, 715, 713, 520, 526, 331, 329, 392, 398]

[198, 208, 17, 3, 838, 848, 913, 899, 710, 720, 529, 515, 326, 336, 401, 387]

[18, 4, 197, 207, 914, 900, 837, 847, 530, 516, 709, 719, 402, 388, 325, 335]

[7, 13, 204, 202, 903, 909, 844, 842, 519, 525, 716, 714, 391, 397, 332, 330]

[11, 9, 200, 206, 907, 905, 840, 846, 523, 521, 712, 718, 395, 393, 328, 334]

[6, 16, 209, 195, 902, 912, 849, 835, 518, 528, 721, 707, 390, 400, 337, 323]

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

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

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

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

*/


0 0
原创粉丝点击