基于约束结果生成列表,使用 Prolog 的 CLPFD

Generate a list based on constraint result, using Prolog's 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 -> 2 -> 3 -> 4)。

我已经设法编写了一个谓词,returns 我知道列表的最大开关数。
问题是如何实际利用它来生成新的约束?我不能直接传递我的 list/matrix 因为它还没有初始化。

大概应该是这样的:

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

谢谢。

没有看到你的代码,这是我的提示,改编自 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

中可用