采用F#推导洛书

洛书:古称龟书,传说有神龟出于洛水,其甲壳上有此图象,结构是戴九履一,左三右七,二四为肩,六八为足,以五居中,五方白圈皆阳数,四隅黑点为阴数。

设计算法寻找此图

  • 1-9个数不能重复
  • 横向数字之和为15
  • 纵向数字之和为15
  • 斜向数字之和为15

代码如下

// 运用 F# 推导洛书
// See more infomation on http://www.1wuyou.com for more help.

let example = [|[|0;0;0|];
                [|0;0;0|];
                [|0;0;0|];|]
let size2 = 9;
let size = 3

let rec invalidNine (m:int array array) (index:int) shu =
    match index with
        | 9 -> false
        | index when m.[index/3].[index%3] = shu -> true
        | _-> 
            invalidNine m (index+1) shu
let rec invalidH (m:int array array) s x y (shu:int) (num:int) (sum:int) (dir:int)= 
    if num = 3 then
        if sum = 15 then Some(false) 
        else Some(true)
    else
       match s,x,y with
        | Some(true),x,y ->Some(true)
        | None,x,y -> None
        | s,x,y when m.[x].[y] = 0 && num>0 -> None
        | _ -> 
            let addnum = if num =0 then shu else m.[x].[y]
            match dir with
            | 1 -> invalidH m s ((x+1)%3) y shu (num+1) (sum+addnum) dir                //水平
            | 2 -> invalidH m s x ((y+1)%3) shu (num+1) (sum+addnum) dir                //垂直
            | 3 -> if (x+y)%2=1 then None else
                        invalidH m s ((x+1)%3)  ((y+1)%3) shu (num+1) (sum+addnum) dir  //右下
            | 4 -> if (x+y)%2=1 then None else
                        invalidH m s ((x+1)%3)  ((y-1+3)%3) shu (num+1) (sum+addnum) dir //右上
    
let Tinvalid m x y shu = 
    invalidNine m 0 shu 
    ||invalidH m (Some(false)) x y shu 0 0 1 = Some(true)
    ||invalidH m (Some(false)) x y shu 0 0 2 = Some(true)
    ||invalidH m (Some(false)) x y shu 0 0 3 = Some(true)
    ||invalidH m (Some(false)) x y shu 0 0 4 = Some(true)


let rec search m x y f accu =
    match x ,y with
        | x,y when x = 3 -> search m 0 (y+1) f accu
        | 0,y when y = 3 -> 
            printfn " 找到一个."
            //example |>Array.iter (fun t->printfn "%A" t)
            f accu
        | x,y ->
            let aux accu n = 
                if Tinvalid m  x y n  then accu else
                    (m.[x].[y] <- n;
                    let accu =  search m (x+1) y f accu in
                    m.[x].[y] <- 0;
                    accu) in
            List.fold aux accu [1..9]
                    


exception Exit
[<EntryPoint>]
let main argv = 
    try
      printfn "开始发现洛书 " 
      search example (0+0) 0 (fun s -> if example.[0].[0]=4 && example.[0].[2]=2 then raise Exit) () 
    with 
        |Exit -> printfn "易无忧找到真正洛书 "  
    
    example |>Array.iter (fun t->printfn "%A" t)
    
    0 
View Code

输出结果

开始发现洛书
 找到一个.
 找到一个.
 找到一个.
易无忧找到真正洛书
[|4; 9; 2|]
[|3; 5; 7|]
[|8; 1; 6|]
请按任意键继续. . .

结果分析:

   事实上我们共得到了8幅洛书 ,这几幅洛书就像是一张透明的正方扑克摆出了八种形态, 但真正的洛书只有一个,我们直接采用最终符合的判定进行了输出,

   为什么唯一的洛书只有一份呢?这个确实一直值得思考的问题,

4巽宫
9离宫
2坤宫
3震宫
5中宫
7兑宫
8艮宫
1坎宫
6乾宫

 此表与后天八卦卦序相对甚密 ,其中是有一定的联系的,其中的时序与方位是与我中华大地的位置南热北冷西高东低,太阳的东升西落四季更替等时空顺序是一致的。

原文地址:https://www.cnblogs.com/1wuyou/p/3836254.html