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

问题描述 投票:3回答:1

我正在尝试使用约束(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)。

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

它可能应该是这样的:

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

谢谢。

prolog constraints puzzle clpfd
1个回答
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提供实时代码

© www.soinside.com 2019 - 2024. All rights reserved.