用selen求解两种六角幻方

第一种三阶六角幻方求解在上文用SQL实现了,有点复杂,性能尚可。
张泽鹏先生写了个selen版,瞬间完成。
现在有第二种六角幻方:由正三角形组成的正六边形幻方

第1、2、3、4行分别有5、7、7、5个正三角形交错排列成为等腰梯形条带,每个三角形填充1-24中不同的数字,每行、每个向左倾斜60度条带、每个向右倾斜60度条带中三角形的数字和相等,求满足条件的一个幻方。

第1行:  1△2▽3△4▽5△
第2行:6△7▽8△9▽10△11▽12△
第3行:13▽14△15▽16△17▽18△19▽
第4行: 20▽21△22▽23△24▽

这个用SQL无法完成,因为五个数之和为75的排列太多,所以想看selen能否处理。
我在张先生的版本基础上修改如下:

use selen::prelude::Model;
use selen::prelude::ModelExt;
use selen::prelude::VarIdExt;

///    a b c d e
///  f g h i j k l
///  m n o p q r s
///    t u v w x
fn main() {
    let mut model = Model::default();

    let a = model.int(1, 24);
    let b = model.int(1, 24);
    let c = model.int(1, 24);
    let d = model.int(1, 24);
    let e = model.int(1, 24);
    let f = model.int(1, 24);
    let g = model.int(1, 24);
    let h = model.int(1, 24);
    let i = model.int(1, 24);
    let j = model.int(1, 24);
    let k = model.int(1, 24);
    let l = model.int(1, 24);
    let m = model.int(1, 24);
    let n = model.int(1, 24);
    let o = model.int(1, 24);
    let p = model.int(1, 24);
    let q = model.int(1, 24);
    let r = model.int(1, 24);
    let s = model.int(1, 24);
    let t = model.int(1, 24);
    let u = model.int(1, 24);
    let v = model.int(1, 24);
    let w = model.int(1, 24);
    let x = model.int(1, 24);


    // 每个数字只能出现一次
    let vars = vec![a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s,t,u,v,w,x];
    model.alldiff(&vars);

    // 橫
    model.new(a.add(b).add(c).add(d).add(e).eq(75));
    model.new(f.add(g).add(h).add(i).add(j).add(k).add(l).eq(75));
    model.new(m.add(n).add(o).add(p).add(q).add(r).add(s).eq(75));
    model.new(t.add(u).add(v).add(w).add(x).eq(75));

    // 左
    model.new(a.add(b).add(f).add(g).add(m).eq(75));
    model.new(c.add(d).add(h).add(i).add(n).add(o).add(t).eq(75));
    model.new(e.add(j).add(k).add(p).add(q).add(u).add(v).eq(75));
    model.new(l.add(r).add(s).add(w).add(x).eq(75));

    // 右
    model.new(d.add(e).add(k).add(l).add(s).eq(75));
    model.new(b.add(c).add(i).add(j).add(q).add(r).add(x).eq(75));
    model.new(a.add(g).add(h).add(o).add(p).add(v).add(w).eq(75));
    model.new(f.add(m).add(n).add(t).add(u).eq(75));

    if let Ok(solution) = model.solve() {
        println!("      {:?} {:?} {:?} {:?} {:?}", solution[a], solution[b], solution[c], solution[d], solution[e]);
        println!(" {:?} {:?} {:?} {:?} {:?} {:?} {:?}", solution[f], solution[g], solution[h], solution[i], solution[j], solution[k], solution[l]);
        println!(" {:?} {:?} {:?} {:?} {:?} {:?} {:?}", solution[m], solution[n], solution[o], solution[p], solution[q], solution[r], solution[s]);
        println!("      {:?} {:?} {:?} {:?} {:?}", solution[t], solution[u], solution[v], solution[w], solution[x]);
    }
}

执行也是瞬间完成。结果如下:

    1 10 18 22 24
20 21  2  4  7  6 15
23  5 11  9  3 16  8
   13 14 12 19 17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值