You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何简化CLP逻辑谜题中的约束条件表达实现?

逻辑谜题Prolog约束求解优化方案

谜题背景

当地游戏夜活动上,四名年轻人参与了拼字游戏(Scrabble)和国际象棋两个项目的角逐:国际象棋项目中利亚姆(Liam)击败了马克(Mark),詹姆斯(James)获得第三名,16岁的选手夺冠;拼字游戏项目中利亚姆获得第二名,15岁的选手夺冠,詹姆斯击败了18岁的选手,19岁的选手获得第三名;凯文(Kevin)比马克小3岁;国际象棋排名垫底的选手在拼字游戏中获得第三名,且仅有一名选手在两个项目中的排名完全相同。

现有代码的问题

你当前调整后的版本已经用permutation/2简化了域声明和全不同约束,但还存在明显可优化的点,以及隐藏错误:

  • 存在笔误:国际象棋排名范围为1~4,约束中错误写了CL #= 5,该分支永远无法满足;最早版本漏写了AM的年龄域,重复声明了AK的年龄域
  • 所有「某年龄选手获得某排名」的条件都用硬编码4个分支的枚举写法,冗余且可读性差
  • 「仅有一名选手两个项目排名相同」的约束硬编码4种分支,写法死板
  • 遗漏了拼字游戏中「詹姆斯击败了18岁的选手」的核心约束,会导致结果不符合题目要求

优化思路

  1. 用列表统一映射人名和对应属性,用CLPFD的element/3替代枚举分支,简化属性和排名的对应约束
  2. 用sum/3统计两个项目排名相等的人数,直接约束为1,替代硬编码分支
  3. 修正所有笔误,补充遗漏的约束

优化后完整代码

:- use_module(library(clpfd)).

solve() :-
    % 列表顺序对应4个人:詹姆斯(J)、凯文(K)、利亚姆(L)、马克(M)
    Age = [AJ, AK, AL, AM],
    ChessRank = [CJ, CK, CL, CM],
    ScrabbleRank = [SJ, SK, SL, SM],

    % 基础约束:年龄、排名都是指定值的全排列
    permutation(Age, [15,16,18,19]),
    permutation(ChessRank, [1,2,3,4]),
    permutation(ScrabbleRank, [1,2,3,4]),

    % 国际象棋规则约束
    CL #< CM, % 利亚姆击败马克
    CJ #= 3, % 詹姆斯第三名
    element(ChessChampionIdx, Age, 16), element(ChessChampionIdx, ChessRank, 1), % 16岁选手夺冠
    element(ChessLastIdx, ChessRank, 4), element(ChessLastIdx, ScrabbleRank, 3), % 象棋垫底的选手拼字获第三

    % 拼字游戏规则约束
    SL #= 2, % 利亚姆获第二名
    element(ScrabbleChampionIdx, Age, 15), element(ScrabbleChampionIdx, ScrabbleRank, 1), % 15岁选手夺冠
    element(ScrabbleThirdIdx, Age, 19), element(ScrabbleThirdIdx, ScrabbleRank, 3), % 19岁选手获第三名
    element(Age18Idx, Age, 18), element(Age18Idx, ScrabbleRank, S18), SJ #< S18, % 詹姆斯击败18岁选手

    % 通用规则约束
    AK #= AM - 3, % 凯文比马克小3岁
    % 仅1名选手两个项目排名完全相同
    maplist(#=, ChessRank, ScrabbleRank, EqList),
    sum(EqList, #=, 1),

    % 求解并输出结果
    label(Age), label(ChessRank), label(ScrabbleRank),
    format('詹姆斯:年龄~d,象棋第~d,拼字第~d~n', [AJ, CJ, SJ]),
    format('凯文:年龄~d,象棋第~d,拼字第~d~n', [AK, CK, SK]),
    format('利亚姆:年龄~d,象棋第~d,拼字第~d~n', [AL, CL, SL]),
    format('马克:年龄~d,象棋第~d,拼字第~d~n', [AM, CM, SM]).

优化说明

  • 用element/3约束某年龄的选手对应某排名,不用再枚举4个人的变量,代码更简洁,修改调整也更方便
  • 用maplist和sum组合实现“仅一个排名相同”的约束,逻辑更清晰,不需要硬编码所有分支
  • 补充了遗漏的拼字游戏约束,同时修正了原代码的笔误,可直接运行得到唯一正确解

内容的提问来源于stack exchange,提问作者vasily

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 16:06:02