使用Prolog的CLPFD

时间:2017-12-20 17:08:45

标签: prolog constraints puzzle clpfd

我尝试使用约束(CLPFD)在Prolog中实现Skyscraper puzzle解算器。

我已经意识到一个很大的限制是计算最大开关在遍历每一行和每列时的次数,并将其与侧线相匹配。

以下是单行示例:

*2* [ _ | _ | _ | _ ] *3*   ->   *2* [ 1 | 4 | 3 | 2 ] *3*

列表[1, 4, 3, 2]适用于线索 2 ,因为它有2个最大切换(0 - > 1 - > 4 )。
它也适用于线索 3 ,因为相同的列表反转 - [2, 3, 4, 1] - 有3个最大开关(0 - &gt; 2 - &gt; 3 < / strong> - &gt; 4 )。

我设法编写了一个谓词,该谓词返回列表中最大开关的数量 问题是如何实际利用它来生成新约束?我无法直接通过我的列表/矩阵,因为它尚未初始化。

应该是这样的:

calculate_max_switches(List, Switches),
% Generate a list whose Switches value is equal to the clue number.

谢谢。

1 个答案:

答案 0 :(得分:2)

没有看到你的代码,这是我的提示,改编自my previous answer

:- use_module(library(clpfd)).

skyscrape_row(Left, Right, Heights) :-
    constraint_view(0, Heights, LHeights),
    sum(LHeights, #=, Left),
    reverse(Heights, Heights_),
    constraint_view(0, Heights_, RHeights),
    sum(RHeights, #=, Right).

constraint_view(_, [], []).
constraint_view(Top, [V|Vs], [R|Rs]) :-
    R #<==> V #> 0 #/\ V #> Top,
    Max #= max(Top, V),
    constraint_view(Max, Vs, Rs).
适用于您的示例的

产生

?- L=[A,B,C,D], L ins 1..4, all_different(L), skyscrape_row(2,3,L), label(L).

A = 1,
B = 4,
C = 3,
D = 2,
L = [1, 4, 3, 2]
A = 2,
B = 4,
C = 3,
D = 1,
L = [2, 4, 3, 1]
A = 3,
B = 4,
C = 2,
D = 1,
L = [3, 4, 2, 1]

SWISH

中提供了实时代码