Prolog中如何固定谓词单个参数并对列表元素批量应用
问题修正说明
你当前代码的核心错误是maplist的调用写法不对,没有正确将R0固定为safe_queens的第一个参数。你写的safe_queens(R0,_)里的匿名变量不会和列表L的元素做绑定,自然无法完成遍历校验。
正确写法
方式1:使用maplist(标准Prolog兼容)
maplist支持传入部分参数已绑定的谓词,你只需要把固定的R0作为第一个参数传入,maplist会自动把列表L里的每个元素依次作为safe_queens的第二个参数传入做校验,不需要额外写匿名变量占位。
修正后的完整代码:
% 校验两个皇后不互相攻击 safe_queens([X1,Y1],[X2,Y2]) :- dif(X1, X2), dif(Y1, Y2), abs(X1 - X2) =\= abs(Y1 - Y2). % 任意皇后和空皇后列表无冲突 no_attack(_, []). % 皇后R0和皇后列表[R|L]无冲突 no_attack(R0, [R|L]) :- % R0和列表第一个皇后R无冲突 safe_queens(R0, R), % R0和列表剩余所有皇后L都无冲突 maplist(safe_queens(R0), L), % 列表第一个皇后R和剩余列表L也无冲突 no_attack(R, L).
注意:原来的
safe_queens里用\==做不等判断不适合n皇后求解场景——求解阶段坐标变量可能还未完成实例化,\==不会做约束性判断,建议换成dif/2(支持约束逻辑的Prolog环境都可用),如果环境不支持dif/2可以替换为\=,注意保证调用时变量已正确实例化即可。
方式2:不使用maplist,纯递归实现
如果不想用高阶谓词maplist,也可以直接把遍历校验逻辑写在递归规则里,逻辑更直白:
no_attack(_, []). no_attack(R0, [R|L]) :- safe_queens(R0, R), no_attack(R0, L), no_attack(R, L).
这里的no_attack(R0, L)就会递归完成R0和L里所有皇后的逐一校验,不需要额外调用maplist。
内容的提问来源于stack exchange,提问作者Elyo
相关产品推荐
相关产品推荐

