/*
程序思想参考百度百科上"幻方法则" 2015-01-27
其实在维基百科上有更全面的,搜索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,依次向右上方填入2、3、4…,如果右上方已有数字,则向下移一格继续填写。如下图用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]
经检查,行的和都是相等的
经检查,列的和都是相等的
经检查,左对角线的和都是相等的
经检查,右对角线的和都是相等的
*/